diff --git a/DEPS b/DEPS
index 3b999dc..eb6263e 100644
--- a/DEPS
+++ b/DEPS
@@ -144,11 +144,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': 'c8e8e7061f1e20428e03cd50f9803096fc5ad3e8',
+  'skia_revision': 'ff2e8fe65f5610a846c69ef5fb12a3fba524dce1',
   # 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': '5bf6b8221240ae424bb2b19713bec7534125b9c5',
+  'v8_revision': 'ffee6baaeee1bcaa8d1bba5e981377d30b37bd88',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -156,11 +156,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '84b5c90e0ba4f5c093a36460ff2b302441cbab40',
+  'angle_revision': '6f0780f8e42e97353a801cbf5c9baae11238df6d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': 'f5182abb681627b0d3b29a099760f7c3c7e7d49b',
+  'swiftshader_revision': '52ce1e9f23861cddc58db9646f32de67d8808111',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -207,7 +207,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': '43959e2a9f07a4874ab89ac4d336115a22f53a7f',
+  'catapult_revision': '60b615536f54726c34d2137494bd447728465db0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -279,7 +279,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': 'f07e85c60462e33f3a62dabf2e055bf10b7b8e62',
+  'dawn_revision': 'c8ab96cdd907c53a6147beaf3e2dcda943818e3f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -833,7 +833,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '70eba7d2d1982af6b2f14aae64f03742508b8d08',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '65c2b1e1d17e7f444b965a5eeefa2af8f0d61216',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1194,7 +1194,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '38439a96a7bdb3e31a1166cbce7acf7d728753d4',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' +  '8707d4db8017e42563b45565dd0fdad217860d4a',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1362,7 +1362,7 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '6453c2f5604ec8bca15e9e1edc64e979da8f1083',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '4c2c412d7e12a6c7db8cecd2798e75e34cc11173',
+    Var('webrtc_git') + '/src.git' + '@' + '08da49d0a488aaf915f90c33b1f9bdbfecbe4367',
 
   'src/third_party/xdg-utils': {
       'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
@@ -1403,7 +1403,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@322819164e52d02cff026592fc9ad4561089d54f',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@9a756b715c2871026e698448c22dc30e520ad88b',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/PRESUBMIT.py b/PRESUBMIT.py
index 74dbe07..6249613d 100644
--- a/PRESUBMIT.py
+++ b/PRESUBMIT.py
@@ -713,7 +713,7 @@
       'base::ScopedMockTimeMessageLoopTaskRunner',
       (
         'ScopedMockTimeMessageLoopTaskRunner is deprecated. Prefer',
-        'ScopedTaskEnvironment::MainThreadType::MOCK_TIME. There are still a',
+        'ScopedTaskEnvironment::TimeSource::MOCK_TIME. There are still a',
         'few cases that may require a ScopedMockTimeMessageLoopTaskRunner',
         '(i.e. mocking the main MessageLoopForUI in browser_tests), but check',
         'with gab@ first if you think you need it)',
diff --git a/WATCHLISTS b/WATCHLISTS
index eac20f6..23d7d41 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1510,6 +1510,15 @@
       'filepath': 'chrome/(browser|common|renderer)/safe_browsing/|'\
                   'components/safe_browsing/',
     },
+    'sampling_profiler': {
+      'filepath': 'base/profiler/'\
+                  '|chrome/common/profiler/'\
+                  '|chrome/common/stack_sampling_configuration*'\
+                  '|chrome/common/thread_profiler*'\
+                  '|chrome/renderer/v8_unwinder*'\
+                  '|components/metrics/*call_stack*'\
+                  '|components/metrics/public/interfaces/call_stack*',
+    },
     'screen_orientation': {
       'filepath': 'screen_orientation',
     },
@@ -2513,6 +2522,7 @@
     'safe_browsing': ['drubery@chromium.org',
                       'timvolodine@chromium.org',
                       'vakh+watch@chromium.org'],
+    'sampling_profiler': ['wittman+watch@chromium.org'],
     'screen_orientation': ['mlamouri+watch-screen-orientation@chromium.org'],
     'security': ['security-watchlist@chromium.org'],
     'select_to_speak': ['katie+watch@chromium.org',
diff --git a/android_webview/browser/aw_browser_context.cc b/android_webview/browser/aw_browser_context.cc
index dedc76d1..5d93053 100644
--- a/android_webview/browser/aw_browser_context.cc
+++ b/android_webview/browser/aw_browser_context.cc
@@ -9,14 +9,19 @@
 #include <utility>
 
 #include "android_webview/browser/aw_browser_policy_connector.h"
+#include "android_webview/browser/aw_content_browser_client.h"
 #include "android_webview/browser/aw_download_manager_delegate.h"
+#include "android_webview/browser/aw_feature_list.h"
 #include "android_webview/browser/aw_form_database_service.h"
 #include "android_webview/browser/aw_metrics_service_client.h"
 #include "android_webview/browser/aw_permission_manager.h"
 #include "android_webview/browser/aw_quota_manager_bridge.h"
 #include "android_webview/browser/aw_resource_context.h"
 #include "android_webview/browser/aw_web_ui_controller_factory.h"
+#include "android_webview/browser/cookie_manager.h"
 #include "android_webview/browser/net/aw_url_request_context_getter.h"
+#include "android_webview/browser/network_service/net_helpers.h"
+#include "android_webview/browser/safe_browsing/aw_safe_browsing_whitelist_manager.h"
 #include "base/base_paths_posix.h"
 #include "base/bind.h"
 #include "base/feature_list.h"
@@ -42,6 +47,7 @@
 #include "components/visitedlink/browser/visitedlink_master.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/cors_exempt_headers.h"
 #include "content/public/browser/download_request_utils.h"
 #include "content/public/browser/network_service_instance.h"
 #include "content/public/browser/ssl_host_state_delegate.h"
@@ -111,6 +117,7 @@
 
 AwBrowserContext::~AwBrowserContext() {
   DCHECK_EQ(this, g_browser_context);
+  BrowserContext::NotifyWillBeDestroyed(this);
   SimpleKeyMap::GetInstance()->Dissociate(this);
   g_browser_context = NULL;
 }
@@ -129,7 +136,6 @@
   return static_cast<AwBrowserContext*>(web_contents->GetBrowserContext());
 }
 
-// static
 base::FilePath AwBrowserContext::GetCacheDir() {
   FilePath cache_path;
   if (!base::PathService::Get(base::DIR_CACHE, &cache_path)) {
@@ -422,4 +428,67 @@
       ::prefs::kSafeBrowsingExtendedReportingOptInAllowed, allowed);
 }
 
+// TODO(amalova): Make sure NetworkContext is configured correctly when
+// off-the-record
+network::mojom::NetworkContextParamsPtr
+AwBrowserContext::GetNetworkContextParams(
+    bool in_memory,
+    const base::FilePath& relative_partition_path) {
+  network::mojom::NetworkContextParamsPtr context_params =
+      network::mojom::NetworkContextParams::New();
+  context_params->user_agent = android_webview::GetUserAgent();
+
+  // TODO(ntfschr): set this value to a proper value based on the user's
+  // preferred locales (http://crbug.com/898555). For now, set this to
+  // "en-US,en" instead of "en-us,en", since Android guarantees region codes
+  // will be uppercase.
+  context_params->accept_language =
+      net::HttpUtil::GenerateAcceptLanguageHeader("en-US,en");
+
+  // HTTP cache
+  context_params->http_cache_enabled = true;
+  context_params->http_cache_max_size = GetHttpCacheSize();
+  context_params->http_cache_path = GetCacheDir();
+
+  // WebView should persist and restore cookies between app sessions (including
+  // session cookies).
+  context_params->cookie_path = AwBrowserContext::GetCookieStorePath();
+  context_params->restore_old_session_cookies = true;
+  context_params->persist_session_cookies = true;
+  context_params->cookie_manager_params =
+      network::mojom::CookieManagerParams::New();
+  context_params->cookie_manager_params->allow_file_scheme_cookies =
+      CookieManager::GetInstance()->AllowFileSchemeCookies();
+
+  context_params->initial_ssl_config = network::mojom::SSLConfig::New();
+  // Allow SHA-1 to be used for locally-installed trust anchors, as WebView
+  // should behave like the Android system would.
+  context_params->initial_ssl_config->sha1_local_anchors_enabled = true;
+  // Do not enforce the Legacy Symantec PKI policies outlined in
+  // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html,
+  // defer to the Android system.
+  context_params->initial_ssl_config->symantec_enforcement_disabled = true;
+
+  // WebView does not currently support Certificate Transparency
+  // (http://crbug.com/921750).
+  context_params->enforce_chrome_ct_policy = false;
+
+  // WebView does not support ftp yet.
+  context_params->enable_ftp_url_support = false;
+
+  context_params->enable_brotli = base::FeatureList::IsEnabled(
+      android_webview::features::kWebViewBrotliSupport);
+
+  context_params->check_clear_text_permitted =
+      AwContentBrowserClient::get_check_cleartext_permitted();
+
+  content::UpdateCorsExemptHeader(context_params.get());
+
+  // Add proxy settings
+  AwProxyConfigMonitor::GetInstance()->AddProxyToNetworkContextParams(
+      context_params);
+
+  return context_params;
+}
+
 }  // namespace android_webview
diff --git a/android_webview/browser/aw_browser_context.h b/android_webview/browser/aw_browser_context.h
index 40cd33b5..a907818 100644
--- a/android_webview/browser/aw_browser_context.h
+++ b/android_webview/browser/aw_browser_context.h
@@ -78,9 +78,7 @@
   static AwBrowserContext* FromWebContents(
       content::WebContents* web_contents);
 
-  // TODO(ntfschr): consider moving these into our PathService in
-  // common/aw_paths.h (http://crbug.com/934184).
-  static base::FilePath GetCacheDir();
+  base::FilePath GetCacheDir();
   static base::FilePath GetCookieStorePath();
   static base::FilePath GetContextStoragePath();
 
@@ -134,6 +132,10 @@
 
   void SetExtendedReportingAllowed(bool allowed);
 
+  network::mojom::NetworkContextParamsPtr GetNetworkContextParams(
+      bool in_memory,
+      const base::FilePath& relative_partition_path);
+
  private:
   void OnAuthPrefsChanged();
   void CreateUserPrefService();
diff --git a/android_webview/browser/aw_browser_context_unittest.cc b/android_webview/browser/aw_browser_context_unittest.cc
new file mode 100644
index 0000000..47d3734
--- /dev/null
+++ b/android_webview/browser/aw_browser_context_unittest.cc
@@ -0,0 +1,54 @@
+// 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 "android_webview/browser/aw_browser_context.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "mojo/core/embedder/embedder.h"
+#include "services/network/public/cpp/features.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace android_webview {
+
+class AwBrowserContextTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    mojo::core::Init();
+    feature_list_.InitAndEnableFeature(network::features::kNetworkService);
+  }
+
+  base::test::ScopedFeatureList feature_list_;
+  // Create the TestBrowserThreads.
+  content::TestBrowserThreadBundle thread_bundle_;
+};
+
+// Tests that constraints on trust for Symantec-issued certificates are not
+// enforced for the NetworkContext, as it should behave like the Android system.
+TEST_F(AwBrowserContextTest, SymantecPoliciesExempted) {
+  AwBrowserContext context;
+  network::mojom::NetworkContextParamsPtr network_context_params =
+      context.GetNetworkContextParams(false, base::FilePath());
+
+  ASSERT_TRUE(network_context_params);
+  ASSERT_TRUE(network_context_params->initial_ssl_config);
+  ASSERT_TRUE(network_context_params->initial_ssl_config
+                  ->symantec_enforcement_disabled);
+}
+
+// Tests that SHA-1 is still allowed for locally-installed trust anchors,
+// including those in application manifests, as it should behave like
+// the Android system.
+TEST_F(AwBrowserContextTest, SHA1LocalAnchorsAllowed) {
+  AwBrowserContext context;
+  network::mojom::NetworkContextParamsPtr network_context_params =
+      context.GetNetworkContextParams(false, base::FilePath());
+
+  ASSERT_TRUE(network_context_params);
+  ASSERT_TRUE(network_context_params->initial_ssl_config);
+  ASSERT_TRUE(
+      network_context_params->initial_ssl_config->sha1_local_anchors_enabled);
+}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index be57bb8..f6b017bb 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -33,7 +33,6 @@
 #include "android_webview/browser/network_service/aw_proxying_restricted_cookie_manager.h"
 #include "android_webview/browser/network_service/aw_proxying_url_loader_factory.h"
 #include "android_webview/browser/network_service/aw_url_loader_throttle.h"
-#include "android_webview/browser/network_service/net_helpers.h"
 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h"
 #include "android_webview/browser/safe_browsing/aw_url_checker_delegate_impl.h"
 #include "android_webview/browser/tracing/aw_tracing_delegate.h"
@@ -75,7 +74,6 @@
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/child_process_security_policy.h"
 #include "content/public/browser/client_certificate_delegate.h"
-#include "content/public/browser/cors_exempt_headers.h"
 #include "content/public/browser/file_url_loader.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle.h"
@@ -122,7 +120,6 @@
 namespace android_webview {
 namespace {
 static bool g_should_create_thread_pool = true;
-
 #if DCHECK_IS_ON()
 // A boolean value to determine if the NetworkContext has been created yet. This
 // exists only to check correctness: g_check_cleartext_permitted may only be set
@@ -130,6 +127,7 @@
 // g_check_cleartext_permitted won't have any effect).
 bool g_created_network_context_params = false;
 #endif
+
 // On apps targeting API level O or later, check cleartext is enforced.
 bool g_check_cleartext_permitted = false;
 
@@ -313,6 +311,11 @@
   g_check_cleartext_permitted = permitted;
 }
 
+// static
+bool AwContentBrowserClient::get_check_cleartext_permitted() {
+  return g_check_cleartext_permitted;
+}
+
 AwContentBrowserClient::AwContentBrowserClient(
     AwFeatureListCreator* aw_feature_list_creator)
     : aw_feature_list_creator_(aw_feature_list_creator) {
@@ -362,8 +365,10 @@
 
   network::mojom::NetworkContextPtr network_context;
   network::mojom::NetworkContextParamsPtr context_params =
-      GetNetworkContextParams();
-
+      aw_context->GetNetworkContextParams(in_memory, relative_partition_path);
+#if DCHECK_IS_ON()
+  g_created_network_context_params = true;
+#endif
   content::GetNetworkService()->CreateNetworkContext(
       MakeRequest(&network_context), std::move(context_params));
 
@@ -374,66 +379,6 @@
   return network_context;
 }
 
-network::mojom::NetworkContextParamsPtr
-AwContentBrowserClient::GetNetworkContextParams() {
-  network::mojom::NetworkContextParamsPtr context_params =
-      network::mojom::NetworkContextParams::New();
-  context_params->user_agent = GetUserAgent();
-  // TODO(ntfschr): set this value to a proper value based on the user's
-  // preferred locales (http://crbug.com/898555). For now, set this to
-  // "en-US,en" instead of "en-us,en", since Android guarantees region codes
-  // will be uppercase.
-  context_params->accept_language =
-      net::HttpUtil::GenerateAcceptLanguageHeader("en-US,en");
-
-  // HTTP cache
-  context_params->http_cache_enabled = true;
-  context_params->http_cache_max_size = GetHttpCacheSize();
-  context_params->http_cache_path = AwBrowserContext::GetCacheDir();
-
-  // WebView should persist and restore cookies between app sessions (including
-  // session cookies).
-  context_params->cookie_path = AwBrowserContext::GetCookieStorePath();
-  context_params->restore_old_session_cookies = true;
-  context_params->persist_session_cookies = true;
-  context_params->cookie_manager_params =
-      network::mojom::CookieManagerParams::New();
-  context_params->cookie_manager_params->allow_file_scheme_cookies =
-      CookieManager::GetInstance()->AllowFileSchemeCookies();
-
-  context_params->initial_ssl_config = network::mojom::SSLConfig::New();
-  // Allow SHA-1 to be used for locally-installed trust anchors, as WebView
-  // should behave like the Android system would.
-  context_params->initial_ssl_config->sha1_local_anchors_enabled = true;
-  // Do not enforce the Legacy Symantec PKI policies outlined in
-  // https://security.googleblog.com/2017/09/chromes-plan-to-distrust-symantec.html,
-  // defer to the Android system.
-  context_params->initial_ssl_config->symantec_enforcement_disabled = true;
-
-  // WebView does not currently support Certificate Transparency
-  // (http://crbug.com/921750).
-  context_params->enforce_chrome_ct_policy = false;
-
-  // WebView does not support ftp yet.
-  context_params->enable_ftp_url_support = false;
-
-  context_params->enable_brotli = base::FeatureList::IsEnabled(
-      android_webview::features::kWebViewBrotliSupport);
-
-#if DCHECK_IS_ON()
-  g_created_network_context_params = true;
-#endif
-  context_params->check_clear_text_permitted = g_check_cleartext_permitted;
-
-  content::UpdateCorsExemptHeader(context_params.get());
-
-  // Add proxy settings
-  AwProxyConfigMonitor::GetInstance()->AddProxyToNetworkContextParams(
-      context_params);
-
-  return context_params;
-}
-
 AwBrowserContext* AwContentBrowserClient::InitBrowserContext() {
   browser_context_ = std::make_unique<AwBrowserContext>();
   return browser_context_.get();
@@ -604,8 +549,9 @@
   // If we pass 0 for size, disk_cache will pick a default size using the
   // heuristics based on available disk size. These are implemented in
   // disk_cache::PreferredCacheSize in net/disk_cache/cache_util.cc.
+  AwBrowserContext* browser_context = static_cast<AwBrowserContext*>(context);
   return content::GeneratedCodeCacheSettings(true, 0,
-                                             AwBrowserContext::GetCacheDir());
+                                             browser_context->GetCacheDir());
 }
 
 void AwContentBrowserClient::AllowCertificateError(
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index 1c0edc11..bfcc7ac 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -46,6 +46,7 @@
   // platform. For details, see
   // https://developer.android.com/reference/android/security/NetworkSecurityPolicy.html#isCleartextTrafficPermitted().
   static void set_check_cleartext_permitted(bool permitted);
+  static bool get_check_cleartext_permitted();
 
   // |aw_feature_list_creator| should not be null.
   explicit AwContentBrowserClient(
@@ -62,7 +63,6 @@
       content::BrowserContext* context,
       bool in_memory,
       const base::FilePath& relative_partition_path) override;
-  network::mojom::NetworkContextParamsPtr GetNetworkContextParams();
 
   std::unique_ptr<content::BrowserMainParts> CreateBrowserMainParts(
       const content::MainFunctionParams& parameters) override;
diff --git a/android_webview/browser/aw_content_browser_client_unittest.cc b/android_webview/browser/aw_content_browser_client_unittest.cc
index 7ae0566..3f6349d 100644
--- a/android_webview/browser/aw_content_browser_client_unittest.cc
+++ b/android_webview/browser/aw_content_browser_client_unittest.cc
@@ -33,33 +33,4 @@
   EXPECT_FALSE(client.ShouldCreateThreadPool());
 }
 
-// Tests that constraints on trust for Symantec-issued certificates are not
-// enforced for the NetworkContext, as it should behave like the Android system.
-TEST_F(AwContentBrowserClientTest, SymantecPoliciesExempted) {
-  AwFeatureListCreator aw_feature_list_creator;
-  AwContentBrowserClient client(&aw_feature_list_creator);
-  network::mojom::NetworkContextParamsPtr network_context_params =
-      client.GetNetworkContextParams();
-
-  ASSERT_TRUE(network_context_params);
-  ASSERT_TRUE(network_context_params->initial_ssl_config);
-  ASSERT_TRUE(network_context_params->initial_ssl_config
-                  ->symantec_enforcement_disabled);
-}
-
-// Tests that SHA-1 is still allowed for locally-installed trust anchors,
-// including those in application manifests, as it should behave like
-// the Android system.
-TEST_F(AwContentBrowserClientTest, SHA1LocalAnchorsAllowed) {
-  AwFeatureListCreator aw_feature_list_creator;
-  AwContentBrowserClient client(&aw_feature_list_creator);
-  network::mojom::NetworkContextParamsPtr network_context_params =
-      client.GetNetworkContextParams();
-
-  ASSERT_TRUE(network_context_params);
-  ASSERT_TRUE(network_context_params->initial_ssl_config);
-  ASSERT_TRUE(
-      network_context_params->initial_ssl_config->sha1_local_anchors_enabled);
-}
-
 }  // namespace android_webview
diff --git a/android_webview/test/BUILD.gn b/android_webview/test/BUILD.gn
index 82379016..52f39b9e 100644
--- a/android_webview/test/BUILD.gn
+++ b/android_webview/test/BUILD.gn
@@ -336,6 +336,7 @@
   ]
 
   sources = [
+    "../browser/aw_browser_context_unittest.cc",
     "../browser/aw_content_browser_client_unittest.cc",
     "../browser/aw_contents_client_bridge_unittest.cc",
     "../browser/aw_cookie_access_policy_unittest.cc",
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index e96ff863..07008ac0 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -190,6 +190,8 @@
     "assistant/assistant_interaction_controller.h",
     "assistant/assistant_notification_controller.cc",
     "assistant/assistant_notification_controller.h",
+    "assistant/assistant_notification_expiry_monitor.cc",
+    "assistant/assistant_notification_expiry_monitor.h",
     "assistant/assistant_screen_context_controller.cc",
     "assistant/assistant_screen_context_controller.h",
     "assistant/assistant_settings.cc",
@@ -1599,6 +1601,7 @@
     "app_menu/notification_menu_view_unittest.cc",
     "app_menu/notification_overflow_view_unittest.cc",
     "assistant/assistant_controller_unittest.cc",
+    "assistant/assistant_notification_controller_unittest.cc",
     "assistant/assistant_screen_context_controller_unittest.cc",
     "assistant/model/assistant_query_history_unittest.cc",
     "assistant/ui/assistant_container_view_unittest.cc",
diff --git a/ash/accessibility/accessibility_focus_ring_controller_impl.cc b/ash/accessibility/accessibility_focus_ring_controller_impl.cc
index 7712c07..8c8b02b 100644
--- a/ash/accessibility/accessibility_focus_ring_controller_impl.cc
+++ b/ash/accessibility/accessibility_focus_ring_controller_impl.cc
@@ -60,6 +60,8 @@
 void AccessibilityFocusRingControllerImpl::SetFocusRing(
     const std::string& focus_ring_id,
     std::unique_ptr<AccessibilityFocusRingInfo> focus_ring) {
+  // This code assumes |focus_ring| is always non-null.
+  DCHECK(focus_ring);
   AccessibilityFocusRingGroup* focus_ring_group =
       GetFocusRingGroupForId(focus_ring_id, true /* Create if missing */);
   if (focus_ring_group->UpdateFocusRing(std::move(focus_ring), this))
diff --git a/ash/accessibility/touch_exploration_manager.cc b/ash/accessibility/touch_exploration_manager.cc
index 1f73633..435ab00 100644
--- a/ash/accessibility/touch_exploration_manager.cc
+++ b/ash/accessibility/touch_exploration_manager.cc
@@ -220,7 +220,8 @@
       SilenceSpokenFeedback();
       // Clear the focus highlight.
       Shell::Get()->accessibility_focus_ring_controller()->SetFocusRing(
-          extension_misc::kChromeVoxExtensionId, nullptr);
+          extension_misc::kChromeVoxExtensionId,
+          std::make_unique<AccessibilityFocusRingInfo>());
     } else {
       touch_exploration_controller_->SetExcludeBounds(gfx::Rect());
     }
diff --git a/ash/assistant/assistant_notification_controller.cc b/ash/assistant/assistant_notification_controller.cc
index 6328039..1e32def2 100644
--- a/ash/assistant/assistant_notification_controller.cc
+++ b/ash/assistant/assistant_notification_controller.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "ash/assistant/assistant_controller.h"
+#include "ash/assistant/assistant_notification_expiry_monitor.h"
 #include "ash/assistant/util/deep_link_util.h"
 #include "ash/public/cpp/notification_utils.h"
 #include "ash/public/cpp/vector_icons/vector_icons.h"
@@ -81,6 +82,7 @@
     AssistantController* assistant_controller)
     : assistant_controller_(assistant_controller),
       binding_(this),
+      expiry_monitor_(this),
       notifier_id_(GetNotifierId()) {
   AddModelObserver(this);
   assistant_controller_->AddObserver(this);
diff --git a/ash/assistant/assistant_notification_controller.h b/ash/assistant/assistant_notification_controller.h
index bd1655b..6a7e63e0 100644
--- a/ash/assistant/assistant_notification_controller.h
+++ b/ash/assistant/assistant_notification_controller.h
@@ -9,6 +9,7 @@
 
 #include "ash/ash_export.h"
 #include "ash/assistant/assistant_controller_observer.h"
+#include "ash/assistant/assistant_notification_expiry_monitor.h"
 #include "ash/assistant/model/assistant_notification_model.h"
 #include "ash/assistant/model/assistant_notification_model_observer.h"
 #include "ash/assistant/model/assistant_ui_model_observer.h"
@@ -97,6 +98,7 @@
   mojo::Binding<mojom::AssistantNotificationController> binding_;
 
   AssistantNotificationModel model_;
+  AssistantNotificationExpiryMonitor expiry_monitor_;
 
   // Owned by AssistantController.
   chromeos::assistant::mojom::Assistant* assistant_ = nullptr;
diff --git a/ash/assistant/assistant_notification_controller_unittest.cc b/ash/assistant/assistant_notification_controller_unittest.cc
new file mode 100644
index 0000000..0fa00a5
--- /dev/null
+++ b/ash/assistant/assistant_notification_controller_unittest.cc
@@ -0,0 +1,291 @@
+// 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 "ash/assistant/assistant_notification_controller.h"
+
+#include "ash/assistant/assistant_controller.h"
+#include "ash/assistant/model/assistant_notification_model_observer.h"
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
+#include "base/test/scoped_task_environment.h"
+#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace ash {
+
+using chromeos::assistant::mojom::AssistantNotificationPtr;
+using testing::_;
+using testing::Eq;
+using testing::Field;
+using testing::StrictMock;
+
+constexpr bool kAnyBool = false;
+
+class AssistantNotificationModelObserverMock
+    : public AssistantNotificationModelObserver {
+ public:
+  AssistantNotificationModelObserverMock() = default;
+  ~AssistantNotificationModelObserverMock() override = default;
+
+  MOCK_METHOD1(OnNotificationAdded,
+               void(const AssistantNotification* notification));
+  MOCK_METHOD1(OnNotificationUpdated,
+               void(const AssistantNotification* notification));
+  MOCK_METHOD2(OnNotificationRemoved,
+               void(const AssistantNotification* notification,
+                    bool from_server));
+  MOCK_METHOD1(OnAllNotificationsRemoved, void(bool from_server));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AssistantNotificationModelObserverMock);
+};
+
+MATCHER_P(IdIs, expected_id, "") {
+  if (arg->client_id != expected_id) {
+    *result_listener << "Received notification with a wrong id.\n"
+                     << "Expected:\n    '" << expected_id << "'\n"
+                     << "Actual:\n    '" << arg->client_id << "'\n";
+    return false;
+  }
+  return true;
+}
+
+class AssistantNotificationControllerTest : public AshTestBase {
+ protected:
+  AssistantNotificationControllerTest() {
+    DestroyScopedTaskEnvironment();
+    scoped_task_environment_ = std::make_unique<
+        base::test::ScopedTaskEnvironment>(
+        base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME,
+        base::test::ScopedTaskEnvironment::NowSource::MAIN_THREAD_MOCK_TIME);
+  }
+  ~AssistantNotificationControllerTest() override = default;
+
+  void SetUp() override {
+    ASSERT_TRUE(chromeos::switches::IsAssistantEnabled());
+
+    AshTestBase::SetUp();
+
+    controller_ =
+        Shell::Get()->assistant_controller()->notification_controller();
+    DCHECK(controller_);
+  }
+
+  AssistantNotificationController& controller() { return *controller_; }
+
+  AssistantNotificationModelObserverMock& AddStrictObserverMock() {
+    observer_ =
+        std::make_unique<StrictMock<AssistantNotificationModelObserverMock>>();
+    controller().AddModelObserver(observer_.get());
+    return *observer_;
+  }
+
+  AssistantNotificationPtr CreateNotification(const std::string& id) {
+    auto notification =
+        chromeos::assistant::mojom::AssistantNotification::New();
+    notification->client_id = id;
+    return notification;
+  }
+
+  AssistantNotificationPtr CreateNotification(const std::string& id,
+                                              int timeout_ms) {
+    auto result = CreateNotification(id);
+    result->expiry_time =
+        base::Time::Now() + base::TimeDelta::FromMilliseconds(timeout_ms);
+    return result;
+  }
+
+  void AddNotification(const std::string& id, int timeout_ms) {
+    controller().AddOrUpdateNotification(CreateNotification(id, timeout_ms));
+  }
+
+  void AddNotification(const std::string& id) {
+    controller().AddOrUpdateNotification(CreateNotification(id));
+  }
+
+  void UpdateNotification(const std::string& id, int timeout_ms) {
+    controller().AddOrUpdateNotification(CreateNotification(id, timeout_ms));
+  }
+
+  void UpdateNotification(const std::string& id) {
+    controller().AddOrUpdateNotification(CreateNotification(id));
+  }
+
+  void RemoveNotification(const std::string& id) {
+    controller().RemoveNotificationById(id, kAnyBool);
+  }
+
+  void ForwardTimeInMs(int time_in_ms) {
+    scoped_task_environment_->FastForwardBy(
+        base::TimeDelta::FromMilliseconds(time_in_ms));
+  }
+
+ private:
+  AssistantNotificationController* controller_;
+  std::unique_ptr<AssistantNotificationModelObserverMock> observer_;
+  std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
+
+  DISALLOW_COPY_AND_ASSIGN(AssistantNotificationControllerTest);
+};
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldInformObserverOfNewNotifications) {
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationAdded(IdIs("id")));
+
+  controller().AddOrUpdateNotification(CreateNotification("id"));
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldInformObserverOfUpdatedNotifications) {
+  const auto notification = CreateNotification("id");
+  controller().AddOrUpdateNotification(notification.Clone());
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationUpdated(IdIs("id")));
+
+  controller().AddOrUpdateNotification(notification.Clone());
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldInformObserverOfRemovedNotifications) {
+  const auto notification = CreateNotification("id");
+  controller().AddOrUpdateNotification(notification.Clone());
+  constexpr bool from_server = kAnyBool;
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved(IdIs("id"), Eq(from_server)));
+
+  controller().RemoveNotificationById(notification->client_id, from_server);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldInformObserverOfRemoveAllNotifications) {
+  const auto notification = CreateNotification("id");
+  controller().AddOrUpdateNotification(notification.Clone());
+  constexpr bool from_server = !kAnyBool;
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnAllNotificationsRemoved(Eq(from_server)));
+
+  controller().RemoveAllNotifications(from_server);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldRemoveNotificationWhenItExpires) {
+  constexpr int timeout_ms = 1000;
+  AddNotification("id", timeout_ms);
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved(IdIs("id"), _));
+
+  ForwardTimeInMs(timeout_ms);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldNotRemoveNotificationsTooSoon) {
+  constexpr int timeout_ms = 1000;
+  AddNotification("id", timeout_ms);
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved).Times(0);
+  ForwardTimeInMs(timeout_ms - 1);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldUseFromServerFalseWhenNotificationExpires) {
+  constexpr int timeout_ms = 1000;
+  AddNotification("id", timeout_ms);
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved(_, Eq(false)));
+
+  ForwardTimeInMs(timeout_ms);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldRemoveEachNotificationAsItExpires) {
+  constexpr int first_timeout_ms = 1000;
+  constexpr int second_timeout_ms = 1500;
+
+  AddNotification("first", first_timeout_ms);
+  AddNotification("second", second_timeout_ms);
+
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved(IdIs("first"), _));
+  ForwardTimeInMs(first_timeout_ms);
+
+  EXPECT_CALL(observer, OnNotificationRemoved(IdIs("second"), _));
+  int delta_between_notifications = second_timeout_ms - first_timeout_ms;
+  ForwardTimeInMs(delta_between_notifications);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldSupport2NotificationsThatExpireAtTheSameTime) {
+  constexpr int timeout_ms = 1000;
+
+  AddNotification("first", timeout_ms);
+  AddNotification("at-same-time", timeout_ms);
+
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved(IdIs("first"), _));
+  EXPECT_CALL(observer, OnNotificationRemoved(IdIs("at-same-time"), _));
+  ForwardTimeInMs(timeout_ms);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldImmediateRemoveNotificationsThatAlreadyExpired) {
+  constexpr int negative_timeout = -1000;
+
+  AddNotification("expired", negative_timeout);
+
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved(IdIs("expired"), _));
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldNotRemoveNotificationsThatWereManuallyRemoved) {
+  constexpr int timeout = 1000;
+
+  AddNotification("id", timeout);
+  RemoveNotification("id");
+
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved).Times(0);
+  ForwardTimeInMs(timeout);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldSupportExpiryTimeSetInUpdate) {
+  constexpr int timeout = 1000;
+
+  AddNotification("id");
+  UpdateNotification("id", timeout);
+
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved);
+  ForwardTimeInMs(timeout);
+}
+
+TEST_F(AssistantNotificationControllerTest,
+       ShouldNotRemoveNotificationIfExpiryTimeIsClearedInUpdate) {
+  constexpr int timeout = 1000;
+
+  AddNotification("id", timeout);
+  UpdateNotification("id");
+
+  auto& observer = AddStrictObserverMock();
+
+  EXPECT_CALL(observer, OnNotificationRemoved).Times(0);
+  ForwardTimeInMs(timeout);
+}
+
+}  // namespace ash
diff --git a/ash/assistant/assistant_notification_expiry_monitor.cc b/ash/assistant/assistant_notification_expiry_monitor.cc
new file mode 100644
index 0000000..ad153820
--- /dev/null
+++ b/ash/assistant/assistant_notification_expiry_monitor.cc
@@ -0,0 +1,130 @@
+// 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 "ash/assistant/assistant_notification_expiry_monitor.h"
+
+#include "ash/assistant/assistant_notification_controller.h"
+#include "ash/assistant/model/assistant_notification_model.h"
+#include "ash/assistant/model/assistant_notification_model_observer.h"
+#include "base/bind.h"
+#include "chromeos/services/assistant/public/mojom/assistant.mojom.h"
+
+namespace ash {
+
+namespace {
+
+bool HasExpired(const AssistantNotificationExpiryMonitor::AssistantNotification*
+                    notification) {
+  return notification->expiry_time.has_value() &&
+         (notification->expiry_time.value() <= base::Time::Now());
+}
+
+// Returns the minimum of the base::Time instances that actually have a value.
+base::Optional<base::Time> Min(base::Optional<base::Time> left,
+                               base::Optional<base::Time> right) {
+  if (!left.has_value())
+    return right;
+
+  if (!right.has_value())
+    return left;
+
+  return std::min(left.value(), right.value());
+}
+
+}  // namespace
+
+class AssistantNotificationExpiryMonitor::Observer
+    : public AssistantNotificationModelObserver {
+ public:
+  Observer(AssistantNotificationExpiryMonitor* monitor) : monitor_(monitor) {}
+  ~Observer() override = default;
+
+  void OnNotificationAdded(const AssistantNotification* notification) override {
+    monitor_->UpdateTimer();
+  }
+
+  void OnNotificationUpdated(
+      const AssistantNotification* notification) override {
+    monitor_->UpdateTimer();
+  }
+
+  void OnNotificationRemoved(const AssistantNotification* notification,
+                             bool from_server) override {
+    monitor_->UpdateTimer();
+  }
+
+  void OnAllNotificationsRemoved(bool from_server) override {
+    monitor_->UpdateTimer();
+  }
+
+ private:
+  AssistantNotificationExpiryMonitor* const monitor_;
+
+  DISALLOW_COPY_AND_ASSIGN(Observer);
+};
+
+AssistantNotificationExpiryMonitor::AssistantNotificationExpiryMonitor(
+    AssistantNotificationController* controller)
+    : controller_(controller), observer_(std::make_unique<Observer>(this)) {
+  DCHECK(controller_);
+  controller_->AddModelObserver(observer_.get());
+}
+
+AssistantNotificationExpiryMonitor::~AssistantNotificationExpiryMonitor() =
+    default;
+
+void AssistantNotificationExpiryMonitor::UpdateTimer() {
+  base::Optional<base::TimeDelta> timeout = GetTimerTimeout();
+  if (timeout) {
+    timer_.Start(
+        FROM_HERE, timeout.value(),
+        base::BindOnce(
+            &AssistantNotificationExpiryMonitor::RemoveExpiredNotifications,
+            base::Unretained(this)));
+  } else {
+    timer_.Stop();
+  }
+}
+
+base::Optional<base::TimeDelta>
+AssistantNotificationExpiryMonitor::GetTimerTimeout() const {
+  base::Optional<base::Time> endtime = GetTimerEndTime();
+  if (endtime)
+    return endtime.value() - base::Time::Now();
+  return base::nullopt;
+}
+
+base::Optional<base::Time> AssistantNotificationExpiryMonitor::GetTimerEndTime()
+    const {
+  base::Optional<base::Time> result = base::nullopt;
+  for (const AssistantNotification* notification : GetNotifications())
+    result = Min(result, notification->expiry_time);
+  return result;
+}
+
+void AssistantNotificationExpiryMonitor::RemoveExpiredNotifications() {
+  for (const NotificationId& id : GetExpiredNotifications()) {
+    VLOG(1) << "Removing expired notification '" << id << "'";
+    controller_->RemoveNotificationById(id, /*from_server=*/false);
+  }
+
+  UpdateTimer();
+}
+
+std::vector<AssistantNotificationExpiryMonitor::NotificationId>
+AssistantNotificationExpiryMonitor::GetExpiredNotifications() const {
+  std::vector<NotificationId> result;
+  for (const AssistantNotification* notification : GetNotifications()) {
+    if (HasExpired(notification))
+      result.push_back(notification->client_id);
+  }
+  return result;
+}
+
+std::vector<const AssistantNotificationExpiryMonitor::AssistantNotification*>
+AssistantNotificationExpiryMonitor::GetNotifications() const {
+  return controller_->model()->GetNotifications();
+}
+
+}  // namespace ash
diff --git a/ash/assistant/assistant_notification_expiry_monitor.h b/ash/assistant/assistant_notification_expiry_monitor.h
new file mode 100644
index 0000000..ba99e5a1
--- /dev/null
+++ b/ash/assistant/assistant_notification_expiry_monitor.h
@@ -0,0 +1,56 @@
+// 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 ASH_ASSISTANT_ASSISTANT_NOTIFICATION_EXPIRY_MONITOR_H_
+#define ASH_ASSISTANT_ASSISTANT_NOTIFICATION_EXPIRY_MONITOR_H_
+
+#include <memory>
+#include <vector>
+
+#include "ash/assistant/model/assistant_notification_model_observer.h"
+#include "base/optional.h"
+#include "base/timer/timer.h"
+
+namespace ash {
+
+class AssistantNotificationController;
+
+// Will track all Assistant notifications by subscribing to the given
+// |controller| and will call
+// |AssistantNotificationController::RemoveNotificationById| when the
+// notification expires (i.e. when the current time passes the value in the
+// expiry_time| field).
+class AssistantNotificationExpiryMonitor {
+ public:
+  using AssistantNotification =
+      chromeos::assistant::mojom::AssistantNotification;
+
+  explicit AssistantNotificationExpiryMonitor(
+      AssistantNotificationController* controller);
+  ~AssistantNotificationExpiryMonitor();
+
+ private:
+  using NotificationId = std::string;
+  class Observer;
+
+  // Start/stop the timer waiting for the next expiry time.
+  // If the timer is already running this will start a new timer with the
+  // (new) expiry time that will expire first.
+  void UpdateTimer();
+
+  base::Optional<base::TimeDelta> GetTimerTimeout() const;
+  base::Optional<base::Time> GetTimerEndTime() const;
+  void RemoveExpiredNotifications();
+  std::vector<NotificationId> GetExpiredNotifications() const;
+  std::vector<const AssistantNotification*> GetNotifications() const;
+
+  base::OneShotTimer timer_;
+  AssistantNotificationController* const controller_;
+  std::unique_ptr<Observer> observer_;
+
+  DISALLOW_COPY_AND_ASSIGN(AssistantNotificationExpiryMonitor);
+};
+
+}  // namespace ash
+#endif  // ASH_ASSISTANT_ASSISTANT_NOTIFICATION_EXPIRY_MONITOR_H_
diff --git a/ash/assistant/model/assistant_notification_model.cc b/ash/assistant/model/assistant_notification_model.cc
index 875396f..af725f1 100644
--- a/ash/assistant/model/assistant_notification_model.cc
+++ b/ash/assistant/model/assistant_notification_model.cc
@@ -79,11 +79,16 @@
 }
 
 std::vector<const chromeos::assistant::mojom::AssistantNotification*>
+AssistantNotificationModel::GetNotifications() const {
+  return GetNotificationsByType(base::nullopt);
+}
+
+std::vector<const chromeos::assistant::mojom::AssistantNotification*>
 AssistantNotificationModel::GetNotificationsByType(
-    AssistantNotificationType type) const {
+    base::Optional<AssistantNotificationType> type) const {
   std::vector<const AssistantNotification*> notifications;
   for (const auto& notification : notifications_) {
-    if (notification.second->type == type)
+    if (!type || notification.second->type == type.value())
       notifications.push_back(notification.second.get());
   }
   return notifications;
diff --git a/ash/assistant/model/assistant_notification_model.h b/ash/assistant/model/assistant_notification_model.h
index 22c8dbf..a203f99 100644
--- a/ash/assistant/model/assistant_notification_model.h
+++ b/ash/assistant/model/assistant_notification_model.h
@@ -58,8 +58,12 @@
   const AssistantNotification* GetNotificationById(const std::string& id) const;
 
   // Returns all notifications matching the specified |type|.
+  // Use base::nullopt to return all notifications independent of their type.
   std::vector<const AssistantNotification*> GetNotificationsByType(
-      AssistantNotificationType type) const;
+      base::Optional<AssistantNotificationType> type) const;
+
+  // Returns all notifications (that have not been removed).
+  std::vector<const AssistantNotification*> GetNotifications() const;
 
   // Returns true if the model contains a notification uniquely identified by
   // |id|, otherwise false.
diff --git a/ash/autoclick/autoclick_unittest.cc b/ash/autoclick/autoclick_unittest.cc
index 032b2d3..b4e6f2e 100644
--- a/ash/autoclick/autoclick_unittest.cc
+++ b/ash/autoclick/autoclick_unittest.cc
@@ -107,7 +107,8 @@
     DestroyScopedTaskEnvironment();
     scoped_task_environment_ =
         std::make_unique<base::test::ScopedTaskEnvironment>(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME);
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   }
   ~AutoclickTest() override = default;
 
diff --git a/ash/home_screen/home_screen_presenter.cc b/ash/home_screen/home_screen_presenter.cc
index ff2b478..977e173 100644
--- a/ash/home_screen/home_screen_presenter.cc
+++ b/ash/home_screen/home_screen_presenter.cc
@@ -8,8 +8,6 @@
 
 #include "ash/home_screen/home_screen_controller.h"
 #include "ash/home_screen/home_screen_delegate.h"
-#include "ash/kiosk_next/kiosk_next_shell_controller_impl.h"
-#include "ash/shell.h"
 #include "base/bind.h"
 #include "base/bind_helpers.h"
 #include "base/logging.h"
@@ -54,24 +52,11 @@
 
   void Start(bool enter) {
     enter_ = enter;
-    kiosk_next_enabled_ =
-        Shell::Get()->kiosk_next_shell_controller()->IsEnabled();
   }
 
   void Report(int value) override {
     // Emit the correct histogram. Note that we have multiple macro instances
     // since each macro instance should be called with a runtime constant.
-    if (kiosk_next_enabled_) {
-      if (enter_) {
-        UMA_HISTOGRAM_PERCENTAGE(
-            "KioskNextHome.StateTransition.AnimationSmoothness.EnterOverview",
-            value);
-      } else {
-        UMA_HISTOGRAM_PERCENTAGE(
-            "KioskNextHome.StateTransition.AnimationSmoothness.ExitOverview",
-            value);
-      }
-    } else {
       if (enter_) {
         UMA_HISTOGRAM_PERCENTAGE(
             "Apps.StateTransition.AnimationSmoothness.EnterOverview", value);
@@ -79,12 +64,10 @@
         UMA_HISTOGRAM_PERCENTAGE(
             "Apps.StateTransition.AnimationSmoothness.ExitOverview", value);
       }
-    }
   }
 
  private:
   bool enter_ = false;
-  bool kiosk_next_enabled_ = false;
 
   DISALLOW_COPY_AND_ASSIGN(OverviewAnimationMetricsReporter);
 };
diff --git a/ash/login/ui/arrow_button_view.cc b/ash/login/ui/arrow_button_view.cc
index 36b59c25..2a2378e 100644
--- a/ash/login/ui/arrow_button_view.cc
+++ b/ash/login/ui/arrow_button_view.cc
@@ -47,6 +47,7 @@
   views::ImageButton::PaintButtonContents(canvas);
 }
 void ArrowButtonView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+  LoginButton::GetAccessibleNodeData(node_data);
   // TODO(tbarzic): Fix this - https://crbug.com/961930.
   if (GetAccessibleName().empty())
     node_data->SetNameExplicitlyEmpty();
diff --git a/ash/login/ui/parent_access_view.cc b/ash/login/ui/parent_access_view.cc
index 84e26c5..df6666e 100644
--- a/ash/login/ui/parent_access_view.cc
+++ b/ash/login/ui/parent_access_view.cc
@@ -149,9 +149,12 @@
 
   // views::View:
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
-    node_data->role = ax::mojom::Role::kLabelText;
-    node_data->SetDescription(accessible_description_);
-    node_data->SetValue(text());
+    views::Textfield::GetAccessibleNodeData(node_data);
+    node_data->role = ax::mojom::Role::kListItem;
+    node_data->AddStringAttribute(ax::mojom::StringAttribute::kRoleDescription,
+                                  base::UTF16ToUTF8(accessible_description_));
+    node_data->SetDescription(text());
+    node_data->SetName(text());
   }
 
   bool IsGroupFocusTraversable() const override { return false; }
@@ -173,7 +176,8 @@
 class ParentAccessView::AccessCodeInput : public views::View,
                                           public views::TextfieldController {
  public:
-  using OnInputChange = base::RepeatingCallback<void(bool complete)>;
+  using OnInputChange =
+      base::RepeatingCallback<void(bool complete, bool last_field_active)>;
   using OnEnter = base::RepeatingClosure;
 
   // Builds the view for an access code that consists out of |length| digits.
@@ -209,10 +213,8 @@
       field->SetBorder(views::CreateSolidSidedBorder(
           0, 0, kAccessCodeInputFieldUnderlineThicknessDp, 0, kTextColor));
       field->SetGroup(kParentAccessInputGroup);
-      if (i < length - 1) {
-        field->set_accessible_description(l10n_util::GetStringUTF16(
-            IDS_ASH_LOGIN_PARENT_ACCESS_NEXT_NUMBER_PROMPT));
-      }
+      field->set_accessible_description(l10n_util::GetStringUTF16(
+          IDS_ASH_LOGIN_PARENT_ACCESS_NEXT_NUMBER_PROMPT));
       input_fields_.push_back(field);
       AddChildView(field);
     }
@@ -227,9 +229,10 @@
     DCHECK_GE(9, value);
 
     ActiveField()->SetText(base::NumberToString16(value));
+    bool was_last_field = IsLastFieldActive();
     FocusNextField();
 
-    on_input_change_.Run(GetCode().has_value());
+    on_input_change_.Run(GetCode().has_value(), was_last_field);
   }
 
   // Clears input from the |active_field_|. If |active_field| is empty moves
@@ -240,7 +243,7 @@
     }
 
     ActiveField()->SetText(base::string16());
-    on_input_change_.Run(false);
+    on_input_change_.Run(false, IsLastFieldActive());
   }
 
   // Returns access code as string if all fields contain input.
@@ -272,6 +275,11 @@
 
   void RequestFocus() override { ActiveField()->RequestFocus(); }
 
+  void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
+    views::View::GetAccessibleNodeData(node_data);
+    node_data->role = ax::mojom::Role::kGroup;
+  }
+
   // views::TextfieldController:
   bool HandleKeyEvent(views::Textfield* sender,
                       const ui::KeyEvent& key_event) override {
@@ -313,6 +321,7 @@
     for (size_t i = 0; i < input_fields_.size(); ++i) {
       if (input_fields_[i] == sender) {
         active_input_index_ = i;
+        RequestFocus();
         break;
       }
     }
@@ -329,6 +338,7 @@
     for (size_t i = 0; i < input_fields_.size(); ++i) {
       if (input_fields_[i] == sender) {
         active_input_index_ = i;
+        RequestFocus();
         break;
       }
     }
@@ -348,13 +358,18 @@
 
   // Moves focus to the next input field if it exists.
   void FocusNextField() {
-    if (active_input_index_ == (static_cast<int>(input_fields_.size()) - 1))
+    if (IsLastFieldActive())
       return;
 
     ++active_input_index_;
     ActiveField()->RequestFocus();
   }
 
+  // Returns whether last input field is currently active.
+  bool IsLastFieldActive() const {
+    return active_input_index_ == (static_cast<int>(input_fields_.size()) - 1);
+  }
+
   // Returns pointer to the active input field.
   views::Textfield* ActiveField() const {
     return input_fields_[active_input_index_];
@@ -722,11 +737,14 @@
   SetPreferredSize(CalculatePreferredSize());
 }
 
-void ParentAccessView::OnInputChange(bool complete) {
+void ParentAccessView::OnInputChange(bool complete, bool last_field_active) {
   if (state_ == State::kError)
     UpdateState(State::kNormal);
 
   submit_button_->SetEnabled(complete);
+
+  if (complete && last_field_active)
+    submit_button_->RequestFocus();
 }
 
 void ParentAccessView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
diff --git a/ash/login/ui/parent_access_view.h b/ash/login/ui/parent_access_view.h
index 559c1fa..cedcafd8 100644
--- a/ash/login/ui/parent_access_view.h
+++ b/ash/login/ui/parent_access_view.h
@@ -121,8 +121,9 @@
   void UpdatePreferredSize();
 
   // Called when access code input changes. |complete| brings information
-  // whether current input code is complete.
-  void OnInputChange(bool complete);
+  // whether current input code is complete. |last_field_active| contains
+  // information whether last input field is currently active.
+  void OnInputChange(bool complete, bool last_field_active);
 
   // Callbacks to be called when user performs certain actions.
   const Callbacks callbacks_;
diff --git a/ash/login/ui/parent_access_view_unittest.cc b/ash/login/ui/parent_access_view_unittest.cc
index 240a44f..dc2deb57 100644
--- a/ash/login/ui/parent_access_view_unittest.cc
+++ b/ash/login/ui/parent_access_view_unittest.cc
@@ -156,6 +156,7 @@
     generator->PressKey(ui::KeyboardCode(ui::KeyboardCode::VKEY_0 + i),
                         ui::EF_NONE);
   }
+  EXPECT_TRUE(test_api.submit_button()->HasFocus());
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
   login_client_->set_validate_parent_access_code_result(true);
@@ -253,8 +254,15 @@
   ui::test::EventGenerator* generator = GetEventGenerator();
   for (int i = 0; i < 6; ++i)
     generator->PressKey(ui::KeyboardCode::VKEY_1, ui::EF_NONE);
+  EXPECT_TRUE(test_api.submit_button()->HasFocus());
   EXPECT_TRUE(test_api.submit_button()->GetEnabled());
 
+  // After access code is completed, focus moves to submit button.
+  // Move focus back to access code input.
+  for (int i = 0; i < 2; ++i)
+    generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_SHIFT_DOWN);
+  EXPECT_TRUE(HasFocusInAnyChildView(test_api.access_code_view()));
+
   // Active field has content - backspace clears the content, but does not move
   // focus.
   generator->PressKey(ui::KeyboardCode::VKEY_BACK, ui::EF_NONE);
@@ -328,6 +336,7 @@
     generator->PressKey(ui::KeyboardCode(ui::KeyboardCode::VKEY_0 + i),
                         ui::EF_NONE);
   }
+  EXPECT_TRUE(test_api.submit_button()->HasFocus());
 
   // Error should be shown after unsuccessful validation.
   login_client_->set_validate_parent_access_code_result(false);
@@ -339,6 +348,12 @@
   EXPECT_EQ(ParentAccessView::State::kError, test_api.state());
   EXPECT_EQ(0, successful_validation_);
 
+  // After access code is completed, focus moves to submit button.
+  // Move focus back to access code input.
+  for (int i = 0; i < 2; ++i)
+    generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_SHIFT_DOWN);
+  EXPECT_TRUE(HasFocusInAnyChildView(test_api.access_code_view()));
+
   // Updating input code (here last digit) should clear error state.
   generator->PressKey(ui::KeyboardCode::VKEY_6, ui::EF_NONE);
   EXPECT_EQ(ParentAccessView::State::kNormal, test_api.state());
@@ -358,15 +373,10 @@
   ParentAccessView::TestApi test_api(view_);
   EXPECT_TRUE(HasFocusInAnyChildView(test_api.access_code_view()));
 
-  // Enter access code, so submit button is enabled and focusable.
+  // Enter access code, so submit button is enabled and focused.
   ui::test::EventGenerator* generator = GetEventGenerator();
   for (int i = 0; i < 6; ++i)
     generator->PressKey(ui::KeyboardCode::VKEY_0, ui::EF_NONE);
-
-  generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_NONE);
-  EXPECT_TRUE(test_api.help_button()->HasFocus());
-
-  generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_NONE);
   EXPECT_TRUE(test_api.submit_button()->HasFocus());
 
   generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_NONE);
@@ -380,6 +390,9 @@
 
   generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_NONE);
   EXPECT_TRUE(HasFocusInAnyChildView(test_api.access_code_view()));
+
+  generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_NONE);
+  EXPECT_TRUE(test_api.help_button()->HasFocus());
 }
 
 // Tests children views backwards traversal with tab key.
@@ -392,6 +405,13 @@
   ui::test::EventGenerator* generator = GetEventGenerator();
   for (int i = 0; i < 6; ++i)
     generator->PressKey(ui::KeyboardCode::VKEY_0, ui::EF_NONE);
+  EXPECT_TRUE(test_api.submit_button()->HasFocus());
+
+  generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_SHIFT_DOWN);
+  EXPECT_TRUE(test_api.help_button()->HasFocus());
+
+  generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_SHIFT_DOWN);
+  EXPECT_TRUE(HasFocusInAnyChildView(test_api.access_code_view()));
 
   generator->PressKey(ui::KeyboardCode::VKEY_TAB, ui::EF_SHIFT_DOWN);
   EXPECT_TRUE(test_api.description_label()->HasFocus());
diff --git a/ash/public/cpp/wallpaper_controller_client.h b/ash/public/cpp/wallpaper_controller_client.h
index 8556241..5f41ae9 100644
--- a/ash/public/cpp/wallpaper_controller_client.h
+++ b/ash/public/cpp/wallpaper_controller_client.h
@@ -15,10 +15,6 @@
   // Opens the wallpaper picker window.
   virtual void OpenWallpaperPicker() = 0;
 
-  // Signals to the client that ash is ready to set wallpapers. The client is
-  // able to decide whatever the first wallpaper it wants to display.
-  virtual void OnReadyToSetWallpaper() = 0;
-
   // Notifies the client that the animation of the first wallpaper since the
   // controller initialization has completed.
   // TODO(crbug.com/875128): Remove this after web-ui login code is completely
diff --git a/ash/shelf/back_button.cc b/ash/shelf/back_button.cc
index d6ea6fb9..f86adc2 100644
--- a/ash/shelf/back_button.cc
+++ b/ash/shelf/back_button.cc
@@ -19,8 +19,8 @@
 // static
 const char BackButton::kViewClassName[] = "ash/BackButton";
 
-BackButton::BackButton(ShelfButtonDelegate* shelf_button_delegate)
-    : ShelfControlButton(shelf_button_delegate) {
+BackButton::BackButton(Shelf* shelf, ShelfButtonDelegate* shelf_button_delegate)
+    : ShelfControlButton(shelf, shelf_button_delegate) {
   SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_BACK_BUTTON_TITLE));
 }
 
diff --git a/ash/shelf/back_button.h b/ash/shelf/back_button.h
index 9946935..8847651a 100644
--- a/ash/shelf/back_button.h
+++ b/ash/shelf/back_button.h
@@ -22,7 +22,7 @@
  public:
   static const char kViewClassName[];
 
-  explicit BackButton(ShelfButtonDelegate* shelf_button_delegate);
+  BackButton(Shelf* shelf, ShelfButtonDelegate* shelf_button_delegate);
   ~BackButton() override;
 
   // views::Button:
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc
index 9e017d10..41d66b7 100644
--- a/ash/shelf/home_button.cc
+++ b/ash/shelf/home_button.cc
@@ -33,8 +33,8 @@
 // static
 const char HomeButton::kViewClassName[] = "ash/HomeButton";
 
-HomeButton::HomeButton(ShelfButtonDelegate* shelf_button_delegate)
-    : ShelfControlButton(shelf_button_delegate),
+HomeButton::HomeButton(Shelf* shelf, ShelfButtonDelegate* shelf_button_delegate)
+    : ShelfControlButton(shelf, shelf_button_delegate),
       controller_(this, shelf_button_delegate) {
   DCHECK(shelf_button_delegate);
   SetAccessibleName(
diff --git a/ash/shelf/home_button.h b/ash/shelf/home_button.h
index d55be059..b4949ecf 100644
--- a/ash/shelf/home_button.h
+++ b/ash/shelf/home_button.h
@@ -30,7 +30,7 @@
  public:
   static const char kViewClassName[];
 
-  explicit HomeButton(ShelfButtonDelegate* shelf_button_delegate);
+  HomeButton(Shelf* shelf, ShelfButtonDelegate* shelf_button_delegate);
   ~HomeButton() override;
 
   // views::Button:
diff --git a/ash/shelf/overflow_button.cc b/ash/shelf/overflow_button.cc
index ac69934..923b995 100644
--- a/ash/shelf/overflow_button.cc
+++ b/ash/shelf/overflow_button.cc
@@ -24,7 +24,8 @@
 namespace ash {
 
 OverflowButton::OverflowButton(ShelfView* shelf_view)
-    : ShelfControlButton(shelf_view), shelf_view_(shelf_view) {
+    : ShelfControlButton(shelf_view->shelf(), shelf_view),
+      shelf_view_(shelf_view) {
   SetAccessibleName(l10n_util::GetStringUTF16(IDS_ASH_SHELF_OVERFLOW_NAME));
 
   horizontal_dots_image_view_ = new views::ImageView();
diff --git a/ash/shelf/shelf_app_button.cc b/ash/shelf/shelf_app_button.cc
index 718f9502a..cc9c0a2 100644
--- a/ash/shelf/shelf_app_button.cc
+++ b/ash/shelf/shelf_app_button.cc
@@ -297,7 +297,7 @@
 const char ShelfAppButton::kViewClassName[] = "ash/ShelfAppButton";
 
 ShelfAppButton::ShelfAppButton(ShelfView* shelf_view)
-    : ShelfButton(shelf_view),
+    : ShelfButton(shelf_view->shelf(), shelf_view),
       icon_view_(new views::ImageView()),
       shelf_view_(shelf_view),
       indicator_(new AppStatusIndicatorView()),
diff --git a/ash/shelf/shelf_button.cc b/ash/shelf/shelf_button.cc
index 03c46d1c..9b74bc9 100644
--- a/ash/shelf/shelf_button.cc
+++ b/ash/shelf/shelf_button.cc
@@ -5,6 +5,7 @@
 #include "ash/shelf/shelf_button.h"
 
 #include "ash/public/cpp/ash_constants.h"
+#include "ash/shelf/shelf.h"
 #include "ash/shelf/shelf_button_delegate.h"
 #include "ash/shelf/shelf_constants.h"
 #include "ui/accessibility/ax_node_data.h"
@@ -12,8 +13,11 @@
 
 namespace ash {
 
-ShelfButton::ShelfButton(ShelfButtonDelegate* shelf_button_delegate)
-    : Button(nullptr), shelf_button_delegate_(shelf_button_delegate) {
+ShelfButton::ShelfButton(Shelf* shelf,
+                         ShelfButtonDelegate* shelf_button_delegate)
+    : Button(nullptr),
+      shelf_(shelf),
+      shelf_button_delegate_(shelf_button_delegate) {
   DCHECK(shelf_button_delegate_);
   set_hide_ink_drop_when_showing_context_menu(false);
   set_ink_drop_base_color(kShelfInkDropBaseColor);
@@ -48,6 +52,12 @@
 // views::Button
 
 void ShelfButton::NotifyClick(const ui::Event& event) {
+  // Pressing a shelf button in the auto-hide shelf should not do anything.
+  // The event can still be received by the auto-hide shelf since we reserved
+  // a portion of the auto-hide shelf within the screen bounds.
+  if (!shelf_->IsVisible())
+    return;
+
   Button::NotifyClick(event);
   if (shelf_button_delegate_)
     shelf_button_delegate_->ButtonPressed(/*sender=*/this, event, GetInkDrop());
diff --git a/ash/shelf/shelf_button.h b/ash/shelf/shelf_button.h
index 72a8399..404977c3 100644
--- a/ash/shelf/shelf_button.h
+++ b/ash/shelf/shelf_button.h
@@ -9,12 +9,13 @@
 #include "ui/views/controls/button/button.h"
 
 namespace ash {
+class Shelf;
 class ShelfButtonDelegate;
 
 // Button used for items on the shelf.
 class ASH_EXPORT ShelfButton : public views::Button {
  public:
-  explicit ShelfButton(ShelfButtonDelegate* shelf_button_delegate);
+  ShelfButton(Shelf* shelf, ShelfButtonDelegate* shelf_button_delegate);
   ~ShelfButton() override;
 
   // views::Button:
@@ -30,6 +31,9 @@
   }
 
  private:
+  // The shelf instance that this button belongs to. Unowned.
+  Shelf* const shelf_;
+
   // A class to which this button delegates handling some of its events.
   ShelfButtonDelegate* const shelf_button_delegate_;
 
diff --git a/ash/shelf/shelf_context_menu_model_unittest.cc b/ash/shelf/shelf_context_menu_model_unittest.cc
index 640bef14..69504da 100644
--- a/ash/shelf/shelf_context_menu_model_unittest.cc
+++ b/ash/shelf/shelf_context_menu_model_unittest.cc
@@ -50,7 +50,6 @@
 
   // WallpaperControllerClient:
   void OpenWallpaperPicker() override { open_count_++; }
-  void OnReadyToSetWallpaper() override {}
   void OnFirstWallpaperAnimationFinished() override {}
 
  private:
diff --git a/ash/shelf/shelf_control_button.cc b/ash/shelf/shelf_control_button.cc
index efa5e8f..7176458 100644
--- a/ash/shelf/shelf_control_button.cc
+++ b/ash/shelf/shelf_control_button.cc
@@ -21,8 +21,9 @@
 namespace ash {
 
 ShelfControlButton::ShelfControlButton(
+    Shelf* shelf,
     ShelfButtonDelegate* shelf_button_delegate)
-    : ShelfButton(shelf_button_delegate) {
+    : ShelfButton(shelf, shelf_button_delegate) {
   set_has_ink_drop_action_on_click(true);
   SetInstallFocusRingOnFocus(true);
   focus_ring()->SetColor(kShelfFocusBorderColor);
diff --git a/ash/shelf/shelf_control_button.h b/ash/shelf/shelf_control_button.h
index d15cb85..3dc6726a 100644
--- a/ash/shelf/shelf_control_button.h
+++ b/ash/shelf/shelf_control_button.h
@@ -19,7 +19,7 @@
 // as the app list, back, and overflow buttons.
 class ASH_EXPORT ShelfControlButton : public ShelfButton {
  public:
-  explicit ShelfControlButton(ShelfButtonDelegate* shelf_button_delegate_);
+  ShelfControlButton(Shelf* shelf, ShelfButtonDelegate* shelf_button_delegate_);
   ~ShelfControlButton() override;
 
   // Get the center point of the button used to draw its background and ink
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 3521a151..47def11 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -394,12 +394,12 @@
   const ShelfItems& items(model_->items());
 
   std::unique_ptr<BackButton> back_button_ptr =
-      std::make_unique<BackButton>(this);
+      std::make_unique<BackButton>(shelf_, this);
   ConfigureChildView(back_button_ptr.get());
   back_button_ = AddChildView(std::move(back_button_ptr));
 
   std::unique_ptr<HomeButton> home_button_ptr =
-      std::make_unique<HomeButton>(this);
+      std::make_unique<HomeButton>(shelf_, this);
   ConfigureChildView(home_button_ptr.get());
   home_button_ = AddChildView(std::move(home_button_ptr));
   home_button_->set_context_menu_controller(this);
@@ -665,12 +665,6 @@
 void ShelfView::ButtonPressed(views::Button* sender,
                               const ui::Event& event,
                               views::InkDrop* ink_drop) {
-  // Press the shelf item in the auto-hide shelf should not open the
-  // corresponding app window. The event can still be received by auto-hide
-  // shelf since we reserved portion of the auto-hide shelf within the screen
-  // bounds.
-  if (!shelf_->IsVisible())
-    return;
 
   if (sender == overflow_button_) {
     ToggleOverflowBubble();
diff --git a/ash/system/accessibility/autoclick_menu_bubble_controller_unittest.cc b/ash/system/accessibility/autoclick_menu_bubble_controller_unittest.cc
index 939f76f..b407f289 100644
--- a/ash/system/accessibility/autoclick_menu_bubble_controller_unittest.cc
+++ b/ash/system/accessibility/autoclick_menu_bubble_controller_unittest.cc
@@ -24,8 +24,10 @@
 const int kMenuViewBoundsBuffer = 100;
 
 // The buffers in dips around a scroll point where the scroll menu is shown.
-const int kScrollViewBoundsXBuffer = 110;
-const int kScrollViewBoundsYBuffer = 10;
+// This should be slightly larger than kScrollPointBufferDips and
+// kScrollRectBufferDips respectively from AutoclickScrollBubbleController to
+// allow for some wiggle room.
+const int kScrollViewBoundsBuffer = 26;
 const int kScrollViewBoundsRectBuffer = 18;
 
 ui::GestureEvent CreateTapEvent() {
@@ -336,17 +338,17 @@
     gfx::Point point = gfx::Point(400, 400);
     GetBubbleController()->SetScrollPosition(scroll_bounds, point);
 
-    // In-line with the point in the Y axis.
-    EXPECT_LT(abs(GetScrollViewBounds().right_center().y() - point.y()),
-              kScrollViewBoundsYBuffer);
+    // Just below the point in the Y axis.
+    EXPECT_LT(abs(GetScrollViewBounds().y() - point.y()),
+              kScrollViewBoundsBuffer);
 
-    // Off to the side, but relatively close, in the X axis.
+    // Just off to the side in the X axis.
     if (test.is_RTL) {
       EXPECT_LT(abs(GetScrollViewBounds().right() - point.x()),
-                kScrollViewBoundsXBuffer);
+                kScrollViewBoundsBuffer);
     } else {
       EXPECT_LT(abs(GetScrollViewBounds().x() - point.x()),
-                kScrollViewBoundsXBuffer);
+                kScrollViewBoundsBuffer);
     }
 
     // Moving the autoclick bubble doesn't impact the scroll bubble once it
@@ -360,16 +362,22 @@
     point = gfx::Point(0, 0);
     GetBubbleController()->SetScrollPosition(scroll_bounds, point);
     EXPECT_LT(abs(GetScrollViewBounds().x() - point.x()),
-              kScrollViewBoundsXBuffer);
+              kScrollViewBoundsBuffer);
     EXPECT_LT(abs(GetScrollViewBounds().y() - point.y()),
-              kScrollViewBoundsYBuffer);
+              kScrollViewBoundsBuffer);
 
     point = gfx::Point(1000, 400);
     GetBubbleController()->SetScrollPosition(scroll_bounds, point);
     EXPECT_LT(abs(GetScrollViewBounds().right() - point.x()),
-              kScrollViewBoundsXBuffer);
-    EXPECT_LT(abs(GetScrollViewBounds().left_center().y() - point.y()),
-              kScrollViewBoundsYBuffer);
+              kScrollViewBoundsBuffer);
+    EXPECT_LT(abs(GetScrollViewBounds().y() - point.y()),
+              kScrollViewBoundsBuffer);
+
+    // If it's too close to the bottom, it will be shown above the point.
+    point = gfx::Point(500, 700);
+    GetBubbleController()->SetScrollPosition(scroll_bounds, point);
+    EXPECT_LT(abs(GetScrollViewBounds().bottom() - point.y()),
+              kScrollViewBoundsBuffer);
   }
 }
 
@@ -466,7 +474,7 @@
       // vertically on the scroll point.
       EXPECT_LT(abs(GetScrollViewBounds().y() +
                     GetScrollViewBounds().height() / 2 - scroll_point.y()),
-                kScrollViewBoundsYBuffer);
+                kScrollViewBoundsRectBuffer);
       EXPECT_LT(GetScrollViewBounds().x() - scroll_bounds.right(),
                 kScrollViewBoundsRectBuffer);
       EXPECT_GT(GetScrollViewBounds().x() - scroll_bounds.right(), 0);
@@ -475,7 +483,7 @@
       // vertically on the scroll point.
       EXPECT_LT(abs(GetScrollViewBounds().y() +
                     GetScrollViewBounds().height() / 2 - scroll_point.y()),
-                kScrollViewBoundsYBuffer);
+                kScrollViewBoundsRectBuffer);
       EXPECT_LT(scroll_bounds.x() - GetScrollViewBounds().right(),
                 kScrollViewBoundsRectBuffer);
       EXPECT_GT(scroll_bounds.x() - GetScrollViewBounds().right(), 0);
@@ -484,7 +492,7 @@
       // horizontally on the scroll point.
       EXPECT_LT(abs(GetScrollViewBounds().x() +
                     GetScrollViewBounds().width() / 2 - scroll_point.x()),
-                kScrollViewBoundsYBuffer);
+                kScrollViewBoundsRectBuffer);
       EXPECT_LT(scroll_bounds.y() - GetScrollViewBounds().bottom(),
                 kScrollViewBoundsRectBuffer);
       EXPECT_GT(scroll_bounds.y() - GetScrollViewBounds().bottom(), 0);
@@ -493,7 +501,7 @@
       // horizontally on the scroll point.
       EXPECT_LT(abs(GetScrollViewBounds().x() +
                     GetScrollViewBounds().width() / 2 - scroll_point.x()),
-                kScrollViewBoundsYBuffer);
+                kScrollViewBoundsRectBuffer);
       EXPECT_LT(GetScrollViewBounds().y() - scroll_bounds.bottom(),
                 kScrollViewBoundsRectBuffer);
       EXPECT_GT(GetScrollViewBounds().y() - scroll_bounds.bottom(), -1);
diff --git a/ash/system/accessibility/autoclick_scroll_bubble_controller.cc b/ash/system/accessibility/autoclick_scroll_bubble_controller.cc
index 468ae77..3609ea0a 100644
--- a/ash/system/accessibility/autoclick_scroll_bubble_controller.cc
+++ b/ash/system/accessibility/autoclick_scroll_bubble_controller.cc
@@ -24,7 +24,7 @@
 namespace {
 // Autoclick scroll menu constants.
 constexpr int kAutoclickScrollMenuSizeDips = 192;
-const int kScrollPointBufferDips = 100;
+const int kScrollPointBufferDips = 16;
 const int kScrollRectBufferDips = 8;
 
 struct Position {
@@ -59,6 +59,12 @@
     gfx::Rect scroll_bounds_in_dips,
     const gfx::Point& scroll_point_in_dips) {
   // TODO(katie): Support multiple displays.
+
+  // Adjust the insets to be the same on all sides, so that when the bubble
+  // lays out it isn't too close on the top or bottom.
+  bubble_view_->UpdateInsets(
+      gfx::Insets(kUnifiedMenuPadding, kUnifiedMenuPadding));
+
   aura::Window* window = Shell::GetPrimaryRootWindow();
   gfx::Rect work_area =
       WorkAreaInsets::ForWindow(window)->user_work_area_bounds();
@@ -76,22 +82,20 @@
         gfx::Rect(scroll_point_in_dips.x(), scroll_point_in_dips.y(), 0, 0);
     // Buffer around the point so that the scroll bubble does not overlap it.
     // ScrollBubbleController will automatically layout to avoid edges.
-    anchor.Inset(-kScrollPointBufferDips, -kScrollPointBufferDips);
+    // Aims to lay out like the context menu, at 16x16 to the bottom right.
+    anchor.Inset(-kScrollPointBufferDips, 0);
     bubble_view_->UpdateAnchorRect(anchor,
-                                   views::BubbleBorder::Arrow::LEFT_CENTER);
+                                   views::BubbleBorder::Arrow::LEFT_TOP);
     return;
   }
 
   // Otherwise, the scrollable area bounds are small compared to the scroll
   // scroll bubble, so we should not overlap the scroll bubble if possible.
   // Try to show the scroll bubble on the side of the rect closest to the point.
-  scroll_bounds_in_dips.Inset(
-      -kScrollRectBufferDips, -kScrollRectBufferDips, -kScrollRectBufferDips,
-      -kScrollRectBufferDips - kCollisionWindowWorkAreaInsetsDp);
-
   // Determine whether there will be space to show the scroll bubble between the
   // scroll bounds and display bounds.
   work_area.Inset(kAutoclickScrollMenuSizeDips, kAutoclickScrollMenuSizeDips);
+  scroll_bounds_in_dips.Inset(-kScrollRectBufferDips, -kScrollRectBufferDips);
   bool fits_left = scroll_bounds_in_dips.x() > work_area.x();
   bool fits_right = scroll_bounds_in_dips.right() < work_area.right();
   bool fits_above = scroll_bounds_in_dips.y() > work_area.y();
@@ -141,8 +145,11 @@
 
   // If the scroll bubble doesn't fit between the scroll bounds and display
   // edges, re-pin the scroll bubble to the menu bubble.
+  // This may not ever happen except on low-resolution screens.
   set_scroll_rect_ = !positions.empty();
   if (!set_scroll_rect_) {
+    bubble_view_->UpdateInsets(gfx::Insets(
+        0, kUnifiedMenuPadding, kUnifiedMenuPadding, kUnifiedMenuPadding));
     UpdateAnchorRect(menu_bubble_rect_, menu_bubble_alignment_);
     return;
   }
diff --git a/ash/system/accessibility/autoclick_scroll_view.cc b/ash/system/accessibility/autoclick_scroll_view.cc
index e573d371e..042ec38 100644
--- a/ash/system/accessibility/autoclick_scroll_view.cc
+++ b/ash/system/accessibility/autoclick_scroll_view.cc
@@ -340,6 +340,10 @@
   SetAnchorRect(rect);
 }
 
+void AutoclickScrollBubbleView::UpdateInsets(gfx::Insets insets) {
+  SetBubbleBorderInsets(insets);
+}
+
 bool AutoclickScrollBubbleView::IsAnchoredToStatusArea() const {
   return false;
 }
diff --git a/ash/system/accessibility/autoclick_scroll_view.h b/ash/system/accessibility/autoclick_scroll_view.h
index 9450052..7aa495d 100644
--- a/ash/system/accessibility/autoclick_scroll_view.h
+++ b/ash/system/accessibility/autoclick_scroll_view.h
@@ -21,9 +21,17 @@
   explicit AutoclickScrollBubbleView(TrayBubbleView::InitParams init_params);
   ~AutoclickScrollBubbleView() override;
 
+  // Updates the scroll bubble positioning by updating the |rect| to which the
+  // bubble anchors and the |arrow| indicating which side of |rect| it should
+  // try to lay out on.
   void UpdateAnchorRect(const gfx::Rect& rect,
                         views::BubbleBorder::Arrow arrow);
 
+  // Updates the scroll bubble's insets. Insets can be set at creation time
+  // using TrayBubbleView::InitParams in the constructor and updated at runtime
+  // here.
+  void UpdateInsets(gfx::Insets insets);
+
   // TrayBubbleView:
   bool IsAnchoredToStatusArea() const override;
 
diff --git a/ash/system/tray/tray_bubble_view.cc b/ash/system/tray/tray_bubble_view.cc
index 99d6a49..1606795 100644
--- a/ash/system/tray/tray_bubble_view.cc
+++ b/ash/system/tray/tray_bubble_view.cc
@@ -470,6 +470,10 @@
   }
 }
 
+void TrayBubbleView::SetBubbleBorderInsets(gfx::Insets insets) {
+  bubble_border_->set_insets(insets);
+}
+
 void TrayBubbleView::CloseBubbleView() {
   if (!delegate_)
     return;
diff --git a/ash/system/tray/tray_bubble_view.h b/ash/system/tray/tray_bubble_view.h
index eb84375..ca8efd14 100644
--- a/ash/system/tray/tray_bubble_view.h
+++ b/ash/system/tray/tray_bubble_view.h
@@ -182,6 +182,10 @@
   void ViewHierarchyChanged(
       const views::ViewHierarchyChangedDetails& details) override;
 
+  // Changes the insets from the bubble border. These were initially set using
+  // the InitParams.insets, but may need to be reset programmatically.
+  void SetBubbleBorderInsets(gfx::Insets insets);
+
  private:
   // This reroutes receiving key events to the TrayBubbleView passed in the
   // constructor. TrayBubbleView is not activated by default. But we want to
diff --git a/ash/wallpaper/wallpaper_controller_impl.cc b/ash/wallpaper/wallpaper_controller_impl.cc
index 2962742..2d9e8ab6 100644
--- a/ash/wallpaper/wallpaper_controller_impl.cc
+++ b/ash/wallpaper/wallpaper_controller_impl.cc
@@ -865,8 +865,6 @@
   SetGlobalChromeOSWallpapersDir(chromeos_wallpapers_path);
   SetGlobalChromeOSCustomWallpapersDir(chromeos_custom_wallpapers_path);
   SetDevicePolicyWallpaperPath(device_policy_wallpaper_path);
-  if (wallpaper_controller_client_)
-    wallpaper_controller_client_->OnReadyToSetWallpaper();
 }
 
 void WallpaperControllerImpl::SetCustomWallpaper(
diff --git a/ash/wallpaper/wallpaper_controller_unittest.cc b/ash/wallpaper/wallpaper_controller_unittest.cc
index 3010090..5cc56b80 100644
--- a/ash/wallpaper/wallpaper_controller_unittest.cc
+++ b/ash/wallpaper/wallpaper_controller_unittest.cc
@@ -231,17 +231,14 @@
   virtual ~TestWallpaperControllerClient() = default;
 
   size_t open_count() const { return open_count_; }
-  size_t ready_count() const { return ready_count_; }
   size_t animation_count() const { return animation_count_; }
 
   // WallpaperControllerClient:
   void OpenWallpaperPicker() override { open_count_++; }
-  void OnReadyToSetWallpaper() override { ready_count_++; }
   void OnFirstWallpaperAnimationFinished() override { animation_count_++; }
 
  private:
   size_t open_count_ = 0;
-  size_t ready_count_ = 0;
   size_t animation_count_ = 0;
 
   DISALLOW_COPY_AND_ASSIGN(TestWallpaperControllerClient);
@@ -548,10 +545,8 @@
   TestWallpaperControllerClient client;
   controller_->SetClient(&client);
 
-  EXPECT_EQ(0u, client.ready_count());
   base::FilePath empty_path;
   controller_->Init(empty_path, empty_path, empty_path, empty_path);
-  EXPECT_EQ(1u, client.ready_count());
 
   EXPECT_EQ(0u, client.open_count());
   EXPECT_TRUE(controller_->CanOpenWallpaperPicker());
diff --git a/ash/wm/overview/delayed_animation_observer_impl_unittest.cc b/ash/wm/overview/delayed_animation_observer_impl_unittest.cc
index 00076b8..79578d4 100644
--- a/ash/wm/overview/delayed_animation_observer_impl_unittest.cc
+++ b/ash/wm/overview/delayed_animation_observer_impl_unittest.cc
@@ -64,7 +64,8 @@
     DestroyScopedTaskEnvironment();
     scoped_task_environment_ =
         std::make_unique<base::test::ScopedTaskEnvironment>(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME);
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   }
   ~ForceDelayObserverTest() override = default;
 
diff --git a/base/allocator/partition_allocator/memory_reclaimer_unittest.cc b/base/allocator/partition_allocator/memory_reclaimer_unittest.cc
index d531ff7..95c6039 100644
--- a/base/allocator/partition_allocator/memory_reclaimer_unittest.cc
+++ b/base/allocator/partition_allocator/memory_reclaimer_unittest.cc
@@ -24,8 +24,7 @@
  public:
   PartitionAllocMemoryReclaimerTest()
       : ::testing::Test(),
-        task_environment_(
-            test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+        task_environment_(test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         allocator_() {}
 
  protected:
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
index a419daa..5bc38cc 100644
--- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc
+++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/cancelable_callback.h"
@@ -4742,6 +4743,153 @@
   CheckPostedTaskRan(true);
 }
 
+namespace {
+
+EnqueueOrder RunTaskAndCaptureEnqueueOrder(scoped_refptr<TestTaskQueue> queue) {
+  EnqueueOrder enqueue_order;
+  base::RunLoop run_loop;
+  queue->GetTaskQueueImpl()->SetOnTaskStartedHandler(base::BindLambdaForTesting(
+      [&](const Task& task, const TaskQueue::TaskTiming&) {
+        EXPECT_FALSE(enqueue_order);
+        enqueue_order = task.enqueue_order();
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+  queue->GetTaskQueueImpl()->SetOnTaskStartedHandler({});
+  EXPECT_TRUE(enqueue_order);
+  return enqueue_order;
+}
+
+}  // namespace
+
+TEST_P(SequenceManagerTest, LastUnblockEnqueueOrder_WithFence) {
+  constexpr TimeDelta kDelay = TimeDelta::FromSeconds(42);
+
+  {
+    // Post a task. Install a fence at the beginning of time and remove it. The
+    // task's EnqueueOrder should be less than GetLastUnblockEnqueueOrder().
+    auto queue = CreateTaskQueue();
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->InsertFence(TaskQueue::InsertFencePosition::kBeginningOfTime);
+    queue->RemoveFence();
+    auto enqueue_order = RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_LT(enqueue_order, queue->GetLastUnblockEnqueueOrder());
+  }
+
+  {
+    // Post a 1st task. Install a now fence. Post a 2nd task. Run the first
+    // task. Remove the fence. The 2nd task's EnqueueOrder should be less than
+    // GetLastUnblockEnqueueOrder().
+    auto queue = CreateTaskQueue();
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+    queue->RemoveFence();
+    auto enqueue_order = RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_LT(enqueue_order, queue->GetLastUnblockEnqueueOrder());
+  }
+
+  {
+    // Post a 1st task. Install a now fence. Post a 2nd task. Remove the fence.
+    // GetLastUnblockEnqueueOrder() should indicate that the queue was never
+    // blocked (front task could always run).
+    auto queue = CreateTaskQueue();
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->RemoveFence();
+    RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+    RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+  }
+
+  {
+    // Post a 1st task. Install a now fence. Post a 2nd task. Install a now
+    // fence (moves the previous fence). GetLastUnblockEnqueueOrder() should
+    // indicate that the queue was never blocked (front task could always run).
+    auto queue = CreateTaskQueue();
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->InsertFence(TaskQueue::InsertFencePosition::kNow);
+    RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+    RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+  }
+
+  {
+    const TimeTicks start_time = mock_tick_clock()->NowTicks();
+
+    // Post a 1st task. Install a delayed fence. Post a 2nd task that will run
+    // after the fence. Run the first task. Remove the fence. The 2nd task's
+    // EnqueueOrder should be less than GetLastUnblockEnqueueOrder().
+    auto queue =
+        CreateTaskQueue(TaskQueue::Spec("test").SetDelayedFencesAllowed(true));
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->InsertFenceAt(start_time + kDelay);
+    queue->task_runner()->PostDelayedTask(FROM_HERE, DoNothing(), 2 * kDelay);
+    RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+    FastForwardBy(2 * kDelay);
+    queue->RemoveFence();
+    auto enqueue_order = RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_LT(enqueue_order, queue->GetLastUnblockEnqueueOrder());
+  }
+
+  {
+    const TimeTicks start_time = mock_tick_clock()->NowTicks();
+
+    // Post a 1st task. Install a delayed fence. Post a 2nd task that will run
+    // before the fence. GetLastUnblockEnqueueOrder() should indicate that the
+    // queue was never blocked (front task could always run).
+    auto queue =
+        CreateTaskQueue(TaskQueue::Spec("test").SetDelayedFencesAllowed(true));
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->InsertFenceAt(start_time + 2 * kDelay);
+    queue->task_runner()->PostDelayedTask(FROM_HERE, DoNothing(), kDelay);
+    RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+    FastForwardBy(3 * kDelay);
+    EXPECT_FALSE(queue->GetLastUnblockEnqueueOrder());
+    queue->RemoveFence();
+  }
+}
+
+TEST_P(SequenceManagerTest, LastUnblockEnqueueOrder_WithEnabled) {
+  {
+    // Post a 1st task. Disable the queue and re-enable it. Post a 2nd task. The
+    // 1st task's EnqueueOrder should be less than GetLastUnblockEnqueueOrder().
+    auto queue = CreateTaskQueue();
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->GetTaskQueueImpl()->SetQueueEnabled(false);
+    queue->GetTaskQueueImpl()->SetQueueEnabled(true);
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    auto first_enqueue_order = RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_LT(first_enqueue_order, queue->GetLastUnblockEnqueueOrder());
+    auto second_enqueue_order = RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_GT(second_enqueue_order, queue->GetLastUnblockEnqueueOrder());
+  }
+
+  {
+    // Disable the queue. Post a 1st task. Re-enable the queue. Post a 2nd task.
+    // The 1st task's EnqueueOrder should be less than
+    // GetLastUnblockEnqueueOrder().
+    auto queue = CreateTaskQueue();
+    queue->GetTaskQueueImpl()->SetQueueEnabled(false);
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    queue->GetTaskQueueImpl()->SetQueueEnabled(true);
+    queue->task_runner()->PostTask(FROM_HERE, DoNothing());
+    auto first_enqueue_order = RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_LT(first_enqueue_order, queue->GetLastUnblockEnqueueOrder());
+    auto second_enqueue_order = RunTaskAndCaptureEnqueueOrder(queue);
+    EXPECT_GT(second_enqueue_order, queue->GetLastUnblockEnqueueOrder());
+  }
+}
+
 }  // namespace sequence_manager_impl_unittest
 }  // namespace internal
 }  // namespace sequence_manager
diff --git a/base/task/sequence_manager/task_queue.cc b/base/task/sequence_manager/task_queue.cc
index 35ff9d7..30086985 100644
--- a/base/task/sequence_manager/task_queue.cc
+++ b/base/task/sequence_manager/task_queue.cc
@@ -315,6 +315,13 @@
   return impl_->BlockedByFence();
 }
 
+EnqueueOrder TaskQueue::GetLastUnblockEnqueueOrder() const {
+  DCHECK_CALLED_ON_VALID_THREAD(associated_thread_->thread_checker);
+  if (!impl_)
+    return EnqueueOrder();
+  return impl_->GetLastUnblockEnqueueOrder();
+}
+
 const char* TaskQueue::GetName() const {
   return name_;
 }
diff --git a/base/task/sequence_manager/task_queue.h b/base/task/sequence_manager/task_queue.h
index d863308..a62613eb 100644
--- a/base/task/sequence_manager/task_queue.h
+++ b/base/task/sequence_manager/task_queue.h
@@ -323,6 +323,12 @@
   // Returns true if the queue has a fence which is blocking execution of tasks.
   bool BlockedByFence() const;
 
+  // Returns an EnqueueOrder generated at the last transition to unblocked. A
+  // queue is unblocked when it is enabled and no fence prevents the front task
+  // from running. If the EnqueueOrder of a task is greater than this when it
+  // starts running, it means that is was never blocked.
+  EnqueueOrder GetLastUnblockEnqueueOrder() const;
+
   void SetObserver(Observer* observer);
 
   // Controls whether or not the queue will emit traces events when tasks are
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc
index a46b72de..0827e46e 100644
--- a/base/task/sequence_manager/task_queue_impl.cc
+++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -777,8 +777,11 @@
     UpdateCrossThreadQueueStateLocked();
   }
 
-  if (IsQueueEnabled() && task_unblocked)
+  if (IsQueueEnabled() && task_unblocked) {
+    main_thread_only().last_unblocked_enqueue_order =
+        sequence_manager_->GetNextSequenceNumber();
     sequence_manager_->ScheduleWork();
+  }
 }
 
 void TaskQueueImpl::InsertFenceAt(TimeTicks time) {
@@ -812,8 +815,11 @@
     UpdateCrossThreadQueueStateLocked();
   }
 
-  if (IsQueueEnabled() && task_unblocked)
+  if (IsQueueEnabled() && task_unblocked) {
+    main_thread_only().last_unblocked_enqueue_order =
+        sequence_manager_->GetNextSequenceNumber();
     sequence_manager_->ScheduleWork();
+  }
 }
 
 bool TaskQueueImpl::BlockedByFence() const {
@@ -842,6 +848,10 @@
   return !!main_thread_only().current_fence;
 }
 
+EnqueueOrder TaskQueueImpl::GetLastUnblockEnqueueOrder() const {
+  return main_thread_only().last_unblocked_enqueue_order;
+}
+
 bool TaskQueueImpl::CouldTaskRun(EnqueueOrder enqueue_order) const {
   if (!IsQueueEnabled())
     return false;
@@ -933,6 +943,11 @@
     // Note the selector calls SequenceManager::OnTaskQueueEnabled which posts
     // a DoWork if needed.
     sequence_manager_->main_thread_only().selector.EnableQueue(this);
+
+    if (!BlockedByFence()) {
+      main_thread_only().last_unblocked_enqueue_order =
+          sequence_manager_->GetNextSequenceNumber();
+    }
   } else {
     sequence_manager_->main_thread_only().selector.DisableQueue(this);
   }
diff --git a/base/task/sequence_manager/task_queue_impl.h b/base/task/sequence_manager/task_queue_impl.h
index ed5489dd..535bb2c 100644
--- a/base/task/sequence_manager/task_queue_impl.h
+++ b/base/task/sequence_manager/task_queue_impl.h
@@ -120,6 +120,7 @@
   void RemoveFence();
   bool HasActiveFence();
   bool BlockedByFence() const;
+  EnqueueOrder GetLastUnblockEnqueueOrder() const;
 
   // Implementation of TaskQueue::SetObserver.
   void SetObserver(TaskQueue::Observer* observer);
@@ -345,6 +346,7 @@
     trace_event::BlameContext* blame_context = nullptr;  // Not owned.
     EnqueueOrder current_fence;
     Optional<TimeTicks> delayed_fence;
+    EnqueueOrder last_unblocked_enqueue_order;
     OnTaskStartedHandler on_task_started_handler;
     OnTaskCompletedHandler on_task_completed_handler;
     // Last reported wake up, used only in UpdateWakeUp to avoid
diff --git a/base/test/null_task_runner.h b/base/test/null_task_runner.h
index c11ab6b0..80b2f941 100644
--- a/base/test/null_task_runner.h
+++ b/base/test/null_task_runner.h
@@ -12,9 +12,15 @@
 
 namespace base {
 
+// ATTENTION: Prefer ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED and
+// a task runner obtained from base/task/post_task.h over this class. A
+// NullTaskRunner might seem appealing, but not running tasks is under-testing
+// the side-effects of the code under tests. ThreadPoolExecutionMode::QUEUED
+// will delay execution until the end of the test (if not requested earlier) but
+// will at least exercise the tasks posted as a side-effect of the test.
+//
 // Helper class for tests that need to provide an implementation of a
 // *TaskRunner class but don't actually care about tasks being run.
-
 class NullTaskRunner : public base::SingleThreadTaskRunner {
  public:
   NullTaskRunner();
diff --git a/base/test/scoped_task_environment.h b/base/test/scoped_task_environment.h
index bd593ceb..25af5e5 100644
--- a/base/test/scoped_task_environment.h
+++ b/base/test/scoped_task_environment.h
@@ -41,6 +41,9 @@
 // RunLoop::Run(UntilIdle) or ScopedTaskEnvironment::RunUntilIdle is called on
 // the thread where the ScopedTaskEnvironment lives.
 //
+// The TimeSource trait can be used to request that delayed tasks be under the
+// manual control of ScopedTaskEnvironment::FastForward*() methods.
+//
 // Tasks posted through base/task/post_task.h run on dedicated threads. If
 // ThreadPoolExecutionMode is QUEUED, they run when RunUntilIdle() or
 // ~ScopedTaskEnvironment is called. If ThreadPoolExecutionMode is ASYNC, they
@@ -54,19 +57,21 @@
 //    public:
 //     (...)
 //
+//    // protected rather than private visibility will allow controlling the
+//    // task environment (e.g. RunUntilIdle(), FastForwardBy(), etc.). from the
+//    // test body.
 //    protected:
-//     // Must be the first member (or at least before any member that cares
-//     // about tasks) to be initialized first and destroyed last. protected
-//     // instead of private visibility will allow controlling the task
-//     // environment (e.g. clock) once such features are added (see design doc
-//     // below for details), until then it at least doesn't hurt :).
-//     base::test::ScopedTaskEnvironment scoped_task_environment_;
+//     // Must generally be the first member to be initialized first and
+//     // destroyed last (some members that require single-threaded
+//     // initialization and tear down may need to come before -- e.g.
+//     // base::test::ScopedFeatureList). Extra traits, like TimeSource, are
+//     // best provided inline when declaring the ScopedTaskEnvironment, as
+//     // such:
+//     base::test::ScopedTaskEnvironment scoped_task_environment_{
+//         base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 //
 //     // Other members go here (or further below in private section.)
 //   };
-//
-// Design and future improvements documented in
-// https://docs.google.com/document/d/1QabRo8c7D9LsYY3cEcaPQbOCLo8Tu-6VLykYXyl3Pkk/edit
 class ScopedTaskEnvironment {
  protected:
   // This enables a two-phase initialization for sub classes such as
diff --git a/base/test/test_mock_time_task_runner.h b/base/test/test_mock_time_task_runner.h
index c4de731..f0ce6c2 100644
--- a/base/test/test_mock_time_task_runner.h
+++ b/base/test/test_mock_time_task_runner.h
@@ -29,6 +29,12 @@
 
 class ThreadTaskRunnerHandle;
 
+// ATTENTION: Prefer using base::test::ScopedTaskEnvironment with a
+// base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME trait instead. The
+// only case where TestMockTimeTaskRunner is necessary is when instantiating
+// multiple TestMockTimeTaskRunners in the same test to deterministically
+// exercise the result of a race between two simulated threads.
+//
 // Runs pending tasks in the order of the tasks' post time + delay, and keeps
 // track of a mock (virtual) tick clock time that can be fast-forwarded.
 //
@@ -60,13 +66,9 @@
 //     delayed ones), it will block until more are posted. As usual,
 //     RunLoop::RunUntilIdle() is equivalent to RunLoop::Run() followed by an
 //     immediate RunLoop::QuitWhenIdle().
-//    -
 //
 // This is a slightly more sophisticated version of TestSimpleTaskRunner, in
 // that it supports running delayed tasks in the correct temporal order.
-//
-// ATTENTION: Consider using base::test::ScopedTaskEnvironment with a
-// base::test::ScopedTaskEnvironment::MOCK_TIME constructor parameter instead.
 class TestMockTimeTaskRunner : public SingleThreadTaskRunner,
                                public RunLoop::Delegate {
  public:
diff --git a/base/test/test_simple_task_runner.h b/base/test/test_simple_task_runner.h
index bff8ee5..9bab3b2 100644
--- a/base/test/test_simple_task_runner.h
+++ b/base/test/test_simple_task_runner.h
@@ -18,6 +18,14 @@
 
 class TimeDelta;
 
+// ATTENTION: Prefer using base::test::ScopedTaskEnvironment and a task runner
+// obtained from base/task/post_task.h over this class. This class isn't as
+// "simple" as it seems specifically because its attempt at being simple makes
+// it run tasks in a surprising order (delays aren't respected and nesting
+// doesn't behave as usual). Should you prefer to flush all tasks regardless of
+// delays, ScopedTaskEnvironment::TimeSource::MOCK_TIME and
+// ScopedTaskEnvironment::FastForwardUntilNoTasksRemain() have you covered.
+//
 // TestSimpleTaskRunner is a simple TaskRunner implementation that can
 // be used for testing.  It implements SingleThreadTaskRunner as that
 // interface implements SequencedTaskRunner, which in turn implements
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc
index 7129fea..ff6cbbe 100644
--- a/base/timer/timer_unittest.cc
+++ b/base/timer/timer_unittest.cc
@@ -438,7 +438,7 @@
 
 TEST(TimerTest, OneShotTimerWithTickClock) {
   test::ScopedTaskEnvironment scoped_task_environment(
-      test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   Receiver receiver;
   OneShotTimer timer(scoped_task_environment.GetMockTickClock());
   timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
@@ -465,7 +465,7 @@
 
 TEST(TimerTest, RepeatingTimerWithTickClock) {
   test::ScopedTaskEnvironment scoped_task_environment(
-      test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   Receiver receiver;
   const int expected_times_called = 10;
   RepeatingTimer timer(scoped_task_environment.GetMockTickClock());
@@ -496,7 +496,7 @@
 
 TEST(TimerTest, DelayTimerWithTickClock) {
   test::ScopedTaskEnvironment scoped_task_environment(
-      test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   Receiver receiver;
   DelayTimer timer(FROM_HERE, TimeDelta::FromSeconds(1), &receiver,
                    &Receiver::OnCalled,
diff --git a/build/android/gyp/create_app_bundle.py b/build/android/gyp/create_app_bundle.py
index 27f11ba4..660290f 100755
--- a/build/android/gyp/create_app_bundle.py
+++ b/build/android/gyp/create_app_bundle.py
@@ -68,9 +68,7 @@
   parser.add_argument(
       '--pathmap-in-paths',
       action='append',
-      help='List of module pathmap files.')
-  parser.add_argument(
-      '--module-names', action='append', help='List of module names.')
+      help='GN-list of module pathmap files.')
   parser.add_argument(
       '--pathmap-out-path', help='Path to combined pathmap file for bundle.')
   parser.add_argument(
@@ -331,46 +329,6 @@
         out_file.write(in_file.read())
 
 
-def _LoadPathmap(pathmap_path):
-  """Load the pathmap of obfuscated resource paths.
-
-  Returns: A dict mapping from obfuscated paths to original paths or an
-           empty dict if passed a None |pathmap_path|.
-  """
-  if pathmap_path is None:
-    return {}
-
-  pathmap = {}
-  with open(pathmap_path, 'r') as f:
-    for line in f:
-      line = line.strip()
-      if line.startswith('--') or line == '':
-        continue
-      original, renamed = line.split(' -> ')
-      pathmap[renamed] = original
-  return pathmap
-
-
-def _WriteBundlePathmap(module_pathmap_paths, module_names,
-                        bundle_pathmap_path):
-  """Combine the contents of module pathmaps into a bundle pathmap.
-
-  This rebases the resource paths inside the module pathmap before adding them
-  to the bundle pathmap. So res/a.xml inside the base module pathmap would be
-  base/res/a.xml in the bundle pathmap.
-  """
-  with open(bundle_pathmap_path, 'w') as bundle_pathmap_file:
-    for module_pathmap_path, module_name in zip(module_pathmap_paths,
-                                                module_names):
-      if not os.path.exists(module_pathmap_path):
-        continue
-      module_pathmap = _LoadPathmap(module_pathmap_path)
-      for short_path, long_path in module_pathmap.iteritems():
-        rebased_long_path = '{}/{}'.format(module_name, long_path)
-        rebased_short_path = '{}/{}'.format(module_name, short_path)
-        line = '{} -> {}\n'.format(rebased_long_path, rebased_short_path)
-        bundle_pathmap_file.write(line)
-
 
 def main(args):
   args = build_utils.ExpandFileArgs(args)
@@ -413,7 +371,6 @@
     cmd_args += ['--output=%s' % tmp_unsigned_bundle]
     cmd_args += ['--config=%s' % tmp_bundle_config]
 
-    print ' '.join(cmd_args)
     build_utils.CheckOutput(cmd_args, print_stdout=True, print_stderr=True)
 
     if options.keystore_path:
@@ -437,8 +394,7 @@
     _ConcatTextFiles(options.rtxt_in_paths, options.rtxt_out_path)
 
   if options.pathmap_out_path:
-    _WriteBundlePathmap(options.pathmap_in_paths, options.module_names,
-                        options.pathmap_out_path)
+    _ConcatTextFiles(options.pathmap_in_paths, options.pathmap_out_path)
 
 
 if __name__ == '__main__':
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index 2b0cb0a..a315070 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -4697,9 +4697,8 @@
         ]
       }
 
-      foreach(_module, _all_modules) {
-        _rebased_build_config =
-            rebase_path(_module.build_config, root_build_dir)
+      foreach(build_config, _all_module_build_configs) {
+        _rebased_build_config = rebase_path(build_config, root_build_dir)
         args += [
           "--uncompressed-assets=@FileArg(" +
               "$_rebased_build_config:uncompressed_assets)",
@@ -4707,7 +4706,6 @@
               "$_rebased_build_config:deps_info:r_text_path)",
           "--pathmap-in-paths=@FileArg(" +
               "$_rebased_build_config:deps_info:module_pathmap_path)",
-          "--module-names=" + _module.name,
         ]
       }
     }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 3dca6c5..1709b0f0 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-8907799450341764928
\ No newline at end of file
+8907772007199750624
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index febaf70..0c1901f 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-8907799448889211232
\ No newline at end of file
+8907771311287432384
\ No newline at end of file
diff --git a/cc/scheduler/compositor_frame_reporter.cc b/cc/scheduler/compositor_frame_reporter.cc
index 8377071d..1a41c5c 100644
--- a/cc/scheduler/compositor_frame_reporter.cc
+++ b/cc/scheduler/compositor_frame_reporter.cc
@@ -7,7 +7,7 @@
 #include <string>
 
 #include "base/metrics/histogram_macros.h"
-#include "base/strings/stringprintf.h"
+#include "base/strings/strcat.h"
 #include "base/trace_event/trace_event.h"
 #include "cc/base/rolling_time_delta_history.h"
 
@@ -207,18 +207,16 @@
   CHECK_GE(histogram_index, 0);
 
   const char* compositor_type = is_single_threaded_ ? "SingleThreaded" : "";
+  const std::string name =
+      base::StrCat({compositor_type, "CompositorLatency.",
+                    kReportTypeNames[static_cast<int>(report_type)],
+                    kStageNames[static_cast<int>(stage_type)]});
 
   STATIC_HISTOGRAM_POINTER_GROUP(
-      base::StringPrintf("%s%s%s%s", compositor_type, "CompositorLatency.",
-                         kReportTypeNames[static_cast<int>(report_type)],
-                         kStageNames[static_cast<int>(stage_type)]),
-      histogram_index, kMaxHistogramIndex,
+      name, histogram_index, kMaxHistogramIndex,
       AddTimeMicrosecondsGranularity(time_delta),
       base::Histogram::FactoryGet(
-          base::StringPrintf("%s%s%s%s", compositor_type, "CompositorLatency.",
-                             kReportTypeNames[static_cast<int>(report_type)],
-                             kStageNames[static_cast<int>(stage_type)]),
-          kHistogramMin, kHistogramMax, kHistogramBucketCount,
+          name, kHistogramMin, kHistogramMax, kHistogramBucketCount,
           base::HistogramBase::kUmaTargetedHistogramFlag));
 }
 
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 8c5f87b..b0769bd3 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -782,6 +782,7 @@
     "//base/test:test_support_java",
     "//chrome/android:app_hooks_java",
     "//chrome/android:chrome_java",
+    "//chrome/android/features/start_surface/internal:java",
     "//chrome/android/features/tab_ui:java",
     "//chrome/android/public/crypto:java",
     "//chrome/android/public/profiles:java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni
index fce09b56..a92cc41 100644
--- a/chrome/android/chrome_public_apk_tmpl.gni
+++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -170,7 +170,7 @@
     strip_resource_names = true
 
     # TODO(753402): enable once aapt2>=3.6.0 and bundletool>0.9.0 are rolled in.
-    short_resource_paths = true
+    short_resource_paths = false
 
     if (defined(shared_libraries) && shared_libraries != []) {
       _native_lib_file =
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPaymentRequestUiTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPaymentRequestUiTest.java
index f9b6b41..45d5beb 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPaymentRequestUiTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPaymentRequestUiTest.java
@@ -24,6 +24,7 @@
 
 import static org.chromium.chrome.browser.autofill_assistant.AssistantTagsForTesting.VERTICAL_EXPANDER_CHEVRON;
 
+import android.os.Build;
 import android.support.test.filters.MediumTest;
 import android.view.View;
 
@@ -33,6 +34,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.chrome.autofill_assistant.R;
 import org.chromium.chrome.browser.ChromeSwitches;
 import org.chromium.chrome.browser.autofill.CardType;
@@ -329,6 +331,7 @@
      */
     @Test
     @MediumTest
+    @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.M, message = "https://crbug.com/984591")
     public void testPaymentMethodsLiveUpdate() throws Exception {
         AssistantPaymentRequestModel model = new AssistantPaymentRequestModel();
         AssistantPaymentRequestCoordinator coordinator = createPaymentRequestCoordinator(model);
diff --git a/chrome/android/features/start_surface/OWNERS b/chrome/android/features/start_surface/OWNERS
new file mode 100644
index 0000000..20b7f06f
--- /dev/null
+++ b/chrome/android/features/start_surface/OWNERS
@@ -0,0 +1 @@
+file://chrome/android/java/src/org/chromium/chrome/browser/tasks/OWNERS
\ No newline at end of file
diff --git a/chrome/android/features/start_surface/internal/BUILD.gn b/chrome/android/features/start_surface/internal/BUILD.gn
new file mode 100644
index 0000000..6d7bfcb
--- /dev/null
+++ b/chrome/android/features/start_surface/internal/BUILD.gn
@@ -0,0 +1,21 @@
+# 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.
+
+import("//build/config/android/rules.gni")
+
+android_library("java") {
+  java_files = [
+    "java/src/org/chromium/chrome/features/start_surface/BottomBarCoordinator.java",
+    "java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java",
+    "java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java",
+    "java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java",
+    "java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java",
+  ]
+
+  deps = [
+    "//base:base_java",
+    "//chrome/android:chrome_java",
+    "//ui/android:ui_full_java",
+  ]
+}
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/BottomBarCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/BottomBarCoordinator.java
new file mode 100644
index 0000000..8a6c34d
--- /dev/null
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/BottomBarCoordinator.java
@@ -0,0 +1,10 @@
+// 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.
+
+package org.chromium.chrome.features.start_surface;
+
+/** The coordinator to control the bottom bar. */
+class BottomBarCoordinator {
+    // TODO(crbug.com/982018): Implement the bottom bar.
+}
\ No newline at end of file
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
new file mode 100644
index 0000000..799bc7ea
--- /dev/null
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/ExploreSurfaceCoordinator.java
@@ -0,0 +1,10 @@
+// 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.
+
+package org.chromium.chrome.features.start_surface;
+
+/** The coordinator to control the explore surface. */
+class ExploreSurfaceCoordinator {
+    // TODO(crbug.com/982018): Implement the explore surface.
+}
\ No newline at end of file
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
new file mode 100644
index 0000000..52241ebe
--- /dev/null
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceCoordinator.java
@@ -0,0 +1,96 @@
+// 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.
+
+package org.chromium.chrome.features.start_surface;
+
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.support.annotation.NonNull;
+
+import org.chromium.base.Callback;
+import org.chromium.base.VisibleForTesting;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.tasks.tab_management.GridTabSwitcher;
+import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
+
+/**
+ * Root coordinator that is responsible for showing start surfaces, like a grid of Tabs, explore
+ * surface and the bottom bar to switch between them.
+ */
+public class StartSurfaceCoordinator implements StartSurface {
+    private final GridTabSwitcher mGridTabSwitcher;
+    private BottomBarCoordinator mBottomBarCoordinator;
+    private ExploreSurfaceCoordinator mExploreSurfaceCoordinator;
+
+    public StartSurfaceCoordinator(ChromeActivity activity) {
+        mGridTabSwitcher =
+                TabManagementModuleProvider.getDelegate().createGridTabSwitcher(activity);
+
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.TWO_PANES_START_SURFACE_ANDROID)) {
+            mBottomBarCoordinator = new BottomBarCoordinator();
+            mExploreSurfaceCoordinator = new ExploreSurfaceCoordinator();
+        }
+    }
+
+    @Override
+    public void setOnTabSelectingListener(OnTabSelectingListener listener) {
+        mGridTabSwitcher.setOnTabSelectingListener(listener);
+    }
+
+    @Override
+    public GridController getGridController() {
+        return mGridTabSwitcher.getGridController();
+    }
+
+    @Override
+    public int getResourceId() {
+        return mGridTabSwitcher.getResourceId();
+    }
+
+    @Override
+    public long getLastDirtyTimeForTesting() {
+        return mGridTabSwitcher.getLastDirtyTimeForTesting();
+    }
+
+    @Override
+    public boolean prepareOverview() {
+        return mGridTabSwitcher.prepareOverview();
+    }
+
+    @Override
+    public void postHiding() {
+        mGridTabSwitcher.postHiding();
+    }
+
+    @Override
+    @NonNull
+    public Rect getThumbnailLocationOfCurrentTab(boolean forceUpdate) {
+        return mGridTabSwitcher.getThumbnailLocationOfCurrentTab(forceUpdate);
+    }
+
+    @Override
+    @VisibleForTesting
+    public void setBitmapCallbackForTesting(Callback<Bitmap> callback) {
+        mGridTabSwitcher.setBitmapCallbackForTesting(callback);
+    }
+
+    @Override
+    @VisibleForTesting
+    public int getBitmapFetchCountForTesting() {
+        return mGridTabSwitcher.getBitmapFetchCountForTesting();
+    }
+
+    @Override
+    @VisibleForTesting
+    public int getSoftCleanupDelayForTesting() {
+        return mGridTabSwitcher.getSoftCleanupDelayForTesting();
+    }
+
+    @Override
+    @VisibleForTesting
+    public int getCleanupDelayForTesting() {
+        return mGridTabSwitcher.getCleanupDelayForTesting();
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
new file mode 100644
index 0000000..8240da5b
--- /dev/null
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceDelegate.java
@@ -0,0 +1,24 @@
+// 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.
+
+package org.chromium.chrome.features.start_surface;
+
+import android.content.Context;
+
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.compositor.layouts.Layout;
+import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
+import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
+
+/** StartSurfaceDelegate. */
+public class StartSurfaceDelegate {
+    public static Layout createStartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
+            LayoutRenderHost renderHost, StartSurface startSurface) {
+        return new StartSurfaceLayout(context, updateHost, renderHost, startSurface);
+    }
+
+    public static StartSurface createStartSurface(ChromeActivity activity) {
+        return new StartSurfaceCoordinator(activity);
+    }
+}
\ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayout.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
similarity index 92%
rename from chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayout.java
rename to chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
index d7ab4b57..30924b5 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayout.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.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.chrome.browser.tasks.tab_management;
+package org.chromium.chrome.features.start_surface;
 
 import static org.chromium.chrome.browser.compositor.animation.CompositorAnimator.FAST_OUT_SLOW_IN_INTERPOLATOR;
 
@@ -50,9 +50,8 @@
 /**
  * A {@link Layout} that shows all tabs in one grid view.
  */
-public class GridTabSwitcherLayout
-        extends Layout implements GridTabSwitcher.GridOverviewModeObserver {
-    private static final String TAG = "GTSLayout";
+public class StartSurfaceLayout extends Layout implements StartSurface.GridOverviewModeObserver {
+    private static final String TAG = "SSLayout";
 
     // Duration of the transition animation
     @VisibleForTesting
@@ -68,8 +67,8 @@
     private boolean mIsAnimating;
 
     private final TabListSceneLayer mSceneLayer = new TabListSceneLayer();
-    private final GridTabSwitcher mGridTabSwitcher;
-    private final GridTabSwitcher.GridController mGridController;
+    private final StartSurface mStartSurface;
+    private final StartSurface.GridController mGridController;
     // To force Toolbar finishes its animation when this Layout finished hiding.
     private final LayoutTab mDummyLayoutTab;
 
@@ -88,18 +87,18 @@
 
     private PerfListener mPerfListenerForTesting;
 
-    public GridTabSwitcherLayout(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost, GridTabSwitcher gridTabSwitcher) {
+    public StartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
+            LayoutRenderHost renderHost, StartSurface startSurface) {
         super(context, updateHost, renderHost);
         mDummyLayoutTab = createLayoutTab(Tab.INVALID_TAB_ID, false, false, false);
         mDummyLayoutTab.setShowToolbar(true);
-        mGridTabSwitcher = gridTabSwitcher;
-        mGridTabSwitcher.setOnTabSelectingListener(this::onTabSelecting);
-        mGridController = gridTabSwitcher.getGridController();
+        mStartSurface = startSurface;
+        mStartSurface.setOnTabSelectingListener(this::onTabSelecting);
+        mGridController = startSurface.getGridController();
         mGridController.addOverviewModeObserver(this);
     }
 
-    // GridTabSwitcher.GridOverviewModeObserver implementation.
+    // StartSurface.GridOverviewModeObserver implementation.
     @Override
     public void startedShowing() {}
 
@@ -129,7 +128,7 @@
         }
         // If we are doing GTS-to-Tab transition animation, we start showing the Bitmap version of
         // the GTS overview in the background while expanding the thumbnail to the viewport.
-        expandTab(mGridTabSwitcher.getThumbnailLocationOfCurrentTab(true));
+        expandTab(mStartSurface.getThumbnailLocationOfCurrentTab(true));
     }
 
     // Layout implementation.
@@ -150,7 +149,7 @@
         super.show(time, animate);
 
         boolean showShrinkingAnimation = animate && FeatureUtilities.isTabToGtsAnimationEnabled();
-        boolean quick = mGridTabSwitcher.prepareOverview();
+        boolean quick = mStartSurface.prepareOverview();
         Log.d(TAG, "SkipSlowZooming = " + getSkipSlowZooming());
         if (getSkipSlowZooming()) {
             showShrinkingAnimation &= quick;
@@ -169,7 +168,7 @@
             return;
         }
 
-        shrinkTab(() -> mGridTabSwitcher.getThumbnailLocationOfCurrentTab(false));
+        shrinkTab(() -> mStartSurface.getThumbnailLocationOfCurrentTab(false));
     }
 
     @Override
@@ -177,7 +176,7 @@
         super.updateLayout(time, dt);
         if (mLayoutTabs == null) return;
 
-        assert mLayoutTabs.length == 1;
+        assert mLayoutTabs.length >= 1;
         boolean needUpdate = mLayoutTabs[0].updateSnap(dt);
         if (needUpdate) requestUpdate();
     }
@@ -362,7 +361,7 @@
     }
 
     private void postHiding() {
-        mGridTabSwitcher.postHiding();
+        mStartSurface.postHiding();
         mIsAnimating = false;
         doneHiding();
     }
@@ -373,14 +372,14 @@
     }
 
     @VisibleForTesting
-    GridTabSwitcher getGridTabSwitcherForTesting() {
-        return mGridTabSwitcher;
+    StartSurface getStartSurfaceForTesting() {
+        return mStartSurface;
     }
 
     private void reportAnimationPerf(boolean isShrinking) {
         int frameRendered = mFrameCount - mStartFrame;
         long elapsedMs = SystemClock.elapsedRealtime() - mStartTime;
-        long lastDirty = mGridTabSwitcher.getLastDirtyTimeForTesting();
+        long lastDirty = mStartSurface.getLastDirtyTimeForTesting();
         int dirtySpan = (int) (lastDirty - mStartTime);
         float fps = 1000.f * frameRendered / elapsedMs;
         String message = String.format(Locale.US,
@@ -433,7 +432,7 @@
         // The content viewport is intentionally sent as both params below.
         mSceneLayer.pushLayers(getContext(), contentViewport, contentViewport, this,
                 layerTitleCache, tabContentManager, resourceManager, fullscreenManager,
-                FeatureUtilities.isTabToGtsAnimationEnabled() ? mGridTabSwitcher.getResourceId()
+                FeatureUtilities.isTabToGtsAnimationEnabled() ? mStartSurface.getResourceId()
                                                               : 0,
                 mBackgroundAlpha);
         mFrameCount++;
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java
similarity index 86%
rename from chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java
rename to chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java
index b6df7b9..8182504b 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.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.chrome.browser.tasks.tab_management;
+package org.chromium.chrome.features.start_surface;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -53,15 +53,15 @@
 import java.util.LinkedList;
 import java.util.List;
 
-/** Tests for the {@link GridTabSwitcherLayout}, mainly for animation performance. */
+/** Tests for the {@link StartSurfaceLayout}, mainly for animation performance. */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         "enable-features=" + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + "<Study,"
                 + ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study",
         "force-fieldtrials=Study/Group"})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-public class GridTabSwitcherLayoutPerfTest {
-    private static final String TAG = "GTSLayoutPerfTest";
+public class StartSurfaceLayoutPerfTest {
+    private static final String TAG = "SSLayoutPerfTest";
     private static final String BASE_PARAMS = "force-fieldtrial-params="
             + "Study.Group:soft-cleanup-delay/0/cleanup-delay/0/skip-slow-zooming/false"
             + "/zooming-min-sdk-version/19/zooming-min-memory-mb/512";
@@ -76,7 +76,7 @@
     public TestRule mProcessor = new Features.InstrumentationProcessor();
 
     private EmbeddedTestServer mTestServer;
-    private GridTabSwitcherLayout mGtsLayout;
+    private StartSurfaceLayout mStartSurfaceLayout;
     private String mUrl;
     private int mRepeat;
     private long mWaitingTime;
@@ -89,8 +89,8 @@
         mActivityTestRule.startMainActivityFromLauncher();
 
         Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
-        assertTrue(layout instanceof GridTabSwitcherLayout);
-        mGtsLayout = (GridTabSwitcherLayout) layout;
+        assertTrue(layout instanceof StartSurfaceLayout);
+        mStartSurfaceLayout = (StartSurfaceLayout) layout;
         mUrl = mTestServer.getURL("/chrome/test/data/android/navigate/simple.html");
         mRepeat = 3;
         mWaitingTime = 0;
@@ -206,10 +206,10 @@
         List<Float> frameRates = new LinkedList<>();
         List<Float> frameInterval = new LinkedList<>();
         List<Float> dirtySpans = new LinkedList<>();
-        GridTabSwitcherLayout.PerfListener collector =
+        StartSurfaceLayout.PerfListener collector =
                 (frameRendered, elapsedMs, maxFrameInterval, dirtySpan) -> {
             assertTrue(elapsedMs
-                    >= GridTabSwitcherLayout.ZOOMING_DURATION * CompositorAnimator.sDurationScale);
+                    >= StartSurfaceLayout.ZOOMING_DURATION * CompositorAnimator.sDurationScale);
             float fps = 1000.f * frameRendered / elapsedMs;
             frameRates.add(fps);
             frameInterval.add((float) maxFrameInterval);
@@ -219,26 +219,29 @@
         mActivityTestRule.loadUrl(fromUrl);
         Thread.sleep(mWaitingTime);
 
-        GridTabSwitcher gts = mGtsLayout.getGridTabSwitcherForTesting();
+        StartSurface startSurface = mStartSurfaceLayout.getStartSurfaceForTesting();
         for (int i = 0; i < mRepeat; i++) {
-            mGtsLayout.setPerfListenerForTesting(collector);
+            mStartSurfaceLayout.setPerfListenerForTesting(collector);
             Thread.sleep(mWaitingTime);
             TestThreadUtils.runOnUiThreadBlocking(
                     () -> mActivityTestRule.getActivity().getLayoutManager().showOverview(true));
             final int expectedSize = i + 1;
-            CriteriaHelper.pollInstrumentationThread(() -> frameRates.size() == expectedSize,
+            CriteriaHelper.pollInstrumentationThread(()
+                                                             -> frameRates.size() == expectedSize,
                     "Have not got PerfListener callback", DEFAULT_MAX_TIME_TO_POLL * 10,
                     DEFAULT_POLLING_INTERVAL);
             assertTrue(mActivityTestRule.getActivity().getLayoutManager().overviewVisible());
 
-            mGtsLayout.setPerfListenerForTesting(null);
+            mStartSurfaceLayout.setPerfListenerForTesting(null);
             // Make sure the fading animation is done.
             Thread.sleep(1000);
             TestThreadUtils.runOnUiThreadBlocking(
-                    () -> { gts.getGridController().onBackPressed(); });
+                    () -> { startSurface.getGridController().onBackPressed(); });
             Thread.sleep(1000);
-            CriteriaHelper.pollInstrumentationThread(
-                    () -> !mActivityTestRule.getActivity().getLayoutManager().overviewVisible(),
+            CriteriaHelper.pollInstrumentationThread(()
+                                                             -> !mActivityTestRule.getActivity()
+                                                                         .getLayoutManager()
+                                                                         .overviewVisible(),
                     "Overview not hidden yet", DEFAULT_MAX_TIME_TO_POLL * 10,
                     DEFAULT_POLLING_INTERVAL);
         }
@@ -291,10 +294,10 @@
             String description) throws InterruptedException {
         List<Float> frameRates = new LinkedList<>();
         List<Float> frameInterval = new LinkedList<>();
-        GridTabSwitcherLayout.PerfListener collector =
+        StartSurfaceLayout.PerfListener collector =
                 (frameRendered, elapsedMs, maxFrameInterval, dirtySpan) -> {
             assertTrue(elapsedMs
-                    >= GridTabSwitcherLayout.ZOOMING_DURATION * CompositorAnimator.sDurationScale);
+                    >= StartSurfaceLayout.ZOOMING_DURATION * CompositorAnimator.sDurationScale);
             float fps = 1000.f * frameRendered / elapsedMs;
             frameRates.add(fps);
             frameInterval.add((float) maxFrameInterval);
@@ -302,7 +305,7 @@
         Thread.sleep(mWaitingTime);
 
         for (int i = 0; i < mRepeat; i++) {
-            mGtsLayout.setPerfListenerForTesting(null);
+            mStartSurfaceLayout.setPerfListenerForTesting(null);
             TestThreadUtils.runOnUiThreadBlocking(
                     () -> mActivityTestRule.getActivity().getLayoutManager().showOverview(true));
             assertTrue(mActivityTestRule.getActivity().getLayoutManager().overviewVisible());
@@ -317,18 +320,21 @@
                 Thread.sleep(1000);
             }
 
-            mGtsLayout.setPerfListenerForTesting(collector);
+            mStartSurfaceLayout.setPerfListenerForTesting(collector);
             Thread.sleep(mWaitingTime);
             Espresso.onView(ViewMatchers.withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
                     .perform(RecyclerViewActions.actionOnItemAtPosition(
                             targetIndex, ViewActions.click()));
 
             final int expectedSize = i + 1;
-            CriteriaHelper.pollInstrumentationThread(() -> frameRates.size() == expectedSize,
+            CriteriaHelper.pollInstrumentationThread(()
+                                                             -> frameRates.size() == expectedSize,
                     "Have not got PerfListener callback", DEFAULT_MAX_TIME_TO_POLL * 10,
                     DEFAULT_POLLING_INTERVAL);
-            CriteriaHelper.pollInstrumentationThread(
-                    () -> !mActivityTestRule.getActivity().getLayoutManager().overviewVisible(),
+            CriteriaHelper.pollInstrumentationThread(()
+                                                             -> !mActivityTestRule.getActivity()
+                                                                         .getLayoutManager()
+                                                                         .overviewVisible(),
                     "Overview not hidden yet");
             Thread.sleep(1000);
         }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
similarity index 88%
rename from chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java
rename to chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
index 1998b81..e039f18d 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.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.chrome.browser.tasks.tab_management;
+package org.chromium.chrome.features.start_surface;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
@@ -13,6 +13,7 @@
 import static org.chromium.content_public.browser.test.util.CriteriaHelper.DEFAULT_POLLING_INTERVAL;
 
 import android.graphics.Bitmap;
+import android.provider.Settings;
 import android.support.annotation.Nullable;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.espresso.Espresso;
@@ -30,6 +31,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.Callback;
+import org.chromium.base.ContextUtils;
 import org.chromium.base.GarbageCollectionTestUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -59,14 +61,14 @@
 import java.util.LinkedList;
 import java.util.List;
 
-/** Tests for the {@link GridTabSwitcherLayout} */
+/** Tests for the {@link StartSurfaceLayout} */
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
         "enable-features=" + ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + "<Study",
         "force-fieldtrials=Study/Group"})
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-public class GridTabSwitcherLayoutTest {
-    private static final String TAG = "GTSLayoutTest";
+public class StartSurfaceLayoutTest {
+    private static final String TAG = "SSLayoutTest";
     private static final String BASE_PARAMS = "force-fieldtrial-params="
             + "Study.Group:soft-cleanup-delay/0/cleanup-delay/0/skip-slow-zooming/false"
             + "/zooming-min-sdk-version/19/zooming-min-memory-mb/512";
@@ -77,7 +79,7 @@
     @Rule
     public TestRule mProcessor = new Features.InstrumentationProcessor();
 
-    private GridTabSwitcherLayout mGtsLayout;
+    private StartSurfaceLayout mStartSurfaceLayout;
     private String mUrl;
     private int mRepeat;
     private List<WeakReference<Bitmap>> mAllBitmaps = new LinkedList<>();
@@ -92,13 +94,13 @@
         mActivityTestRule.startMainActivityFromLauncher();
 
         Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
-        assertTrue(layout instanceof GridTabSwitcherLayout);
-        mGtsLayout = (GridTabSwitcherLayout) layout;
+        assertTrue(layout instanceof StartSurfaceLayout);
+        mStartSurfaceLayout = (StartSurfaceLayout) layout;
         mUrl = testServer.getURL("/chrome/test/data/android/navigate/simple.html");
         mRepeat = 3;
 
-        GridTabSwitcherCoordinator coordinator =
-                (GridTabSwitcherCoordinator) mGtsLayout.getGridTabSwitcherForTesting();
+        StartSurfaceCoordinator coordinator =
+                (StartSurfaceCoordinator) mStartSurfaceLayout.getStartSurfaceForTesting();
         coordinator.setBitmapCallbackForTesting(mBitmapListener);
         Assert.assertEquals(0, coordinator.getBitmapFetchCountForTesting());
 
@@ -110,10 +112,9 @@
     @MediumTest
     @CommandLineFlags.Add({BASE_PARAMS})
     public void testTabToGridFromLiveTab() throws InterruptedException {
-        GridTabSwitcher gts = mGtsLayout.getGridTabSwitcherForTesting();
-        GridTabSwitcherMediator mediator = (GridTabSwitcherMediator) gts.getGridController();
-        assertEquals(0, mediator.getSoftCleanupDelayForTesting());
-        assertEquals(0, mediator.getCleanupDelayForTesting());
+        StartSurface startSurface = mStartSurfaceLayout.getStartSurfaceForTesting();
+        assertEquals(0, startSurface.getSoftCleanupDelayForTesting());
+        assertEquals(0, startSurface.getCleanupDelayForTesting());
 
         prepareTabs(2, NTP_URL);
         testTabToGrid(mUrl);
@@ -138,10 +139,9 @@
     @MediumTest
     @CommandLineFlags.Add({BASE_PARAMS + "/soft-cleanup-delay/10000/cleanup-delay/10000"})
     public void testTabToGridFromLiveTabWarm() throws InterruptedException {
-        GridTabSwitcher gts = mGtsLayout.getGridTabSwitcherForTesting();
-        GridTabSwitcherMediator mediator = (GridTabSwitcherMediator) gts.getGridController();
-        assertEquals(10000, mediator.getSoftCleanupDelayForTesting());
-        assertEquals(10000, mediator.getCleanupDelayForTesting());
+        StartSurface startSurface = mStartSurfaceLayout.getStartSurfaceForTesting();
+        assertEquals(10000, startSurface.getSoftCleanupDelayForTesting());
+        assertEquals(10000, startSurface.getCleanupDelayForTesting());
 
         prepareTabs(2, NTP_URL);
         testTabToGrid(mUrl);
@@ -221,12 +221,12 @@
 
         final int initCount = getCaptureCount();
 
-        GridTabSwitcher gts = mGtsLayout.getGridTabSwitcherForTesting();
+        StartSurface startSurface = mStartSurfaceLayout.getStartSurfaceForTesting();
         for (int i = 0; i < mRepeat; i++) {
             enterGTS();
 
             TestThreadUtils.runOnUiThreadBlocking(
-                    () -> { gts.getGridController().onBackPressed(); });
+                    () -> { startSurface.getGridController().onBackPressed(); });
             // clang-format off
             CriteriaHelper.pollInstrumentationThread(
                     () -> !mActivityTestRule.getActivity().getLayoutManager().overviewVisible(),
@@ -344,8 +344,8 @@
     @CommandLineFlags.Add({BASE_PARAMS})
     public void testRestoredTabsDontFetch() throws Exception {
         prepareTabs(2, mUrl);
-        GridTabSwitcherCoordinator coordinator =
-                (GridTabSwitcherCoordinator) mGtsLayout.getGridTabSwitcherForTesting();
+        StartSurfaceCoordinator coordinator =
+                (StartSurfaceCoordinator) mStartSurfaceLayout.getStartSurfaceForTesting();
         int oldCount = coordinator.getBitmapFetchCountForTesting();
 
         // Restart Chrome.
@@ -356,9 +356,9 @@
         Assert.assertEquals(3, mActivityTestRule.tabsCount(false));
 
         Layout layout = mActivityTestRule.getActivity().getLayoutManager().getOverviewLayout();
-        assertTrue(layout instanceof GridTabSwitcherLayout);
-        mGtsLayout = (GridTabSwitcherLayout) layout;
-        coordinator = (GridTabSwitcherCoordinator) mGtsLayout.getGridTabSwitcherForTesting();
+        assertTrue(layout instanceof StartSurfaceLayout);
+        mStartSurfaceLayout = (StartSurfaceLayout) layout;
+        coordinator = (StartSurfaceCoordinator) mStartSurfaceLayout.getStartSurfaceForTesting();
         Assert.assertEquals(0, coordinator.getBitmapFetchCountForTesting() - oldCount);
     }
 
@@ -450,11 +450,11 @@
             // NTP is not invalidated, so no new captures.
             delta = 0;
         } else {
-            // The final capture at GridTabSwitcherLayout#finishedShowing time.
+            // The final capture at StartSurfaceLayout#finishedShowing time.
             delta = 1;
             // TODO(wychen): refactor areAnimatorsEnabled() to a util class.
             if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
-                    && TabGridContainerViewBinderTest.areAnimatorsEnabled()) {
+                    && areAnimatorsEnabled()) {
                 // The faster capturing without writing back to cache.
                 delta += 1;
             }
@@ -472,7 +472,7 @@
         } else {
             expected = mRepeat;
             if (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_TO_GTS_ANIMATION)
-                    && TabGridContainerViewBinderTest.areAnimatorsEnabled()) {
+                    && areAnimatorsEnabled()) {
                 expected += mRepeat;
             }
             if (switchToAnotherTab) {
@@ -522,4 +522,19 @@
         }
         return true;
     }
+
+    /**
+     * Should be the same as {@link ValueAnimator#areAnimatorsEnabled}, which requires API level 26.
+     * TODO(crbug.com/982018): put this interface in a place to share with
+     * TabGridContainerViewBinderTest.areAnimatorsEnabled.
+     */
+    private static boolean areAnimatorsEnabled() {
+        // We default to assuming that animations are enabled in case ANIMATOR_DURATION_SCALE is not
+        // defined.
+        final float defaultScale = 1f;
+        float durationScale =
+                Settings.Global.getFloat(ContextUtils.getApplicationContext().getContentResolver(),
+                        Settings.Global.ANIMATOR_DURATION_SCALE, defaultScale);
+        return !(durationScale == 0.0);
+    }
 }
diff --git a/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni b/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni
new file mode 100644
index 0000000..b08ff1d
--- /dev/null
+++ b/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni
@@ -0,0 +1,8 @@
+# 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.
+
+start_surface_test_java_sources = [
+  "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java",
+  "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java",
+]
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
new file mode 100644
index 0000000..fbcb871
--- /dev/null
+++ b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
@@ -0,0 +1,12 @@
+// 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.
+
+package org.chromium.chrome.features.start_surface;
+
+import org.chromium.chrome.browser.tasks.tab_management.GridTabSwitcher;
+
+/** Interface to communicate with the start surface. */
+public interface StartSurface extends GridTabSwitcher {
+    // TODO(crbug.com/982018): Decouple StartSurface and GridTabSwitcher.
+}
\ No newline at end of file
diff --git a/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni b/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni
new file mode 100644
index 0000000..af55df2e
--- /dev/null
+++ b/chrome/android/features/start_surface/public/start_surface_public_java_sources.gni
@@ -0,0 +1,5 @@
+# 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.
+
+start_surface_public_java_sources = [ "//chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java" ]
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index e6d9578..421df94c 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -23,7 +23,6 @@
     "java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupUtils.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/ClosableTabGridViewHolder.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java",
-    "java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayout.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherMediator.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/SelectableTabGridView.java",
@@ -72,6 +71,7 @@
     "//chrome/android:chrome_java",
     "//chrome/android:chrome_strings_grd",
     "//chrome/android:ui_locale_string_resources",
+    "//chrome/android/features/start_surface/internal:java",
     "//chrome/app:java_strings_grd",
     "//components/embedder_support/android:web_contents_delegate_java",
     "//components/feature_engagement:feature_engagement_java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java
index 147f977..779e509 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java
@@ -4,9 +4,12 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.support.annotation.NonNull;
 
+import org.chromium.base.Callback;
+import org.chromium.base.VisibleForTesting;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.ui.resources.dynamics.ViewResourceAdapter;
@@ -92,7 +95,7 @@
         void showOverview(boolean animate);
 
         /**
-         * Called by the GridTabSwitcherLayout when the system back button is pressed.
+         * Called by the StartSurfaceLayout when the system back button is pressed.
          * @return Whether or not the GridTabSwitcher consumed the event.
          */
         boolean onBackPressed();
@@ -138,4 +141,30 @@
      */
     @NonNull
     Rect getThumbnailLocationOfCurrentTab(boolean forceUpdate);
+
+    /**
+     * Set a hook to receive all the {@link Bitmap}s returned by
+     * {@link TabListMediator.ThumbnailFetcher} for testing.
+     * @param callback The callback to send bitmaps through.
+     */
+    @VisibleForTesting
+    void setBitmapCallbackForTesting(Callback<Bitmap> callback);
+
+    /**
+     * @return The number of thumbnail fetching for testing.
+     */
+    @VisibleForTesting
+    int getBitmapFetchCountForTesting();
+
+    /**
+     * @return The soft cleanup delay for testing.
+     */
+    @VisibleForTesting
+    int getSoftCleanupDelayForTesting();
+
+    /**
+     * @return The cleanup delay for testing.
+     */
+    @VisibleForTesting
+    int getCleanupDelayForTesting();
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java
index 7e11e8c..d69a2df 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherCoordinator.java
@@ -161,6 +161,30 @@
         return mTabGridCoordinator.getLastDirtyTimeForTesting();
     }
 
+    @Override
+    @VisibleForTesting
+    public void setBitmapCallbackForTesting(Callback<Bitmap> callback) {
+        TabListMediator.ThumbnailFetcher.sBitmapCallbackForTesting = callback;
+    }
+
+    @Override
+    @VisibleForTesting
+    public int getBitmapFetchCountForTesting() {
+        return TabListMediator.ThumbnailFetcher.sFetchCountForTesting;
+    }
+
+    @Override
+    @VisibleForTesting
+    public int getSoftCleanupDelayForTesting() {
+        return mMediator.getCleanupDelayForTesting();
+    }
+
+    @Override
+    @VisibleForTesting
+    public int getCleanupDelayForTesting() {
+        return mMediator.getCleanupDelayForTesting();
+    }
+
     // ResetHandler implementation.
     @Override
     public boolean resetWithTabList(@Nullable TabList tabList, boolean quickMode) {
@@ -196,22 +220,4 @@
         mMediator.destroy();
         mLifecycleDispatcher.unregister(this);
     }
-
-    /**
-     * Set a hook to receive all the {@link Bitmap}s returned by
-     * {@link TabListMediator.ThumbnailFetcher} for testing.
-     * @param callback The callback to send bitmaps through.
-     */
-    @VisibleForTesting
-    void setBitmapCallbackForTesting(Callback<Bitmap> callback) {
-        TabListMediator.ThumbnailFetcher.sBitmapCallbackForTesting = callback;
-    }
-
-    /**
-     * @return The number of thumbnail fetching for testing.
-     */
-    @VisibleForTesting
-    int getBitmapFetchCountForTesting() {
-        return TabListMediator.ThumbnailFetcher.sFetchCountForTesting;
-    }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
index 7b6269d5..8b0f064 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
@@ -12,24 +12,46 @@
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
+import org.chromium.chrome.features.start_surface.StartSurface;
 import org.chromium.components.module_installer.ModuleInterface;
 
 /**
  * Interface to get access to components concerning tab management.
+ * TODO(crbug.com/982018): Move DFM configurations to 'chrome/android/modules/start_surface/'
  */
 @ModuleInterface(module = "tab_management",
         impl = "org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegateImpl")
 public interface TabManagementDelegate {
     /**
-     * Create the {@link GridTabSwitcherLayout}.
+     * Create the {@link GridTabSwitcher}.
+     * @param activity The {@link ChromeActivity} creates this switcher.
+     * @return The {@link GridTabSwitcher}.
+     */
+    GridTabSwitcher createGridTabSwitcher(ChromeActivity activity);
+
+    /**
+     * Create the {@link TabGroupUi}.
+     * @param parentView The parent view of this UI.
+     * @param themeColorProvider The {@link ThemeColorProvider} for this UI.
+     * @return The {@link TabGroupUi}.
+     */
+    TabGroupUi createTabGroupUi(ViewGroup parentView, ThemeColorProvider themeColorProvider);
+
+    /**
+     * Create the {@link StartSurfaceLayout}.
      * @param context The current Android's context.
      * @param updateHost The parent {@link LayoutUpdateHost}.
      * @param renderHost The parent {@link LayoutRenderHost}.
-     * @param gridTabSwitcher The {@link GridTabSwitcher} the layout should own.
-     * @return The {@link GridTabSwitcherLayout}.
+     * @param startSurface The {@link StartSurface} the layout should own.
+     * @return The {@link StartSurfaceLayout}.
      */
-    Layout createGTSLayout(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost, GridTabSwitcher gridTabSwitcher);
-    GridTabSwitcher createGridTabSwitcher(ChromeActivity activity);
-    TabGroupUi createTabGroupUi(ViewGroup parentView, ThemeColorProvider themeColorProvider);
+    Layout createStartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
+            LayoutRenderHost renderHost, StartSurface startSurface);
+
+    /**
+     * Create the {@link StartSurface}
+     * @param activity The {@link ChromeActivity} creates this {@link StartSurface}.
+     * @return the {@link StartSurface}
+     */
+    StartSurface createStartSurface(ChromeActivity activity);
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
index 5ea8ef4..4de6907 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
@@ -17,6 +17,9 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
 import org.chromium.chrome.browser.metrics.UmaSessionStats;
+import org.chromium.chrome.features.start_surface.StartSurface;
+import org.chromium.chrome.features.start_surface.StartSurfaceCoordinator;
+import org.chromium.chrome.features.start_surface.StartSurfaceLayout;
 
 /**
  * Impl class that will resolve components for tab management.
@@ -24,12 +27,6 @@
 @UsedByReflection("TabManagementModule")
 public class TabManagementDelegateImpl implements TabManagementDelegate {
     @Override
-    public Layout createGTSLayout(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost, GridTabSwitcher gridTabSwitcher) {
-        return new GridTabSwitcherLayout(context, updateHost, renderHost, gridTabSwitcher);
-    }
-
-    @Override
     public GridTabSwitcher createGridTabSwitcher(ChromeActivity activity) {
         if (UmaSessionStats.isMetricsServiceAvailable()) {
             UmaSessionStats.registerSyntheticFieldTrial(
@@ -47,4 +44,15 @@
             ViewGroup parentView, ThemeColorProvider themeColorProvider) {
         return new TabGroupUiCoordinator(parentView, themeColorProvider);
     }
+
+    @Override
+    public Layout createStartSurfaceLayout(Context context, LayoutUpdateHost updateHost,
+            LayoutRenderHost renderHost, StartSurface startSurface) {
+        return new StartSurfaceLayout(context, updateHost, renderHost, startSurface);
+    }
+
+    @Override
+    public StartSurface createStartSurface(ChromeActivity activity) {
+        return new StartSurfaceCoordinator(activity);
+    }
 }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java
index b528df5e..9be35b9 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java
@@ -272,7 +272,7 @@
     /**
      * Should be the same as {@link ValueAnimator#areAnimatorsEnabled}, which requires API level 26.
      */
-    public static boolean areAnimatorsEnabled() {
+    private static boolean areAnimatorsEnabled() {
         // We default to assuming that animations are enabled in case ANIMATOR_DURATION_SCALE is not
         // defined.
         final float defaultScale = 1f;
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni
index 4d87d7b8..259f4b6 100644
--- a/chrome/android/features/tab_ui/tab_management_java_sources.gni
+++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -2,6 +2,9 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import(
+    "//chrome/android/features/start_surface/public/start_surface_public_java_sources.gni")
+
 public_tab_management_java_sources = [
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcher.java",
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/SilenceLintErrors.java",
@@ -10,9 +13,9 @@
   "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementModuleProvider.java",
 ]
 
+public_tab_management_java_sources += start_surface_public_java_sources
+
 tab_management_test_java_sources = [
-  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutPerfTest.java",
-  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/GridTabSwitcherLayoutTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridContainerViewBinderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogParentTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabListViewHolderTest.java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
index e9e4f80..e270437 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -292,8 +292,6 @@
     public static final String PER_METHOD_CAN_MAKE_PAYMENT_QUOTA =
             "WebPaymentsPerMethodCanMakePaymentQuota";
     public static final String PHOTO_PICKER_VIDEO_SUPPORT = "PhotoPickerVideoSupport";
-    public static final String WEB_PAYMENTS_REDACT_SHIPPING_ADDRESS =
-            "WebPaymentsRedactShippingAddress";
     public static final String PREDICTIVE_PREFETCHING_ALLOWED_ON_ALL_CONNECTION_TYPES =
             "PredictivePrefetchingAllowedOnAllConnectionTypes";
     public static final String PRIORITIZE_BOOTSTRAP_TASKS = "PrioritizeBootstrapTasks";
@@ -329,17 +327,22 @@
     public static final String TRUSTED_WEB_ACTIVITY_POST_MESSAGE = "TrustedWebActivityPostMessage";
     public static final String TRUSTED_WEB_ACTIVITY_NOTIFICATION_DELEGATION_ENROLMENT =
             "TrustedWebActivityNotificationDelegationAutoEnrolment";
+    public static final String TWO_PANES_START_SURFACE_ANDROID = "TwoPanesStartSurfaceAndroid";
     public static final String VIDEO_PERSISTENCE = "VideoPersistence";
     public static final String USAGE_STATS = "UsageStats";
     public static final String VR_BROWSING_FEEDBACK = "VrBrowsingFeedback";
     public static final String USER_ACTIVATION_V2 = "UserActivationV2";
     public static final String WEB_AUTH = "WebAuthentication";
     public static final String WEB_PAYMENTS = "WebPayments";
+    public static final String WEB_PAYMENTS_ALWAYS_ALLOW_JUST_IN_TIME_PAYMENT_APP =
+            "AlwaysAllowJustInTimePaymentApp";
     public static final String WEB_PAYMENTS_EXPERIMENTAL_FEATURES =
             "WebPaymentsExperimentalFeatures";
     public static final String WEB_PAYMENTS_METHOD_SECTION_ORDER_V2 =
             "WebPaymentsMethodSectionOrderV2";
     public static final String WEB_PAYMENTS_MODIFIERS = "WebPaymentsModifiers";
+    public static final String WEB_PAYMENTS_REDACT_SHIPPING_ADDRESS =
+            "WebPaymentsRedactShippingAddress";
     public static final String WEB_PAYMENTS_RETURN_GOOGLE_PAY_IN_BASIC_CARD =
             "ReturnGooglePayInBasicCard";
     public static final String WEB_PAYMENTS_SINGLE_APP_UI_SKIP = "WebPaymentsSingleAppUiSkip";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 52eff60..9fe3d479 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -135,7 +135,6 @@
 import org.chromium.chrome.browser.tasks.JourneyManager;
 import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
 import org.chromium.chrome.browser.tasks.TasksUma;
-import org.chromium.chrome.browser.tasks.tab_management.GridTabSwitcher;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarButtonInProductHelpController;
@@ -149,6 +148,7 @@
 import org.chromium.chrome.browser.util.UrlConstants;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
 import org.chromium.chrome.browser.widget.OverviewListLayout;
+import org.chromium.chrome.features.start_surface.StartSurface;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.FeatureConstants;
 import org.chromium.components.feature_engagement.Tracker;
@@ -676,18 +676,17 @@
             if (isTablet()) {
                 mLayoutManager = new LayoutManagerChromeTablet(compositorViewHolder);
             } else {
-                GridTabSwitcher gridTabSwitcher = null;
+                StartSurface startSurface = null;
 
                 if (FeatureUtilities.isGridTabSwitcherEnabled()) {
                     TabManagementDelegate tabManagementDelegate =
                             TabManagementModuleProvider.getDelegate();
                     if (tabManagementDelegate != null) {
-                        gridTabSwitcher = tabManagementDelegate.createGridTabSwitcher(this);
+                        startSurface = tabManagementDelegate.createStartSurface(this);
                     }
                 }
 
-                mLayoutManager =
-                        new LayoutManagerChromePhone(compositorViewHolder, gridTabSwitcher);
+                mLayoutManager = new LayoutManagerChromePhone(compositorViewHolder, startSurface);
             }
             mLayoutManager.setEnableAnimations(DeviceClassManager.enableAnimations());
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
index 4b579ec..5244967d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -30,13 +30,13 @@
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.browser.tasks.tab_management.GridTabSwitcher;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate;
 import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider;
 import org.chromium.chrome.browser.toolbar.ToolbarManager;
 import org.chromium.chrome.browser.util.AccessibilityUtil;
 import org.chromium.chrome.browser.util.FeatureUtilities;
 import org.chromium.chrome.browser.widget.OverviewListLayout;
+import org.chromium.chrome.features.start_surface.StartSurface;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 
 import java.util.List;
@@ -68,12 +68,12 @@
 
     /**
      * Creates the {@link LayoutManagerChrome} instance.
-     * @param host                 A {@link LayoutManagerHost} instance.
-     * @param gridTabSwitcher An interface to talk to the Grid Tab Switcher. If it's NULL, VTS
-     *                        should be used, otherwise GTS should be used.
+     * @param host         A {@link LayoutManagerHost} instance.
+     * @param startSurface An interface to talk to the Grid Tab Switcher. If it's NULL, VTS
+     *                     should be used, otherwise GTS should be used.
      */
     public LayoutManagerChrome(LayoutManagerHost host, boolean createOverviewLayout,
-            @Nullable GridTabSwitcher gridTabSwitcher) {
+            @Nullable StartSurface startSurface) {
         super(host);
         Context context = host.getContext();
         LayoutRenderHost renderHost = host.getLayoutRenderHost();
@@ -87,13 +87,13 @@
         mOverviewListLayout = new OverviewListLayout(context, this, renderHost);
         mToolbarSwipeLayout = new ToolbarSwipeLayout(context, this, renderHost);
         if (createOverviewLayout) {
-            if (gridTabSwitcher != null) {
+            if (startSurface != null) {
                 assert FeatureUtilities.isGridTabSwitcherEnabled();
                 TabManagementDelegate tabManagementDelegate =
                         TabManagementModuleProvider.getDelegate();
                 assert tabManagementDelegate != null;
-                mOverviewLayout = tabManagementDelegate.createGTSLayout(
-                        context, this, renderHost, gridTabSwitcher);
+                mOverviewLayout = tabManagementDelegate.createStartSurfaceLayout(
+                        context, this, renderHost, startSurface);
             } else {
                 mOverviewLayout = new StackLayout(context, this, renderHost);
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
index 5ad6eee1..58aa1716 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromePhone.java
@@ -17,7 +17,7 @@
 import org.chromium.chrome.browser.tabmodel.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.chrome.browser.tasks.tab_management.GridTabSwitcher;
+import org.chromium.chrome.features.start_surface.StartSurface;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 
 /**
@@ -30,12 +30,12 @@
 
     /**
      * Creates an instance of a {@link LayoutManagerChromePhone}.
-     * @param host                A {@link LayoutManagerHost} instance.
-     * @param gridTabSwitcher An interface to talk to the Grid Tab Switcher. If it's NULL, VTS
-     *                        should be used, otherwise GTS should be used.
+     * @param host         A {@link LayoutManagerHost} instance.
+     * @param startSurface An interface to talk to the Grid Tab Switcher. If it's NULL, VTS
+     *                     should be used, otherwise GTS should be used.
      */
-    public LayoutManagerChromePhone(LayoutManagerHost host, GridTabSwitcher gridTabSwitcher) {
-        super(host, true, gridTabSwitcher);
+    public LayoutManagerChromePhone(LayoutManagerHost host, StartSurface startSurface) {
+        super(host, true, startSurface);
         Context context = host.getContext();
         LayoutRenderHost renderHost = host.getLayoutRenderHost();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java
index dec558b..f93a455 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadDirectoryProvider.java
@@ -10,6 +10,7 @@
 import android.content.IntentFilter;
 import android.os.Build;
 import android.os.Environment;
+import android.text.TextUtils;
 
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
@@ -257,6 +258,20 @@
         return downloadDir;
     }
 
+    /**
+     * Returns whether the downloaded file path is on an external SD card.
+     * @param filePath The download file path.
+     */
+    public static boolean isDownloadOnSDCard(String filePath) {
+        File[] dirs = ContextUtils.getApplicationContext().getExternalFilesDirs(
+                Environment.DIRECTORY_DOWNLOADS);
+        if (dirs.length <= 1 || TextUtils.isEmpty(filePath)) return false;
+        for (int i = 1; i < dirs.length; ++i) {
+            if (filePath.startsWith(dirs[i].getAbsolutePath())) return true;
+        }
+        return false;
+    }
+
     private void updateDirectories() {
         // If asynchronous task is pending, wait for its result.
         if (mAllDirectoriesTask != null) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
index f1c56269..9760415 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadManagerService.java
@@ -818,7 +818,7 @@
 
         Uri contentUri = filePath == null ? queryResult.contentUri
                                           : DownloadUtils.getUriForOtherApps(filePath);
-        if (contentUri == null) return null;
+        if (contentUri == null || Uri.EMPTY.equals(contentUri)) return null;
 
         Uri fileUri = filePath == null ? contentUri : Uri.fromFile(new File(filePath));
         return createLaunchIntent(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
index a9ac017..947155a3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -585,9 +585,7 @@
         Uri uri = null;
 
         try {
-            File primaryDir = DownloadDirectoryProvider.getPrimaryDownloadDirectory();
-            boolean isOnSDCard = !TextUtils.isEmpty(filePath)
-                    && !filePath.contains(primaryDir.getAbsolutePath());
+            boolean isOnSDCard = DownloadDirectoryProvider.isDownloadOnSDCard(filePath);
             if (ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOAD_FILE_PROVIDER)
                     && isOnSDCard) {
                 // Use custom file provider to generate content URI for download on SD card.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index b9fa3458..afbe97f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -540,9 +540,12 @@
                 AutofillPaymentApp.merchantSupportsAutofillPaymentInstruments(mMethodData);
         mUserCanAddCreditCard = mMerchantSupportsAutofillPaymentInstruments
                 && !ChromeFeatureList.isEnabled(ChromeFeatureList.NO_CREDIT_CARD_ABORT);
+
+        boolean mayCrawl = !mUserCanAddCreditCard
+                || PaymentsExperimentalFeatures.isEnabled(
+                        ChromeFeatureList.WEB_PAYMENTS_ALWAYS_ALLOW_JUST_IN_TIME_PAYMENT_APP);
         PaymentAppFactory.getInstance().create(mWebContents,
-                Collections.unmodifiableMap(mMethodData), !mUserCanAddCreditCard /* mayCrawl */,
-                this /* callback */);
+                Collections.unmodifiableMap(mMethodData), mayCrawl, this /* callback */);
 
         // Log the various types of payment methods that were requested by the merchant.
         boolean requestedMethodGoogle = false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java
index 9022891..ba0ceee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SignOutDialogFragment.java
@@ -121,7 +121,7 @@
                         "Signin.UserRequestedWipeDataOnSignout", mWipeUserData.isChecked());
             }
             SignOutDialogListener targetFragment = (SignOutDialogListener) getTargetFragment();
-            targetFragment.onSignOutClicked(mWipeUserData.isChecked());
+            targetFragment.onSignOutClicked(mWipeUserData != null && mWipeUserData.isChecked());
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java
index e42e5d3..019fd3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninActivity.java
@@ -11,8 +11,12 @@
 import android.support.v4.app.Fragment;
 import android.support.v4.app.FragmentManager;
 
+import org.chromium.base.Log;
+import org.chromium.base.library_loader.ProcessInitException;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.SynchronousInitializationActivity;
+import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeBaseAppCompatActivity;
+import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
 
 import java.lang.annotation.Retention;
@@ -22,7 +26,7 @@
  * Allows user to pick an account and sign in. Started from Settings and various sign-in promos.
  */
 // TODO(https://crbug.com/820491): extend AsyncInitializationActivity.
-public class SigninActivity extends SynchronousInitializationActivity {
+public class SigninActivity extends ChromeBaseAppCompatActivity {
     private static final String TAG = "SigninActivity";
     private static final String ARGUMENT_FRAGMENT_ARGS = "SigninActivity.FragmentArgs";
 
@@ -101,6 +105,15 @@
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+        // Make sure the native is initialized before calling super.onCreate(), as it might recreate
+        // SigninFragment that currently depends on native. See https://crbug.com/983730.
+        try {
+            ChromeBrowserInitializer.getInstance().handleSynchronousStartup();
+        } catch (ProcessInitException e) {
+            Log.e(TAG, "Failed to start browser process.", e);
+            ChromeApplication.reportStartupErrorAndExit(e);
+        }
+
         super.onCreate(savedInstanceState);
         setContentView(R.layout.signin_activity);
 
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index a1b751d..d65826c 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -7,6 +7,8 @@
 import("//chrome/android/chrome_junit_test_java_sources.gni")
 import("//chrome/android/chrome_test_java_sources.gni")
 import("//chrome/android/features/autofill_assistant/public/java_sources.gni")
+import(
+    "//chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni")
 import("//chrome/android/features/tab_ui/tab_management_java_sources.gni")
 import("//chrome/android/feed/feed_java_sources.gni")
 import("//chrome/android/touchless/touchless_java_sources.gni")
@@ -39,6 +41,7 @@
   chrome_test_java_sources += feed_test_java_sources
 }
 
+chrome_test_java_sources += start_surface_test_java_sources
 chrome_junit_test_java_sources += tab_management_junit_java_sources
 chrome_test_java_sources += tab_management_test_java_sources
 
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index d6de96d..8e21f915 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1892,7 +1892,6 @@
     "//chrome/common:channel_info",
     "//chrome/common/net",
     "//chrome/installer/util:with_no_strings",
-    "//components/about_handler",
     "//components/app_modal",
     "//components/assist_ranker",
     "//components/autofill/content/browser",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 924a2a9..6be5e92 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -22,7 +22,6 @@
   "+chrome/services/util_win/public",
   "+chrome/services/wifi_util_win/public",
   "+chromeos",
-  "+components/about_handler",
   "+components/about_ui",
   "+components/account_id",
   "+components/app_modal",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b60c247..433184a 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1547,6 +1547,9 @@
      flag_descriptions::kOnlyNewPasswordFormParsingName,
      flag_descriptions::kOnlyNewPasswordFormParsingDescription, kOsAll,
      FEATURE_VALUE_TYPE(password_manager::features::kOnlyNewParser)},
+    {"username-first-flow", flag_descriptions::kUsernameFirstFlowName,
+     flag_descriptions::kUsernameFirstFlowDescription, kOsAll,
+     FEATURE_VALUE_TYPE(password_manager::features::kUsernameFirstFlow)},
     {"enable-show-autofill-signatures",
      flag_descriptions::kShowAutofillSignaturesName,
      flag_descriptions::kShowAutofillSignaturesDescription, kOsAll,
@@ -3047,6 +3050,11 @@
          autofill::features::kAutofillRestrictUnownedFieldsToFormlessCheckout)},
 
 #if defined(OS_ANDROID)
+    {"enable-two-panes-start-surface",
+     flag_descriptions::kTwoPanesStartSurfaceAndroidName,
+     flag_descriptions::kTwoPanesStartSurfaceAndroidDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kTwoPanesStartSurfaceAndroid)},
+
     {"enable-horizontal-tab-switcher",
      flag_descriptions::kHorizontalTabSwitcherAndroidName,
      flag_descriptions::kHorizontalTabSwitcherAndroidDescription, kOsAndroid,
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc
index 33279230..1b32285 100644
--- a/chrome/browser/android/chrome_feature_list.cc
+++ b/chrome/browser/android/chrome_feature_list.cc
@@ -179,12 +179,14 @@
     &kTrustedWebActivity,
     &kTrustedWebActivityPostMessage,
     &kTrustedWebActivityNotificationDelegationEnrolment,
+    &kTwoPanesStartSurfaceAndroid,
     &kUmaBackgroundSessions,
     &kUsageStatsFeature,
     &kVideoPersistence,
     &kVrBrowsingFeedback,
     &kOfferWipeDataOnSignout,
     &network::features::kNetworkService,
+    &payments::features::kAlwaysAllowJustInTimePaymentApp,
     &payments::features::kReturnGooglePayInBasicCard,
     &payments::features::kWebPaymentsExperimentalFeatures,
     &payments::features::kWebPaymentsMethodSectionOrderV2,
@@ -556,6 +558,9 @@
     "TrustedWebActivityNotificationDelegationAutoEnrolment",
     base::FEATURE_ENABLED_BY_DEFAULT};
 
+const base::Feature kTwoPanesStartSurfaceAndroid{
+    "TwoPanesStartSurfaceAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // If enabled, keep logging and reporting UMA while chrome is backgrounded.
 const base::Feature kUmaBackgroundSessions{"UMABackgroundSessions",
                                            base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/android/chrome_feature_list.h b/chrome/browser/android/chrome_feature_list.h
index dfba3c2..87650529 100644
--- a/chrome/browser/android/chrome_feature_list.h
+++ b/chrome/browser/android/chrome_feature_list.h
@@ -117,6 +117,7 @@
 extern const base::Feature kTrustedWebActivity;
 extern const base::Feature kTrustedWebActivityPostMessage;
 extern const base::Feature kTrustedWebActivityNotificationDelegationEnrolment;
+extern const base::Feature kTwoPanesStartSurfaceAndroid;
 extern const base::Feature kUmaBackgroundSessions;
 extern const base::Feature kUsageStatsFeature;
 extern const base::Feature kUserMediaScreenCapturing;
diff --git a/chrome/browser/autofill/autofill_keyboard_accessory_adapter.cc b/chrome/browser/autofill/autofill_keyboard_accessory_adapter.cc
index 339addef..4caa854 100644
--- a/chrome/browser/autofill/autofill_keyboard_accessory_adapter.cc
+++ b/chrome/browser/autofill/autofill_keyboard_accessory_adapter.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/memory/weak_ptr.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
 #include "chrome/browser/ui/autofill/autofill_popup_layout_model.h"
 #include "components/autofill/core/browser/ui/popup_item_ids.h"
@@ -18,22 +17,6 @@
 
 namespace autofill {
 
-constexpr base::char16 kLabelSeparator = ' ';
-constexpr size_t kMaxBulletCount = 8;
-
-namespace {
-base::string16 CreateLabel(const Suggestion& suggestion) {
-  base::string16 password =
-      suggestion.additional_label.substr(0, kMaxBulletCount);
-  // The label contains the signon_realm or is empty. The additional_label can
-  // never be empty since it must contain a password.
-  if (suggestion.label.empty())
-    return password;
-  return suggestion.label + kLabelSeparator + password;
-}
-
-}  // namespace
-
 AutofillKeyboardAccessoryAdapter::AutofillKeyboardAccessoryAdapter(
     AutofillPopupController* controller,
     unsigned int animation_duration_millis,
@@ -66,15 +49,12 @@
   DCHECK(controller_) << "Call OnSuggestionsChanged only from its owner!";
   DCHECK(view_) << "OnSuggestionsChanged called before a View was set!";
 
-  labels_.clear();
   front_element_ = base::nullopt;
   for (int i = 0; i < GetLineCount(); ++i) {
     const Suggestion& suggestion = controller_->GetSuggestionAt(i);
     if (suggestion.frontend_id != POPUP_ITEM_ID_CLEAR_FORM &&
-        suggestion.frontend_id != POPUP_ITEM_ID_CREATE_HINT) {
-      labels_.push_back(CreateLabel(suggestion));
+        suggestion.frontend_id != POPUP_ITEM_ID_CREATE_HINT)
       continue;
-    }
     DCHECK(!front_element_.has_value()) << "Additional front item at: " << i;
     front_element_ = base::Optional<int>(i);
   }
@@ -108,7 +88,11 @@
 const base::string16& AutofillKeyboardAccessoryAdapter::GetElidedLabelAt(
     int row) const {
   DCHECK(controller_) << "Call OnSuggestionsChanged only from its owner!";
-  return labels_[row];
+  const base::string16& label =
+      controller_->GetElidedLabelAt(OffsetIndexFor(row));
+  if (label.empty())
+    return GetSuggestionAt(row).additional_label;
+  return label;
 }
 
 bool AutofillKeyboardAccessoryAdapter::GetRemovalConfirmationText(
diff --git a/chrome/browser/autofill/autofill_keyboard_accessory_adapter.h b/chrome/browser/autofill/autofill_keyboard_accessory_adapter.h
index c8b597d4..8ad5806 100644
--- a/chrome/browser/autofill/autofill_keyboard_accessory_adapter.h
+++ b/chrome/browser/autofill/autofill_keyboard_accessory_adapter.h
@@ -100,9 +100,6 @@
   AutofillPopupController* controller_;  // weak.
   std::unique_ptr<AutofillKeyboardAccessoryAdapter::AccessoryView> view_;
 
-  // The labels to be used for the input chips.
-  std::vector<base::string16> labels_;
-
   // If 0, don't animate suggestion view.
   const unsigned int animation_duration_millis_;
 
diff --git a/chrome/browser/autofill/autofill_keyboard_accessory_adapter_unittest.cc b/chrome/browser/autofill/autofill_keyboard_accessory_adapter_unittest.cc
index cb78884..12ef283 100644
--- a/chrome/browser/autofill/autofill_keyboard_accessory_adapter_unittest.cc
+++ b/chrome/browser/autofill/autofill_keyboard_accessory_adapter_unittest.cc
@@ -5,7 +5,6 @@
 #include <cstddef>
 
 #include <memory>
-#include <string>
 #include <utility>
 #include <vector>
 
@@ -52,20 +51,13 @@
   DISALLOW_COPY_AND_ASSIGN(MockAccessoryView);
 };
 
-Suggestion createPasswordEntry(std::string password,
-                               std::string username,
-                               std::string psl_origin) {
-  Suggestion s(/*value=*/username, /*label=*/psl_origin, /*icon=*/"",
-               PopupItemId::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY);
-  s.additional_label = ASCIIToUTF16(password);
-  return s;
-}
-
 std::vector<Suggestion> createSuggestions() {
   std::vector<Suggestion> suggestions = {
-      createPasswordEntry("****************", "Alf", ""),
-      createPasswordEntry("****************", "Berta", "psl.origin.eg"),
-      createPasswordEntry("***", "Carl", "")};
+      Suggestion("*", "A", "", PopupItemId::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY),
+      Suggestion("**", "", "", PopupItemId::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY),
+      Suggestion("***", "C", "",
+                 PopupItemId::POPUP_ITEM_ID_AUTOCOMPLETE_ENTRY)};
+  suggestions[1].additional_label = ASCIIToUTF16("B");
   return suggestions;
 }
 
@@ -182,19 +174,14 @@
 }
 
 TEST_F(AutofillKeyboardAccessoryAdapterTest, UseAdditionalLabelForElidedLabel) {
-  controller()->set_suggestions(createSuggestions(/*clearItemOffset=*/1));
+  controller()->set_suggestions(createSuggestions());
   NotifyAboutSuggestions();
 
-  // If there is a label, use it but cap at 8 bullets.
-  EXPECT_EQ(adapter_as_controller()->GetElidedLabelAt(0),
-            ASCIIToUTF16("********"));
+  // If there is a label, use it.
+  EXPECT_EQ(adapter_as_controller()->GetElidedLabelAt(0), ASCIIToUTF16("A"));
 
   // If the label is empty, use the additional label:
-  EXPECT_EQ(adapter_as_controller()->GetElidedLabelAt(1),
-            ASCIIToUTF16("psl.origin.eg ********"));
-
-  // If the password has less than 8 bullets, show the exact amount.
-  EXPECT_EQ(adapter_as_controller()->GetElidedLabelAt(2), ASCIIToUTF16("***"));
+  EXPECT_EQ(adapter_as_controller()->GetElidedLabelAt(1), ASCIIToUTF16("B"));
 }
 
 TEST_F(AutofillKeyboardAccessoryAdapterTest, ProvideReorderedSuggestions) {
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index b75261a..51ff368 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -1102,6 +1102,11 @@
       std::make_unique<SecureOriginPrefsObserver>(local_state());
   site_isolation_prefs_observer_ =
       std::make_unique<SiteIsolationPrefsObserver>(local_state());
+
+  // Create SystemNetworkContextManager without a NetworkService if it has not
+  // been requested yet.
+  if (!SystemNetworkContextManager::HasInstance())
+    SystemNetworkContextManager::CreateInstance(local_state());
 }
 
 void BrowserProcessImpl::PreMainMessageLoopRun() {
diff --git a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
index 047af7f..5231a88 100644
--- a/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
+++ b/chrome/browser/browsing_data/browsing_data_remover_browsertest.cc
@@ -290,10 +290,7 @@
  public:
   BrowsingDataRemoverBrowserTest() {
     std::vector<base::Feature> enabled_features = {
-        leveldb::kLevelDBRewriteFeature,
-        // Ensure that kOnionSoupDOMStorage is enabled because the old
-        // SessionStorage implementation causes flaky tests.
-        blink::features::kOnionSoupDOMStorage};
+        leveldb::kLevelDBRewriteFeature};
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
     enabled_features.push_back(media::kExternalClearKeyForTesting);
 #endif
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 3c7bc53..21c9bba 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -1641,6 +1641,15 @@
 #endif
 }
 
+bool ChromeContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+    base::StringPiece scheme) {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  return scheme == extensions::kExtensionScheme;
+#else
+  return false;
+#endif
+}
+
 network::mojom::URLLoaderFactoryPtrInfo
 ChromeContentBrowserClient::CreateURLLoaderFactoryForNetworkRequests(
     content::RenderProcessHost* process,
@@ -5513,7 +5522,7 @@
 
 base::Optional<std::string>
 ChromeContentBrowserClient::GetOriginPolicyErrorPage(
-    content::OriginPolicyErrorReason error_reason,
+    network::OriginPolicyState error_reason,
     content::NavigationHandle* handle) {
   return security_interstitials::OriginPolicyUI::GetErrorPageAsHTML(
       error_reason, handle);
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index c13bbb3..09412248 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -151,6 +151,8 @@
   bool ShouldLockToOrigin(content::BrowserContext* browser_context,
                           const GURL& effective_site_url) override;
   const char* GetInitiatorSchemeBypassingDocumentBlocking() override;
+  bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+      base::StringPiece scheme) override;
   network::mojom::URLLoaderFactoryPtrInfo
   CreateURLLoaderFactoryForNetworkRequests(
       content::RenderProcessHost* process,
@@ -570,7 +572,7 @@
       content::BrowserContext* browser_context,
       blink::mojom::RendererPreferenceWatcherPtr watcher) override;
   base::Optional<std::string> GetOriginPolicyErrorPage(
-      content::OriginPolicyErrorReason error_reason,
+      network::OriginPolicyState error_reason,
       content::NavigationHandle* handle) override;
   bool CanIgnoreCertificateErrorIfNeeded() override;
   void OnNetworkServiceDataUseUpdate(int32_t network_traffic_annotation_id_hash,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 689a782..8a8c907 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1136,6 +1136,8 @@
     "login/auth/chrome_cryptohome_authenticator.h",
     "login/auth/chrome_login_performer.cc",
     "login/auth/chrome_login_performer.h",
+    "login/challenge_response_auth_keys_loader.cc",
+    "login/challenge_response_auth_keys_loader.h",
     "login/chrome_restart_request.cc",
     "login/chrome_restart_request.h",
     "login/configuration_keys.cc",
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
index cdc46dd2..0578946 100644
--- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
+++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -119,6 +119,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/task_manager/task_manager_interface.h"
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
+#include "chrome/browser/ui/ash/wallpaper_controller_client.h"
 #include "chrome/browser/ui/webui/chromeos/login/discover/discover_manager.h"
 #include "chrome/browser/upgrade_detector/upgrade_detector_chromeos.h"
 #include "chrome/common/channel_info.h"
@@ -971,6 +972,9 @@
   g_browser_process->platform_part()->session_manager()->Initialize(
       parsed_command_line(), profile(), is_running_test);
 
+  // This step requires the session manager to have been initialized.
+  WallpaperControllerClient::Get()->SetInitialWallpaper();
+
   // Guest user profile is never initialized with locale settings,
   // so we need special handling for Guest session.
   if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
index 388211c..75b155be 100644
--- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
+++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc
@@ -271,7 +271,9 @@
     profile_.reset(new TestingProfile);
     OwnerSettingsServiceChromeOSFactory::GetInstance()
         ->SetOwnerKeyUtilForTesting(owner_key_util_);
-    user_context_.SetKey(Key("fakepass"));
+    Key key("fakepass");
+    key.SetLabel(kCryptohomeGAIAKeyLabel);
+    user_context_.SetKey(key);
     user_context_.SetUserIDHash("me_nowhere_com_hash");
     const user_manager::User* user =
         user_manager_->AddUser(user_context_.GetAccountId());
diff --git a/chrome/browser/chromeos/login/challenge_response_auth_keys_loader.cc b/chrome/browser/chromeos/login/challenge_response_auth_keys_loader.cc
new file mode 100644
index 0000000..e0045c3
--- /dev/null
+++ b/chrome/browser/chromeos/login/challenge_response_auth_keys_loader.cc
@@ -0,0 +1,136 @@
+// 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 "chrome/browser/chromeos/login/challenge_response_auth_keys_loader.h"
+
+#include <cstdint>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/optional.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/certificate_provider/certificate_provider.h"
+#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h"
+#include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chromeos/login/auth/challenge_response/cert_utils.h"
+#include "chromeos/login/auth/challenge_response/known_user_pref_utils.h"
+#include "components/account_id/account_id.h"
+#include "components/user_manager/known_user.h"
+
+namespace chromeos {
+
+namespace {
+
+// Loads the persistently stored information about the challenge-response keys
+// that can be used for authenticating the user.
+std::vector<std::string> LoadStoredChallengeResponseSpkiKeysForUser(
+    const AccountId& account_id) {
+  const base::Value known_user_value =
+      user_manager::known_user::GetChallengeResponseKeys(account_id);
+  std::vector<std::string> spki_items;
+  if (!DeserializeChallengeResponseKeysFromKnownUser(known_user_value,
+                                                     &spki_items)) {
+    return {};
+  }
+  return spki_items;
+}
+
+// Returns the certificate provider service that should be used for querying the
+// currently available cryptographic keys.
+// The sign-in profile is used since it's where the needed extensions are
+// installed (e.g., for the smart card based login they are force-installed via
+// the DeviceLoginScreenExtensions admin policy).
+CertificateProviderService* GetCertificateProviderService() {
+  return CertificateProviderServiceFactory::GetForBrowserContext(
+      ProfileHelper::GetSigninProfile());
+}
+
+// Maps from the TLS 1.3 SignatureScheme values into the challenge-response key
+// algorithm list.
+std::vector<ChallengeResponseKey::SignatureAlgorithm> MakeAlgorithmListFromSsl(
+    const std::vector<uint16_t>& ssl_algorithms) {
+  std::vector<ChallengeResponseKey::SignatureAlgorithm>
+      challenge_response_algorithms;
+  for (auto ssl_algorithm : ssl_algorithms) {
+    base::Optional<ChallengeResponseKey::SignatureAlgorithm> algorithm =
+        GetChallengeResponseKeyAlgorithmFromSsl(ssl_algorithm);
+    if (algorithm)
+      challenge_response_algorithms.push_back(*algorithm);
+  }
+  return challenge_response_algorithms;
+}
+
+}  // namespace
+
+// static
+bool ChallengeResponseAuthKeysLoader::CanAuthenticateUser(
+    const AccountId& account_id) {
+  return !LoadStoredChallengeResponseSpkiKeysForUser(account_id).empty();
+}
+
+ChallengeResponseAuthKeysLoader::ChallengeResponseAuthKeysLoader() = default;
+
+ChallengeResponseAuthKeysLoader::~ChallengeResponseAuthKeysLoader() = default;
+
+void ChallengeResponseAuthKeysLoader::LoadAvailableKeys(
+    const AccountId& account_id,
+    LoadAvailableKeysCallback callback) {
+  // Load the list of public keys of the cryptographic keys that can be used for
+  // authenticating the user.
+  std::vector<std::string> suitable_public_key_spki_items =
+      LoadStoredChallengeResponseSpkiKeysForUser(account_id);
+  if (suitable_public_key_spki_items.empty()) {
+    // This user's profile doesn't support challenge-response authentication.
+    std::move(callback).Run({} /* challenge_response_keys */);
+    return;
+  }
+
+  // Asynchronously poll all certificate providers to get the list of currently
+  // available cryptographic keys.
+  std::unique_ptr<CertificateProvider> cert_provider =
+      GetCertificateProviderService()->CreateCertificateProvider();
+  cert_provider->GetCertificates(base::BindOnce(
+      &ChallengeResponseAuthKeysLoader::ContinueLoadAvailableKeysWithCerts,
+      weak_ptr_factory_.GetWeakPtr(), account_id,
+      std::move(suitable_public_key_spki_items), std::move(callback)));
+}
+
+void ChallengeResponseAuthKeysLoader::ContinueLoadAvailableKeysWithCerts(
+    const AccountId& account_id,
+    const std::vector<std::string>& suitable_public_key_spki_items,
+    LoadAvailableKeysCallback callback,
+    net::ClientCertIdentityList /* cert_identities */) {
+  CertificateProviderService* const cert_provider_service =
+      GetCertificateProviderService();
+  std::vector<ChallengeResponseKey> filtered_keys;
+  // Filter those of the currently available cryptographic keys that can be used
+  // for authenticating the user. Also fill out for the selected keys the
+  // currently available cryptographic signature algorithms.
+  for (const auto& suitable_spki : suitable_public_key_spki_items) {
+    std::vector<uint16_t> supported_ssl_algorithms;
+    cert_provider_service->GetSupportedAlgorithmsBySpki(
+        suitable_spki, &supported_ssl_algorithms);
+    if (supported_ssl_algorithms.empty()) {
+      // This key is not currently exposed by any certificate provider or,
+      // potentially, is exposed but without supporting any signature algorithm.
+      continue;
+    }
+    std::vector<ChallengeResponseKey::SignatureAlgorithm> supported_algorithms =
+        MakeAlgorithmListFromSsl(supported_ssl_algorithms);
+    if (supported_algorithms.empty()) {
+      // This currently available key doesn't support any of the algorithms that
+      // are supported by the challenge-response user authentication.
+      continue;
+    }
+    ChallengeResponseKey filtered_key;
+    filtered_key.set_public_key_spki_der(suitable_spki);
+    filtered_key.set_signature_algorithms(supported_algorithms);
+    filtered_keys.push_back(filtered_key);
+  }
+  std::move(callback).Run(std::move(filtered_keys));
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/login/challenge_response_auth_keys_loader.h b/chrome/browser/chromeos/login/challenge_response_auth_keys_loader.h
new file mode 100644
index 0000000..cd1d48e
--- /dev/null
+++ b/chrome/browser/chromeos/login/challenge_response_auth_keys_loader.h
@@ -0,0 +1,69 @@
+// 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_BROWSER_CHROMEOS_LOGIN_CHALLENGE_RESPONSE_AUTH_KEYS_LOADER_H_
+#define CHROME_BROWSER_CHROMEOS_LOGIN_CHALLENGE_RESPONSE_AUTH_KEYS_LOADER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "chromeos/login/auth/challenge_response_key.h"
+#include "net/ssl/client_cert_identity.h"
+
+class AccountId;
+
+namespace chromeos {
+
+// This class allows to prepare parameters for the challenge-response
+// authentication.
+//
+// This authentication is based on making challenges against cryptographic
+// key(s). The challenge generation and processing the authentication secrets
+// is performed by the cryptohomed daemon and the underlying layers. The browser
+// is responsible for providing the cryptohomed with the public key information
+// (which is the responsibility of this class) and for forwarding the challenge
+// requests to the component that talks to the cryptographic token (which is the
+// responsibility of CryptohomeKeyDelegateServiceProvider).
+class ChallengeResponseAuthKeysLoader final {
+ public:
+  using LoadAvailableKeysCallback = base::OnceCallback<void(
+      std::vector<ChallengeResponseKey> challenge_response_keys)>;
+
+  // Returns whether the given user, whose profile must already exist on the
+  // device, supports authentication via the challenge-response protocol.
+  static bool CanAuthenticateUser(const AccountId& account_id);
+
+  ChallengeResponseAuthKeysLoader();
+  ~ChallengeResponseAuthKeysLoader();
+
+  // Prepares the ChallengeResponseKey values containing the currently available
+  // cryptographic keys that can be used to authenticate the given user.
+  //
+  // The callback is run with an empty |challenge_response_keys| in the cases
+  // when the user's profile doesn't support challenge-response authentication
+  // or when there's no currently available suitable cryptographic key.
+  void LoadAvailableKeys(const AccountId& account_id,
+                         LoadAvailableKeysCallback callback);
+
+ private:
+  // Asynchronous job which is scheduled by LoadAvailableKeys after the list of
+  // currently available cryptographic keys is refreshed from certificate
+  // providers.
+  void ContinueLoadAvailableKeysWithCerts(
+      const AccountId& account_id,
+      const std::vector<std::string>& suitable_public_key_spki_items,
+      LoadAvailableKeysCallback callback,
+      net::ClientCertIdentityList cert_identities);
+
+  base::WeakPtrFactory<ChallengeResponseAuthKeysLoader> weak_ptr_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(ChallengeResponseAuthKeysLoader);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_LOGIN_CHALLENGE_RESPONSE_AUTH_KEYS_LOADER_H_
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.cc b/chrome/browser/chromeos/login/lock/screen_locker.cc
index 902eb699..6066bcb8 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.cc
+++ b/chrome/browser/chromeos/login/lock/screen_locker.cc
@@ -4,9 +4,6 @@
 
 #include "chrome/browser/chromeos/login/lock/screen_locker.h"
 
-#include <string>
-#include <vector>
-
 #include "ash/public/cpp/ash_switches.h"
 #include "ash/public/cpp/login_screen.h"
 #include "ash/public/cpp/login_screen_model.h"
@@ -354,6 +351,19 @@
   if (user_context.IsUsingPin())
     unlock_attempt_type_ = AUTH_PIN;
 
+  // TODO(crbug.com/826417): Remove this, and instead add a new UI control that
+  // calls ScreenLocker via a separate code path.
+  if (ChallengeResponseAuthKeysLoader::CanAuthenticateUser(
+          user_context.GetAccountId())) {
+    unlock_attempt_type_ = AUTH_CHALLENGE_RESPONSE;
+    challenge_response_auth_keys_loader_.LoadAvailableKeys(
+        user_context.GetAccountId(),
+        base::BindOnce(&ScreenLocker::OnChallengeResponseKeysPrepared,
+                       weak_factory_.GetWeakPtr(), user_context));
+    // OnChallengeResponseKeysPrepared will call ContinueAuthenticate.
+    return;
+  }
+
   const user_manager::User* user = FindUnlockUser(user_context.GetAccountId());
   if (user) {
     // Check to see if the user submitted a PIN and it is valid.
@@ -370,6 +380,21 @@
   ContinueAuthenticate(user_context);
 }
 
+void ScreenLocker::OnChallengeResponseKeysPrepared(
+    const UserContext& user_context,
+    std::vector<ChallengeResponseKey> challenge_response_keys) {
+  if (challenge_response_keys.empty()) {
+    // TODO(crbug.com/826417): Indicate the error in the UI.
+    if (on_auth_complete_)
+      std::move(on_auth_complete_).Run(false /* auth_success */);
+    return;
+  }
+  UserContext new_user_context = user_context;
+  *new_user_context.GetMutableChallengeResponseKeys() =
+      std::move(challenge_response_keys);
+  ContinueAuthenticate(new_user_context);
+}
+
 void ScreenLocker::OnPinAttemptDone(const UserContext& user_context,
                                     bool success) {
   if (success) {
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.h b/chrome/browser/chromeos/login/lock/screen_locker.h
index eeffd73..82fa19a0 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/screen_locker.h
@@ -8,6 +8,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <vector>
 
 #include "ash/public/cpp/login_types.h"
 #include "base/callback_forward.h"
@@ -18,9 +19,11 @@
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/chromeos/login/challenge_response_auth_keys_loader.h"
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/ui/login_display.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
+#include "chromeos/login/auth/challenge_response_key.h"
 #include "chromeos/login/auth/user_context.h"
 #include "components/user_manager/user.h"
 #include "mojo/public/cpp/bindings/binding.h"
@@ -166,10 +169,17 @@
   friend class base::DeleteHelper<ScreenLocker>;
   friend class ViewsScreenLocker;
 
-  // Track whether the user used pin or password to unlock the lock screen.
-  // Values corrospond to UMA histograms, do not modify, or add or delete other
+  // Track the type of the authentication that the user used to unlock the lock
+  // screen.
+  // Values correspond to UMA histograms; do not modify, or add or delete other
   // than directly before AUTH_COUNT.
-  enum UnlockType { AUTH_PASSWORD = 0, AUTH_PIN, AUTH_FINGERPRINT, AUTH_COUNT };
+  enum UnlockType {
+    AUTH_PASSWORD = 0,
+    AUTH_PIN = 1,
+    AUTH_FINGERPRINT = 2,
+    AUTH_CHALLENGE_RESPONSE = 3,
+    AUTH_COUNT
+  };
 
   ~ScreenLocker() override;
 
@@ -192,6 +202,13 @@
   // lock request is failed.
   void OnStartLockCallback(bool locked);
 
+  // Callback to be invoked when the |cert_provider_based_auth_preparer_|
+  // completes building the currently available challenge-response keys. Used
+  // only during the challenge-response unlock.
+  void OnChallengeResponseKeysPrepared(
+      const UserContext& user_context,
+      std::vector<ChallengeResponseKey> challenge_response_keys);
+
   void OnPinAttemptDone(const UserContext& user_context, bool success);
 
   // Called to continue authentication against cryptohome after the pin login
@@ -262,6 +279,8 @@
   // This is used to update fingerprint state when password is required.
   base::OneShotTimer update_fingerprint_state_timer_;
 
+  ChallengeResponseAuthKeysLoader challenge_response_auth_keys_loader_;
+
   base::WeakPtrFactory<ScreenLocker> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(ScreenLocker);
diff --git a/chrome/browser/chromeos/login/login_client_cert_usage_observer.cc b/chrome/browser/chromeos/login/login_client_cert_usage_observer.cc
index 8debad0..5cbe19e 100644
--- a/chrome/browser/chromeos/login/login_client_cert_usage_observer.cc
+++ b/chrome/browser/chromeos/login/login_client_cert_usage_observer.cc
@@ -7,14 +7,15 @@
 #include <cstdint>
 
 #include "base/logging.h"
+#include "base/optional.h"
 #include "base/strings/string_piece.h"
 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service.h"
 #include "chrome/browser/chromeos/certificate_provider/certificate_provider_service_factory.h"
 #include "chrome/browser/chromeos/profiles/profile_helper.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chromeos/login/auth/challenge_response/cert_utils.h"
 #include "net/cert/asn1_util.h"
 #include "net/cert/x509_util.h"
-#include "third_party/boringssl/src/include/openssl/ssl.h"
 
 namespace chromeos {
 
@@ -44,24 +45,10 @@
   }
   signature_algorithms->clear();
   for (auto ssl_algorithm : ssl_algorithms) {
-    switch (ssl_algorithm) {
-      case SSL_SIGN_RSA_PKCS1_SHA1:
-        signature_algorithms->push_back(
-            ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha1);
-        break;
-      case SSL_SIGN_RSA_PKCS1_SHA256:
-        signature_algorithms->push_back(
-            ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha256);
-        break;
-      case SSL_SIGN_RSA_PKCS1_SHA384:
-        signature_algorithms->push_back(
-            ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha384);
-        break;
-      case SSL_SIGN_RSA_PKCS1_SHA512:
-        signature_algorithms->push_back(
-            ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha512);
-        break;
-    }
+    base::Optional<ChallengeResponseKey::SignatureAlgorithm> algorithm =
+        GetChallengeResponseKeyAlgorithmFromSsl(ssl_algorithm);
+    if (algorithm)
+      signature_algorithms->push_back(*algorithm);
   }
   return !signature_algorithms->empty();
 }
diff --git a/chrome/browser/chromeos/policy/device_local_account.cc b/chrome/browser/chromeos/policy/device_local_account.cc
index c8064c2..cac7b9c4 100644
--- a/chrome/browser/chromeos/policy/device_local_account.cc
+++ b/chrome/browser/chromeos/policy/device_local_account.cc
@@ -29,6 +29,7 @@
 const char kPublicAccountDomainPrefix[] = "public-accounts";
 const char kKioskAppAccountDomainPrefix[] = "kiosk-apps";
 const char kArcKioskAppAccountDomainPrefix[] = "arc-kiosk-apps";
+const char kSAMLPublicAccountDomainPrefix[] = "saml-public-accounts";
 const char kDeviceLocalAccountDomainSuffix[] = ".device-local.localhost";
 
 }  // namespace
@@ -94,6 +95,9 @@
     case DeviceLocalAccount::TYPE_ARC_KIOSK_APP:
       domain_prefix = kArcKioskAppAccountDomainPrefix;
       break;
+    case DeviceLocalAccount::TYPE_SAML_PUBLIC_SESSION:
+      domain_prefix = kSAMLPublicAccountDomainPrefix;
+      break;
     case DeviceLocalAccount::TYPE_COUNT:
       NOTREACHED();
       break;
@@ -132,6 +136,11 @@
       *type = DeviceLocalAccount::TYPE_ARC_KIOSK_APP;
     return true;
   }
+  if (domain_prefix == kSAMLPublicAccountDomainPrefix) {
+    if (type)
+      *type = DeviceLocalAccount::TYPE_SAML_PUBLIC_SESSION;
+    return true;
+  }
 
   // |user_id| is a device-local account but its type is not recognized.
   NOTREACHED();
@@ -142,6 +151,7 @@
 
 void SetDeviceLocalAccounts(chromeos::OwnerSettingsServiceChromeOS* service,
                             const std::vector<DeviceLocalAccount>& accounts) {
+  // TODO(https://crbug.com/984021): handle TYPE_SAML_PUBLIC_SESSION
   base::ListValue list;
   for (std::vector<DeviceLocalAccount>::const_iterator it = accounts.begin();
        it != accounts.end(); ++it) {
@@ -186,6 +196,7 @@
 
 std::vector<DeviceLocalAccount> GetDeviceLocalAccounts(
     chromeos::CrosSettings* cros_settings) {
+  // TODO(https://crbug.com/984021): handle TYPE_SAML_PUBLIC_SESSION
   std::vector<DeviceLocalAccount> accounts;
 
   const base::ListValue* list = NULL;
diff --git a/chrome/browser/chromeos/policy/device_local_account.h b/chrome/browser/chromeos/policy/device_local_account.h
index bc7b59adf..9f9ca486 100644
--- a/chrome/browser/chromeos/policy/device_local_account.h
+++ b/chrome/browser/chromeos/policy/device_local_account.h
@@ -49,6 +49,8 @@
     // An account that serves as a container for a single full-screen
     // Android app.
     TYPE_ARC_KIOSK_APP,
+    // SAML public session account
+    TYPE_SAML_PUBLIC_SESSION,
     // Sentinel, must be last.
     TYPE_COUNT
   };
diff --git a/chrome/browser/chromeos/policy/device_scheduled_update_checker_unittest.cc b/chrome/browser/chromeos/policy/device_scheduled_update_checker_unittest.cc
index 603fd16..eca146b 100644
--- a/chrome/browser/chromeos/policy/device_scheduled_update_checker_unittest.cc
+++ b/chrome/browser/chromeos/policy/device_scheduled_update_checker_unittest.cc
@@ -172,7 +172,8 @@
  protected:
   DeviceScheduledUpdateCheckerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME) {
+            base::test::ScopedTaskEnvironment::MainThreadType::IO,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
     auto fake_update_engine_client =
         std::make_unique<chromeos::FakeUpdateEngineClient>();
     fake_update_engine_client_ = fake_update_engine_client.get();
diff --git a/chrome/browser/chromeos/policy/external_data_handlers/device_wilco_dtc_configuration_external_data_handler.cc b/chrome/browser/chromeos/policy/external_data_handlers/device_wilco_dtc_configuration_external_data_handler.cc
index 0403f9fb..4b137e7 100644
--- a/chrome/browser/chromeos/policy/external_data_handlers/device_wilco_dtc_configuration_external_data_handler.cc
+++ b/chrome/browser/chromeos/policy/external_data_handlers/device_wilco_dtc_configuration_external_data_handler.cc
@@ -34,14 +34,18 @@
 
 void DeviceWilcoDtcConfigurationExternalDataHandler::
     OnDeviceExternalDataCleared(const std::string& policy) {
-  GetWilcoDtcSupportdManager()->SetConfigurationData(nullptr);
+  auto* wilco_manager = GetWilcoDtcSupportdManager();
+  if (wilco_manager)
+    wilco_manager->SetConfigurationData(nullptr);
 }
 
 void DeviceWilcoDtcConfigurationExternalDataHandler::
     OnDeviceExternalDataFetched(const std::string& policy,
                                 std::unique_ptr<std::string> data,
                                 const base::FilePath& file_path) {
-  GetWilcoDtcSupportdManager()->SetConfigurationData(std::move(data));
+  auto* wilco_manager = GetWilcoDtcSupportdManager();
+  if (wilco_manager)
+    wilco_manager->SetConfigurationData(std::move(data));
 }
 
 void DeviceWilcoDtcConfigurationExternalDataHandler::Shutdown() {
diff --git a/chrome/browser/chromeos/policy/system_log_uploader.cc b/chrome/browser/chromeos/policy/system_log_uploader.cc
index 6593fbd..9e06dd7e 100644
--- a/chrome/browser/chromeos/policy/system_log_uploader.cc
+++ b/chrome/browser/chromeos/policy/system_log_uploader.cc
@@ -73,7 +73,6 @@
   if (!temp_dir.CreateUniqueTempDir())
     return compressed_logs;
 
-  std::vector<base::FilePath> file_names;
   for (const auto& syslog_entry : *system_logs) {
     base::FilePath file_path(temp_dir.GetPath().Append(syslog_entry.first));
     base::FilePath relative_path;
@@ -89,19 +88,18 @@
       PLOG(ERROR) << "Can't write log file: " << file_path.value();
       continue;
     }
-    file_names.push_back(relative_path);
   }
   system_logs.reset();
 
-  base::ScopedFILE file(base::CreateAndOpenTemporaryFile(&zip_file));
-  if (!file.get()) {
+  if (!base::CreateTemporaryFile(&zip_file)) {
     PLOG(ERROR) << "Failed to create file to store zipped logs";
     return compressed_logs;
   }
-  if (!zip::ZipFiles(temp_dir.GetPath(), file_names, fileno(file.get()))) {
+  if (!zip::Zip(/*src_dir=*/temp_dir.GetPath(), /*dest_file=*/zip_file,
+                /*include_hidden_files=*/false)) {
     SYSLOG(ERROR) << "Failed to zip system logs";
     return compressed_logs;
-  };
+  }
   if (!base::ReadFileToString(zip_file, &compressed_logs)) {
     PLOG(ERROR) << "Failed to read zipped system logs";
     return compressed_logs;
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
index eb5942e..d407b90 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter_unittest.cc
@@ -131,7 +131,7 @@
  public:
   AdapterTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   ~AdapterTest() override = default;
 
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/als_reader_impl_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/als_reader_impl_unittest.cc
index 0b22575..8066a4c 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/als_reader_impl_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/als_reader_impl_unittest.cc
@@ -56,7 +56,7 @@
   AlsReaderImplTest()
       : scoped_task_environment_(
             std::make_unique<base::test::ScopedTaskEnvironment>(
-                base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME)) {
+                base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME)) {
     CHECK(temp_dir_.CreateUniqueTempDir());
     ambient_light_path_ = temp_dir_.GetPath().Append("test_als");
     als_reader_.SetTaskRunnerForTesting(base::SequencedTaskRunnerHandle::Get());
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc
index de8666f..ad16487 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor_impl_unittest.cc
@@ -71,7 +71,7 @@
  public:
   BrightnessMonitorImplTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   ~BrightnessMonitorImplTest() override {}
 
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/model_config_loader_impl_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/model_config_loader_impl_unittest.cc
index 09c7a73..f66b851 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/model_config_loader_impl_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/model_config_loader_impl_unittest.cc
@@ -56,7 +56,7 @@
  public:
   ModelConfigLoaderImplTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
     CHECK(temp_dir_.CreateUniqueTempDir());
     temp_params_path_ = temp_dir_.GetPath().Append("model_params.json");
   }
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
index 988f99114..3b658a1e 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl_unittest.cc
@@ -163,7 +163,7 @@
  public:
   ModellerImplTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
     CHECK(temp_dir_.CreateUniqueTempDir());
     TestingProfile::Builder profile_builder;
     profile_builder.SetProfileName("testuser@gmail.com");
diff --git a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc
index 701a673..be85c012 100644
--- a/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/adaptive_screen_brightness_manager_unittest.cc
@@ -83,7 +83,8 @@
  public:
   AdaptiveScreenBrightnessManagerTest()
       : ChromeRenderViewHostTestHarness(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME,
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
                 QUEUED) {}
 
diff --git a/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc b/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc
index 16d42a7..0fb267a 100644
--- a/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/idle_event_notifier_unittest.cc
@@ -57,7 +57,7 @@
  public:
   IdleEventNotifierTest()
       : scoped_task_env_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
                 QUEUED) {}
 
diff --git a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
index 97ccaa427..e471312 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
@@ -171,7 +171,8 @@
  public:
   UserActivityManagerTest()
       : ChromeRenderViewHostTestHarness(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME,
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         model_(thread_bundle()->GetMainThreadTaskRunner()) {}
 
diff --git a/chrome/browser/chromeos/system/system_clock.cc b/chrome/browser/chromeos/system/system_clock.cc
index a1b661a..638115a4 100644
--- a/chrome/browser/chromeos/system/system_clock.cc
+++ b/chrome/browser/chromeos/system/system_clock.cc
@@ -163,8 +163,8 @@
 }
 
 bool SystemClock::ShouldUse24HourClock() const {
-  // On login screen and in guest mode owner default is used for
-  // kUse24HourClock preference.
+  // default is used for kUse24HourClock preference on login screen and whenever
+  // set so in user's preference
   const chromeos::LoginState::LoggedInUserType status =
       LoginState::IsInitialized() ? LoginState::Get()->GetLoggedInUserType()
                                   : LoginState::LOGGED_IN_USER_NONE;
@@ -176,21 +176,17 @@
   bool system_use_24_hour_clock = true;
   const bool system_value_found = cros_settings->GetBoolean(
       kSystemUse24HourClock, &system_use_24_hour_clock);
+  const bool default_value =
+      system_value_found ? system_use_24_hour_clock
+                         : (base::GetHourClockType() == base::k24HourClock);
 
-  if ((status == LoginState::LOGGED_IN_USER_NONE) || !user_pref_registrar_) {
-    return (system_value_found
-                ? system_use_24_hour_clock
-                : (base::GetHourClockType() == base::k24HourClock));
-  }
+  if ((status == LoginState::LOGGED_IN_USER_NONE) || !user_pref_registrar_)
+    return default_value;
 
   const PrefService::Preference* user_pref =
       user_pref_registrar_->prefs()->FindPreference(prefs::kUse24HourClock);
-  if (status == LoginState::LOGGED_IN_USER_GUEST &&
-      user_pref->IsDefaultValue()) {
-    return (system_value_found
-                ? system_use_24_hour_clock
-                : (base::GetHourClockType() == base::k24HourClock));
-  }
+  if (status == LoginState::LOGGED_IN_USER_GUEST && user_pref->IsDefaultValue())
+    return default_value;
 
   user_manager::User* active_user =
       user_manager::UserManager::Get()->GetActiveUser();
@@ -201,6 +197,10 @@
           user_profile->GetPrefs()->FindPreference(prefs::kUse24HourClock);
     }
   }
+  if (status != LoginState::LOGGED_IN_USER_REGULAR &&
+      user_pref->IsDefaultValue()) {
+    return default_value;
+  }
 
   bool use_24_hour_clock = true;
   user_pref->GetValue()->GetAsBoolean(&use_24_hour_clock);
diff --git a/chrome/browser/chromeos/tpm_firmware_update_unittest.cc b/chrome/browser/chromeos/tpm_firmware_update_unittest.cc
index cc2a5d2c..5b46a6b 100644
--- a/chrome/browser/chromeos/tpm_firmware_update_unittest.cc
+++ b/chrome/browser/chromeos/tpm_firmware_update_unittest.cc
@@ -119,7 +119,7 @@
   std::unique_ptr<base::ScopedPathOverride> path_override_location_;
   std::unique_ptr<base::ScopedPathOverride> path_override_srk_vulnerable_roca_;
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   ScopedCrosSettingsTestHelper cros_settings_test_helper_;
   chromeos::system::ScopedFakeStatisticsProvider statistics_provider_;
 };
diff --git a/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_bridge_unittest.cc b/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_bridge_unittest.cc
index 5047626..cc6ee49 100644
--- a/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_bridge_unittest.cc
+++ b/chrome/browser/chromeos/wilco_dtc_supportd/wilco_dtc_supportd_bridge_unittest.cc
@@ -233,7 +233,7 @@
   }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
  private:
   FakeMojoWilcoDtcSupportdServiceFactory
diff --git a/chrome/browser/content_index/content_index_browsertest.cc b/chrome/browser/content_index/content_index_browsertest.cc
new file mode 100644
index 0000000..47980f81
--- /dev/null
+++ b/chrome/browser/content_index/content_index_browsertest.cc
@@ -0,0 +1,181 @@
+// 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 <map>
+#include <memory>
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "base/strings/string_util.h"
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/content_index/content_index_provider_impl.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/offline_items_collection/core/offline_content_provider.h"
+#include "components/offline_items_collection/core/offline_item.h"
+#include "content/public/common/content_switches.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "third_party/re2/src/re2/re2.h"
+#include "url/gurl.h"
+
+using offline_items_collection::ContentId;
+using offline_items_collection::OfflineContentProvider;
+using offline_items_collection::OfflineItem;
+using offline_items_collection::OfflineItemVisuals;
+
+namespace {
+
+std::string GetDescriptionIdFromOfflineItemKey(const std::string& id) {
+  std::string description_id;
+  bool result = re2::RE2::FullMatch(id, re2::RE2("\\d+-(.*)"), &description_id);
+  EXPECT_TRUE(result);
+  return description_id;
+}
+
+class ContentIndexTest : public InProcessBrowserTest,
+                         public OfflineContentProvider::Observer {
+ public:
+  ContentIndexTest() = default;
+  ~ContentIndexTest() override = default;
+
+  void SetUpOnMainThread() override {
+    https_server_ = std::make_unique<net::EmbeddedTestServer>(
+        net::EmbeddedTestServer::TYPE_HTTPS);
+    https_server_->ServeFilesFromSourceDirectory("chrome/test/data");
+    ASSERT_TRUE(https_server_->Start());
+
+    ui_test_utils::NavigateToURL(
+        browser(), https_server_->GetURL("/content_index/content_index.html"));
+
+    RunScript("RegisterServiceWorker()");
+
+    auto* provider = browser()->profile()->GetContentIndexProvider();
+    DCHECK(provider);
+    provider_ = static_cast<ContentIndexProviderImpl*>(provider);
+    provider_->AddObserver(this);
+  }
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    command_line->AppendSwitch(
+        switches::kEnableExperimentalWebPlatformFeatures);
+  }
+
+  // Runs |script| and expects it to complete successfully. |script| must
+  // result in a Promise. Returns the resolved contents of the Promise.
+  std::string RunScript(const std::string& script) {
+    std::string result;
+    RunScript(script, &result);
+    return result.substr(5);  // Ignore the trailing `ok - `.
+  }
+
+  // OfflineContentProvider::Observer implementation:
+  void OnItemsAdded(
+      const OfflineContentProvider::OfflineItemList& items) override {
+    ASSERT_EQ(items.size(), 1u);
+    offline_items_[GetDescriptionIdFromOfflineItemKey(items[0].id.id)] =
+        items[0];
+  }
+
+  void OnItemRemoved(const ContentId& id) override {
+    offline_items_.erase(GetDescriptionIdFromOfflineItemKey(id.id));
+  }
+
+  void OnItemUpdated(
+      const OfflineItem& item,
+      const base::Optional<offline_items_collection::UpdateDelta>& update_delta)
+      override {
+    std::string id = GetDescriptionIdFromOfflineItemKey(item.id.id);
+    ASSERT_TRUE(offline_items_.count(id));
+    offline_items_[id] = item;
+  }
+
+  std::map<std::string, OfflineItem>& offline_items() { return offline_items_; }
+  ContentIndexProviderImpl* provider() { return provider_; }
+
+ private:
+  void RunScript(const std::string& script, std::string* result) {
+    ASSERT_TRUE(content::ExecuteScriptAndExtractString(
+        browser()->tab_strip_model()->GetActiveWebContents()->GetMainFrame(),
+        "WrapFunction(async () => " + script + ")", result));
+    ASSERT_TRUE(
+        base::StartsWith(*result, "ok - ", base::CompareCase::SENSITIVE))
+        << "Unexpected result: " << *result;
+  }
+
+  std::map<std::string, OfflineItem> offline_items_;
+  ContentIndexProviderImpl* provider_;
+  std::unique_ptr<net::EmbeddedTestServer> https_server_;
+};
+
+IN_PROC_BROWSER_TEST_F(ContentIndexTest, OfflineItemObserversReceiveEvents) {
+  RunScript("AddContent('my-id-1')");
+  RunScript("AddContent('my-id-2')");
+  base::RunLoop().RunUntilIdle();  // Wait for the provider to get the content.
+
+  EXPECT_EQ(offline_items().size(), 2u);
+  ASSERT_TRUE(offline_items().count("my-id-1"));
+  EXPECT_TRUE(offline_items().count("my-id-2"));
+  EXPECT_EQ(RunScript("GetIds()"), "my-id-1,my-id-2");
+
+  std::string description1 = offline_items().at("my-id-1").description;
+  RunScript("AddContent('my-id-1')");     // update
+  RunScript("DeleteContent('my-id-2')");  // delete
+  base::RunLoop().RunUntilIdle();  // Wait for the provider to get the content.
+
+  EXPECT_EQ(offline_items().size(), 1u);
+  ASSERT_TRUE(offline_items().count("my-id-1"));
+  EXPECT_FALSE(offline_items().count("my-id-2"));
+
+  // Expect the description to have been updated.
+  EXPECT_NE(description1, offline_items().at("my-id-1").description);
+}
+
+IN_PROC_BROWSER_TEST_F(ContentIndexTest, GetVisuals) {
+  RunScript("AddContent('my-id')");
+  base::RunLoop().RunUntilIdle();  // Wait for the provider to get the content.
+
+  base::RunLoop run_loop;
+  SkBitmap icon;
+  provider()->GetVisualsForItem(
+      offline_items().at("my-id").id,
+      OfflineContentProvider::GetVisualsOptions(),
+      base::BindLambdaForTesting(
+          [&](const ContentId& id,
+              std::unique_ptr<OfflineItemVisuals> visuals) {
+            ASSERT_EQ(offline_items().at("my-id").id, id);
+            ASSERT_TRUE(visuals);
+            icon = visuals->icon.AsBitmap();
+            run_loop.Quit();
+          }));
+  run_loop.Run();
+
+  EXPECT_FALSE(icon.isNull());
+  EXPECT_FALSE(icon.drawsNothing());
+}
+
+IN_PROC_BROWSER_TEST_F(ContentIndexTest, LaunchUrl) {
+  RunScript("AddContent('my-id')");
+  base::RunLoop().RunUntilIdle();  // Wait for the provider to get the content.
+
+  EXPECT_EQ(browser()->tab_strip_model()->count(), 1);
+  GURL current_url =
+      browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
+  EXPECT_TRUE(base::EndsWith(current_url.spec(),
+                             "/content_index/content_index.html",
+                             base::CompareCase::SENSITIVE));
+
+  provider()->OpenItem(offline_items_collection::LaunchLocation::DOWNLOAD_HOME,
+                       offline_items().at("my-id").id);
+  base::RunLoop().RunUntilIdle();  // Wait for the page to open.
+  EXPECT_EQ(browser()->tab_strip_model()->count(), 2);
+  current_url = browser()->tab_strip_model()->GetActiveWebContents()->GetURL();
+  EXPECT_TRUE(base::EndsWith(current_url.spec(),
+                             "/content_index/content_index.html?launch",
+                             base::CompareCase::SENSITIVE));
+}
+
+}  // namespace
diff --git a/chrome/browser/content_index/content_index_provider_factory.cc b/chrome/browser/content_index/content_index_provider_factory.cc
index 266a2bac..5ca42fc 100644
--- a/chrome/browser/content_index/content_index_provider_factory.cc
+++ b/chrome/browser/content_index/content_index_provider_factory.cc
@@ -29,13 +29,11 @@
   DependsOn(OfflineContentAggregatorFactory::GetInstance());
 }
 
-ContentIndexProviderFactory::~ContentIndexProviderFactory() {}
+ContentIndexProviderFactory::~ContentIndexProviderFactory() = default;
 
 KeyedService* ContentIndexProviderFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  auto* aggregator = OfflineContentAggregatorFactory::GetForKey(
-      Profile::FromBrowserContext(context)->GetProfileKey());
-  return new ContentIndexProviderImpl(aggregator);
+  return new ContentIndexProviderImpl(Profile::FromBrowserContext(context));
 }
 
 content::BrowserContext* ContentIndexProviderFactory::GetBrowserContextToUse(
diff --git a/chrome/browser/content_index/content_index_provider_impl.cc b/chrome/browser/content_index/content_index_provider_impl.cc
index 69dc9f1e..c27e613 100644
--- a/chrome/browser/content_index/content_index_provider_impl.cc
+++ b/chrome/browser/content_index/content_index_provider_impl.cc
@@ -7,13 +7,24 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/task/post_task.h"
+#include "build/build_config.h"
 #include "chrome/browser/offline_items_collection/offline_content_aggregator_factory.h"
+#include "chrome/browser/profiles/profile.h"
 #include "components/offline_items_collection/core/offline_content_aggregator.h"
 #include "components/offline_items_collection/core/offline_item.h"
 #include "components/offline_items_collection/core/update_delta.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/gfx/image/image_skia.h"
 
+#if defined(OS_ANDROID)
+#include "chrome/browser/android/service_tab_launcher.h"
+#include "content/public/browser/page_navigator.h"
+#include "content/public/common/referrer.h"
+#else
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
+#endif
+
 using offline_items_collection::ContentId;
 using offline_items_collection::LaunchLocation;
 using offline_items_collection::OfflineItem;
@@ -78,17 +89,18 @@
   item.state = offline_items_collection::OfflineItemState::COMPLETE;
   item.is_resumable = false;
   item.can_rename = false;
-
-  // TODO(crbug.com/973844): Include URL info.
+  item.page_url = entry.launch_url;
 
   return item;
 }
 
 }  // namespace
 
-ContentIndexProviderImpl::ContentIndexProviderImpl(
-    offline_items_collection::OfflineContentAggregator* aggregator)
-    : aggregator_(aggregator), weak_ptr_factory_(this) {
+ContentIndexProviderImpl::ContentIndexProviderImpl(Profile* profile)
+    : profile_(profile),
+      aggregator_(OfflineContentAggregatorFactory::GetForKey(
+          profile_->GetProfileKey())),
+      weak_ptr_factory_(this) {
   aggregator_->RegisterProvider(kProviderNamespace, this);
 }
 
@@ -144,7 +156,22 @@
 
 void ContentIndexProviderImpl::OpenItem(LaunchLocation location,
                                         const ContentId& id) {
-  NOTIMPLEMENTED();
+  auto it = entries_.find(id.id);
+  if (it == entries_.end())
+    return;
+
+#if defined(OS_ANDROID)
+  content::OpenURLParams params(
+      it->second.offline_item.page_url, content::Referrer(),
+      WindowOpenDisposition::NEW_FOREGROUND_TAB, ui::PAGE_TRANSITION_LINK,
+      /* is_renderer_initiated= */ false);
+  ServiceTabLauncher::GetInstance()->LaunchTab(profile_, params,
+                                               base::DoNothing());
+#else
+  NavigateParams nav_params(profile_, it->second.offline_item.page_url,
+                            ui::PAGE_TRANSITION_LINK);
+  Navigate(&nav_params);
+#endif
 }
 
 void ContentIndexProviderImpl::RemoveItem(const ContentId& id) {
@@ -179,7 +206,7 @@
   for (const auto& entry : entries_)
     list.push_back(entry.second.offline_item);
 
-  // TODO(crbug.com/1687257): Consider fetching these from the DB rather than
+  // TODO(crbug.com/973844): Consider fetching these from the DB rather than
   // storing them in memory.
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), std::move(list)));
diff --git a/chrome/browser/content_index/content_index_provider_impl.h b/chrome/browser/content_index/content_index_provider_impl.h
index 810381a..2cc148ba 100644
--- a/chrome/browser/content_index/content_index_provider_impl.h
+++ b/chrome/browser/content_index/content_index_provider_impl.h
@@ -20,13 +20,14 @@
 class OfflineContentAggregator;
 }  // namespace offline_items_collection
 
+class Profile;
+
 class ContentIndexProviderImpl
     : public KeyedService,
       public offline_items_collection::OfflineContentProvider,
       public content::ContentIndexProvider {
  public:
-  explicit ContentIndexProviderImpl(
-      offline_items_collection::OfflineContentAggregator* aggregator);
+  explicit ContentIndexProviderImpl(Profile* profile);
   ~ContentIndexProviderImpl() override;
 
   // KeyedService implementation.
@@ -70,6 +71,7 @@
                   VisualsCallback callback,
                   SkBitmap icon);
 
+  Profile* profile_;
   offline_items_collection::OfflineContentAggregator* aggregator_;
   std::map<std::string, EntryData> entries_;
   base::ObserverList<Observer>::Unchecked observers_;
diff --git a/chrome/browser/content_index/content_index_provider_unittest.cc b/chrome/browser/content_index/content_index_provider_unittest.cc
index c86cf92..6e18b20 100644
--- a/chrome/browser/content_index/content_index_provider_unittest.cc
+++ b/chrome/browser/content_index/content_index_provider_unittest.cc
@@ -11,13 +11,13 @@
 #include "base/test/bind_test_util.h"
 #include "base/time/time.h"
 #include "chrome/test/base/testing_profile.h"
-#include "components/offline_items_collection/core/offline_content_aggregator.h"
 #include "components/offline_items_collection/core/offline_content_provider.h"
 #include "content/public/browser/content_index_provider.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/gfx/image/image.h"
+#include "url/gurl.h"
 
 using offline_items_collection::ContentId;
 using offline_items_collection::OfflineContentAggregator;
@@ -28,6 +28,7 @@
 using testing::_;
 
 constexpr int64_t kServiceWorkerRegistrationId = 42;
+const GURL kLaunchURL = GURL("https://example.com/foo");
 
 class ProviderClient : public content::ContentIndexProvider::Client {
  public:
@@ -51,8 +52,7 @@
                                      public OfflineContentProvider::Observer {
  public:
   void SetUp() override {
-    aggregator_ = std::make_unique<OfflineContentAggregator>();
-    provider_ = std::make_unique<ContentIndexProviderImpl>(aggregator_.get());
+    provider_ = std::make_unique<ContentIndexProviderImpl>(&profile_);
     provider_->AddObserver(this);
   }
 
@@ -70,9 +70,9 @@
     auto description = blink::mojom::ContentDescription::New(
         id, "title", "description", blink::mojom::ContentCategory::ARTICLE,
         "icon_url", "launch_url");
-    return content::ContentIndexEntry(
-        kServiceWorkerRegistrationId, std::move(description),
-        /* launch_url= */ GURL(), base::Time::Now());
+    return content::ContentIndexEntry(kServiceWorkerRegistrationId,
+                                      std::move(description), kLaunchURL,
+                                      base::Time::Now());
   }
 
   SkBitmap GetVisuals(const ContentId& id) {
@@ -110,8 +110,7 @@
 
  protected:
   content::TestBrowserThreadBundle threads_;
-  std::unique_ptr<offline_items_collection::OfflineContentAggregator>
-      aggregator_;
+  TestingProfile profile_;
   ProviderClient client_;
   std::unique_ptr<ContentIndexProviderImpl> provider_;
 };
@@ -131,6 +130,7 @@
   EXPECT_FALSE(item.description.empty());
   EXPECT_FALSE(item.is_transient);
   EXPECT_TRUE(item.is_openable);
+  EXPECT_EQ(item.page_url, kLaunchURL);
 }
 
 TEST_F(ContentIndexProviderImplTest, ObserverUpdates) {
diff --git a/chrome/browser/enterprise_reporting/report_uploader_unittest.cc b/chrome/browser/enterprise_reporting/report_uploader_unittest.cc
index ecf6ce1b..76f63c2 100644
--- a/chrome/browser/enterprise_reporting/report_uploader_unittest.cc
+++ b/chrome/browser/enterprise_reporting/report_uploader_unittest.cc
@@ -26,7 +26,7 @@
  public:
   ReportUploaderTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
     CreateUploader(0);
   }
   ~ReportUploaderTest() override {}
diff --git a/chrome/browser/enterprise_reporting/request_timer_unittest.cc b/chrome/browser/enterprise_reporting/request_timer_unittest.cc
index 2362a66..ca19db7 100644
--- a/chrome/browser/enterprise_reporting/request_timer_unittest.cc
+++ b/chrome/browser/enterprise_reporting/request_timer_unittest.cc
@@ -13,7 +13,7 @@
  public:
   RequestTimerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void RunTask() { task_count_ += 1; }
 
diff --git a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
index 9cfe681..5295ff2 100644
--- a/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_api_unittest.cc
@@ -35,7 +35,6 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chrome/test/base/testing_profile_manager.h"
-#include "components/about_handler/about_protocol_handler.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/prefs/pref_member.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 625eded..da706346 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1768,6 +1768,11 @@
     "expiry_milestone": -1
   },
   {
+    "name": "enable-two-panes-start-surface",
+    "owners": [ "gogerald"],
+    "expiry_milestone": 83
+  },
+  {
     "name": "enable-unsafe-webgpu",
     "owners": [ "//third_party/blink/renderer/modules/webgpu/OWNERS" ],
     "expiry_milestone": 82
@@ -3144,6 +3149,11 @@
     "expiry_milestone": 76
   },
   {
+    "name": "username-first-flow",
+    "owners": [ "dvadym" ],
+    "expiry_milestone": 80
+  },
+  {
     "name": "views-cast-dialog",
     "owners": [ "//chrome/browser/media/router/OWNERS" ],
     "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index ac7f765..e0768e8 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1999,6 +1999,12 @@
     "Enable simple user activation for APIs that are otherwise controlled by "
     "user gesture tokens.";
 
+const char kUsernameFirstFlowName[] = "Username first flow";
+const char kUsernameFirstFlowDescription[] =
+    "Support of username saving and filling on username first flow i.e. login "
+    "flows where a user has to type username first on one page and then "
+    "password on another page";
+
 const char kUseSearchClickForRightClickName[] =
     "Use Search+Click for right click";
 const char kUseSearchClickForRightClickDescription[] =
@@ -2563,6 +2569,11 @@
 const char kTranslateAndroidManualTriggerDescription[] =
     "Show a menu item in the main menu that triggers page translation.";
 
+const char kTwoPanesStartSurfaceAndroidName[] = "Two Panes Start Surface";
+const char kTwoPanesStartSurfaceAndroidDescription[] =
+    "Enable showing two panes start surface when launching Chrome via the "
+    "launcher.";
+
 const char kUpdateMenuBadgeName[] = "Force show update menu badge";
 const char kUpdateMenuBadgeDescription[] =
     "When enabled, a badge will be shown on the app menu button if the update "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 90768ad..6e5f67ca 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -757,6 +757,9 @@
 extern const char kOnlyNewPasswordFormParsingName[];
 extern const char kOnlyNewPasswordFormParsingDescription[];
 
+extern const char kUsernameFirstFlowName[];
+extern const char kUsernameFirstFlowDescription[];
+
 extern const char kNewPrintPreviewLayoutName[];
 extern const char kNewPrintPreviewLayoutDescription[];
 
@@ -1511,6 +1514,9 @@
 extern const char kTranslateAndroidManualTriggerName[];
 extern const char kTranslateAndroidManualTriggerDescription[];
 
+extern const char kTwoPanesStartSurfaceAndroidName[];
+extern const char kTwoPanesStartSurfaceAndroidDescription[];
+
 extern const char kUpdateMenuBadgeName[];
 extern const char kUpdateMenuBadgeDescription[];
 
diff --git a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
index 4674699..ffa4a4f 100644
--- a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
+++ b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_unittest.cc
@@ -20,7 +20,7 @@
  public:
   GoogleSearchDomainMixingMetricsEmitterTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     GoogleSearchDomainMixingMetricsEmitter::RegisterProfilePrefs(
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc
index 23ace4c..16cad93 100644
--- a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc
+++ b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer_unittest.cc
@@ -62,7 +62,7 @@
  public:
   DiscoveryNetworkMonitorMetricObserverTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         start_ticks_(thread_bundle_.NowTicks()),
         metrics_(std::make_unique<MockMetrics>()),
         mock_metrics_(metrics_.get()),
diff --git a/chrome/browser/media/router/issue_manager_unittest.cc b/chrome/browser/media/router/issue_manager_unittest.cc
index a43501f..325932e 100644
--- a/chrome/browser/media/router/issue_manager_unittest.cc
+++ b/chrome/browser/media/router/issue_manager_unittest.cc
@@ -32,7 +32,7 @@
  protected:
   IssueManagerTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
     manager_.set_task_runner_for_test(thread_bundle_.GetMainThreadTaskRunner());
   }
   ~IssueManagerTest() override {}
diff --git a/chrome/browser/memory/memory_pressure_monitor_utils_unittest.cc b/chrome/browser/memory/memory_pressure_monitor_utils_unittest.cc
index 970029b1..7b8c183 100644
--- a/chrome/browser/memory/memory_pressure_monitor_utils_unittest.cc
+++ b/chrome/browser/memory/memory_pressure_monitor_utils_unittest.cc
@@ -40,7 +40,7 @@
  public:
   ObservationWindowTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         tick_clock_(scoped_task_environment_.GetMockTickClock()) {}
   ~ObservationWindowTest() override = default;
 
diff --git a/chrome/browser/memory/memory_pressure_monitor_win_unittest.cc b/chrome/browser/memory/memory_pressure_monitor_win_unittest.cc
index 047eaee..d3a8c75 100644
--- a/chrome/browser/memory/memory_pressure_monitor_win_unittest.cc
+++ b/chrome/browser/memory/memory_pressure_monitor_win_unittest.cc
@@ -36,7 +36,7 @@
  public:
   MemoryPressureMonitorWinTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         tick_clock_(scoped_task_environment_.GetMockTickClock()) {}
   ~MemoryPressureMonitorWinTest() override = default;
 
diff --git a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
index 11821d1..342edd4 100644
--- a/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
+++ b/chrome/browser/metrics/perf/profile_provider_chromeos_unittest.cc
@@ -141,7 +141,7 @@
  public:
   ProfileProviderTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     // ProfileProvider requires chromeos::LoginState and
diff --git a/chrome/browser/metrics/plugin_metrics_provider_unittest.cc b/chrome/browser/metrics/plugin_metrics_provider_unittest.cc
index 18702b4..48f7a2e 100644
--- a/chrome/browser/metrics/plugin_metrics_provider_unittest.cc
+++ b/chrome/browser/metrics/plugin_metrics_provider_unittest.cc
@@ -119,7 +119,7 @@
 
 TEST_F(PluginMetricsProviderTest, RecordCurrentStateWithDelay) {
   content::TestBrowserThreadBundle thread_bundle(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
 
   PluginMetricsProvider provider(prefs());
 
@@ -134,7 +134,7 @@
 
 TEST_F(PluginMetricsProviderTest, RecordCurrentStateIfPending) {
   content::TestBrowserThreadBundle thread_bundle(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
 
   PluginMetricsProvider provider(prefs());
 
diff --git a/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc b/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc
index 56ca98e..867b3f2 100644
--- a/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_win_unittest.cc
@@ -50,7 +50,7 @@
  public:
   NotificationPlatformBridgeWinTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   ~NotificationPlatformBridgeWinTest() override = default;
 
diff --git a/chrome/browser/notifications/win/notification_image_retainer_unittest.cc b/chrome/browser/notifications/win/notification_image_retainer_unittest.cc
index 1e68551..9c373baf 100644
--- a/chrome/browser/notifications/win/notification_image_retainer_unittest.cc
+++ b/chrome/browser/notifications/win/notification_image_retainer_unittest.cc
@@ -26,7 +26,7 @@
  public:
   NotificationImageRetainerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         user_data_dir_override_(chrome::DIR_USER_DATA) {}
 
   ~NotificationImageRetainerTest() override = default;
diff --git a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
index fa8c0640..f53b98f 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client_unittest.cc
@@ -131,7 +131,7 @@
  public:
   DummyLogReceiver() = default;
 
-  void LogSavePasswordProgress(const std::string& text) override {}
+  void LogEntry(const base::Value& entry) override {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(DummyLogReceiver);
@@ -277,7 +277,7 @@
   return true;
 }
 
-TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressNotifyRenderer) {
+TEST_F(ChromePasswordManagerClientTest, LogEntryNotifyRenderer) {
   bool logging_active = true;
   // Ensure the existence of a driver, which will send the IPCs we listen for
   // below.
@@ -291,7 +291,8 @@
   DummyLogReceiver log_receiver;
   autofill::LogRouter* log_router = password_manager::
       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile());
-  EXPECT_EQ(std::string(), log_router->RegisterReceiver(&log_receiver));
+  EXPECT_EQ(std::vector<base::Value>(),
+            log_router->RegisterReceiver(&log_receiver));
   EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
   EXPECT_TRUE(logging_active);
 
@@ -523,7 +524,8 @@
   autofill::LogRouter* log_router = password_manager::
       PasswordManagerInternalsServiceFactory::GetForBrowserContext(profile());
   DummyLogReceiver log_receiver;
-  EXPECT_EQ(std::string(), log_router->RegisterReceiver(&log_receiver));
+  EXPECT_EQ(std::vector<base::Value>(),
+            log_router->RegisterReceiver(&log_receiver));
 
   // But then navigate to a WebUI, there the logging should not be active.
   NavigateAndCommit(GURL("about:password-manager-internals"));
diff --git a/chrome/browser/performance_manager/graph/graph_test_harness.cc b/chrome/browser/performance_manager/graph/graph_test_harness.cc
index 39072ba6..0b6db7c 100644
--- a/chrome/browser/performance_manager/graph/graph_test_harness.cc
+++ b/chrome/browser/performance_manager/graph/graph_test_harness.cc
@@ -11,7 +11,7 @@
 
 GraphTestHarness::GraphTestHarness()
     : task_env_(
-          base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+          base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
           base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED) {}
 
 GraphTestHarness::~GraphTestHarness() = default;
diff --git a/chrome/browser/performance_monitor/system_monitor_unittest.cc b/chrome/browser/performance_monitor/system_monitor_unittest.cc
index f15a928..d30e8c2 100644
--- a/chrome/browser/performance_monitor/system_monitor_unittest.cc
+++ b/chrome/browser/performance_monitor/system_monitor_unittest.cc
@@ -57,7 +57,7 @@
 
   SystemMonitorTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     EXPECT_EQ(nullptr, SystemMonitor::Get());
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 714a5303..43ccef7 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -533,8 +533,8 @@
 #endif  // !defined(OS_MACOSX)
 
 #if defined(OS_CHROMEOS)
-  { key::kCertificateManagementAllowed,
-    prefs::kCertificateManagementAllowed,
+  { key::kClientCertificateManagementAllowed,
+    prefs::kClientCertificateManagementAllowed,
     base::Value::Type::INTEGER },
   { key::kChromeOsLockOnIdleSuspend,
     ash::prefs::kEnableAutoScreenLock,
diff --git a/chrome/browser/prefs/chrome_pref_service_factory.cc b/chrome/browser/prefs/chrome_pref_service_factory.cc
index 26bb789..95d2de3 100644
--- a/chrome/browser/prefs/chrome_pref_service_factory.cc
+++ b/chrome/browser/prefs/chrome_pref_service_factory.cc
@@ -318,9 +318,6 @@
   // As part of improving pref metrics on other platforms we may want to find
   // ways to defer preference loading until the device ID can be used.
   rlz_lib::GetMachineId(&legacy_device_id);
-
-  UMA_HISTOGRAM_BOOLEAN("Settings.LegacyMachineIdGenerationSuccess",
-                        !legacy_device_id.empty());
 #endif
   std::string seed;
   CHECK(ui::ResourceBundle::HasSharedInstance());
diff --git a/chrome/browser/prefs/profile_pref_store_manager.cc b/chrome/browser/prefs/profile_pref_store_manager.cc
index 6c0ac41f..24140cf 100644
--- a/chrome/browser/prefs/profile_pref_store_manager.cc
+++ b/chrome/browser/prefs/profile_pref_store_manager.cc
@@ -130,7 +130,6 @@
   // won't have kicked in yet on the main thread.
   bool success = serializer.Serialize(*master_prefs);
 
-  UMA_HISTOGRAM_BOOLEAN("Settings.InitializedFromMasterPrefs", success);
   return success;
 }
 
diff --git a/chrome/browser/previews/previews_lite_page_browsertest.cc b/chrome/browser/previews/previews_lite_page_browsertest.cc
index 583714e9..93c03e8c 100644
--- a/chrome/browser/previews/previews_lite_page_browsertest.cc
+++ b/chrome/browser/previews/previews_lite_page_browsertest.cc
@@ -55,6 +55,7 @@
 #include "components/history/core/browser/history_service.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
+#include "components/optimization_guide/bloom_filter.h"
 #include "components/optimization_guide/hints_component_info.h"
 #include "components/optimization_guide/optimization_guide_features.h"
 #include "components/optimization_guide/optimization_guide_service.h"
@@ -66,7 +67,6 @@
 #include "components/previews/content/previews_optimization_guide.h"
 #include "components/previews/content/previews_ui_service.h"
 #include "components/previews/content/previews_user_data.h"
-#include "components/previews/core/bloom_filter.h"
 #include "components/previews/core/previews_constants.h"
 #include "components/previews/core/previews_experiments.h"
 #include "components/previews/core/previews_features.h"
@@ -1980,7 +1980,7 @@
 IN_PROC_BROWSER_TEST_P(
     PreviewsLitePageAndPageHintsBrowserTest,
     DISABLE_ON_WIN_MAC_CHROMESOS(PreviewsServerIsInBloomFilter)) {
-  previews::BloomFilter blacklist_bloom_filter(7, 511);
+  optimization_guide::BloomFilter blacklist_bloom_filter(7, 511);
   blacklist_bloom_filter.Add(previews_server_url().host());
   blacklist_bloom_filter.Add("subdomain." + previews_server_url().host());
 
diff --git a/chrome/browser/previews/previews_prober_unittest.cc b/chrome/browser/previews/previews_prober_unittest.cc
index 55f8e63..9485abf8 100644
--- a/chrome/browser/previews/previews_prober_unittest.cc
+++ b/chrome/browser/previews/previews_prober_unittest.cc
@@ -77,7 +77,7 @@
  public:
   PreviewsProberTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         test_shared_loader_factory_(
             base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
                 &test_url_loader_factory_)),
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index 14f20ec..1a0de268 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -701,13 +701,6 @@
       this, io_data_.GetResourceContextNoInit());
 #endif
 
-  {
-    TRACE_EVENT0("browser", "ProfileImpl::SetSaveSessionStorageOnDisk");
-    content::BrowserContext::GetDefaultStoragePartition(this)
-        ->GetDOMStorageContext()
-        ->SetSaveSessionStorageOnDisk();
-  }
-
   // The DomDistillerViewerSource is not a normal WebUI so it must be registered
   // as a URLDataSource early.
   dom_distiller::RegisterViewerSource(this);
diff --git a/chrome/browser/profiles/profile_io_data.cc b/chrome/browser/profiles/profile_io_data.cc
index 02e0b00..285f9e09 100644
--- a/chrome/browser/profiles/profile_io_data.cc
+++ b/chrome/browser/profiles/profile_io_data.cc
@@ -43,7 +43,6 @@
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
-#include "components/about_handler/about_protocol_handler.h"
 #include "components/content_settings/core/browser/content_settings_provider.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
diff --git a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
index 9f587ea..86327b1b 100644
--- a/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
+++ b/chrome/browser/resource_coordinator/tab_lifecycle_unit_source.cc
@@ -9,9 +9,8 @@
 #include "base/stl_util.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/performance_manager/graph/graph_impl.h"
-#include "chrome/browser/performance_manager/graph/page_node_impl.h"
 #include "chrome/browser/performance_manager/performance_manager.h"
+#include "chrome/browser/performance_manager/public/graph/page_node.h"
 #include "chrome/browser/performance_manager/public/web_contents_proxy.h"
 #include "chrome/browser/resource_coordinator/discard_metrics_lifecycle_unit_observer.h"
 #include "chrome/browser/resource_coordinator/lifecycle_unit_source_observer.h"
@@ -65,20 +64,17 @@
 // TabLifecycleUnitSource on the UI thread. This is created on the UI thread
 // and ownership passed to the performance manager.
 class TabLifecycleStateObserver
-    : public performance_manager::GraphImplObserverDefaultImpl {
+    : public performance_manager::PageNode::ObserverDefaultImpl,
+      public performance_manager::GraphOwned {
  public:
-  using NodeBase = performance_manager::NodeBase;
-  using PageNodeImpl = performance_manager::PageNodeImpl;
+  using Graph = performance_manager::Graph;
+  using PageNode = performance_manager::PageNode;
   using WebContentsProxy = performance_manager::WebContentsProxy;
 
   TabLifecycleStateObserver() = default;
   ~TabLifecycleStateObserver() override = default;
 
  private:
-  bool ShouldObserve(const NodeBase* node) override {
-    return node->type() == performance_manager::PageNodeImpl::Type();
-  }
-
   static void OnLifecycleStateChangedImpl(
       const WebContentsProxy& contents_proxy,
       mojom::LifecycleState state) {
@@ -89,13 +85,22 @@
       TabLifecycleUnitSource::OnLifecycleStateChanged(contents, state);
   }
 
-  void OnLifecycleStateChanged(PageNodeImpl* page_node) override {
+  // performance_manager::PageNode::ObserverDefaultImpl::
+  void OnPageLifecycleStateChanged(const PageNode* page_node) override {
     // Forward the notification over to the UI thread.
     base::PostTaskWithTraits(
         FROM_HERE, {content::BrowserThread::UI},
         base::BindOnce(&TabLifecycleStateObserver::OnLifecycleStateChangedImpl,
-                       page_node->contents_proxy(),
-                       page_node->lifecycle_state()));
+                       page_node->GetContentProxy(),
+                       page_node->GetLifecycleState()));
+  }
+
+  void OnPassedToGraph(Graph* graph) override {
+    graph->AddPageNodeObserver(this);
+  }
+
+  void OnTakenFromGraph(Graph* graph) override {
+    graph->RemovePageNodeObserver(this);
   }
 
   DISALLOW_COPY_AND_ASSIGN(TabLifecycleStateObserver);
@@ -117,12 +122,14 @@
   if (perf_man) {
     // The performance manager dies on its own sequence, so posting unretained
     // is fine.
-    perf_man->task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            &performance_manager::PerformanceManager::RegisterObserver,
-            base::Unretained(perf_man),
-            std::make_unique<TabLifecycleStateObserver>()));
+    perf_man->CallOnGraph(
+        FROM_HERE, base::BindOnce(
+                       [](std::unique_ptr<TabLifecycleStateObserver>
+                              tab_lifecycle_observer,
+                          performance_manager::GraphImpl* graph) {
+                         graph->PassToGraph(std::move(tab_lifecycle_observer));
+                       },
+                       std::make_unique<TabLifecycleStateObserver>()));
   }
 }
 
diff --git a/chrome/browser/resources/local_ntp/customize.js b/chrome/browser/resources/local_ntp/customize.js
index dedb2121..6fbf87d 100644
--- a/chrome/browser/resources/local_ntp/customize.js
+++ b/chrome/browser/resources/local_ntp/customize.js
@@ -1831,7 +1831,12 @@
     tile.dataset.attributionLine1 = '';
     tile.dataset.attributionLine2 = '';
     tile.dataset.attributionActionUrl = '';
-    customize.richerPicker_selectBackgroundTile(tile);
+    if ($(customize.IDS.BACKGROUNDS_DEFAULT)
+            .classList.contains(customize.CLASSES.SELECTED)) {
+      customize.richerPicker_deselectBackgroundTile(tile);
+    } else {
+      customize.richerPicker_selectBackgroundTile(tile);
+    }
   };
   $(customize.IDS.BACKGROUNDS_DEFAULT).onkeydown = function(event) {
     if (event.keyCode === customize.KEYCODES.ENTER ||
diff --git a/chrome/browser/resources/local_ntp/local_ntp.css b/chrome/browser/resources/local_ntp/local_ntp.css
index 7c5cbb1..4e4a88ef 100644
--- a/chrome/browser/resources/local_ntp/local_ntp.css
+++ b/chrome/browser/resources/local_ntp/local_ntp.css
@@ -919,6 +919,8 @@
 
 #backgrounds-menu .bg-sel-tile-bg.selected .bg-sel-tile,
 #backgrounds-image-menu .bg-sel-tile-bg.selected .bg-sel-tile {
+  box-shadow: 0 1px 3px 0 rgba(var(--GG800-rgb), .3),
+      0 4px 8px 3px rgba(var(--GG800-rgb), .15);
   height: 144px;
   margin: 16px 16px 0 16px;
   width: 144px;
@@ -1167,6 +1169,11 @@
   width: 116px;
 }
 
+#backgrounds-default.selected #backgrounds-default-icon {
+  box-shadow: 0 1px 3px 0 rgba(var(--GG800-rgb), .3),
+      0 4px 8px 3px rgba(var(--GG800-rgb), .15);
+}
+
 #backgrounds-default:not(.selected) .mini-page {
   padding-top: 32px;
 }
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
index 72f767c..f198cc9 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
+++ b/chrome/browser/resources/settings/chromeos/os_settings_menu/os_settings_menu.html
@@ -14,6 +14,9 @@
   <template>
     <style include="settings-shared">
       :host {
+        --menu-link-color: var(--google-blue-600);
+        --menu-text-color: var(--google-grey-refresh-700);
+        --menu-icon-color: var(--google-grey-refresh-700);
         box-sizing: border-box;
         display: block;
         padding-bottom: 2px;
@@ -24,49 +27,74 @@
         -webkit-tap-highlight-color: transparent;
       }
 
-      a[href],
-      #advancedButton {
+      /* Override --cr-selectable-focus mixin. */
+      [selectable]:not(cr-radio-group):focus,
+      [selectable]:not(cr-radio-group) > :focus {
+        background-color: transparent;
+      }
+
+      /* The <a> is the entire tap target, including the padding around the
+         visible icon and text. */
+      a {
+        background: transparent;
+        display: block;
+        padding: 3px 0;
+      }
+
+      /* The "item" draws the icon, text, and rounded background. */
+      a > .item {
         align-items: center;
-        color: var(--settings-nav-item-color);
+        border: 1px solid transparent;
+        border-radius: 0 20px 20px 0;
+        color: var(--menu-text-color);
         display: flex;
         font-weight: 500;
         margin-inline-end: 2px;  /* Margin so selected outline is visible. */
-        margin-inline-start: 1px;
-        min-height: 20px;
-        padding-bottom: 10px;
-        padding-inline-start: 23px;  /* 24px - 1px from margin for outline. */
-        padding-top: 10px;
+        min-height: 32px;
+        padding-inline-start: 24px;
+        pointer-events: none;
       }
 
-      a[href].iron-selected {
-        color: var(--cr-link-color);
+      a.iron-selected > .item {
+        background-color: var(--google-blue-50);
+        color: var(--menu-link-color);
       }
 
-      a[href]:focus {
-        background: transparent;
-        outline: auto 5px -webkit-focus-ring-color;
+      :host-context(.focus-outline-visible) a:focus > .item {
+        border-color: var(--google-blue-600);
+      }
+
+      a:hover:not(.iron-selected) > .item {
+        background-color: var(--google-grey-refresh-100);
       }
 
       iron-icon {
-        --iron-icon-fill-color: var(--settings-nav-icon-color);
+        --iron-icon-fill-color: var(--menu-icon-color);
         margin-inline-end: 24px;
         pointer-events: none;
         vertical-align: top;
       }
 
-      .iron-selected > iron-icon {
-        fill: var(--cr-link-color);
+      a.iron-selected > .item > iron-icon {
+        fill: var(--menu-link-color);
       }
 
+      /* TODO(crbug.com/950007): Finalize "Advanced" button style. */
       #advancedButton {
-        --ink-color: var(--settings-nav-item-color);
+        --ink-color: var(--menu-text-color);
+        align-items: center;
         background: none;
-        border: none;
         border-radius: initial;
+        border: none;
         box-shadow: none;
+        color: var(--menu-text-color);
+        display: flex;
+        font-weight: 500;
         height: unset;
+        margin-inline-end: 2px;
         margin-top: 8px;
         padding-inline-end: 0;
+        padding-inline-start: 24px;
         text-transform: none;
       }
 
@@ -105,94 +133,135 @@
         selectable="a"
         role="navigation" on-click="onLinkClick_">
       <a href="/internet">
-        <iron-icon icon="settings:network-wifi"></iron-icon>
-        $i18n{internetPageTitle}
+        <div class="item">
+          <iron-icon icon="settings:network-wifi"></iron-icon>
+          $i18n{internetPageTitle}
+        </div>
       </a>
       <a href="/bluetooth">
-        <iron-icon icon="cr:bluetooth"></iron-icon>
-        $i18n{bluetoothPageTitle}
+        <div class="item">
+          <iron-icon icon="cr:bluetooth"></iron-icon>
+          $i18n{bluetoothPageTitle}
+        </div>
       </a>
       <a id="multidevice" href="/multidevice"
           hidden="[[!pageVisibility.multidevice]]">
-        <iron-icon icon="settings:multidevice-better-together-suite">
-        </iron-icon>
-        $i18n{multidevicePageTitle}
+        <div class="item">
+          <iron-icon icon="settings:multidevice-better-together-suite">
+          </iron-icon>
+          $i18n{multidevicePageTitle}
+        </div>
       </a>
       <a id="people" href="/people" hidden="[[!pageVisibility.people]]">
-        <iron-icon icon="cr:person"></iron-icon>
-        $i18n{peoplePageTitle}
+        <div class="item">
+          <iron-icon icon="cr:person"></iron-icon>
+          $i18n{peoplePageTitle}
+        </div>
       </a>
       <a id="personalization" href="/personalization">
-        <iron-icon icon="settings:palette"></iron-icon>
-        $i18n{personalizationPageTitle}
+        <div class="item">
+          <iron-icon icon="settings:palette"></iron-icon>
+          $i18n{personalizationPageTitle}
+        </div>
       </a>
       <a href="/device">
-        <iron-icon icon="settings:laptop-chromebook"></iron-icon>
-        $i18n{devicePageTitle}
+        <div class="item">
+          <iron-icon icon="settings:laptop-chromebook"></iron-icon>
+          $i18n{devicePageTitle}
+        </div>
       </a>
       <!-- TODO(jamescook): Rename path to "/assistant". -->
       <a href="/search" hidden="[[!showAssistant]]">
-        <iron-icon icon="settings:assistant"></iron-icon>
-        $i18n{osAssistantPageTitle}
+        <div class="item">
+          <iron-icon icon="settings:assistant"></iron-icon>
+          $i18n{osAssistantPageTitle}
+        </div>
       </a>
       <a href="/apps" hidden="[[!showApps]]">
-        <iron-icon icon="settings:apps"></iron-icon>
-        $i18n{appsPageTitle}
+        <div class="item">
+          <iron-icon icon="settings:apps"></iron-icon>
+          $i18n{appsPageTitle}
+        </div>
       </a>
       <a href="/androidApps" hidden="[[!showAndroidApps]]">
-        <iron-icon icon="settings:play-prism"></iron-icon>
-        $i18n{androidAppsPageTitle}
+        <div class="item">
+          <iron-icon icon="settings:play-prism"></iron-icon>
+          $i18n{androidAppsPageTitle}
+        </div>
       </a>
       <a href="/crostini" hidden="[[!showCrostini]]">
-        <iron-icon icon="settings:crostini-mascot"></iron-icon>
-        $i18n{crostiniPageTitle}
+        <div class="item">
+          <iron-icon icon="settings:crostini-mascot"></iron-icon>
+          $i18n{crostiniPageTitle}
+        </div>
       </a>
       <a href="/pluginVm" hidden="[[!showPluginVm]]">
-        <iron-icon icon="settings:plugin-vm"></iron-icon>
-        $i18n{pluginVmPageTitle}
+        <div class="item">
+          <iron-icon icon="settings:plugin-vm"></iron-icon>
+          $i18n{pluginVmPageTitle}
+        </div>
       </a>
       <cr-button id="advancedButton" aria-active-attribute="aria-expanded"
           on-click="onAdvancedButtonToggle_"
           hidden="[[!pageVisibility.advancedSettings]]">
         <span>$i18n{advancedPageTitle}</span>
         <iron-icon icon="[[arrowState_(advancedOpened)]]">
-        </iron-icon></cr-button>
+        </iron-icon>
+      </cr-button>
       <iron-collapse id="advancedSubmenu" opened="[[advancedOpened]]"
           hidden="[[!pageVisibility.advancedSettings]]">
         <iron-selector id="subMenu" selectable="a" attr-for-selected="href"
             role="navigation" on-click="onLinkClick_">
           <a href="/dateTime">
-            <iron-icon icon="settings:access-time"></iron-icon>
-            $i18n{dateTimePageTitle}
+            <div class="item">
+              <iron-icon icon="settings:access-time"></iron-icon>
+              $i18n{dateTimePageTitle}
+            </div>
           </a>
           <a href="/privacy">
-            <iron-icon icon="cr:security"></iron-icon>
-            $i18n{privacyPageTitle}
+            <div class="item">
+              <iron-icon icon="cr:security"></iron-icon>
+              $i18n{privacyPageTitle}
+            </div>
           </a>
           <a href="/languages">
-            <iron-icon icon="settings:language"></iron-icon>
-            $i18n{osLanguagesPageTitle}
+            <div class="item">
+              <iron-icon icon="settings:language"></iron-icon>
+              $i18n{osLanguagesPageTitle}
+            </div>
           </a>
           <a href="/downloads">
-            <iron-icon icon="cr:file-download"></iron-icon>
-            $i18n{downloadsPageTitle}
+            <div class="item">
+              <iron-icon icon="cr:file-download"></iron-icon>
+              $i18n{downloadsPageTitle}
+            </div>
           </a>
           <a href="/printing">
-            <iron-icon icon="cr:print"></iron-icon>
-            $i18n{printingPageTitle}
+            <div class="item">
+              <iron-icon icon="cr:print"></iron-icon>
+              $i18n{printingPageTitle}
+            </div>
           </a>
           <a href="/accessibility">
-            <iron-icon icon="settings:accessibility"></iron-icon>
-            $i18n{a11yPageTitle}
+            <div class="item">
+              <iron-icon icon="settings:accessibility"></iron-icon>
+              $i18n{a11yPageTitle}
+            </div>
           </a>
           <a id="reset" href="/reset" hidden="[[!pageVisibility.reset]]">
-            <iron-icon icon="settings:restore"></iron-icon>
-            $i18n{resetPageTitle}
+            <div class="item">
+              <iron-icon icon="settings:restore"></iron-icon>
+              $i18n{resetPageTitle}
+            </div>
           </a>
         </iron-selector>
       </iron-collapse>
       <div id="menuSeparator"></div>
-      <a id="about-menu" href="/help">$i18n{aboutOsPageTitle}</a>
+      <a id="about-menu" href="/help">
+        <div class="item">
+          $i18n{aboutOsPageTitle}
+        </div>
+      </a>
     </iron-selector>
   </template>
   <script src="os_settings_menu.js"></script>
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc b/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc
index 4a3e7a19..9940414a 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_report_uploader_impl.cc
@@ -127,9 +127,6 @@
     const std::string& response_body,
     int response_code,
     int net_error) {
-  UMA_HISTOGRAM_TIMES("SBIRS.ReportUploadTime",
-                      base::TimeTicks::Now() - time_begin_);
-
   Result result = UPLOAD_REQUEST_FAILED;
   std::unique_ptr<ClientIncidentResponse> response;
   if (net_error == net::OK && response_code == net::HTTP_OK) {
diff --git a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
index 6f4cd994..01c92ef 100644
--- a/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/incident_reporting_service.cc
@@ -923,9 +923,6 @@
     }
     return;
   }
-
-  UMA_HISTOGRAM_COUNTS_100("SBIRS.IncidentCount", count);
-
   // Perform final synchronous collection tasks for the report.
   DoExtensionCollection(report->mutable_extension_data());
 
diff --git a/chrome/browser/safe_browsing/incident_reporting/state_store.cc b/chrome/browser/safe_browsing/incident_reporting/state_store.cc
index 32c0a5f6..a18b1ec1 100644
--- a/chrome/browser/safe_browsing/incident_reporting/state_store.cc
+++ b/chrome/browser/safe_browsing/incident_reporting/state_store.cc
@@ -129,20 +129,13 @@
   Transaction transaction(this);
   std::unique_ptr<base::DictionaryValue> value_dict(
       platform_state_store::Load(profile_));
-
-  InitializationResult state_store_init_result = PSS_MATCHES;
-  if (!value_dict) {
-    state_store_init_result = PSS_NULL;
-  } else if (value_dict->empty()) {
-    if (incidents_sent_ && !incidents_sent_->empty())
-      state_store_init_result = PSS_EMPTY;
-    transaction.ClearAll();
-  } else if (!incidents_sent_ || !incidents_sent_->Equals(value_dict.get())) {
-    state_store_init_result = PSS_DIFFERS;
-    transaction.ReplacePrefDict(std::move(value_dict));
+  if (value_dict) {
+    if (value_dict->empty())
+      transaction.ClearAll();
+    else if (!incidents_sent_ || !incidents_sent_->Equals(value_dict.get()))
+      transaction.ReplacePrefDict(std::move(value_dict));
   }
-  UMA_HISTOGRAM_ENUMERATION("SBIRS.StateStoreInit", state_store_init_result,
-                            NUM_INITIALIZATION_RESULTS);
+
   if (incidents_sent_)
     CleanLegacyValues(&transaction);
 }
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
index b6c23c6b6..1e035b5 100644
--- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
+++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model.cc
@@ -208,8 +208,6 @@
                             startup_urls_reset_state(), RESET_STATE_MAX);
   UMA_HISTOGRAM_ENUMERATION("SettingsResetPrompt.ResetState_Homepage",
                             homepage_reset_state(), RESET_STATE_MAX);
-  base::UmaHistogramSparse("SettingsResetPrompt.DelayBeforePromptParam",
-                           prompt_config_->delay_before_prompt().InSeconds());
 }
 
 void SettingsResetPromptModel::InitDefaultSearchData() {
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc
index 3b6c9b8c..6ad8c46 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc
+++ b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.cc
@@ -48,7 +48,7 @@
   std::vector<App> apps;
   if (!app_name.empty()) {
     // TODO: Get the icon and ID and test
-    apps.emplace_back(nullptr, std::move(app_name), nullptr);
+    apps.emplace_back(std::string(), std::move(app_name), std::string());
   }
   return apps;
 }
@@ -64,7 +64,7 @@
       std::move(callback));
 }
 
-void ClickToCallSharingDialogController::OnAppChosen(App app) {
+void ClickToCallSharingDialogController::OnAppChosen(const App& app) {
   ExternalProtocolHandler::LaunchUrlWithoutSecurityCheck(phone_url_,
                                                          web_contents_);
 }
diff --git a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h
index 7882ccb..5b87398 100644
--- a/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h
+++ b/chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h
@@ -33,7 +33,7 @@
   std::vector<App> GetApps() override;
   void OnDeviceChosen(const SharingDeviceInfo& device,
                       SharingService::SendMessageCallback callback) override;
-  void OnAppChosen(App app) override;
+  void OnAppChosen(const App& app) override;
 
  private:
   content::WebContents* web_contents_;
diff --git a/chrome/browser/sharing/sharing_dialog_controller.h b/chrome/browser/sharing/sharing_dialog_controller.h
index e76e2ab..0498802f 100644
--- a/chrome/browser/sharing/sharing_dialog_controller.h
+++ b/chrome/browser/sharing/sharing_dialog_controller.h
@@ -45,7 +45,7 @@
                               SharingService::SendMessageCallback callback) = 0;
 
   // Called when user chooses a local app to complete the task.
-  virtual void OnAppChosen(App app) = 0;
+  virtual void OnAppChosen(const App& app) = 0;
 
   DISALLOW_COPY_AND_ASSIGN(SharingDialogController);
 };
diff --git a/chrome/browser/signin/dice_response_handler_unittest.cc b/chrome/browser/signin/dice_response_handler_unittest.cc
index d41a153..6125709 100644
--- a/chrome/browser/signin/dice_response_handler_unittest.cc
+++ b/chrome/browser/signin/dice_response_handler_unittest.cc
@@ -85,8 +85,9 @@
  protected:
   DiceResponseHandlerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::
-                IO_MOCK_TIME),  // URLRequestContext requires IO.
+            base::test::ScopedTaskEnvironment::MainThreadType::IO,
+            base::test::ScopedTaskEnvironment::TimeSource::
+                MOCK_TIME),  // URLRequestContext requires IO.
         signin_client_(&pref_service_),
         identity_test_env_(/*test_url_loader_factory=*/nullptr,
                            &pref_service_,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 51d56dd..6efb3ac 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2972,6 +2972,8 @@
       "views/send_tab_to_self/send_tab_to_self_icon_view.h",
       "views/session_crashed_bubble_view.cc",
       "views/session_crashed_bubble_view.h",
+      "views/sharing/click_to_call/click_to_call_dialog_view.cc",
+      "views/sharing/click_to_call/click_to_call_dialog_view.h",
       "views/simple_message_box_views.cc",
       "views/simple_message_box_views.h",
       "views/status_bubble_views.cc",
diff --git a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
index 5593be0..d75043f7 100644
--- a/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
+++ b/chrome/browser/ui/app_list/search/search_result_ranker/search_result_ranker_unittest.cc
@@ -76,7 +76,7 @@
  public:
   SearchResultRankerTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
   ~SearchResultRankerTest() override {}
 
   // testing::Test overrides:
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.cc b/chrome/browser/ui/ash/wallpaper_controller_client.cc
index 95a43f3..f81641e 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.cc
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.cc
@@ -149,6 +149,50 @@
   InitController();
 }
 
+void WallpaperControllerClient::SetInitialWallpaper() {
+  // Apply device customization.
+  namespace customization_util = chromeos::customization_wallpaper_util;
+  if (customization_util::ShouldUseCustomizedDefaultWallpaper()) {
+    base::FilePath customized_default_small_path;
+    base::FilePath customized_default_large_path;
+    if (customization_util::GetCustomizedDefaultWallpaperPaths(
+            &customized_default_small_path, &customized_default_large_path)) {
+      wallpaper_controller_->SetCustomizedDefaultWallpaperPaths(
+          customized_default_small_path, customized_default_large_path);
+    }
+  }
+
+  // Guest wallpaper should be initialized when guest logs in.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+          chromeos::switches::kGuestSession)) {
+    return;
+  }
+
+  // Do not set wallpaper in tests.
+  if (chromeos::WizardController::IsZeroDelayEnabled())
+    return;
+
+  // Show the wallpaper of the active user during an user session.
+  if (user_manager::UserManager::Get()->IsUserLoggedIn()) {
+    ShowUserWallpaper(
+        user_manager::UserManager::Get()->GetActiveUser()->GetAccountId());
+    return;
+  }
+
+  // Show a white wallpaper during OOBE.
+  if (session_manager::SessionManager::Get()->session_state() ==
+      session_manager::SessionState::OOBE) {
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(1, 1);
+    bitmap.eraseColor(SK_ColorWHITE);
+    wallpaper_controller_->ShowOneShotWallpaper(
+        gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+    return;
+  }
+
+  ShowWallpaperOnLoginScreen();
+}
+
 // static
 WallpaperControllerClient* WallpaperControllerClient::Get() {
   return g_wallpaper_controller_client_instance;
@@ -457,50 +501,6 @@
                       extensions::AppLaunchSource::kSourceChromeInternal));
 }
 
-void WallpaperControllerClient::OnReadyToSetWallpaper() {
-  // Apply device customization.
-  namespace customization_util = chromeos::customization_wallpaper_util;
-  if (customization_util::ShouldUseCustomizedDefaultWallpaper()) {
-    base::FilePath customized_default_small_path;
-    base::FilePath customized_default_large_path;
-    if (customization_util::GetCustomizedDefaultWallpaperPaths(
-            &customized_default_small_path, &customized_default_large_path)) {
-      wallpaper_controller_->SetCustomizedDefaultWallpaperPaths(
-          customized_default_small_path, customized_default_large_path);
-    }
-  }
-
-  // Guest wallpaper should be initialized when guest logs in.
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
-          chromeos::switches::kGuestSession)) {
-    return;
-  }
-
-  // Do not set wallpaper in tests.
-  if (chromeos::WizardController::IsZeroDelayEnabled())
-    return;
-
-  // Show the wallpaper of the active user during an user session.
-  if (user_manager::UserManager::Get()->IsUserLoggedIn()) {
-    ShowUserWallpaper(
-        user_manager::UserManager::Get()->GetActiveUser()->GetAccountId());
-    return;
-  }
-
-  // Show a white wallpaper during OOBE.
-  if (session_manager::SessionManager::Get()->session_state() ==
-      session_manager::SessionState::OOBE) {
-    SkBitmap bitmap;
-    bitmap.allocN32Pixels(1, 1);
-    bitmap.eraseColor(SK_ColorWHITE);
-    wallpaper_controller_->ShowOneShotWallpaper(
-        gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
-    return;
-  }
-
-  ShowWallpaperOnLoginScreen();
-}
-
 void WallpaperControllerClient::OnFirstWallpaperAnimationFinished() {
   content::NotificationService::current()->Notify(
       chrome::NOTIFICATION_WALLPAPER_ANIMATION_FINISHED,
diff --git a/chrome/browser/ui/ash/wallpaper_controller_client.h b/chrome/browser/ui/ash/wallpaper_controller_client.h
index 11d72c5..16299018 100644
--- a/chrome/browser/ui/ash/wallpaper_controller_client.h
+++ b/chrome/browser/ui/ash/wallpaper_controller_client.h
@@ -28,6 +28,10 @@
   // Tests can provide a mock interface for the ash controller.
   void InitForTesting(ash::WallpaperController* controller);
 
+  // Sets the initial wallpaper. Should be called after the session manager has
+  // been initialized.
+  void SetInitialWallpaper();
+
   static WallpaperControllerClient* Get();
 
   // Returns files identifier for the |account_id|.
@@ -100,7 +104,6 @@
 
   // ash::WallpaperControllerClient:
   void OpenWallpaperPicker() override;
-  void OnReadyToSetWallpaper() override;
   void OnFirstWallpaperAnimationFinished() override;
 
   void DeviceWallpaperImageFilePathChanged();
diff --git a/chrome/browser/ui/search/local_ntp_browsertest.cc b/chrome/browser/ui/search/local_ntp_browsertest.cc
index e7bd0af..1bac48c2 100644
--- a/chrome/browser/ui/search/local_ntp_browsertest.cc
+++ b/chrome/browser/ui/search/local_ntp_browsertest.cc
@@ -37,7 +37,6 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/ntp_tiles/constants.h"
-#include "components/ntp_tiles/features.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/interstitial_page.h"
@@ -109,8 +108,7 @@
   LocalNTPTest()
       : LocalNTPTest(
             /*enabled_features=*/{},
-            /*disabled_features=*/{features::kFirstRunDefaultSearchShortcut,
-                                   ntp_tiles::kDefaultSearchShortcut}) {}
+            /*disabled_features=*/{features::kFirstRunDefaultSearchShortcut}) {}
 
   void SetUpOnMainThread() override {
     // Some tests depend on the prepopulated most visited tiles coming from
@@ -1168,9 +1166,7 @@
 class LocalNTPNoSearchShortcutTest : public LocalNTPTest {
  public:
   LocalNTPNoSearchShortcutTest()
-      : LocalNTPTest({},
-                     {features::kFirstRunDefaultSearchShortcut,
-                      ntp_tiles::kDefaultSearchShortcut}) {}
+      : LocalNTPTest({}, {features::kFirstRunDefaultSearchShortcut}) {}
 };
 
 IN_PROC_BROWSER_TEST_F(LocalNTPNoSearchShortcutTest, SearchShortcutHidden) {
@@ -1185,32 +1181,6 @@
   EXPECT_FALSE(ContainsDefaultSearchTile(iframe));
 }
 
-class LocalNTPNonFRESearchShortcutTest : public LocalNTPTest {
- public:
-  LocalNTPNonFRESearchShortcutTest()
-      : LocalNTPTest({ntp_tiles::kDefaultSearchShortcut}, {}) {}
-
-  void SetUpOnMainThread() override {
-    // Make sure TopSites are available before running the tests.
-    InstantService* instant_service =
-        InstantServiceFactory::GetForProfile(browser()->profile());
-    TestInstantServiceObserver mv_observer(instant_service);
-    instant_service->UpdateMostVisitedInfo();
-    mv_observer.WaitForMostVisitedItems(kDefaultMostVisitedItemCount + 1);
-  }
-};
-
-IN_PROC_BROWSER_TEST_F(LocalNTPNonFRESearchShortcutTest, SearchShortcutAdded) {
-  content::WebContents* active_tab =
-      local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank"));
-  local_ntp_test_utils::NavigateToNTPAndWaitUntilLoaded(browser());
-  ASSERT_TRUE(search::IsInstantNTP(active_tab));
-
-  content::RenderFrameHost* iframe = GetIframe(active_tab, kMostVisitedIframe);
-
-  EXPECT_TRUE(ContainsDefaultSearchTile(iframe));
-}
-
 #if defined(GOOGLE_CHROME_BUILD)
 class LocalNTPFRESearchShortcutTest : public LocalNTPTest {
  public:
diff --git a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
index 6fd4fe9..0c30acaa 100644
--- a/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
+++ b/chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.cc
@@ -68,7 +68,7 @@
   if (!entry)
     return false;
 
-  *url = ShouldDisplayURL() ? entry->GetVirtualURL() : GURL();
+  *url = entry->GetVirtualURL();
   return true;
 }
 
diff --git a/chrome/browser/ui/views/hats/hats_web_dialog.cc b/chrome/browser/ui/views/hats/hats_web_dialog.cc
index dd98b7c..161a905 100644
--- a/chrome/browser/ui/views/hats/hats_web_dialog.cc
+++ b/chrome/browser/ui/views/hats/hats_web_dialog.cc
@@ -4,27 +4,25 @@
 
 #include "chrome/browser/ui/views/hats/hats_web_dialog.h"
 
+#include <algorithm>
+
 #include "base/bind.h"
 #include "base/strings/string_util.h"
-#include "base/task/post_task.h"
-#include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_dialogs.h"
-#include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/hats/hats_service.h"
 #include "chrome/browser/ui/hats/hats_service_factory.h"
+#include "chrome/browser/ui/views/chrome_web_dialog_view.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/common/pref_names.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/grit/browser_resources.h"
-#include "chrome/grit/chromium_strings.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/prefs/pref_service.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/version_info/version_info.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/views/widget/widget.h"
 #include "url/url_canon.h"
 #include "url/url_util.h"
 
@@ -83,10 +81,19 @@
   auto* hats_dialog = new HatsWebDialog(
       HatsServiceFactory::GetForProfile(profile, true)->en_site_id());
 
+  // Create a web dialog aligned to the bottom center of the location bar.
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
-
-  chrome::ShowWebDialog(browser_view->GetWidget()->GetNativeView(), profile,
-                        hats_dialog);
+  LocationBarView* location_bar = browser_view->GetLocationBarView();
+  DCHECK(location_bar);
+  gfx::Rect bounds(location_bar->bounds());
+  views::View::ConvertRectToScreen(browser_view->toolbar(), &bounds);
+  views::Widget::InitParams params;
+  params.bounds = gfx::Rect(
+      bounds.x() +
+          std::max(0, bounds.width() / 2 - kDefaultHatsDialogWidth / 2),
+      bounds.bottom(), kDefaultHatsDialogWidth, kDefaultHatsDialogHeight);
+  chrome::ShowWebDialogWithParams(browser_view->GetWidget()->GetNativeView(),
+                                  profile, hats_dialog, &params);
 }
 
 HatsWebDialog::HatsWebDialog(const std::string& site_id) : site_id_(site_id) {
diff --git a/chrome/browser/ui/views/hats/hats_web_dialog.h b/chrome/browser/ui/views/hats/hats_web_dialog.h
index 93615c1c..01a00bd 100644
--- a/chrome/browser/ui/views/hats/hats_web_dialog.h
+++ b/chrome/browser/ui/views/hats/hats_web_dialog.h
@@ -43,7 +43,6 @@
   bool HandleContextMenu(content::RenderFrameHost* render_frame_host,
                          const content::ContextMenuParams& params) override;
 
-  const std::string html_data_;
   const std::string site_id_;
 
   DISALLOW_COPY_AND_ASSIGN(HatsWebDialog);
diff --git a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc
index 86ded9cd..942cdd05 100644
--- a/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc
+++ b/chrome/browser/ui/views/media_router/cast_dialog_no_sinks_view_unittest.cc
@@ -23,7 +23,8 @@
 
   void SetUp() override {
     auto thread_bundle = std::make_unique<content::TestBrowserThreadBundle>(
-        base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME);
+        base::test::ScopedTaskEnvironment::MainThreadType::UI,
+        base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
     thread_bundle_ = thread_bundle.get();
     set_scoped_task_environment(std::move(thread_bundle));
     set_views_delegate(std::make_unique<ChromeTestViewsDelegate>());
diff --git a/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc b/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc
index 0840575c..ca2c532 100644
--- a/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc
+++ b/chrome/browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc
@@ -137,7 +137,7 @@
  protected:
   RelaunchNotificationControllerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         scoped_local_state_(TestingBrowserProcess::GetGlobal()),
         upgrade_detector_(scoped_task_environment_.GetMockClock(),
diff --git a/chrome/browser/ui/views/relaunch_notification/wall_clock_timer_unittest.cc b/chrome/browser/ui/views/relaunch_notification/wall_clock_timer_unittest.cc
index 8b79527e..3d67e811 100644
--- a/chrome/browser/ui/views/relaunch_notification/wall_clock_timer_unittest.cc
+++ b/chrome/browser/ui/views/relaunch_notification/wall_clock_timer_unittest.cc
@@ -36,7 +36,7 @@
  protected:
   WallClockTimerTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
     auto mock_power_monitor_source = std::make_unique<StubPowerMonitorSource>();
     mock_power_monitor_source_ = mock_power_monitor_source.get();
     base::PowerMonitor::Initialize(std::move(mock_power_monitor_source));
diff --git a/chrome/browser/ui/views/sharing/OWNERS b/chrome/browser/ui/views/sharing/OWNERS
new file mode 100644
index 0000000..e6dd3dd
--- /dev/null
+++ b/chrome/browser/ui/views/sharing/OWNERS
@@ -0,0 +1,3 @@
+file://chrome/browser/sharing/OWNERS
+
+# COMPONENT: UI>Browser>Sharing
diff --git a/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.cc b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.cc
new file mode 100644
index 0000000..e478b20
--- /dev/null
+++ b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.cc
@@ -0,0 +1,145 @@
+// 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 "chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/app/vector_icons/vector_icons.h"
+#include "chrome/browser/ui/views/chrome_layout_provider.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
+
+#include "base/logging.h"
+
+namespace {
+// Icon sizes in DIP.
+// TODO: Confirm the number with the team designer.
+constexpr int kPrimaryIconSize = 20;
+constexpr int kPrimaryIconBorderWidth = 6;
+
+SkColor GetColorfromTheme() {
+  const ui::NativeTheme* native_theme =
+      ui::NativeTheme::GetInstanceForNativeUi();
+  return native_theme->GetSystemColor(
+      ui::NativeTheme::kColorId_DefaultIconColor);
+}
+
+std::unique_ptr<views::ImageView> CreateDeviceIcon(
+    const sync_pb::SyncEnums::DeviceType device_type) {
+  const gfx::VectorIcon* vector_icon;
+  if (device_type == sync_pb::SyncEnums::TYPE_TABLET) {
+    vector_icon = &kTabletIcon;
+  } else {
+    vector_icon = &kHardwareSmartphoneIcon;
+  }
+  gfx::ImageSkia image = gfx::CreateVectorIcon(*vector_icon, kPrimaryIconSize,
+                                               GetColorfromTheme());
+  auto icon_view = std::make_unique<views::ImageView>();
+  icon_view->SetImage(image);
+  icon_view->SetBorder(
+      views::CreateEmptyBorder(gfx::Insets(kPrimaryIconBorderWidth)));
+  return icon_view;
+}
+
+}  // namespace
+
+ClickToCallDialogView::ClickToCallDialogView(
+    views::View* anchor_view,
+    PageActionIconView* icon_view,
+    content::WebContents* web_contents,
+    std::unique_ptr<ClickToCallSharingDialogController> controller)
+    : LocationBarBubbleDelegateView(anchor_view, gfx::Point(), web_contents),
+      icon_view_(icon_view),
+      controller_(std::move(controller)),
+      devices_(controller_->GetSyncedDevices()),
+      apps_(controller_->GetApps()) {}
+
+ClickToCallDialogView::~ClickToCallDialogView() = default;
+
+int ClickToCallDialogView::GetDialogButtons() const {
+  return ui::DIALOG_BUTTON_NONE;
+}
+
+void ClickToCallDialogView::Init() {
+  auto* provider = ChromeLayoutProvider::Get();
+  set_margins(
+      gfx::Insets(provider->GetDistanceMetric(
+                      views::DISTANCE_DIALOG_CONTENT_MARGIN_TOP_CONTROL),
+                  0,
+                  provider->GetDistanceMetric(
+                      views::DISTANCE_DIALOG_CONTENT_MARGIN_BOTTOM_CONTROL),
+                  0));
+  SetLayoutManager(std::make_unique<views::FillLayout>());
+
+  PopulateDialogView();
+}
+
+void ClickToCallDialogView::ButtonPressed(views::Button* sender,
+                                          const ui::Event& event) {
+  if (!sender || sender->tag() < 0)
+    return;
+  size_t index = static_cast<size_t>(sender->tag());
+  DCHECK(index < devices_.size() + apps_.size());
+
+  if (index < devices_.size()) {
+    controller_->OnDeviceChosen(devices_[index], base::DoNothing());
+    CloseBubble();
+    return;
+  }
+
+  index -= devices_.size();
+
+  if (index < apps_.size()) {
+    controller_->OnAppChosen(apps_[index]);
+    CloseBubble();
+  }
+}
+
+void ClickToCallDialogView::PopulateDialogView() {
+  dialog_buttons_.clear();
+  int tag = 0;
+  views::View* dialog_view = new views::View();
+  dialog_view->SetLayoutManager(std::make_unique<views::BoxLayout>(
+      views::BoxLayout::Orientation::kVertical));
+  AddChildView(dialog_view);
+  // Devices:
+  for (const auto& device : devices_) {
+    auto dialog_button = std::make_unique<HoverButton>(
+        this, CreateDeviceIcon(device.device_type()),
+        base::UTF8ToUTF16(device.human_readable_name()),
+        base::string16() /* No subtitle */);
+    dialog_button->SetEnabled(true);
+    dialog_button->set_tag(tag++);
+    dialog_buttons_.push_back(
+        dialog_view->AddChildView(std::move(dialog_button)));
+  }
+
+  // Apps:
+  for (const auto& app : apps_) {
+    auto dialog_button = std::make_unique<HoverButton>(this, app.name);
+    // TODO(yasmo): Create Icon View.
+    dialog_button->SetEnabled(true);
+    dialog_button->set_tag(tag++);
+    dialog_buttons_.push_back(
+        dialog_view->AddChildView(std::move(dialog_button)));
+  }
+
+  // TODO: See if GetWidget can be not null:
+  if (GetWidget())
+    SizeToContents();
+}
+
+gfx::Size ClickToCallDialogView::CalculatePreferredSize() const {
+  const int width = ChromeLayoutProvider::Get()->GetDistanceMetric(
+      DISTANCE_BUBBLE_PREFERRED_WIDTH);
+  return gfx::Size(width, GetHeightForWidth(width));
+}
+
+bool ClickToCallDialogView::ShouldShowCloseButton() const {
+  return true;
+}
+
+base::string16 ClickToCallDialogView::GetWindowTitle() const {
+  return base::UTF8ToUTF16(controller_->GetTitle());
+}
diff --git a/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h
new file mode 100644
index 0000000..61b84a50
--- /dev/null
+++ b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h
@@ -0,0 +1,76 @@
+// 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_BROWSER_UI_VIEWS_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_DIALOG_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_DIALOG_VIEW_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "chrome/browser/sharing/click_to_call/click_to_call_sharing_dialog_controller.h"
+#include "chrome/browser/sharing/sharing_device_info.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
+#include "chrome/browser/ui/views/hover_button.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
+#include "chrome/browser/ui/views/page_action/omnibox_page_action_icon_container_view.h"
+#include "ui/views/controls/button/button.h"
+
+namespace views {
+class View;
+}  // namespace views
+
+class PageActionIconView;
+
+class ClickToCallDialogView : public views::ButtonListener,
+                              public LocationBarBubbleDelegateView {
+ public:
+  // Bubble will be anchored to |anchor_view|.
+  ClickToCallDialogView(
+      views::View* anchor_view,
+      PageActionIconView* icon_view,
+      content::WebContents* web_contents,
+      std::unique_ptr<ClickToCallSharingDialogController> controller);
+
+  ~ClickToCallDialogView() override;
+
+  // views::WidgetDelegateView:
+  bool ShouldShowCloseButton() const override;
+  base::string16 GetWindowTitle() const override;
+
+  // views::DialogDelegate:
+  int GetDialogButtons() const override;
+
+  // views::ButtonListener:
+  void ButtonPressed(views::Button* sender, const ui::Event& event) override;
+
+  // views::View:
+  gfx::Size CalculatePreferredSize() const override;
+
+ private:
+  friend class ClickToCallDialogViewTest;
+  FRIEND_TEST_ALL_PREFIXES(ClickToCallDialogViewTest, PopulateDialogView);
+  FRIEND_TEST_ALL_PREFIXES(ClickToCallDialogViewTest, DevicePressed);
+  FRIEND_TEST_ALL_PREFIXES(ClickToCallDialogViewTest, AppPressed);
+
+  // views::BubbleDialogDelegateView:
+  void Init() override;
+
+  // Populates the dialog view containing valid devices and apps.
+  void PopulateDialogView();
+
+  PageActionIconView* icon_view_;
+  std::unique_ptr<ClickToCallSharingDialogController> controller_;
+  // Contains references to device and app buttons in
+  // the order they appear.
+  std::vector<HoverButton*> dialog_buttons_;
+  std::vector<SharingDeviceInfo> devices_;
+  std::vector<ClickToCallSharingDialogController::App> apps_;
+
+  DISALLOW_COPY_AND_ASSIGN(ClickToCallDialogView);
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_SHARING_CLICK_TO_CALL_CLICK_TO_CALL_DIALOG_VIEW_H_
diff --git a/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view_unittest.cc b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view_unittest.cc
new file mode 100644
index 0000000..56d9918
--- /dev/null
+++ b/chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view_unittest.cc
@@ -0,0 +1,182 @@
+// 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 "chrome/browser/ui/views/sharing/click_to_call/click_to_call_dialog_view.h"
+
+#include <map>
+#include <string>
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/test/simple_test_clock.h"
+#include "chrome/test/base/testing_profile.h"
+#include "chrome/test/views/chrome_views_test_base.h"
+#include "components/send_tab_to_self/target_device_info.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event_utils.h"
+
+using namespace testing;
+
+namespace {
+
+class ClickToCallSharingDialogControllerMock
+    : public ClickToCallSharingDialogController {
+ public:
+  ClickToCallSharingDialogControllerMock(content::WebContents* web_contents,
+                                         SharingService* sharing_service,
+                                         std::string phone_number)
+      : ClickToCallSharingDialogController(web_contents,
+                                           sharing_service,
+                                           phone_number) {}
+  ~ClickToCallSharingDialogControllerMock() override = default;
+
+  MOCK_METHOD2(OnDeviceChosen,
+               void(const SharingDeviceInfo& device,
+                    SharingService::SendMessageCallback callback));
+  MOCK_METHOD1(OnAppChosen, void(const App& app));
+
+  MOCK_METHOD0(GetSyncedDevices, std::vector<SharingDeviceInfo>());
+
+  MOCK_METHOD0(GetApps, std::vector<App>());
+};
+
+class ClickToCallDialogViewMock : public ClickToCallDialogView {
+ public:
+  ClickToCallDialogViewMock(
+      views::View* anchor_view,
+      PageActionIconView* icon_view,
+      content::WebContents* web_contents,
+      std::unique_ptr<ClickToCallSharingDialogController> controller)
+      : ClickToCallDialogView(anchor_view,
+                              icon_view,
+                              web_contents,
+                              std::move(controller)) {}
+  ~ClickToCallDialogViewMock() override = default;
+
+  // The delegate cannot find widget since it is created from a null profile.
+  // This method will be called inside ButtonPressed(). Unit tests will
+  // crash without mocking.
+  MOCK_METHOD0(CloseBubble, void());
+};
+
+}  // namespace
+
+MATCHER_P(DeviceEquals, device, "") {
+  return device->guid() == arg.guid();
+}
+
+MATCHER_P(AppEquals, app, "") {
+  return app->name == arg.name;
+}
+
+class ClickToCallDialogViewTest : public ChromeViewsTestBase {
+ protected:
+  void SetUp() override {
+    ChromeViewsTestBase::SetUp();
+
+    // Create an anchor for the bubble.
+    views::Widget::InitParams params =
+        CreateParams(views::Widget::InitParams::TYPE_WINDOW);
+    params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+    anchor_widget_ = std::make_unique<views::Widget>();
+    anchor_widget_->Init(params);
+
+    controller_ = std::make_unique<ClickToCallSharingDialogControllerMock>(
+        nullptr, nullptr, std::string());
+
+    devices_ = SetUpDevices();
+    apps_ = SetUpApps();
+  }
+
+  void TearDown() override {
+    anchor_widget_.reset();
+    ChromeViewsTestBase::TearDown();
+  }
+
+  std::vector<SharingDeviceInfo> SetUpDevices() {
+    std::vector<SharingDeviceInfo> devices;
+    devices.emplace_back("device_guid_1", "device1",
+                         sync_pb::SyncEnums::TYPE_PHONE, base::Time::Now(), 1);
+    devices.emplace_back("device_guid_2", "device2",
+                         sync_pb::SyncEnums::TYPE_PHONE, base::Time::Now(), 1);
+    devices.emplace_back("device_guid_3", "device3",
+                         sync_pb::SyncEnums::TYPE_PHONE, base::Time::Now(), 1);
+    return devices;
+  }
+
+  std::vector<ClickToCallSharingDialogController::App> SetUpApps() {
+    std::vector<ClickToCallSharingDialogController::App> apps;
+    apps.emplace_back(std::string(), base::UTF8ToUTF16("app_1"), std::string());
+    apps.emplace_back(std::string(), base::UTF8ToUTF16("app_2"), std::string());
+    return apps;
+  }
+
+  std::unique_ptr<views::Widget> anchor_widget_;
+  std::unique_ptr<ClickToCallSharingDialogControllerMock> controller_;
+  std::vector<SharingDeviceInfo> devices_;
+  std::vector<ClickToCallSharingDialogController::App> apps_;
+};
+
+TEST_F(ClickToCallDialogViewTest, PopulateDialogView) {
+  EXPECT_CALL(*controller_.get(), GetSyncedDevices())
+      .WillOnce(Return(ByMove(std::move(devices_))));
+  EXPECT_CALL(*controller_.get(), GetApps())
+      .WillOnce(Return(ByMove(std::move(apps_))));
+  std::unique_ptr<ClickToCallDialogView> bubble_view_ =
+      std::make_unique<ClickToCallDialogViewMock>(
+          anchor_widget_->GetContentsView(), nullptr, nullptr,
+          std::move(controller_));
+
+  bubble_view_->Init();
+  EXPECT_EQ(5UL, bubble_view_->dialog_buttons_.size());
+}
+
+TEST_F(ClickToCallDialogViewTest, DevicePressed) {
+  SharingDeviceInfo sharing_device_info("device_guid_2", "device2",
+                                        sync_pb::SyncEnums::TYPE_PHONE,
+                                        base::Time::Now(), 1);
+  EXPECT_CALL(*controller_.get(), GetSyncedDevices())
+      .WillOnce(Return(ByMove(std::move(devices_))));
+  EXPECT_CALL(*controller_.get(), GetApps())
+      .WillOnce(Return(ByMove(std::move(apps_))));
+  EXPECT_CALL(*controller_.get(),
+              OnDeviceChosen(DeviceEquals(&sharing_device_info), _));
+
+  std::unique_ptr<ClickToCallDialogView> bubble_view_ =
+      std::make_unique<ClickToCallDialogViewMock>(
+          anchor_widget_->GetContentsView(), nullptr, nullptr,
+          std::move(controller_));
+
+  bubble_view_->Init();
+
+  const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                             ui::EventTimeForNow(), 0, 0);
+
+  // Choose second device: device1(tag=0), device2(tag=1)
+  bubble_view_->ButtonPressed(bubble_view_->dialog_buttons_[1], event);
+}
+
+TEST_F(ClickToCallDialogViewTest, AppPressed) {
+  ClickToCallSharingDialogController::App app(
+      std::string(), base::UTF8ToUTF16("app_1"), std::string());
+  EXPECT_CALL(*controller_.get(), GetSyncedDevices())
+      .WillOnce(Return(ByMove(std::move(devices_))));
+  EXPECT_CALL(*controller_.get(), GetApps())
+      .WillOnce(Return(ByMove(std::move(apps_))));
+  EXPECT_CALL(*controller_.get(), OnAppChosen(AppEquals(&app)));
+
+  std::unique_ptr<ClickToCallDialogView> bubble_view_ =
+      std::make_unique<ClickToCallDialogViewMock>(
+          anchor_widget_->GetContentsView(), nullptr, nullptr,
+          std::move(controller_));
+
+  bubble_view_->Init();
+
+  const ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                             ui::EventTimeForNow(), 0, 0);
+
+  // Choose first app: device1(tag=0), device2(tag=1), device3(tag=2),
+  // app1(tag=3)
+  bubble_view_->ButtonPressed(bubble_view_->dialog_buttons_[3], event);
+}
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index a36900a..f1d3bc18a 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -209,7 +209,8 @@
 Tab::~Tab() {
   // Observer must be unregistered before child views are destroyed.
   tab_close_button_observer_.reset();
-  controller_->UpdateHoverCard(nullptr);
+  if (controller_->HoverCardIsShowingForTab(this))
+    controller_->UpdateHoverCard(nullptr);
 }
 
 void Tab::AnimationEnded(const gfx::Animation* animation) {
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h
index dac07175..c87a9e4 100644
--- a/chrome/browser/ui/views/tabs/tab_controller.h
+++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -109,6 +109,9 @@
   // will cause the tab hover card to be hidden.
   virtual void UpdateHoverCard(Tab* tab) = 0;
 
+  // Returns true if the hover card is showing for the given tab.
+  virtual bool HoverCardIsShowingForTab(Tab* tab) = 0;
+
   // Returns whether |tab| needs to be painted. When this returns true, |clip|
   // is set to the path which should be clipped out of the current tab's region
   // (for hit testing or painting), if any.  |clip| is only non-empty when
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index b9566df..b249d17 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1638,6 +1638,14 @@
     hover_card_->FadeOutToHide();
 }
 
+bool TabStrip::HoverCardIsShowingForTab(Tab* tab) {
+  if (!base::FeatureList::IsEnabled(features::kTabHoverCards))
+    return false;
+
+  return hover_card_ && hover_card_->GetWidget()->IsVisible() &&
+         !hover_card_->IsFadingOut() && hover_card_->GetAnchorView() == tab;
+}
+
 bool TabStrip::ShouldPaintTab(const Tab* tab, float scale, SkPath* clip) {
   if (!MaySetClip())
     return true;
@@ -2918,14 +2926,6 @@
       extra_vertical_space / 2, kHorizontalInset, 0, kHorizontalInset)));
 }
 
-bool TabStrip::HoverCardIsShowingForTab(Tab* tab) {
-  if (!base::FeatureList::IsEnabled(features::kTabHoverCards))
-    return false;
-
-  return hover_card_ && hover_card_->GetWidget()->IsVisible() &&
-         !hover_card_->IsFadingOut() && hover_card_->GetAnchorView() == tab;
-}
-
 void TabStrip::ButtonPressed(views::Button* sender, const ui::Event& event) {
   if (sender == new_tab_button_) {
     base::RecordAction(base::UserMetricsAction("NewTab_Button"));
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
index 20ea2fc..8443001 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.h
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -252,6 +252,7 @@
   void OnMouseEventInTab(views::View* source,
                          const ui::MouseEvent& event) override;
   void UpdateHoverCard(Tab* tab) override;
+  bool HoverCardIsShowingForTab(Tab* tab) override;
   bool ShouldPaintTab(const Tab* tab, float scale, SkPath* clip) override;
   int GetStrokeThickness() const override;
   bool CanPaintThrobberToLayer() const override;
@@ -524,9 +525,6 @@
   // whenever any input of the computation of the border's sizing changes.
   void UpdateNewTabButtonBorder();
 
-  // Returns true if the hover card is showing for the given tab.
-  bool HoverCardIsShowingForTab(Tab* tab);
-
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc
index ed448526..740968a 100644
--- a/chrome/browser/ui/views/tabs/tab_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -79,6 +79,7 @@
   void OnMouseEventInTab(views::View* source,
                          const ui::MouseEvent& event) override {}
   void UpdateHoverCard(Tab* tab) override {}
+  bool HoverCardIsShowingForTab(Tab* tab) override { return false; }
   bool ShouldPaintTab(const Tab* tab, float scale, SkPath* clip) override {
     return true;
   }
diff --git a/chrome/browser/ui/webauthn/ble_device_hover_list_model.cc b/chrome/browser/ui/webauthn/ble_device_hover_list_model.cc
index ecd90162..3320c7c 100644
--- a/chrome/browser/ui/webauthn/ble_device_hover_list_model.cc
+++ b/chrome/browser/ui/webauthn/ble_device_hover_list_model.cc
@@ -29,9 +29,8 @@
 }
 
 bool ShouldShowItemInView(const AuthenticatorReference& authenticator) {
-  return authenticator.is_in_pairing_mode() && !authenticator.is_paired() &&
-         authenticator.transport() ==
-             AuthenticatorTransport::kBluetoothLowEnergy;
+  return authenticator.is_in_pairing_mode && !authenticator.is_paired &&
+         authenticator.transport == AuthenticatorTransport::kBluetoothLowEnergy;
 }
 
 }  // namespace
@@ -42,8 +41,7 @@
     : authenticator_list_(authenticator_list), delegate_(delegate) {
   int tag_counter = 0;
   for (const auto& authenticator : authenticator_list_->authenticator_list()) {
-    authenticator_tags_.emplace(++tag_counter,
-                                authenticator.authenticator_id());
+    authenticator_tags_.emplace(++tag_counter, authenticator.authenticator_id);
   }
 
   authenticator_list_->SetObserver(this);
@@ -74,7 +72,7 @@
 }
 
 base::string16 BleDeviceHoverListModel::GetItemText(int item_tag) const {
-  return GetAuthenticator(item_tag)->authenticator_display_name();
+  return GetAuthenticator(item_tag)->authenticator_display_name;
 }
 
 base::string16 BleDeviceHoverListModel::GetDescriptionText(int item_tag) const {
@@ -121,7 +119,7 @@
   auto item_tag = authenticator_tags_.empty()
                       ? 0
                       : (--authenticator_tags_.end())->first + 1;
-  authenticator_tags_.emplace(item_tag, authenticator.authenticator_id());
+  authenticator_tags_.emplace(item_tag, authenticator.authenticator_id);
 
   if (ShouldShowItemInView(authenticator) && observer())
     observer()->OnListItemAdded(item_tag);
@@ -129,7 +127,7 @@
 
 void BleDeviceHoverListModel::OnAuthenticatorRemoved(
     const AuthenticatorReference& removed_authenticator) {
-  const auto& authenticator_id = removed_authenticator.authenticator_id();
+  const auto& authenticator_id = removed_authenticator.authenticator_id;
   auto it = FindElementByValue(&authenticator_tags_, authenticator_id);
   CHECK(it != authenticator_tags_.end());
   const auto item_tag = it->first;
@@ -144,7 +142,7 @@
     return;
 
   auto it = FindElementByValue(&authenticator_tags_,
-                               changed_authenticator.authenticator_id());
+                               changed_authenticator.authenticator_id);
   CHECK(it != authenticator_tags_.end());
   const auto changed_item_tag = it->first;
   if (ShouldShowItemInView(changed_authenticator)) {
@@ -161,5 +159,5 @@
     base::StringPiece previous_id) {
   auto it = FindElementByValue(&authenticator_tags_, previous_id);
   CHECK(it != authenticator_tags_.end());
-  it->second = changed_authenticator.authenticator_id();
+  it->second = changed_authenticator.authenticator_id;
 }
diff --git a/chrome/browser/ui/webauthn/sheet_models.cc b/chrome/browser/ui/webauthn/sheet_models.cc
index d04ff76..df2b3f4 100644
--- a/chrome/browser/ui/webauthn/sheet_models.cc
+++ b/chrome/browser/ui/webauthn/sheet_models.cc
@@ -607,7 +607,7 @@
   DCHECK(ble_authenticator);
   return l10n_util::GetStringFUTF16(
       IDS_WEBAUTHN_BLE_PIN_ENTRY_TITLE,
-      ble_authenticator->authenticator_display_name());
+      ble_authenticator->authenticator_display_name);
 }
 
 base::string16 AuthenticatorBlePinEntrySheetModel::GetStepDescription() const {
diff --git a/chrome/browser/ui/webui/certificates_handler.cc b/chrome/browser/ui/webui/certificates_handler.cc
index d8a430d9..9db6be9b 100644
--- a/chrome/browser/ui/webui/certificates_handler.cc
+++ b/chrome/browser/ui/webui/certificates_handler.cc
@@ -80,7 +80,7 @@
 
 #if defined(OS_CHROMEOS)
 // Enumeration of certificate management permissions which corresponds to
-// values of policy CertificateManagementAllowed.
+// values of policy ClientCertificateManagementAllowed.
 enum class CertificateManagementPermission : int {
   // Allow users to manage all certificates
   kAll = 0,
@@ -576,7 +576,7 @@
   CHECK(args->GetBoolean(1, &use_hardware_backed_));
 
 #if defined(OS_CHROMEOS)
-  CHECK(IsCertificateManagementAllowedPolicy(Slot::kUser))
+  CHECK(IsClientCertificateManagementAllowedPolicy(Slot::kUser))
       << "Importing certificates not allowed by policy";
 #endif
 
@@ -741,7 +741,7 @@
   AssignWebUICallbackId(args);
 
 #if defined(OS_CHROMEOS)
-  CHECK(IsCertificateManagementAllowedPolicy(Slot::kUser))
+  CHECK(IsClientCertificateManagementAllowedPolicy(Slot::kUser))
       << "Importing certificates not allowed by policy";
 #endif
 
@@ -812,11 +812,6 @@
   CHECK_EQ(1U, args->GetSize());
   AssignWebUICallbackId(args);
 
-#if defined(OS_CHROMEOS)
-  CHECK(IsCertificateManagementAllowedPolicy(Slot::kUser))
-      << "Importing certificates not allowed by policy";
-#endif
-
   select_file_dialog_ = ui::SelectFileDialog::Create(
       this,
       std::make_unique<ChromeSelectFilePolicy>(web_ui()->GetWebContents()));
@@ -949,12 +944,14 @@
 }
 
 void CertificatesHandler::CertificateManagerModelReady() {
-  bool import_allowed = true;
+  bool client_import_allowed = true;
 #if defined(OS_CHROMEOS)
-  import_allowed = IsCertificateManagementAllowedPolicy(Slot::kUser);
+  client_import_allowed =
+      IsClientCertificateManagementAllowedPolicy(Slot::kUser);
 #endif
   if (IsJavascriptAllowed()) {
-    FireWebUIListener("certificates-model-ready", base::Value(import_allowed));
+    FireWebUIListener("certificates-model-ready",
+                      base::Value(client_import_allowed));
   }
   certificate_manager_model_->Refresh();
 }
@@ -1135,12 +1132,12 @@
 }
 
 #if defined(OS_CHROMEOS)
-bool CertificatesHandler::IsCertificateManagementAllowedPolicy(
+bool CertificatesHandler::IsClientCertificateManagementAllowedPolicy(
     Slot slot) const {
   Profile* profile = Profile::FromWebUI(web_ui());
   PrefService* prefs = profile->GetPrefs();
   auto policy_value = static_cast<CertificateManagementPermission>(
-      prefs->GetInteger(prefs::kCertificateManagementAllowed));
+      prefs->GetInteger(prefs::kClientCertificateManagementAllowed));
 
   if (slot == Slot::kUser) {
     return policy_value != CertificateManagementPermission::kNone;
@@ -1156,8 +1153,9 @@
   }
 
 #if defined(OS_CHROMEOS)
-  return !IsCertificateManagementAllowedPolicy(
-      cert_info->device_wide() ? Slot::kSystem : Slot::kUser);
+  return cert_info->type() == net::CertType::USER_CERT &&
+         !IsClientCertificateManagementAllowedPolicy(
+             cert_info->device_wide() ? Slot::kSystem : Slot::kUser);
 #else
   return false;
 #endif
@@ -1169,7 +1167,7 @@
   // Allow users to manage all certificates by default. This can be overridden
   // by enterprise policy.
   registry->RegisterIntegerPref(
-      prefs::kCertificateManagementAllowed,
+      prefs::kClientCertificateManagementAllowed,
       static_cast<int>(CertificateManagementPermission::kAll));
 }
 #endif  // defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/webui/certificates_handler.h b/chrome/browser/ui/webui/certificates_handler.h
index 1993c59..8a688f13 100644
--- a/chrome/browser/ui/webui/certificates_handler.h
+++ b/chrome/browser/ui/webui/certificates_handler.h
@@ -178,13 +178,14 @@
 
 #if defined(OS_CHROMEOS)
   // Returns true if the user may manage certificates on |slot| according
-  // CertificateManagementAllowed to policy.
-  bool IsCertificateManagementAllowedPolicy(Slot slot) const;
+  // ClientCertificateManagementAllowed to policy.
+  bool IsClientCertificateManagementAllowedPolicy(Slot slot) const;
 #endif
 
   // Returns true if the certificate represented by |cert_info| is read-only
   // (i.e. can not be deleted). Evaluates the certificate attributes and, on
-  // Chrome OS devices, the enterprise policy CertificateManagementAllowed.
+  // Chrome OS devices, the enterprise policy
+  // ClientCertificateManagementAllowed.
   bool IsCertificateReadOnly(
       const CertificateManagerModel::CertInfo* cert_info);
 
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
index 3fa20360..5742c4d 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -59,6 +59,7 @@
 #include "chromeos/constants/devicetype.h"
 #include "chromeos/dbus/util/version_loader.h"
 #include "chromeos/login/auth/challenge_response/cert_utils.h"
+#include "chromeos/login/auth/cryptohome_key_constants.h"
 #include "chromeos/login/auth/saml_password_attributes.h"
 #include "chromeos/login/auth/user_context.h"
 #include "chromeos/settings/cros_settings_names.h"
@@ -753,10 +754,12 @@
 
   set_populated_email(username);
   DCHECK(authpolicy_login_helper_);
+  Key key(password);
+  key.SetLabel(kCryptohomeGaiaKeyLabel);
   authpolicy_login_helper_->AuthenticateUser(
       username, std::string() /* object_guid */, password,
       base::BindOnce(&GaiaScreenHandler::DoAdAuth, weak_factory_.GetWeakPtr(),
-                     username, Key(password)));
+                     username, key));
 }
 
 void GaiaScreenHandler::HandleCancelActiveDirectoryAuth() {
@@ -1305,7 +1308,9 @@
     user_context->GetMutableChallengeResponseKeys()->push_back(
         challenge_response_key);
   } else {
-    user_context->SetKey(Key(password));
+    Key key(password);
+    key.SetLabel(kCryptohomeGaiaKeyLabel);
+    user_context->SetKey(key);
     user_context->SetPasswordKey(Key(password));
   }
   if (!auth_code.empty())
diff --git a/chrome/browser/ui/webui/favicon_source.cc b/chrome/browser/ui/webui/favicon_source.cc
index 4d23446..5877c66 100644
--- a/chrome/browser/ui/webui/favicon_source.cc
+++ b/chrome/browser/ui/webui/favicon_source.cc
@@ -34,14 +34,14 @@
 
 namespace {
 
-// web_contents->GetURL in general will not necessarily yield the original URL
-// that started the request, but we're only interested in verifying if it was
-// issued by a history page, for whom this is the case. If it is not possible to
-// obtain the URL, we return the empty GURL.
+// web_contents->GetLastCommittedURL in general will not necessarily yield the
+// original URL that started the request, but we're only interested in verifying
+// if it was issued by a history page, for whom this is the case. If it is not
+// possible to obtain the URL, we return the empty GURL.
 GURL GetUnsafeRequestOrigin(
     const content::ResourceRequestInfo::WebContentsGetter& wc_getter) {
   content::WebContents* web_contents = wc_getter.Run();
-  return web_contents ? web_contents->GetURL() : GURL();
+  return web_contents ? web_contents->GetLastCommittedURL() : GURL();
 }
 
 bool ParseHistoryUiOrigin(const GURL& url,
diff --git a/chrome/browser/ui/webui/favicon_source_unittest.cc b/chrome/browser/ui/webui/favicon_source_unittest.cc
index 1c9bc3f..7aa1ff7 100644
--- a/chrome/browser/ui/webui/favicon_source_unittest.cc
+++ b/chrome/browser/ui/webui/favicon_source_unittest.cc
@@ -4,11 +4,23 @@
 
 #include "chrome/browser/ui/webui/favicon_source.h"
 
+#include <memory>
+#include <utility>
+
+#include "base/test/bind_test_util.h"
+#include "chrome/browser/favicon/favicon_service_factory.h"
+#include "chrome/browser/favicon/history_ui_favicon_request_handler_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/favicon/core/history_ui_favicon_request_handler.h"
+#include "components/favicon/core/test/mock_favicon_service.h"
 #include "components/favicon_base/favicon_url_parser.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/resource_request_info.h"
+#include "content/public/browser/web_contents.h"
 #include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/web_contents_tester.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/native_theme/test_native_theme.h"
@@ -20,14 +32,43 @@
 using testing::Return;
 using testing::ReturnArg;
 
+namespace {
+
+const int kDummyTaskId = 1;
+
+}  // namespace
+
 void Noop(scoped_refptr<base::RefCountedMemory>) {}
 
+class MockHistoryUiFaviconRequestHandler
+    : public favicon::HistoryUiFaviconRequestHandler {
+ public:
+  MockHistoryUiFaviconRequestHandler() = default;
+  ~MockHistoryUiFaviconRequestHandler() override = default;
+
+  MOCK_METHOD7(GetRawFaviconForPageURL,
+               void(const GURL& page_url,
+                    int desired_size_in_pixel,
+                    favicon_base::FaviconRawBitmapCallback callback,
+                    favicon::HistoryUiFaviconRequestOrigin request_origin,
+                    favicon::FaviconRequestPlatform request_platform,
+                    const GURL& icon_url_for_uma,
+                    base::CancelableTaskTracker* tracker));
+
+  MOCK_METHOD5(GetFaviconImageForPageURL,
+               void(const GURL& page_url,
+                    favicon_base::FaviconImageCallback callback,
+                    favicon::HistoryUiFaviconRequestOrigin request_origin,
+                    const GURL& icon_url_for_uma,
+                    base::CancelableTaskTracker* tracker));
+};
+
 class TestFaviconSource : public FaviconSource {
  public:
-  // chrome::FaviconUrlFormat::kFavicon2 is arbitrary below.
-  TestFaviconSource(Profile* profile, ui::NativeTheme* theme)
-      : FaviconSource(profile, chrome::FaviconUrlFormat::kFavicon2),
-        theme_(theme) {}
+  TestFaviconSource(chrome::FaviconUrlFormat format,
+                    Profile* profile,
+                    ui::NativeTheme* theme)
+      : FaviconSource(profile, format), theme_(theme) {}
 
   ~TestFaviconSource() override {}
 
@@ -40,39 +81,171 @@
   ui::NativeTheme* const theme_;
 };
 
-// TODO(victorvianna): Add test coverage regarding usage of new/old format once
-// FaviconRequestHandler is mockable.
-class FaviconSourceTest : public testing::Test {
+class FaviconSourceTestBase : public testing::Test {
  public:
-  FaviconSourceTest() : source_(&profile_, &theme_) {}
+  explicit FaviconSourceTestBase(chrome::FaviconUrlFormat format)
+      : source_(format, &profile_, &theme_) {
+    // Setup testing factories for main dependencies.
+    BrowserContextKeyedServiceFactory::TestingFactory
+        history_ui_favicon_request_handler_factory =
+            base::BindRepeating([](content::BrowserContext*) {
+              return base::WrapUnique<KeyedService>(
+                  new MockHistoryUiFaviconRequestHandler());
+            });
+    mock_history_ui_favicon_request_handler_ =
+        static_cast<MockHistoryUiFaviconRequestHandler*>(
+            HistoryUiFaviconRequestHandlerFactory::GetInstance()
+                ->SetTestingFactoryAndUse(
+                    &profile_, history_ui_favicon_request_handler_factory));
+    BrowserContextKeyedServiceFactory::TestingFactory favicon_service_factory =
+        base::BindRepeating([](content::BrowserContext*) {
+          return static_cast<std::unique_ptr<KeyedService>>(
+              std::make_unique<favicon::MockFaviconService>());
+        });
+    mock_favicon_service_ = static_cast<favicon::MockFaviconService*>(
+        FaviconServiceFactory::GetInstance()->SetTestingFactoryAndUse(
+            &profile_, favicon_service_factory));
+
+    // Setup TestWebContents.
+    test_web_contents_ =
+        content::WebContentsTester::CreateTestWebContents(&profile_, nullptr);
+    test_web_contents_getter_ = base::BindLambdaForTesting(
+        [&] { return (content::WebContents*)test_web_contents_.get(); });
+
+    // On call, dependencies will return empty favicon by default.
+    ON_CALL(*mock_favicon_service_, GetRawFaviconForPageURL(_, _, _, _, _, _))
+        .WillByDefault([](auto, auto, auto, auto,
+                          favicon_base::FaviconRawBitmapCallback callback,
+                          auto) {
+          std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
+          return kDummyTaskId;
+        });
+    ON_CALL(*mock_history_ui_favicon_request_handler_,
+            GetRawFaviconForPageURL(_, _, _, _, _, _, _))
+        .WillByDefault([](auto, auto,
+                          favicon_base::FaviconRawBitmapCallback callback, auto,
+                          auto, auto, auto) {
+          std::move(callback).Run(favicon_base::FaviconRawBitmapResult());
+        });
+
+    // Mock default icon loading.
+    ON_CALL(*source(), LoadIconBytes(_, _))
+        .WillByDefault(Return(kDummyIconBytes.get()));
+  }
 
   void SetDarkMode(bool dark_mode) { theme_.SetDarkMode(dark_mode); }
 
   TestFaviconSource* source() { return &source_; }
 
- private:
+ protected:
+  const scoped_refptr<base::RefCountedBytes> kDummyIconBytes;
   content::TestBrowserThreadBundle thread_bundle_;
   ui::TestNativeTheme theme_;
   TestingProfile profile_;
+  MockHistoryUiFaviconRequestHandler* mock_history_ui_favicon_request_handler_;
+  favicon::MockFaviconService* mock_favicon_service_;
+  std::unique_ptr<content::WebContents> test_web_contents_;
+  WebContentsGetter test_web_contents_getter_;
   TestFaviconSource source_;
 };
 
-TEST_F(FaviconSourceTest, DarkDefault) {
-  SetDarkMode(true);
+class FaviconSourceTestWithLegacyFormat : public FaviconSourceTestBase {
+ public:
+  FaviconSourceTestWithLegacyFormat()
+      : FaviconSourceTestBase(chrome::FaviconUrlFormat::kFaviconLegacy) {}
+};
 
-  auto bytes = base::MakeRefCounted<base::RefCountedBytes>(1);
-  EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON_DARK))
-      .WillOnce(Return(bytes.get()));
-  source()->StartDataRequest(std::string(), WebContentsGetter(),
+class FaviconSourceTestWithFavicon2Format : public FaviconSourceTestBase {
+ public:
+  FaviconSourceTestWithFavicon2Format()
+      : FaviconSourceTestBase(chrome::FaviconUrlFormat::kFavicon2) {}
+};
+
+TEST_F(FaviconSourceTestWithLegacyFormat, DarkDefault) {
+  SetDarkMode(true);
+  EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON_DARK));
+  source()->StartDataRequest(std::string(), test_web_contents_getter_,
                              base::BindRepeating(&Noop));
 }
 
-TEST_F(FaviconSourceTest, LightDefault) {
+TEST_F(FaviconSourceTestWithLegacyFormat, LightDefault) {
   SetDarkMode(false);
-
-  auto bytes = base::MakeRefCounted<base::RefCountedBytes>(1);
-  EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON))
-      .WillOnce(Return(bytes.get()));
-  source()->StartDataRequest(std::string(), WebContentsGetter(),
+  EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON));
+  source()->StartDataRequest(std::string(), test_web_contents_getter_,
                              base::BindRepeating(&Noop));
 }
+
+TEST_F(FaviconSourceTestWithLegacyFormat,
+       ShouldNotQueryHistoryUiFaviconRequestHandler) {
+  content::WebContentsTester::For(test_web_contents_.get())
+      ->SetLastCommittedURL(GURL(chrome::kChromeUIHistoryURL));
+
+  EXPECT_CALL(*mock_history_ui_favicon_request_handler_,
+              GetRawFaviconForPageURL)
+      .Times(0);
+
+  source()->StartDataRequest("size/16@1x/https://www.google.com",
+                             test_web_contents_getter_,
+                             base::BindRepeating(&Noop));
+}
+
+TEST_F(FaviconSourceTestWithFavicon2Format, DarkDefault) {
+  SetDarkMode(true);
+  EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON_DARK));
+  source()->StartDataRequest(std::string(), test_web_contents_getter_,
+                             base::BindRepeating(&Noop));
+}
+
+TEST_F(FaviconSourceTestWithFavicon2Format, LightDefault) {
+  SetDarkMode(false);
+  EXPECT_CALL(*source(), LoadIconBytes(_, IDR_DEFAULT_FAVICON));
+  source()->StartDataRequest(std::string(), test_web_contents_getter_,
+                             base::BindRepeating(&Noop));
+}
+
+TEST_F(FaviconSourceTestWithFavicon2Format,
+       ShouldNotQueryHistoryUiFaviconRequestHandlerIfNotAllowed) {
+  content::WebContentsTester::For(test_web_contents_.get())
+      ->SetLastCommittedURL(GURL(chrome::kChromeUIHistoryURL));
+
+  EXPECT_CALL(*mock_history_ui_favicon_request_handler_,
+              GetRawFaviconForPageURL)
+      .Times(0);
+
+  source()->StartDataRequest(
+      "?size=16&scale_factor=1x&url_type=page_url&url=https%3A%2F%2Fwww.google."
+      "com&allow_google_server_fallback=0",
+      test_web_contents_getter_, base::BindRepeating(&Noop));
+}
+
+TEST_F(FaviconSourceTestWithFavicon2Format,
+       ShouldNotQueryHistoryUiFaviconRequestHandlerIfHasNotHistoryUiOrigin) {
+  content::WebContentsTester::For(test_web_contents_.get())
+      ->SetLastCommittedURL(GURL("chrome://non-history-url"));
+
+  EXPECT_CALL(*mock_history_ui_favicon_request_handler_,
+              GetRawFaviconForPageURL)
+      .Times(0);
+
+  source()->StartDataRequest(
+      "?size=16&scale_factor=1x&url_type=page_url&url=https%3A%2F%2Fwww.google."
+      "com&allow_google_server_fallback=1",
+      test_web_contents_getter_, base::BindRepeating(&Noop));
+}
+
+TEST_F(
+    FaviconSourceTestWithFavicon2Format,
+    ShouldQueryHistoryUiFaviconRequestHandlerIfHasHistoryUiOriginAndAllowed) {
+  content::WebContentsTester::For(test_web_contents_.get())
+      ->SetLastCommittedURL(GURL(chrome::kChromeUIHistoryURL));
+
+  EXPECT_CALL(
+      *mock_history_ui_favicon_request_handler_,
+      GetRawFaviconForPageURL(GURL("https://www.google.com"), _, _, _, _, _, _))
+      .Times(1);
+
+  source()->StartDataRequest(
+      "?size=16&scale_factor=1x&url_type=page_url&url=https%3A%2F%2Fwww.google."
+      "com&allow_google_server_fallback=1",
+      test_web_contents_getter_, base::BindRepeating(&Noop));
+}
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
index 95e4088..4fbf410 100644
--- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
+++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -30,7 +30,6 @@
 #include "components/security_interstitials/core/ssl_error_ui.h"
 #include "components/supervised_user_error_page/supervised_user_error_page.h"
 #include "content/public/browser/interstitial_page_delegate.h"
-#include "content/public/browser/origin_policy_error_reason.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/url_data_source.h"
@@ -424,7 +423,7 @@
 security_interstitials::SecurityInterstitialPage*
 CreateOriginPolicyInterstitialPage(content::WebContents* web_contents) {
   return security_interstitials::OriginPolicyUI::GetBlockingPage(
-      content::OriginPolicyErrorReason::kCannotLoadPolicy, web_contents,
+      network::OriginPolicyState::kCannotLoadPolicy, web_contents,
       GURL("https://example.com/broken/origin/policy"));
 }
 
diff --git a/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
index 44d7fd39..8f72bc2 100644
--- a/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
+++ b/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
@@ -88,7 +88,6 @@
       return false;
 #endif
     case ntp_tiles::TileSource::CUSTOM_LINKS:
-    case ntp_tiles::TileSource::SEARCH_PAGE:
 #if !defined(OS_ANDROID)
       return true;
 #else
diff --git a/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc b/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc
index f454270f..25b11e49 100644
--- a/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc
+++ b/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui.cc
@@ -50,7 +50,7 @@
   void OnJavascriptDisallowed() override;
 
   // LogReceiver implementation.
-  void LogSavePasswordProgress(const std::string& text) override;
+  void LogEntry(const base::Value& entry) override;
 
   void StartSubscription();
   void EndSubscription();
@@ -101,8 +101,9 @@
 
   registered_with_logging_service_ = true;
 
-  std::string past_logs(service->RegisterReceiver(this));
-  LogSavePasswordProgress(past_logs);
+  const auto& past_logs = service->RegisterReceiver(this);
+  for (const auto& entry : past_logs)
+    LogEntry(entry);
 }
 
 void PasswordManagerInternalsUIHandler::EndSubscription() {
@@ -116,14 +117,10 @@
     service->UnregisterReceiver(this);
 }
 
-void PasswordManagerInternalsUIHandler::LogSavePasswordProgress(
-    const std::string& text) {
-  if (!registered_with_logging_service_ || text.empty())
+void PasswordManagerInternalsUIHandler::LogEntry(const base::Value& entry) {
+  if (!registered_with_logging_service_ || entry.is_none())
     return;
-  std::string no_quotes(text);
-  std::replace(no_quotes.begin(), no_quotes.end(), '"', ' ');
-  base::Value text_string_value(net::EscapeForHTML(no_quotes));
-  CallJavascriptFunction("addLog", text_string_value);
+  CallJavascriptFunction("addRawLog", entry);
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui_browsertest.cc b/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui_browsertest.cc
index a2d08b5e..bcd4a96 100644
--- a/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/password_manager_internals/password_manager_internals_ui_browsertest.cc
@@ -72,8 +72,7 @@
       GetWebContents()->GetWebUI()->GetController());
 }
 
-IN_PROC_BROWSER_TEST_F(PasswordManagerInternalsWebUIBrowserTest,
-                       LogSavePasswordProgress) {
+IN_PROC_BROWSER_TEST_F(PasswordManagerInternalsWebUIBrowserTest, LogEntry) {
   password_manager::PasswordManagerInternalsService* service =
       password_manager::PasswordManagerInternalsServiceFactory::
           GetForBrowserContext(browser()->profile());
@@ -84,7 +83,7 @@
 
 // Test that a single internals page is empty on load.
 IN_PROC_BROWSER_TEST_F(PasswordManagerInternalsWebUIBrowserTest,
-                       LogSavePasswordProgress_EmptyOnLoad) {
+                       LogEntry_EmptyOnLoad) {
   password_manager::PasswordManagerInternalsService* service =
       password_manager::PasswordManagerInternalsServiceFactory::
           GetForBrowserContext(browser()->profile());
@@ -94,7 +93,7 @@
 
 // Test that a single internals page is flushed on reload.
 IN_PROC_BROWSER_TEST_F(PasswordManagerInternalsWebUIBrowserTest,
-                       LogSavePasswordProgress_FlushedOnReload) {
+                       LogEntry_FlushedOnReload) {
   password_manager::PasswordManagerInternalsService* service =
       password_manager::PasswordManagerInternalsServiceFactory::
           GetForBrowserContext(browser()->profile());
@@ -110,7 +109,7 @@
 // waits with displaying until the internals page is ready (trying to display
 // the old logs just on construction time would fail).
 IN_PROC_BROWSER_TEST_F(PasswordManagerInternalsWebUIBrowserTest,
-                       LogSavePasswordProgress_MultipleTabsIdentical) {
+                       LogEntry_MultipleTabsIdentical) {
   // First, open one tab with the internals page, and log something.
   password_manager::PasswordManagerInternalsService* service =
       password_manager::PasswordManagerInternalsServiceFactory::
@@ -127,7 +126,7 @@
 // Test that in the presence of more internals pages, reload does not cause
 // flushing the logs.
 IN_PROC_BROWSER_TEST_F(PasswordManagerInternalsWebUIBrowserTest,
-                       LogSavePasswordProgress_NotFlushedOnReloadIfMultiple) {
+                       LogEntry_NotFlushedOnReloadIfMultiple) {
   // Open one more tab with the internals page.
   OpenInternalsPage(WindowOpenDisposition::NEW_FOREGROUND_TAB);
   // Now log something.
@@ -144,7 +143,7 @@
 
 // Test that navigation away from the internals page works OK.
 IN_PROC_BROWSER_TEST_F(PasswordManagerInternalsWebUIBrowserTest,
-                       LogSavePasswordProgress_NavigateAway) {
+                       LogEntry_NavigateAway) {
   password_manager::PasswordManagerInternalsService* service =
       password_manager::PasswordManagerInternalsServiceFactory::
           GetForBrowserContext(browser()->profile());
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
index 5832a33..9534da45 100644
--- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
+++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -288,7 +288,6 @@
     settings.SetKey(
         kSettingUsername,
         base::Value(username.empty() ? kUsernamePlaceholder : username));
-    settings.SetKey(kSettingJobTitle, base::Value(job_title));
     settings.SetKey(kSettingSendUserInfo, base::Value(true));
   }
   StartLocalPrint(std::move(settings), std::move(print_data),
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc b/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
index 1b5860f..e47b9a2 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_chromeos_unittest.cc
@@ -68,7 +68,7 @@
   UpgradeDetectorChromeosTest()
       : utc_(icu::TimeZone::createTimeZone("Etc/GMT")),
         scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         scoped_local_state_(TestingBrowserProcess::GetGlobal()) {
     // Disable the detector's check to see if autoupdates are inabled.
     // Without this, tests put the detector into an invalid state by detecting
diff --git a/chrome/browser/upgrade_detector/upgrade_detector_impl_unittest.cc b/chrome/browser/upgrade_detector/upgrade_detector_impl_unittest.cc
index 6f1da0d..44615cb 100644
--- a/chrome/browser/upgrade_detector/upgrade_detector_impl_unittest.cc
+++ b/chrome/browser/upgrade_detector/upgrade_detector_impl_unittest.cc
@@ -113,7 +113,7 @@
  protected:
   UpgradeDetectorImplTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         scoped_local_state_(TestingBrowserProcess::GetGlobal()) {
     // Disable the detector's check to see if autoupdates are inabled.
     // Without this, tests put the detector into an invalid state by detecting
diff --git a/chrome/browser/webauthn/authenticator_reference.cc b/chrome/browser/webauthn/authenticator_reference.cc
index dcb2717..e6917ec 100644
--- a/chrome/browser/webauthn/authenticator_reference.cc
+++ b/chrome/browser/webauthn/authenticator_reference.cc
@@ -4,8 +4,6 @@
 
 #include "chrome/browser/webauthn/authenticator_reference.h"
 
-#include <utility>
-
 AuthenticatorReference::AuthenticatorReference(
     base::StringPiece authenticator_id,
     base::StringPiece16 authenticator_display_name,
@@ -13,12 +11,12 @@
     bool is_in_pairing_mode,
     bool is_paired,
     bool requires_ble_pairing_pin)
-    : authenticator_id_(authenticator_id),
-      authenticator_display_name_(authenticator_display_name),
-      transport_(transport),
-      is_in_pairing_mode_(is_in_pairing_mode),
-      is_paired_(is_paired),
-      requires_ble_pairing_pin_(requires_ble_pairing_pin) {}
+    : authenticator_id(authenticator_id),
+      authenticator_display_name(authenticator_display_name),
+      transport(transport),
+      is_in_pairing_mode(is_in_pairing_mode),
+      is_paired(is_paired),
+      requires_ble_pairing_pin(requires_ble_pairing_pin) {}
 
 AuthenticatorReference::AuthenticatorReference(AuthenticatorReference&& data) =
     default;
@@ -27,19 +25,3 @@
     AuthenticatorReference&& other) = default;
 
 AuthenticatorReference::~AuthenticatorReference() = default;
-
-void AuthenticatorReference::SetAuthenticatorId(std::string authenticator_id) {
-  authenticator_id_ = std::move(authenticator_id);
-}
-
-void AuthenticatorReference::SetIsInPairingMode(bool is_in_pairing_mode) {
-  is_in_pairing_mode_ = is_in_pairing_mode;
-}
-
-void AuthenticatorReference::SetIsPaired(bool is_paired) {
-  is_paired_ = is_paired;
-}
-
-void AuthenticatorReference::SetDispatched(bool dispatched) {
-  dispatched_ = dispatched;
-}
diff --git a/chrome/browser/webauthn/authenticator_reference.h b/chrome/browser/webauthn/authenticator_reference.h
index b965bae..6acd540f 100644
--- a/chrome/browser/webauthn/authenticator_reference.h
+++ b/chrome/browser/webauthn/authenticator_reference.h
@@ -15,8 +15,7 @@
 // Encapsulates information about authenticators that have been found but to
 // which the CTAP request is not dispatched until after receiving confirmation
 // from the user via the UI.
-class AuthenticatorReference {
- public:
+struct AuthenticatorReference {
   AuthenticatorReference(base::StringPiece device_id,
                          base::StringPiece16 authenticator_display_name,
                          device::FidoTransportProtocol transport,
@@ -27,30 +26,15 @@
   AuthenticatorReference& operator=(AuthenticatorReference&& other);
   ~AuthenticatorReference();
 
-  void SetAuthenticatorId(std::string);
-  void SetIsInPairingMode(bool);
-  void SetIsPaired(bool);
-  void SetDispatched(bool);
-
-  const std::string& authenticator_id() const { return authenticator_id_; }
-  const base::string16& authenticator_display_name() const {
-    return authenticator_display_name_;
-  }
-  device::FidoTransportProtocol transport() const { return transport_; }
-  bool is_in_pairing_mode() const { return is_in_pairing_mode_; }
-  bool is_paired() const { return is_paired_; }
-  bool requires_ble_pairing_pin() const { return requires_ble_pairing_pin_; }
-  bool dispatched() const { return dispatched_; }
+  std::string authenticator_id;
+  base::string16 authenticator_display_name;
+  device::FidoTransportProtocol transport;
+  bool is_in_pairing_mode = false;
+  bool is_paired = false;
+  bool requires_ble_pairing_pin = true;
+  bool dispatched = false;
 
  private:
-  std::string authenticator_id_;
-  base::string16 authenticator_display_name_;
-  device::FidoTransportProtocol transport_;
-  bool is_in_pairing_mode_ = false;
-  bool is_paired_ = false;
-  bool requires_ble_pairing_pin_ = true;
-  bool dispatched_ = false;
-
   DISALLOW_COPY_AND_ASSIGN(AuthenticatorReference);
 };
 
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index 03905a4..69fc81c 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -278,7 +278,7 @@
   SetCurrentStep(Step::kBleVerifying);
   DispatchRequestAsync(selected_authenticator);
 #else
-  if (selected_authenticator->requires_ble_pairing_pin()) {
+  if (selected_authenticator->requires_ble_pairing_pin) {
     SetCurrentStep(Step::kBlePinEntry);
     return;
   }
@@ -307,7 +307,7 @@
   }
 
   DCHECK_EQ(device::FidoTransportProtocol::kBluetoothLowEnergy,
-            selected_authenticator->transport());
+            selected_authenticator->transport);
   ble_pairing_callback_.Run(
       *ephemeral_state_.selected_authenticator_id_, base::UTF16ToUTF8(pin),
       base::BindOnce(&AuthenticatorRequestDialogModel::OnPairingSuccess,
@@ -325,7 +325,7 @@
   if (!authenticator)
     return;
 
-  authenticator->SetIsPaired(true /* is_paired */);
+  authenticator->is_paired = true;
   DCHECK(ble_device_paired_callback_);
   ble_device_paired_callback_.Run(*ephemeral_state_.selected_authenticator_id_);
 
@@ -370,7 +370,7 @@
   auto touch_id_authenticator_it =
       std::find_if(authenticators.begin(), authenticators.end(),
                    [](const auto& authenticator) {
-                     return authenticator.transport() ==
+                     return authenticator.transport ==
                             device::FidoTransportProtocol::kInternal;
                    });
 
@@ -544,8 +544,8 @@
       *authenticator.AuthenticatorTransport(), authenticator.IsInPairingMode(),
       authenticator.IsPaired(), authenticator.RequiresBlePairingPin());
 
-  if (authenticator_reference.is_paired() &&
-      authenticator_reference.transport() ==
+  if (authenticator_reference.is_paired &&
+      authenticator_reference.transport ==
           AuthenticatorTransport::kBluetoothLowEnergy) {
     DispatchRequestAsync(&authenticator_reference);
   }
@@ -562,12 +562,12 @@
     AuthenticatorReference* authenticator) {
   // Dispatching to the same authenticator twice may result in unexpected
   // behavior.
-  if (authenticator->dispatched()) {
+  if (authenticator->dispatched) {
     return;
   }
 
-  DispatchRequestAsyncInternal(authenticator->authenticator_id());
-  authenticator->SetDispatched(true);
+  DispatchRequestAsyncInternal(authenticator->authenticator_id);
+  authenticator->dispatched = true;
 }
 
 void AuthenticatorRequestDialogModel::DispatchRequestAsyncInternal(
@@ -611,7 +611,7 @@
 void AuthenticatorRequestDialogModel::SetSelectedAuthenticatorForTesting(
     AuthenticatorReference test_authenticator) {
   ephemeral_state_.selected_authenticator_id_ =
-      test_authenticator.authenticator_id();
+      test_authenticator.authenticator_id;
   ephemeral_state_.saved_authenticators_.AddAuthenticator(
       std::move(test_authenticator));
 }
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
index 9f9229b5..57fbf51 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model_unittest.cc
@@ -97,7 +97,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   base::ListValue test_paired_device_list_;
 
  private:
diff --git a/chrome/browser/webauthn/observable_authenticator_list.cc b/chrome/browser/webauthn/observable_authenticator_list.cc
index b8810b9..ccc7f06 100644
--- a/chrome/browser/webauthn/observable_authenticator_list.cc
+++ b/chrome/browser/webauthn/observable_authenticator_list.cc
@@ -48,7 +48,7 @@
   if (!authenticator)
     return;
 
-  authenticator->SetAuthenticatorId(std::move(new_id));
+  authenticator->authenticator_id = std::move(new_id);
   if (observer_)
     observer_->OnAuthenticatorIdChanged(*authenticator, previous_id);
 }
@@ -60,7 +60,7 @@
   if (it == authenticator_list_.end())
     return;
 
-  it->SetIsInPairingMode(is_in_pairing_mode);
+  it->is_in_pairing_mode = is_in_pairing_mode;
   if (observer_)
     observer_->OnAuthenticatorPairingModeChanged(*it);
 }
@@ -89,7 +89,7 @@
     base::StringPiece authenticator_id) {
   return std::find_if(authenticator_list_.begin(), authenticator_list_.end(),
                       [authenticator_id](const auto& authenticator) {
-                        return authenticator.authenticator_id() ==
+                        return authenticator.authenticator_id ==
                                authenticator_id;
                       });
 }
diff --git a/chrome/browser/win/conflicts/inspection_results_cache_unittest.cc b/chrome/browser/win/conflicts/inspection_results_cache_unittest.cc
index 6f7ad63..d4d0182 100644
--- a/chrome/browser/win/conflicts/inspection_results_cache_unittest.cc
+++ b/chrome/browser/win/conflicts/inspection_results_cache_unittest.cc
@@ -49,7 +49,7 @@
  public:
   InspectionResultsCacheTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir());
diff --git a/chrome/browser/win/conflicts/module_blacklist_cache_updater_unittest.cc b/chrome/browser/win/conflicts/module_blacklist_cache_updater_unittest.cc
index 29c459b..456f450 100644
--- a/chrome/browser/win/conflicts/module_blacklist_cache_updater_unittest.cc
+++ b/chrome/browser/win/conflicts/module_blacklist_cache_updater_unittest.cc
@@ -101,7 +101,7 @@
       : dll1_(kDllPath1),
         dll2_(kDllPath2),
         scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         user_data_dir_override_(chrome::DIR_USER_DATA),
         module_list_filter_(CreateModuleListFilter()),
         module_blacklist_cache_path_(
diff --git a/chrome/browser/win/conflicts/module_database_unittest.cc b/chrome/browser/win/conflicts/module_database_unittest.cc
index c037b40a..01722283 100644
--- a/chrome/browser/win/conflicts/module_database_unittest.cc
+++ b/chrome/browser/win/conflicts/module_database_unittest.cc
@@ -38,7 +38,8 @@
       : dll1_(kDll1),
         dll2_(kDll2),
         test_browser_thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME),
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()),
         module_database_(std::make_unique<ModuleDatabase>(
             nullptr,
diff --git a/chrome/browser/win/conflicts/module_inspector_unittest.cc b/chrome/browser/win/conflicts/module_inspector_unittest.cc
index 5eb256b..9201251 100644
--- a/chrome/browser/win/conflicts/module_inspector_unittest.cc
+++ b/chrome/browser/win/conflicts/module_inspector_unittest.cc
@@ -54,7 +54,7 @@
  public:
   ModuleInspectorTest()
       : test_browser_thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   // Callback for ModuleInspector.
   void OnModuleInspected(const ModuleInfoKey& module_key,
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index dd05246dd..b721e90 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -2688,13 +2688,13 @@
 const char kAllowPopupsDuringPageUnload[] = "allow_popups_during_page_unload";
 
 #if defined(OS_CHROMEOS)
-// Enum that specifies certificate management permissions for user. It can have
-// one of the following values.
-// 0: Users can manage all certificates.
+// Enum that specifies client certificate management permissions for user. It
+// can have one of the following values. 0: Users can manage all certificates.
 // 1: Users can manage user certificates, but not device certificates.
 // 2: Disallow users from managing certificates
-// Controlled by CertificateManagementAllowed policy.
-const char kCertificateManagementAllowed[] = "certificate_management_allowed";
+// Controlled by ClientCertificateManagementAllowed policy.
+const char kClientCertificateManagementAllowed[] =
+    "certificate_management_allowed";
 #endif
 
 const char kSharingVapidKey[] = "sharing.vapid_key";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 941c6273..a51dcec 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -949,7 +949,7 @@
 #endif
 
 #if defined(OS_CHROMEOS)
-extern const char kCertificateManagementAllowed[];
+extern const char kClientCertificateManagementAllowed[];
 #endif
 
 extern const char kSharingVapidKey[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 26e47395..e1ce9d8 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -818,6 +818,7 @@
       "../browser/chrome_worker_browsertest.cc",
       "../browser/client_hints/client_hints_browsertest.cc",
       "../browser/component_updater/component_patcher_operation_browsertest.cc",
+      "../browser/content_index/content_index_browsertest.cc",
       "../browser/content_settings/content_settings_browsertest.cc",
       "../browser/crash_recovery_browsertest.cc",
       "../browser/custom_handlers/protocol_handler_registry_browsertest.cc",
@@ -3344,6 +3345,7 @@
     "//components/content_settings/core/test:test_support",
     "//components/data_reduction_proxy/core/browser:test_support",
     "//components/data_use_measurement/core",
+    "//components/favicon/core/test:test_support",
     "//components/mirroring:mirroring_tests",
     "//components/nacl/common:buildflags",
     "//components/ntp_snippets:test_support",
@@ -4789,6 +4791,7 @@
       "../browser/signin/signin_global_error_unittest.cc",
       "../browser/signin/signin_ui_util_unittest.cc",
       "../browser/signin/signin_util_unittest.cc",
+      "../browser/ui/views/sharing/click_to_call/click_to_call_dialog_view_unittest.cc",
       "../browser/ui/webui/signin/signin_create_profile_handler_unittest.cc",
       "../browser/ui/webui/signin/signin_error_handler_unittest.cc",
       "../browser/ui/webui/signin/sync_confirmation_handler_unittest.cc",
diff --git a/chrome/test/chromedriver/BUILD.gn b/chrome/test/chromedriver/BUILD.gn
index 0fd94e4b..f3d3e5f 100644
--- a/chrome/test/chromedriver/BUILD.gn
+++ b/chrome/test/chromedriver/BUILD.gn
@@ -258,6 +258,8 @@
     "util.h",
     "version.cc",
     "version.h",
+    "webauthn_commands.cc",
+    "webauthn_commands.h",
     "window_commands.cc",
     "window_commands.h",
   ]
diff --git a/chrome/test/chromedriver/client/chromedriver.py b/chrome/test/chromedriver/client/chromedriver.py
index 82d77b0e..9e5342d 100644
--- a/chrome/test/chromedriver/client/chromedriver.py
+++ b/chrome/test/chromedriver/client/chromedriver.py
@@ -618,3 +618,20 @@
 
   def GenerateTestReport(self, message):
     self.ExecuteCommand(Command.GENERATE_TEST_REPORT, {'message': message})
+
+  def AddVirtualAuthenticator(self, protocol=None, transport=None,
+                              hasResidentKey=None, hasUserVerification=None,
+                              isUserVerified=None):
+    options = {}
+    if protocol is not None:
+      options['protocol'] = protocol
+    if transport is not None:
+      options['transport'] = transport
+    if hasResidentKey is not None:
+      options['hasResidentKey'] = hasResidentKey
+    if hasUserVerification is not None:
+      options['hasUserVerification'] = hasUserVerification
+    if isUserVerified is not None:
+      options['isUserVerified'] = isUserVerified
+
+    return self.ExecuteCommand(Command.ADD_VIRTUAL_AUTHENTICATOR, options)
diff --git a/chrome/test/chromedriver/client/command_executor.py b/chrome/test/chromedriver/client/command_executor.py
index b8db817..f3f49f3 100644
--- a/chrome/test/chromedriver/client/command_executor.py
+++ b/chrome/test/chromedriver/client/command_executor.py
@@ -170,6 +170,8 @@
       _Method.POST, '/session/:sessionId/chromium/send_command_and_get_result')
   GENERATE_TEST_REPORT = (
       _Method.POST, '/session/:sessionId/reporting/generate_test_report')
+  ADD_VIRTUAL_AUTHENTICATOR = (
+      _Method.POST, '/session/:sessionId/webauthn/authenticator')
 
   # Custom Chrome commands.
   IS_LOADING = (_Method.GET, '/session/:sessionId/is_loading')
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index a278f2d..04e39d51 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -33,6 +33,7 @@
 #include "chrome/test/chromedriver/session_thread_map.h"
 #include "chrome/test/chromedriver/util.h"
 #include "chrome/test/chromedriver/version.h"
+#include "chrome/test/chromedriver/webauthn_commands.h"
 #include "net/server/http_server_request_info.h"
 #include "net/server/http_server_response_info.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -738,6 +739,16 @@
           WrapToCommand("SetNetworkConnection",
                         base::BindRepeating(&ExecuteSetNetworkConnection))),
 
+      // Extension for WebAuthn API:
+      // TODO(nsatragno): Update the link to the official spec once it lands.
+      // https://github.com/nsatragno/webauthn/pull/1/files
+      CommandMapping(kPost, "session/:sessionId/webauthn/authenticator",
+                     WrapToCommand("AddVirtualAuthenticator",
+                                   base::BindRepeating(
+                                       &ExecuteWebAuthnCommand,
+                                       base::BindRepeating(
+                                           &ExecuteAddVirtualAuthenticator)))),
+
       //
       // Non-standard extension commands
       //
@@ -757,11 +768,10 @@
           WrapToCommand("UploadFile", base::BindRepeating(&ExecuteUploadFile))),
       // Command is used by Ruby OSS mode
       // No W3C equivalent.
-      CommandMapping(
-          kGet, "session/:sessionId/element/:id/value",
-          WrapToCommand("GetElementValue",
-                        base::BindRepeating(&ExecuteGetElementValue),
-                        false /*w3c_standard_command*/)),
+      CommandMapping(kGet, "session/:sessionId/element/:id/value",
+                     WrapToCommand("GetElementValue",
+                                   base::BindRepeating(&ExecuteGetElementValue),
+                                   false /*w3c_standard_command*/)),
       // Command is used by Selenium Java tests
       CommandMapping(
           kGet, kShutdownPath,
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index 7566e455..7e4f7da 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -222,6 +222,8 @@
         # on tab creation. https://crbug.com/chromedriver/3018
         'ChromeDriverTest.testNewWindowDoesNotFocus',
         'ChromeDriverTest.testNewTabDoesNotFocus',
+        # Android does not support the virtual authenticator environment.
+        'ChromeDriverSecureContextTest.testAddVirtualAuthenticator',
     ]
 )
 _ANDROID_NEGATIVE_FILTER['chrome_stable'] = (
@@ -2021,6 +2023,45 @@
     self.assertEquals('test', report['type']);
     self.assertEquals('test report message', report['body']['message']);
 
+# Tests that require a secure context.
+class ChromeDriverSecureContextTest(ChromeDriverBaseTest):
+  @staticmethod
+  def GlobalSetUp():
+    cert_path = os.path.join(chrome_paths.GetTestData(),
+                             'chromedriver/invalid_ssl_cert.pem')
+    ChromeDriverSecureContextTest._https_server = webserver.WebServer(
+        chrome_paths.GetTestData(), cert_path)
+
+  @staticmethod
+  def GlobalTearDown():
+    ChromeDriverSecureContextTest._https_server.Shutdown()
+
+  @staticmethod
+  def GetHttpsUrlForFile(file_path, host=None):
+    return ChromeDriverSecureContextTest._https_server.GetUrl(
+        host) + file_path
+
+  def setUp(self):
+    self._driver = self.CreateDriver(
+        chrome_switches=['host-resolver-rules=MAP * 127.0.0.1'])
+
+  def testAddVirtualAuthenticator(self):
+    script = """
+      let done = arguments[0];
+      registerCredential().then(done);
+    """
+    self._driver.Load(self.GetHttpsUrlForFile(
+        '/chromedriver/webauthn_test.html', 'chromedriver.test'))
+    self._driver.AddVirtualAuthenticator(
+        protocol = 'ctap2',
+        transport = 'usb',
+        hasResidentKey = False,
+        hasUserVerification = False,
+    )
+    result = self._driver.ExecuteAsyncScript(script)
+    self.assertEquals('OK', result['status'])
+    self.assertEquals(['usb'], result['credential']['transports'])
+
 # Tests in the following class are expected to be moved to ChromeDriverTest
 # class when we no longer support the legacy mode.
 class ChromeDriverW3cTest(ChromeDriverBaseTestWithWebServer):
@@ -3639,10 +3680,12 @@
   # multiple GlobalSetup and GlobalTearDown, and reducing the number of HTTP
   # servers used for the test.
   ChromeDriverTest.GlobalSetUp()
+  ChromeDriverSecureContextTest.GlobalSetUp()
   HeadlessInvalidCertificateTest.GlobalSetUp()
   MobileEmulationCapabilityTest.GlobalSetUp()
   result = unittest.TextTestRunner(stream=sys.stdout, verbosity=2).run(tests)
   ChromeDriverTest.GlobalTearDown()
+  ChromeDriverSecureContextTest.GlobalTearDown()
   HeadlessInvalidCertificateTest.GlobalTearDown()
   MobileEmulationCapabilityTest.GlobalTearDown()
 
diff --git a/chrome/test/chromedriver/webauthn_commands.cc b/chrome/test/chromedriver/webauthn_commands.cc
new file mode 100644
index 0000000..9ef31f2
--- /dev/null
+++ b/chrome/test/chromedriver/webauthn_commands.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 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 "chrome/test/chromedriver/webauthn_commands.h"
+
+#include <utility>
+
+#include "base/callback.h"
+#include "base/containers/flat_map.h"
+#include "base/values.h"
+#include "chrome/test/chromedriver/chrome/status.h"
+#include "chrome/test/chromedriver/chrome/web_view.h"
+#include "chrome/test/chromedriver/session.h"
+
+Status ExecuteWebAuthnCommand(const WebAuthnCommand& command,
+                              Session* session,
+                              const base::DictionaryValue& params,
+                              std::unique_ptr<base::Value>* value) {
+  WebView* web_view = nullptr;
+  Status status = session->GetTargetWindow(&web_view);
+  if (status.IsError())
+    return status;
+
+  status = web_view->ConnectIfNecessary();
+  if (status.IsError())
+    return status;
+
+  status = web_view->SendCommand("WebAuthn.enable", base::DictionaryValue());
+  if (status.IsError())
+    return status;
+
+  return command.Run(web_view, params, value);
+}
+
+Status ExecuteAddVirtualAuthenticator(WebView* web_view,
+                                      const base::Value& params,
+                                      std::unique_ptr<base::Value>* value) {
+  base::DictionaryValue options;
+  const base::flat_map<const char*, const char*> mapping = {
+      {"options.protocol", "protocol"},
+      {"options.transport", "transport"},
+      {"options.hasResidentKey", "hasResidentKey"},
+      {"options.hasUserVerification", "hasUserVerification"},
+      {"options.automaticPresenceSimulation", "isUserVerified"},
+  };
+  for (const std::pair<const char*, const char*>& pair : mapping) {
+    const base::Value* value = params.FindKey(pair.second);
+    if (value)
+      options.SetPath(pair.first, value->Clone());
+  }
+
+  return web_view->SendCommandAndGetResult("WebAuthn.addVirtualAuthenticator",
+                                           options, value);
+}
diff --git a/chrome/test/chromedriver/webauthn_commands.h b/chrome/test/chromedriver/webauthn_commands.h
new file mode 100644
index 0000000..8d2b1913
--- /dev/null
+++ b/chrome/test/chromedriver/webauthn_commands.h
@@ -0,0 +1,37 @@
+// Copyright (c) 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_TEST_CHROMEDRIVER_WEBAUTHN_COMMANDS_H_
+#define CHROME_TEST_CHROMEDRIVER_WEBAUTHN_COMMANDS_H_
+
+#include <memory>
+
+#include "base/callback_forward.h"
+
+namespace base {
+class DictionaryValue;
+class Value;
+}  // namespace base
+
+struct Session;
+class Status;
+class WebView;
+
+using WebAuthnCommand =
+    base::RepeatingCallback<Status(WebView* web_view,
+                                   const base::Value& params,
+                                   std::unique_ptr<base::Value>* value)>;
+
+// Executes a WebAuthn command.
+Status ExecuteWebAuthnCommand(const WebAuthnCommand& command,
+                              Session* session,
+                              const base::DictionaryValue& params,
+                              std::unique_ptr<base::Value>* value);
+
+// Add a virtual authenticator.
+Status ExecuteAddVirtualAuthenticator(WebView* web_view,
+                                      const base::Value& params,
+                                      std::unique_ptr<base::Value>* value);
+
+#endif  // CHROME_TEST_CHROMEDRIVER_WEBAUTHN_COMMANDS_H_
diff --git a/chrome/test/data/OWNERS b/chrome/test/data/OWNERS
index 72e8ffc..177e36d 100644
--- a/chrome/test/data/OWNERS
+++ b/chrome/test/data/OWNERS
@@ -1 +1,2 @@
 *
+# COMPONENT: Test
diff --git a/chrome/test/data/chromedriver/webauthn_test.html b/chrome/test/data/chromedriver/webauthn_test.html
new file mode 100644
index 0000000..680f7c0
--- /dev/null
+++ b/chrome/test/data/chromedriver/webauthn_test.html
@@ -0,0 +1,38 @@
+<html>
+  <script>
+async function registerCredential(options = {}) {
+  options = Object.assign({
+    authenticatorSelection: {
+      requireResidentKey: false,
+    },
+    rp: {
+      id: "chromedriver.test",
+      name: "ChromeDriver Test",
+    },
+    challenge: Uint8Array.from("challenge"),
+    pubKeyCredParams: [
+      {type: "public-key", alg: -7},
+    ],
+    user: {
+      name: "name",
+      displayName: "displayName",
+      id: Uint8Array.from([1]),
+    },
+  }, options);
+
+  try {
+    const credential = await navigator.credentials.create({publicKey: options});
+    return {
+      status: "OK",
+      credential: {
+        id: credential.id,
+        rawId: Array.from(new Uint8Array(credential.rawId)),
+        transports: credential.response.getTransports(),
+      }
+    };
+  } catch (error) {
+    return {status: error.toString()};
+  }
+}
+  </script>
+</html>
diff --git a/chrome/test/data/content_index/content_index.html b/chrome/test/data/content_index/content_index.html
new file mode 100644
index 0000000..e666a1a
--- /dev/null
+++ b/chrome/test/data/content_index/content_index.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>ContentIndexBrowserTest helper page</title>
+    <script src="../result_queue.js"></script>
+    <script src="content_index.js"></script>
+  </head>
+  <body>
+  </body>
+</html>
diff --git a/chrome/test/data/content_index/content_index.js b/chrome/test/data/content_index/content_index.js
new file mode 100644
index 0000000..d9616f73
--- /dev/null
+++ b/chrome/test/data/content_index/content_index.js
@@ -0,0 +1,37 @@
+// 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.
+
+function WrapFunction(fn) {
+  fn().then(result => sendResultToTest(`ok - ${result}`))
+      .catch(sendErrorToTest);
+}
+
+async function RegisterServiceWorker() {
+  await navigator.serviceWorker.register('sw.js', { scope: 'content_index' });
+}
+
+async function AddContent(id) {
+  const registration = await navigator.serviceWorker.ready;
+
+  await registration.index.add({
+    id: id,
+    title: `title ${id}`,
+    description: `description ${id} ${Math.random()}`,
+    category: 'article',
+    iconUrl: '/anchor_download_test.png',
+    launchUrl: '/content_index/content_index.html?launch',
+  });
+}
+
+async function DeleteContent(id) {
+  const registration = await navigator.serviceWorker.ready;
+  await registration.index.delete(id);
+}
+
+async function GetIds() {
+  const registration = await navigator.serviceWorker.ready;
+
+  const descriptions = await registration.index.getDescriptions();
+  return descriptions.map(d => d.id);
+}
diff --git a/chrome/test/data/content_index/sw.js b/chrome/test/data/content_index/sw.js
new file mode 100644
index 0000000..ca769bb5
--- /dev/null
+++ b/chrome/test/data/content_index/sw.js
@@ -0,0 +1,7 @@
+// 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.
+
+// Service Worker initialization listeners.
+self.addEventListener('install', e => e.waitUntil(skipWaiting()));
+self.addEventListener('activate', e => e.waitUntil(clients.claim()));
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index c7eb2919..b81ee327 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -4463,9 +4463,9 @@
     "pref_mappings": [{ "pref": "child_user.parent_access_code.config" }]
   },
 
-  "CertificateManagementAllowed": {
+  "ClientCertificateManagementAllowed": {
     "os": ["chromeos"],
-    "test_policy": { "CertificateManagementAllowed": 2 },
+    "test_policy": { "ClientCertificateManagementAllowed": 2 },
     "pref_mappings": [{ "pref": "certificate_management_allowed" }]
   },
 
diff --git a/chrome/test/data/webui/settings/certificate_manager_test.js b/chrome/test/data/webui/settings/certificate_manager_test.js
index 7f722a0..0efb082 100644
--- a/chrome/test/data/webui/settings/certificate_manager_test.js
+++ b/chrome/test/data/webui/settings/certificate_manager_test.js
@@ -762,6 +762,43 @@
             certificateType: CertificateType.CA
           }));
     });
+
+    if (cr.isChromeOS) {
+      // Test that ClientCertificateManagementAllowed policy is applied to the
+      // UI.
+      test('ImportButton_ClientPolicy', function() {
+        const paperTabsElement = page.shadowRoot.querySelector('cr-tabs');
+        paperTabsElement.selected = CertificateCategoryIndex.PERSONAL;
+        Polymer.dom.flush();
+        paperTabsElement.selected = CertificateCategoryIndex.CA;
+        Polymer.dom.flush();
+        const certificateLists =
+            page.shadowRoot.querySelectorAll('certificate-list');
+        // Import buttons are shown in the client and CA certificate tabs.
+        let clientImportButton = certificateLists[0].$$('#import');
+        assertFalse(clientImportButton.hidden);
+        let clientImportAndBindButton =
+            certificateLists[0].$$('#importAndBind');
+        assertFalse(clientImportAndBindButton.hidden);
+        let caImportButton = certificateLists[1].$$('#import');
+        assertFalse(caImportButton.hidden);
+
+        return browserProxy.whenCalled('refreshCertificates').then(function() {
+          cr.webUIListenerCallback(
+              'certificates-model-ready', false /* clientImportAllowed */);
+          // Verify that import buttons are hidden in the client certificate
+          // tab.
+          clientImportButton = certificateLists[0].$$('#import');
+          assertTrue(clientImportButton.hidden);
+          clientImportAndBindButton = certificateLists[0].$$('#importAndBind');
+          assertTrue(clientImportAndBindButton.hidden);
+          // Verify that import button is shown in the CA certificate tab.
+          caImportButton = certificateLists[1].$$('#import');
+          assertFalse(caImportButton.hidden);
+        });
+      });
+    }
+
   });
 
   suite('CertificateListTests', function() {
diff --git a/chromecast/base/metrics/cast_metrics_helper_unittest.cc b/chromecast/base/metrics/cast_metrics_helper_unittest.cc
index 01e8f3a2..7b4b0380 100644
--- a/chromecast/base/metrics/cast_metrics_helper_unittest.cc
+++ b/chromecast/base/metrics/cast_metrics_helper_unittest.cc
@@ -71,7 +71,7 @@
  public:
   CastMetricsHelperTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         metrics_helper_(scoped_task_environment_.GetMainThreadTaskRunner(),
                         scoped_task_environment_.GetMockTickClock()) {
     metrics_helper_.SetMetricsSink(&metrics_sink_);
diff --git a/chromecast/media/audio/cast_audio_output_stream_unittest.cc b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
index 9960ad1..9c58872 100644
--- a/chromecast/media/audio/cast_audio_output_stream_unittest.cc
+++ b/chromecast/media/audio/cast_audio_output_stream_unittest.cc
@@ -228,7 +228,7 @@
   CastAudioOutputStreamTest()
       : audio_thread_("CastAudioThread"),
         scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         format_(::media::AudioParameters::AUDIO_PCM_LINEAR),
         channel_layout_(::media::CHANNEL_LAYOUT_MONO),
         sample_rate_(::media::AudioParameters::kAudioCDSampleRate),
diff --git a/chromeos/components/nearby/scheduled_executor_impl_unittest.cc b/chromeos/components/nearby/scheduled_executor_impl_unittest.cc
index b878eafd..26e5af1 100644
--- a/chromeos/components/nearby/scheduled_executor_impl_unittest.cc
+++ b/chromeos/components/nearby/scheduled_executor_impl_unittest.cc
@@ -48,7 +48,7 @@
  protected:
   ScheduledExecutorImplTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         scheduled_executor_(std::make_unique<ScheduledExecutorImpl>(
             scoped_task_environment_.GetMainThreadTaskRunner())) {}
 
diff --git a/chromeos/components/power/dark_resume_controller_unittest.cc b/chromeos/components/power/dark_resume_controller_unittest.cc
index 7ba188b9..c457122 100644
--- a/chromeos/components/power/dark_resume_controller_unittest.cc
+++ b/chromeos/components/power/dark_resume_controller_unittest.cc
@@ -30,7 +30,7 @@
  public:
   DarkResumeControllerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         wake_lock_provider_(
             connector_factory_.RegisterInstance(device::mojom::kServiceName)) {}
 
diff --git a/chromeos/cryptohome/cryptohome_util.cc b/chromeos/cryptohome/cryptohome_util.cc
index d326904..db71013 100644
--- a/chromeos/cryptohome/cryptohome_util.cc
+++ b/chromeos/cryptohome/cryptohome_util.cc
@@ -8,6 +8,7 @@
 
 #include "base/logging.h"
 #include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/dbus/constants/cryptohome_key_delegate_constants.h"
 #include "chromeos/dbus/cryptohome/key.pb.h"
 #include "chromeos/dbus/cryptohome/rpc.pb.h"
 #include "components/device_event_log/device_event_log.h"
@@ -242,19 +243,36 @@
 
 AuthorizationRequest CreateAuthorizationRequest(const std::string& label,
                                                 const std::string& secret) {
-  cryptohome::AuthorizationRequest auth_request;
-  Key* key = auth_request.mutable_key();
-  if (!label.empty())
-    key->mutable_data()->set_label(label);
+  return CreateAuthorizationRequestFromKeyDef(
+      KeyDefinition::CreateForPassword(secret, label, PRIV_DEFAULT));
+}
 
-  key->set_secret(secret);
+AuthorizationRequest CreateAuthorizationRequestFromKeyDef(
+    const KeyDefinition& key_def) {
+  cryptohome::AuthorizationRequest auth_request;
+  KeyDefinitionToKey(key_def, auth_request.mutable_key());
+
+  switch (key_def.type) {
+    case KeyDefinition::TYPE_PASSWORD:
+      break;
+    case KeyDefinition::TYPE_CHALLENGE_RESPONSE:
+      // Specify the additional KeyDelegate information that allows cryptohomed
+      // to call back to Chrome to perform cryptographic challenges.
+      auth_request.mutable_key_delegate()->set_dbus_service_name(
+          cryptohome::kCryptohomeKeyDelegateServiceName);
+      auth_request.mutable_key_delegate()->set_dbus_object_path(
+          cryptohome::kCryptohomeKeyDelegateServicePath);
+      break;
+  }
+
   return auth_request;
 }
 
 // TODO(crbug.com/797848): Finish testing this method.
 void KeyDefinitionToKey(const KeyDefinition& key_def, Key* key) {
   KeyData* data = key->mutable_data();
-  data->set_label(key_def.label);
+  if (!key_def.label.empty())
+    data->set_label(key_def.label);
 
   switch (key_def.type) {
     case KeyDefinition::TYPE_PASSWORD:
diff --git a/chromeos/cryptohome/cryptohome_util.h b/chromeos/cryptohome/cryptohome_util.h
index 2cca060..ad805fc7 100644
--- a/chromeos/cryptohome/cryptohome_util.h
+++ b/chromeos/cryptohome/cryptohome_util.h
@@ -53,6 +53,11 @@
 AuthorizationRequest CreateAuthorizationRequest(const std::string& label,
                                                 const std::string& secret);
 
+// Creates an AuthorizationRequest from the given key definition.
+COMPONENT_EXPORT(CHROMEOS_CRYPTOHOME)
+AuthorizationRequest CreateAuthorizationRequestFromKeyDef(
+    const KeyDefinition& key_def);
+
 // Converts the given KeyDefinition to a Key.
 COMPONENT_EXPORT(CHROMEOS_CRYPTOHOME)
 void KeyDefinitionToKey(const KeyDefinition& key_def, Key* key);
diff --git a/chromeos/cryptohome/cryptohome_util_unittest.cc b/chromeos/cryptohome/cryptohome_util_unittest.cc
index 46f3205..b6fb549 100644
--- a/chromeos/cryptohome/cryptohome_util_unittest.cc
+++ b/chromeos/cryptohome/cryptohome_util_unittest.cc
@@ -46,6 +46,67 @@
   EXPECT_EQ(auth_request.key().secret(), kExpectedSecret);
 }
 
+TEST(CryptohomeUtilTest,
+     CreateAuthorizationRequestFromKeyDefPasswordEmptyLabel) {
+  const std::string kExpectedSecret = "secret";
+
+  const AuthorizationRequest auth_request =
+      CreateAuthorizationRequestFromKeyDef(KeyDefinition::CreateForPassword(
+          kExpectedSecret, std::string() /* label */, PRIV_DEFAULT));
+
+  EXPECT_FALSE(auth_request.key().data().has_label());
+  EXPECT_EQ(auth_request.key().secret(), kExpectedSecret);
+}
+
+TEST(CryptohomeUtilTest,
+     CreateAuthorizationRequestFromKeyDefPasswordWithLabel) {
+  const std::string kExpectedSecret = "secret";
+
+  const AuthorizationRequest auth_request =
+      CreateAuthorizationRequestFromKeyDef(KeyDefinition::CreateForPassword(
+          kExpectedSecret, kKeyLabel, PRIV_DEFAULT));
+
+  EXPECT_EQ(auth_request.key().data().label(), kKeyLabel);
+  EXPECT_EQ(auth_request.key().secret(), kExpectedSecret);
+}
+
+TEST(CryptohomeUtilTest,
+     CreateAuthorizationRequestFromKeyDefChallengeResponse) {
+  using Algorithm = ChallengeResponseKey::SignatureAlgorithm;
+  const std::string kKeySpki = "spki";
+  const Algorithm kKeyAlgorithm = Algorithm::kRsassaPkcs1V15Sha1;
+  const ChallengeSignatureAlgorithm kKeyAlgorithmProto =
+      CHALLENGE_RSASSA_PKCS1_V1_5_SHA1;
+
+  ChallengeResponseKey challenge_response_key;
+  challenge_response_key.set_public_key_spki_der(kKeySpki);
+  challenge_response_key.set_signature_algorithms({kKeyAlgorithm});
+  const KeyDefinition key_def = KeyDefinition::CreateForChallengeResponse(
+      {challenge_response_key}, kKeyLabel, PRIV_DEFAULT);
+
+  const AuthorizationRequest auth_request =
+      CreateAuthorizationRequestFromKeyDef(key_def);
+
+  EXPECT_FALSE(auth_request.key().has_secret());
+  EXPECT_EQ(auth_request.key().data().type(),
+            KeyData::KEY_TYPE_CHALLENGE_RESPONSE);
+  EXPECT_EQ(auth_request.key().data().label(), kKeyLabel);
+  EXPECT_TRUE(auth_request.key().data().privileges().mount());
+  ASSERT_EQ(auth_request.key().data().challenge_response_key_size(), 1);
+  EXPECT_EQ(
+      auth_request.key().data().challenge_response_key(0).public_key_spki_der(),
+      kKeySpki);
+  ASSERT_EQ(auth_request.key()
+                .data()
+                .challenge_response_key(0)
+                .signature_algorithm_size(),
+            1);
+  EXPECT_EQ(
+      auth_request.key().data().challenge_response_key(0).signature_algorithm(
+          0),
+      kKeyAlgorithmProto);
+}
+
 TEST(CryptohomeUtilTest, BaseReplyToMountErrorNullOptional) {
   const base::Optional<BaseReply> reply = base::nullopt;
 
diff --git a/chromeos/dbus/native_timer_unittest.cc b/chromeos/dbus/native_timer_unittest.cc
index cd5fc11..81a3817 100644
--- a/chromeos/dbus/native_timer_unittest.cc
+++ b/chromeos/dbus/native_timer_unittest.cc
@@ -20,7 +20,8 @@
  public:
   NativeTimerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::MainThreadType::IO,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   ~NativeTimerTest() override = default;
 
diff --git a/chromeos/login/auth/BUILD.gn b/chromeos/login/auth/BUILD.gn
index 973c33a..1fb40ec 100644
--- a/chromeos/login/auth/BUILD.gn
+++ b/chromeos/login/auth/BUILD.gn
@@ -54,6 +54,10 @@
     "challenge_response/known_user_pref_utils.h",
     "cryptohome_authenticator.cc",
     "cryptohome_authenticator.h",
+    "cryptohome_key_constants.cc",
+    "cryptohome_key_constants.h",
+    "cryptohome_parameter_utils.cc",
+    "cryptohome_parameter_utils.h",
     "extended_authenticator.cc",
     "extended_authenticator.h",
     "extended_authenticator_impl.cc",
diff --git a/chromeos/login/auth/DEPS b/chromeos/login/auth/DEPS
index a6a8e02..5c8dfe2 100644
--- a/chromeos/login/auth/DEPS
+++ b/chromeos/login/auth/DEPS
@@ -20,6 +20,7 @@
   "+google_apis",
   "+net",
   "+testing",
+  "+third_party/boringssl/src/include",
   "+third_party/cros_system_api",
   "+url",
 ]
diff --git a/chromeos/login/auth/challenge_response/cert_utils.cc b/chromeos/login/auth/challenge_response/cert_utils.cc
index 6d30478..b63d7d32f 100644
--- a/chromeos/login/auth/challenge_response/cert_utils.cc
+++ b/chromeos/login/auth/challenge_response/cert_utils.cc
@@ -11,6 +11,7 @@
 #include "net/cert/asn1_util.h"
 #include "net/cert/x509_certificate.h"
 #include "net/cert/x509_util.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
 
 namespace chromeos {
 
@@ -30,6 +31,23 @@
 
 }  // namespace
 
+base::Optional<ChallengeResponseKey::SignatureAlgorithm>
+GetChallengeResponseKeyAlgorithmFromSsl(uint16_t ssl_algorithm) {
+  switch (ssl_algorithm) {
+    case SSL_SIGN_RSA_PKCS1_SHA1:
+      return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha1;
+    case SSL_SIGN_RSA_PKCS1_SHA256:
+      return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha256;
+    case SSL_SIGN_RSA_PKCS1_SHA384:
+      return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha384;
+    case SSL_SIGN_RSA_PKCS1_SHA512:
+      return ChallengeResponseKey::SignatureAlgorithm::kRsassaPkcs1V15Sha512;
+    default:
+      // This algorithm is unsupported by ChallengeResponseKey.
+      return {};
+  }
+}
+
 bool ExtractChallengeResponseKeyFromCert(
     const net::X509Certificate& certificate,
     const std::vector<ChallengeResponseKey::SignatureAlgorithm>&
diff --git a/chromeos/login/auth/challenge_response/cert_utils.h b/chromeos/login/auth/challenge_response/cert_utils.h
index f43e178d..d904f4b 100644
--- a/chromeos/login/auth/challenge_response/cert_utils.h
+++ b/chromeos/login/auth/challenge_response/cert_utils.h
@@ -5,9 +5,11 @@
 #ifndef CHROMEOS_LOGIN_AUTH_CHALLENGE_RESPONSE_CERT_UTILS_H_
 #define CHROMEOS_LOGIN_AUTH_CHALLENGE_RESPONSE_CERT_UTILS_H_
 
+#include <cstdint>
 #include <vector>
 
 #include "base/component_export.h"
+#include "base/optional.h"
 #include "chromeos/login/auth/challenge_response_key.h"
 
 namespace net {
@@ -16,6 +18,12 @@
 
 namespace chromeos {
 
+// Maps from the TLS 1.3 SignatureScheme value into the challenge-response key
+// algorithm.
+COMPONENT_EXPORT(CHROMEOS_LOGIN_AUTH)
+base::Optional<ChallengeResponseKey::SignatureAlgorithm>
+GetChallengeResponseKeyAlgorithmFromSsl(uint16_t ssl_algorithm);
+
 // Constructs the ChallengeResponseKey instance based on the public key referred
 // by the specified certificate and on the specified list of supported
 // algorithms. Returns false on failure.
diff --git a/chromeos/login/auth/challenge_response/known_user_pref_utils.cc b/chromeos/login/auth/challenge_response/known_user_pref_utils.cc
index 473c6cc..f7f8628 100644
--- a/chromeos/login/auth/challenge_response/known_user_pref_utils.cc
+++ b/chromeos/login/auth/challenge_response/known_user_pref_utils.cc
@@ -4,10 +4,10 @@
 
 #include "chromeos/login/auth/challenge_response/known_user_pref_utils.h"
 
-#include <string>
 #include <utility>
 
 #include "base/base64.h"
+#include "base/logging.h"
 #include "base/values.h"
 
 namespace chromeos {
@@ -31,4 +31,37 @@
   return pref_value;
 }
 
+bool DeserializeChallengeResponseKeysFromKnownUser(
+    const base::Value& pref_value,
+    std::vector<std::string>* public_key_spki_list) {
+  public_key_spki_list->clear();
+  if (!pref_value.is_list())
+    return false;
+  for (const base::Value& key_representation : pref_value.GetList()) {
+    if (!key_representation.is_dict()) {
+      LOG(WARNING) << "Ignoring challenge-response key info: not a dictionary";
+      continue;
+    }
+    const base::Value* spki_base64 = key_representation.FindKeyOfType(
+        kPublicKeySpkiKey, base::Value::Type::STRING);
+    if (!spki_base64) {
+      LOG(WARNING)
+          << "Ignoring challenge-response key info: missing SPKI property";
+      continue;
+    }
+    std::string spki;
+    if (!base::Base64Decode(spki_base64->GetString(), &spki)) {
+      LOG(WARNING)
+          << "Ignoring challenge-response key info: invalid SPKI base64";
+      continue;
+    }
+    if (spki.empty()) {
+      LOG(WARNING) << "Ignoring challenge-response key info: empty SPKI";
+      continue;
+    }
+    public_key_spki_list->emplace_back(std::move(spki));
+  }
+  return !public_key_spki_list->empty();
+}
+
 }  // namespace chromeos
diff --git a/chromeos/login/auth/challenge_response/known_user_pref_utils.h b/chromeos/login/auth/challenge_response/known_user_pref_utils.h
index 94c5d7b..45fdb7f 100644
--- a/chromeos/login/auth/challenge_response/known_user_pref_utils.h
+++ b/chromeos/login/auth/challenge_response/known_user_pref_utils.h
@@ -5,6 +5,7 @@
 #ifndef CHROMEOS_LOGIN_AUTH_CHALLENGE_RESPONSE_KNOWN_USER_PREF_UTILS_H_
 #define CHROMEOS_LOGIN_AUTH_CHALLENGE_RESPONSE_KNOWN_USER_PREF_UTILS_H_
 
+#include <string>
 #include <vector>
 
 #include "base/component_export.h"
@@ -26,6 +27,11 @@
     SerializeChallengeResponseKeysForKnownUser(
         const std::vector<ChallengeResponseKey>& challenge_response_keys);
 
+bool COMPONENT_EXPORT(CHROMEOS_LOGIN_AUTH)
+    DeserializeChallengeResponseKeysFromKnownUser(
+        const base::Value& pref_value,
+        std::vector<std::string>* public_key_spki_list);
+
 }  // namespace chromeos
 
 #endif  // CHROMEOS_LOGIN_AUTH_CHALLENGE_RESPONSE_KNOWN_USER_PREF_UTILS_H_
diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc
index a4a7d48..120d775 100644
--- a/chromeos/login/auth/cryptohome_authenticator.cc
+++ b/chromeos/login/auth/cryptohome_authenticator.cc
@@ -20,10 +20,10 @@
 #include "chromeos/cryptohome/cryptohome_util.h"
 #include "chromeos/cryptohome/homedir_methods.h"
 #include "chromeos/cryptohome/system_salt_getter.h"
-#include "chromeos/dbus/constants/cryptohome_key_delegate_constants.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
-#include "chromeos/login/auth/challenge_response/key_label_utils.h"
+#include "chromeos/login/auth/cryptohome_key_constants.h"
+#include "chromeos/login/auth/cryptohome_parameter_utils.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/login/auth/login_event_recorder.h"
 #include "chromeos/login/auth/user_context.h"
@@ -39,9 +39,6 @@
 
 namespace {
 
-// The label used for the key derived from the user's GAIA credentials.
-const char kCryptohomeGAIAKeyLabel[] = "gaia";
-
 // The label used for the key generated by Cryptohome for public mount.
 const char kCryptohomePublicMountKeyLabel[] = "publicmount";
 
@@ -229,47 +226,19 @@
   // that returns directly would not generate 2 OnLoginSucces() calls.
   attempt->UsernameHashRequested();
 
-  cryptohome::KeyDefinition key_definition;
-  cryptohome::AuthorizationRequest auth;
-  cryptohome::Key* auth_key = auth.mutable_key();
-
-  if (!attempt->user_context.GetChallengeResponseKeys().empty()) {
-    // For the challenge-response key, no secret is passed, only public-key
-    // information. The authorization request consists of the same key as the
-    // persisted key, plus the additional KeyDelegate information that allows
-    // cryptohomed to call back to Chrome to perform challenges.
-    key_definition = cryptohome::KeyDefinition::CreateForChallengeResponse(
-        attempt->user_context.GetChallengeResponseKeys(),
-        GenerateChallengeResponseKeyLabel(
-            attempt->user_context.GetChallengeResponseKeys()),
-        cryptohome::PRIV_DEFAULT);
-    cryptohome::KeyDefinitionToKey(key_definition, auth_key);
-    auth.mutable_key_delegate()->set_dbus_service_name(
-        cryptohome::kCryptohomeKeyDelegateServiceName);
-    auth.mutable_key_delegate()->set_dbus_object_path(
-        cryptohome::kCryptohomeKeyDelegateServicePath);
-  } else {
-    key_definition = cryptohome::KeyDefinition::CreateForPassword(
-        key->GetSecret(), kCryptohomeGAIAKeyLabel, cryptohome::PRIV_DEFAULT);
-    // Don't set the authorization's key label, implicitly setting it to an
-    // empty string, which is a wildcard allowing any key to match. This is
-    // necessary because cryptohomes created by Chrome OS M38 and older will
-    // have a legacy key with no label while those created by Chrome OS M39 and
-    // newer will have a key with the label kCryptohomeGAIAKeyLabel.
-    //
-    // This logic does not apply to PIN and weak keys in general, as those do
-    // not authenticate against a wildcard label.
-    if (attempt->user_context.IsUsingPin())
-      auth_key->mutable_data()->set_label(key->GetLabel());
-    auth_key->set_secret(key->GetSecret());
-  }
+  const cryptohome::AuthorizationRequest auth =
+      CreateAuthorizationRequestFromKeyDef(
+          cryptohome_parameter_utils::CreateAuthorizationKeyDefFromUserContext(
+              attempt->user_context));
 
   cryptohome::MountRequest mount;
   if (ephemeral)
     mount.set_require_ephemeral(true);
   if (create_if_nonexistent) {
-    cryptohome::KeyDefinitionToKey(key_definition,
-                                   mount.mutable_create()->add_keys());
+    cryptohome::KeyDefinitionToKey(
+        cryptohome_parameter_utils::CreateKeyDefFromUserContext(
+            attempt->user_context),
+        mount.mutable_create()->add_keys());
   }
   if (attempt->user_context.IsForcingDircrypto())
     mount.set_force_dircrypto_if_available(true);
@@ -405,7 +374,7 @@
         cryptohome::GetKeyDataReplyToKeyDefinitions(reply);
     if (key_definitions.size() == 1) {
       const cryptohome::KeyDefinition& key_definition = key_definitions.front();
-      DCHECK_EQ(kCryptohomeGAIAKeyLabel, key_definition.label);
+      DCHECK_EQ(kCryptohomeGaiaKeyLabel, key_definition.label);
 
       // Extract the key type and salt from |key_definition|, if present.
       std::unique_ptr<int64_t> type;
@@ -478,7 +447,7 @@
   }
 
   cryptohome::GetKeyDataRequest request;
-  request.mutable_key()->mutable_data()->set_label(kCryptohomeGAIAKeyLabel);
+  request.mutable_key()->mutable_data()->set_label(kCryptohomeGaiaKeyLabel);
   CryptohomeClient::Get()->GetKeyDataEx(
       cryptohome::CreateAccountIdentifierFromAccountId(
           attempt->user_context.GetAccountId()),
@@ -725,7 +694,17 @@
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   DCHECK_EQ(user_manager::USER_TYPE_PUBLIC_ACCOUNT, user_context.GetUserType());
 
-  current_state_.reset(new AuthAttemptState(user_context,
+  // Set the cryptohome key label, as cryptohome requires a non-empty label to
+  // be specified for the new mount creation requests, regardless of whether the
+  // request is for a Public Session (which uses an ephemeral mount with an
+  // empty password) or for a normal user.
+  // TODO(crbug.com/826417): Introduce a separate constant for the Public
+  // Session key label.
+  UserContext new_user_context = user_context;
+  DCHECK(user_context.GetKey()->GetLabel().empty());
+  new_user_context.GetKey()->SetLabel(kCryptohomeGaiaKeyLabel);
+
+  current_state_.reset(new AuthAttemptState(new_user_context,
                                             false,    // unlock
                                             false,    // online_complete
                                             false));  // user_is_new
diff --git a/chromeos/login/auth/cryptohome_key_constants.cc b/chromeos/login/auth/cryptohome_key_constants.cc
new file mode 100644
index 0000000..0f01c66420
--- /dev/null
+++ b/chromeos/login/auth/cryptohome_key_constants.cc
@@ -0,0 +1,18 @@
+// 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 "chromeos/login/auth/cryptohome_key_constants.h"
+
+namespace chromeos {
+
+// The label used for the key derived from the user's GAIA credentials.
+//
+// Also, for historical reasons, this key is used for Active Directory users and
+// for Public Session keys.
+//
+// TODO(crbug.com/826417): Introduce a separate constant for the Public Session
+// key label.
+const char kCryptohomeGaiaKeyLabel[] = "gaia";
+
+}  // namespace chromeos
diff --git a/chromeos/login/auth/cryptohome_key_constants.h b/chromeos/login/auth/cryptohome_key_constants.h
new file mode 100644
index 0000000..a310880
--- /dev/null
+++ b/chromeos/login/auth/cryptohome_key_constants.h
@@ -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.
+
+#ifndef CHROMEOS_LOGIN_AUTH_CRYPTOHOME_KEY_CONSTANTS_H_
+#define CHROMEOS_LOGIN_AUTH_CRYPTOHOME_KEY_CONSTANTS_H_
+
+#include "base/component_export.h"
+
+namespace chromeos {
+
+COMPONENT_EXPORT(CHROMEOS_LOGIN_AUTH)
+extern const char kCryptohomeGaiaKeyLabel[];
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_LOGIN_AUTH_CRYPTOHOME_KEY_CONSTANTS_H_
diff --git a/chromeos/login/auth/cryptohome_parameter_utils.cc b/chromeos/login/auth/cryptohome_parameter_utils.cc
new file mode 100644
index 0000000..1b13ab4d
--- /dev/null
+++ b/chromeos/login/auth/cryptohome_parameter_utils.cc
@@ -0,0 +1,63 @@
+// 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 "chromeos/login/auth/cryptohome_parameter_utils.h"
+
+#include "base/logging.h"
+#include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/login/auth/challenge_response/key_label_utils.h"
+#include "chromeos/login/auth/key.h"
+#include "chromeos/login/auth/user_context.h"
+
+using cryptohome::KeyDefinition;
+
+namespace chromeos {
+namespace cryptohome_parameter_utils {
+
+KeyDefinition CreateKeyDefFromUserContext(const UserContext& user_context) {
+  if (!user_context.GetChallengeResponseKeys().empty()) {
+    // The case of challenge-response keys. No secret is passed, only public-key
+    // information.
+    return KeyDefinition::CreateForChallengeResponse(
+        user_context.GetChallengeResponseKeys(),
+        GenerateChallengeResponseKeyLabel(
+            user_context.GetChallengeResponseKeys()),
+        cryptohome::PRIV_DEFAULT);
+  }
+
+  // The case of a password or a PIN.
+  const Key* key = user_context.GetKey();
+  // If the |key| is a plain text password, crash rather than attempting to
+  // mount the cryptohome with a plain text password.
+  CHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType());
+  return KeyDefinition::CreateForPassword(key->GetSecret(), key->GetLabel(),
+                                          cryptohome::PRIV_DEFAULT);
+}
+
+KeyDefinition CreateAuthorizationKeyDefFromUserContext(
+    const UserContext& user_context) {
+  KeyDefinition key_def = CreateKeyDefFromUserContext(user_context);
+
+  // Don't set the authorization's key label, implicitly setting it to an empty
+  // string, which is a wildcard allowing any key to match. This is necessary
+  // because cryptohomes created by Chrome OS M38 and older will have a legacy
+  // key with no label while those created by Chrome OS M39 and newer will have
+  // a key with the label kCryptohomeGaiaKeyLabel.
+  //
+  // This logic does not apply to challenge-response, PIN and weak keys in
+  // general, as those do not authenticate against a wildcard label.
+  switch (key_def.type) {
+    case KeyDefinition::TYPE_PASSWORD:
+      if (!user_context.IsUsingPin())
+        key_def.label.clear();
+      break;
+    case KeyDefinition::TYPE_CHALLENGE_RESPONSE:
+      break;
+  }
+
+  return key_def;
+}
+
+}  // namespace cryptohome_parameter_utils
+}  // namespace chromeos
diff --git a/chromeos/login/auth/cryptohome_parameter_utils.h b/chromeos/login/auth/cryptohome_parameter_utils.h
new file mode 100644
index 0000000..ec5f390
--- /dev/null
+++ b/chromeos/login/auth/cryptohome_parameter_utils.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 CHROMEOS_LOGIN_AUTH_CRYPTOHOME_PARAMETER_UTILS_H_
+#define CHROMEOS_LOGIN_AUTH_CRYPTOHOME_PARAMETER_UTILS_H_
+
+#include "base/component_export.h"
+
+namespace cryptohome {
+struct KeyDefinition;
+}
+
+namespace chromeos {
+
+class UserContext;
+
+namespace cryptohome_parameter_utils {
+
+// This file provides helper functions for building and operating with
+// cryptohome parameters based on the Chrome OS login data structures.
+
+// Creates the cryptohome key definition structure based on the credentials and
+// other information from the given user context.
+COMPONENT_EXPORT(CHROMEOS_LOGIN_AUTH)
+cryptohome::KeyDefinition CreateKeyDefFromUserContext(
+    const UserContext& user_context);
+
+// Similar to CreateKeyDefFromUserContext(), but the returned value is
+// slightly altered to be suitable for authorization requests to cryptohome.
+COMPONENT_EXPORT(CHROMEOS_LOGIN_AUTH)
+cryptohome::KeyDefinition CreateAuthorizationKeyDefFromUserContext(
+    const UserContext& user_context);
+
+}  // namespace cryptohome_parameter_utils
+}  // namespace chromeos
+
+#endif  // CHROMEOS_LOGIN_AUTH_CRYPTOHOME_PARAMETER_UTILS_H_
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc
index 788bbb93..25ddb10 100644
--- a/chromeos/login/auth/extended_authenticator_impl.cc
+++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -16,6 +16,7 @@
 #include "chromeos/cryptohome/system_salt_getter.h"
 #include "chromeos/dbus/cryptohome/cryptohome_client.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
+#include "chromeos/login/auth/cryptohome_parameter_utils.h"
 #include "chromeos/login/auth/key.h"
 #include "chromeos/login/auth/login_event_recorder.h"
 #include "chromeos/login/auth/user_context.h"
@@ -185,10 +186,11 @@
     const base::Closure& success_callback,
     const UserContext& user_context) {
   RecordStartMarker("CheckKeyEx");
-  const Key* const key = user_context.GetKey();
   cryptohome::HomedirMethods::GetInstance()->CheckKeyEx(
       cryptohome::Identification(user_context.GetAccountId()),
-      cryptohome::CreateAuthorizationRequest(key->GetLabel(), key->GetSecret()),
+      cryptohome::CreateAuthorizationRequestFromKeyDef(
+          cryptohome_parameter_utils::CreateAuthorizationKeyDefFromUserContext(
+              user_context)),
       cryptohome::CheckKeyRequest(),
       base::Bind(&ExtendedAuthenticatorImpl::OnOperationComplete, this,
                  "CheckKeyEx", user_context, success_callback));
diff --git a/chromeos/login/auth/key.h b/chromeos/login/auth/key.h
index d01a634..c033d735 100644
--- a/chromeos/login/auth/key.h
+++ b/chromeos/login/auth/key.h
@@ -13,6 +13,8 @@
 
 // Key for user authentication. The class supports hashing of plain text
 // passwords to generate keys as well as the use of pre-hashed keys.
+//
+// TODO(crbug.com/826417): Consider making this class movable.
 class COMPONENT_EXPORT(CHROMEOS_LOGIN_AUTH) Key {
  public:
   enum KeyType {
diff --git a/chromeos/services/assistant/assistant_manager_service_impl.cc b/chromeos/services/assistant/assistant_manager_service_impl.cc
index e7867040b..37e0094 100644
--- a/chromeos/services/assistant/assistant_manager_service_impl.cc
+++ b/chromeos/services/assistant/assistant_manager_service_impl.cc
@@ -36,6 +36,7 @@
 #include "libassistant/shared/internal_api/assistant_manager_delegate.h"
 #include "libassistant/shared/internal_api/assistant_manager_internal.h"
 #include "libassistant/shared/public/media_manager.h"
+#include "mojo/public/mojom/base/time.mojom.h"
 #include "services/media_session/public/mojom/constants.mojom.h"
 #include "services/media_session/public/mojom/media_session.mojom.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -609,6 +610,11 @@
   notification_ptr->grouping_key = notification.grouping_key;
   notification_ptr->obfuscated_gaia_id = notification.obfuscated_gaia_id;
 
+  if (notification.expiry_timestamp_ms) {
+    notification_ptr->expiry_time =
+        base::Time::FromJavaTime(notification.expiry_timestamp_ms);
+  }
+
   // The server sometimes sends an empty |notification_id|, but our client
   // requires a non-empty |client_id| for notifications. Known instances in
   // which the server sends an empty |notification_id| are for Reminders.
diff --git a/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc b/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc
index 67c16972..c642f43 100644
--- a/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc
+++ b/chromeos/services/assistant/platform/power_manager_provider_impl_unittest.cc
@@ -28,7 +28,8 @@
  public:
   PowerManagerProviderImplTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO_MOCK_TIME),
+            base::test::ScopedTaskEnvironment::MainThreadType::IO,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         wake_lock_provider_(
             connector_factory_.RegisterInstance(device::mojom::kServiceName)) {}
   ~PowerManagerProviderImplTest() override = default;
diff --git a/chromeos/services/assistant/public/mojom/assistant.mojom b/chromeos/services/assistant/public/mojom/assistant.mojom
index 0b8d098a..adb929c 100644
--- a/chromeos/services/assistant/public/mojom/assistant.mojom
+++ b/chromeos/services/assistant/public/mojom/assistant.mojom
@@ -295,6 +295,10 @@
 
   // Whether this notification can turn on the display if it was off.
   bool is_high_priority = false;
+
+  // When the notification should expire.
+  // Expressed as milliseconds since Unix Epoch.
+  mojo_base.mojom.Time? expiry_time;
 };
 
 // Models status of an app.
diff --git a/components/about_handler/BUILD.gn b/components/about_handler/BUILD.gn
deleted file mode 100644
index d1450023..0000000
--- a/components/about_handler/BUILD.gn
+++ /dev/null
@@ -1,17 +0,0 @@
-# Copyright 2015 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("about_handler") {
-  sources = [
-    "about_protocol_handler.cc",
-    "about_protocol_handler.h",
-    "url_request_about_job.cc",
-    "url_request_about_job.h",
-  ]
-
-  deps = [
-    "//base",
-    "//net",
-  ]
-}
diff --git a/components/about_handler/DEPS b/components/about_handler/DEPS
deleted file mode 100644
index 8fa9d48..0000000
--- a/components/about_handler/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+net",
-]
diff --git a/components/about_handler/OWNERS b/components/about_handler/OWNERS
deleted file mode 100644
index da122a46..0000000
--- a/components/about_handler/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-mmenke@chromium.org
-davidben@chromium.org
-
-# COMPONENT: Internals>Network
diff --git a/components/about_handler/about_protocol_handler.cc b/components/about_handler/about_protocol_handler.cc
deleted file mode 100644
index 1f55f04..0000000
--- a/components/about_handler/about_protocol_handler.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 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/about_handler/about_protocol_handler.h"
-
-#include "components/about_handler/url_request_about_job.h"
-
-namespace about_handler {
-
-AboutProtocolHandler::AboutProtocolHandler() {
-}
-
-AboutProtocolHandler::~AboutProtocolHandler() {
-}
-
-net::URLRequestJob* AboutProtocolHandler::MaybeCreateJob(
-    net::URLRequest* request,
-    net::NetworkDelegate* network_delegate) const {
-  return new URLRequestAboutJob(request, network_delegate);
-}
-
-bool AboutProtocolHandler::IsSafeRedirectTarget(const GURL& location) const {
-  return false;
-}
-
-}  // namespace about_handler
diff --git a/components/about_handler/about_protocol_handler.h b/components/about_handler/about_protocol_handler.h
deleted file mode 100644
index eab2af0..0000000
--- a/components/about_handler/about_protocol_handler.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2012 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_ABOUT_HANDLER_ABOUT_PROTOCOL_HANDLER_H_
-#define COMPONENTS_ABOUT_HANDLER_ABOUT_PROTOCOL_HANDLER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "net/url_request/url_request_job_factory.h"
-
-namespace about_handler {
-
-// Implements a ProtocolHandler for About jobs.
-class AboutProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler {
- public:
-  AboutProtocolHandler();
-  ~AboutProtocolHandler() override;
-  net::URLRequestJob* MaybeCreateJob(
-      net::URLRequest* request,
-      net::NetworkDelegate* network_delegate) const override;
-  bool IsSafeRedirectTarget(const GURL& location) const override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(AboutProtocolHandler);
-};
-
-}  // namespace about_handler
-
-#endif  // COMPONENTS_ABOUT_HANDLER_ABOUT_PROTOCOL_HANDLER_H_
diff --git a/components/about_handler/url_request_about_job.cc b/components/about_handler/url_request_about_job.cc
deleted file mode 100644
index 7d9e190..0000000
--- a/components/about_handler/url_request_about_job.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright (c) 2012 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.
-
-// Simple implementation of about: protocol handler that treats everything as
-// about:blank.  No other about: features should be available to web content,
-// so they're not implemented here.
-
-#include "components/about_handler/url_request_about_job.h"
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-
-namespace about_handler {
-
-URLRequestAboutJob::URLRequestAboutJob(net::URLRequest* request,
-                                       net::NetworkDelegate* network_delegate)
-    : URLRequestJob(request, network_delegate) {}
-
-void URLRequestAboutJob::Start() {
-  // Start reading asynchronously so that all error reporting and data
-  // callbacks happen as they would for network requests.
-  base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(&URLRequestAboutJob::StartAsync,
-                                weak_factory_.GetWeakPtr()));
-}
-
-void URLRequestAboutJob::Kill() {
-  weak_factory_.InvalidateWeakPtrs();
-  URLRequestJob::Kill();
-}
-
-bool URLRequestAboutJob::GetMimeType(std::string* mime_type) const {
-  *mime_type = "text/html";
-  return true;
-}
-
-URLRequestAboutJob::~URLRequestAboutJob() {
-}
-
-void URLRequestAboutJob::StartAsync() {
-  NotifyHeadersComplete();
-}
-
-}  // namespace about_handler
diff --git a/components/about_handler/url_request_about_job.h b/components/about_handler/url_request_about_job.h
deleted file mode 100644
index d54530a9..0000000
--- a/components/about_handler/url_request_about_job.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2011 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_ABOUT_HANDLER_URL_REQUEST_ABOUT_JOB_H_
-#define COMPONENTS_ABOUT_HANDLER_URL_REQUEST_ABOUT_JOB_H_
-
-#include <string>
-
-#include "base/memory/weak_ptr.h"
-#include "net/url_request/url_request.h"
-#include "net/url_request/url_request_job.h"
-
-namespace about_handler {
-
-class URLRequestAboutJob : public net::URLRequestJob {
- public:
-  URLRequestAboutJob(net::URLRequest* request,
-                     net::NetworkDelegate* network_delegate);
-
-  // URLRequestJob:
-  void Start() override;
-  void Kill() override;
-  bool GetMimeType(std::string* mime_type) const override;
-
- private:
-  ~URLRequestAboutJob() override;
-
-  void StartAsync();
-
-  base::WeakPtrFactory<URLRequestAboutJob> weak_factory_{this};
-};
-
-}  // namespace about_handler
-
-#endif  // COMPONENTS_ABOUT_HANDLER_URL_REQUEST_ABOUT_JOB_H_
diff --git a/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc b/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
index 596aceee..e0605d8 100644
--- a/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
+++ b/components/arc/wake_lock/arc_wake_lock_bridge_unittest.cc
@@ -28,7 +28,7 @@
  public:
   ArcWakeLockBridgeTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         wake_lock_provider_(
             connector_factory_.RegisterInstance(device::mojom::kServiceName)) {
     bridge_service_ = std::make_unique<ArcBridgeService>();
diff --git a/components/autofill/android/java/strings/autofill_strings.grd b/components/autofill/android/java/strings/autofill_strings.grd
index e4e1b59..14606f6 100644
--- a/components/autofill/android/java/strings/autofill_strings.grd
+++ b/components/autofill/android/java/strings/autofill_strings.grd
@@ -22,7 +22,7 @@
     <output filename="values-tl/autofill_strings.xml" lang="fil" type="android" />
     <output filename="values-fr/autofill_strings.xml" lang="fr" type="android" />
     <output filename="values-gu/autofill_strings.xml" lang="gu" type="android" />
-    <output filename="values-iw/autofill_strings.xml" lang="he" type="android" />
+    <output filename="values-iw/autofill_strings.xml" lang="iw" type="android" />
     <output filename="values-hi/autofill_strings.xml" lang="hi" type="android" />
     <output filename="values-hr/autofill_strings.xml" lang="hr" type="android" />
     <output filename="values-hu/autofill_strings.xml" lang="hu" type="android" />
diff --git a/components/autofill/core/browser/autofill_type.cc b/components/autofill/core/browser/autofill_type.cc
index e873833..89d06bf7 100644
--- a/components/autofill/core/browser/autofill_type.cc
+++ b/components/autofill/core/browser/autofill_type.cc
@@ -779,6 +779,10 @@
       return "PRICE";
     case NOT_PASSWORD:
       return "NOT_PASSWORD";
+    case SINGLE_USERNAME:
+      return "SINGLE_USERNAME";
+    case NOT_USERNAME:
+      return "NOT_USERNAME";
     case AMBIGUOUS_TYPE:
       return "AMBIGUOUS_TYPE";
     case MAX_VALID_FIELD_TYPE:
diff --git a/components/autofill/core/browser/field_types.h b/components/autofill/core/browser/field_types.h
index 022575a16..8be69f9 100644
--- a/components/autofill/core/browser/field_types.h
+++ b/components/autofill/core/browser/field_types.h
@@ -175,9 +175,19 @@
   // Password-type fields which are not actual passwords.
   NOT_PASSWORD = 99,
 
+  // Username field when there is no corresponding password field. It might be
+  // because of:
+  // 1. Username first flow: a user has to type username first on one page and
+  // then password on another page
+  // 2. Username and password fields are in different <form>s.
+  SINGLE_USERNAME = 100,
+
+  // Text-type fields which are not usernames.
+  NOT_USERNAME = 101,
+
   // No new types can be added without a corresponding change to the Autofill
   // server.
-  MAX_VALID_FIELD_TYPE = 100,
+  MAX_VALID_FIELD_TYPE = 102,
 };
 
 // The list of all HTML autocomplete field type hints supported by Chrome.
diff --git a/components/autofill/core/browser/logging/log_buffer.cc b/components/autofill/core/browser/logging/log_buffer.cc
index 8cfd472..8a07c418 100644
--- a/components/autofill/core/browser/logging/log_buffer.cc
+++ b/components/autofill/core/browser/logging/log_buffer.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "components/autofill/core/browser/logging/log_buffer.h"
+
 #include <string>
 
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/browser/logging/log_buffer.h"
-#include "net/base/escape.h"
 
 namespace autofill {
 
@@ -106,8 +106,9 @@
 
   base::Value::DictStorage storage;
   storage.try_emplace("type", std::make_unique<base::Value>("text"));
-  storage.try_emplace("value",
-                      std::make_unique<base::Value>(net::EscapeForHTML(text)));
+  // This text is not HTML escaped because the rest of the frame work takes care
+  // of that and it must not be escaped twice.
+  storage.try_emplace("value", std::make_unique<base::Value>(text));
   base::Value node_to_add(std::move(storage));
   AppendChildToLastNode(&buf.buffer_, std::move(node_to_add));
   return buf;
@@ -133,7 +134,7 @@
     return buf;
   if (!url.is_valid())
     return buf << "Invalid URL";
-  return buf << net::EscapeForHTML(url.GetOrigin().spec());
+  return buf << url.GetOrigin().spec();
 }
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/logging/log_buffer_unittest.cc b/components/autofill/core/browser/logging/log_buffer_unittest.cc
index d3c686b..90a518b9 100644
--- a/components/autofill/core/browser/logging/log_buffer_unittest.cc
+++ b/components/autofill/core/browser/logging/log_buffer_unittest.cc
@@ -13,20 +13,24 @@
 
 namespace autofill {
 
-TEST(LogBuffer, EscapeStrings) {
+TEST(LogBuffer, JSONSerializeString) {
   LogBuffer buffer;
   buffer << "<foo><!--\"";
   std::string json;
   EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
-  EXPECT_EQ(R"({"type":"text","value":"&lt;foo&gt;&lt;!--&quot;"})", json);
+  // JSON takes care of serializing the <, we don't want &lt; as that would then
+  // be escaped twice.
+  EXPECT_EQ(R"({"type":"text","value":"\u003Cfoo>\u003C!--\""})", json);
 }
 
-TEST(LogBuffer, EscapeUtf16Strings) {
+TEST(LogBuffer, JSONSerializeString16) {
   LogBuffer buffer;
   buffer << base::ASCIIToUTF16("<foo><!--\"");
   std::string json;
   EXPECT_TRUE(base::JSONWriter::Write(buffer.RetrieveResult(), &json));
-  EXPECT_EQ(R"({"type":"text","value":"&lt;foo&gt;&lt;!--&quot;"})", json);
+  // JSON takes care of serializing the <, we don't want &lt; as that would then
+  // be escaped twice.
+  EXPECT_EQ(R"({"type":"text","value":"\u003Cfoo>\u003C!--\""})", json);
 }
 
 TEST(LogBuffer, SupportNumbers) {
@@ -152,7 +156,7 @@
       /**/ R"({"children":[)"                   // tr
       /****/ R"({"children":[{"type":"text","value":"y"}],)"
       /******/ R"("type":"node","value":"td"},)"
-      /****/ R"({"children":[{"type":"text","value":"foobar&lt;!--"}],)"
+      /****/ R"({"children":[{"type":"text","value":"foobar\u003C!--"}],)"
       /******/ R"("type":"node","value":"td"}],)"
       /**/ R"("type":"node","value":"tr"}],"type":"node","value":"table"})",
       json);
diff --git a/components/autofill/core/browser/logging/log_manager.cc b/components/autofill/core/browser/logging/log_manager.cc
index 8a4f250..a94a4ee1 100644
--- a/components/autofill/core/browser/logging/log_manager.cc
+++ b/components/autofill/core/browser/logging/log_manager.cc
@@ -20,7 +20,8 @@
   // LogManager
   void OnLogRouterAvailabilityChanged(bool router_can_be_used) override;
   void SetSuspended(bool suspended) override;
-  void LogSavePasswordProgress(const std::string& text) const override;
+  void LogTextMessage(const std::string& text) const override;
+  void LogEntry(base::Value&& entry) const override;
   bool IsLoggingActive() const override;
 
  private:
@@ -73,12 +74,18 @@
   }
 }
 
-void LogManagerImpl::LogSavePasswordProgress(const std::string& text) const {
+void LogManagerImpl::LogTextMessage(const std::string& text) const {
   if (!IsLoggingActive())
     return;
   log_router_->ProcessLog(text);
 }
 
+void LogManagerImpl::LogEntry(base::Value&& entry) const {
+  if (!IsLoggingActive())
+    return;
+  log_router_->ProcessLog(std::move(entry));
+}
+
 bool LogManagerImpl::IsLoggingActive() const {
   return can_use_log_router_ && !is_suspended_;
 }
diff --git a/components/autofill/core/browser/logging/log_manager.h b/components/autofill/core/browser/logging/log_manager.h
index 0467671..942145a 100644
--- a/components/autofill/core/browser/logging/log_manager.h
+++ b/components/autofill/core/browser/logging/log_manager.h
@@ -11,6 +11,10 @@
 #include "base/callback.h"
 #include "base/macros.h"
 
+namespace base {
+class Value;
+}
+
 namespace autofill {
 
 class LogRouter;
@@ -33,10 +37,14 @@
   virtual void SetSuspended(bool suspended) = 0;
 
   // Forward |text| for display to the LogRouter (if registered with one).
-  virtual void LogSavePasswordProgress(const std::string& text) const = 0;
+  virtual void LogTextMessage(const std::string& text) const = 0;
 
-  // Returns true if logs recorded via LogSavePasswordProgress will be
-  // displayed, and false otherwise.
+  // Forward a DOM structured log entry to the LogRouter (if registered with
+  // one).
+  virtual void LogEntry(base::Value&& entry) const = 0;
+
+  // Returns true if logs recorded via LogTextMessage will be displayed, and
+  // false otherwise.
   virtual bool IsLoggingActive() const = 0;
 
   // Returns the production code implementation of LogManager. If |log_router|
diff --git a/components/autofill/core/browser/logging/log_manager_unittest.cc b/components/autofill/core/browser/logging/log_manager_unittest.cc
index 4542679..d1bcc7c1 100644
--- a/components/autofill/core/browser/logging/log_manager_unittest.cc
+++ b/components/autofill/core/browser/logging/log_manager_unittest.cc
@@ -23,7 +23,7 @@
 class MockLogReceiver : public autofill::LogReceiver {
  public:
   MockLogReceiver() = default;
-  MOCK_METHOD1(LogSavePasswordProgress, void(const std::string&));
+  MOCK_METHOD1(LogEntry, void(const base::Value&));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockLogReceiver);
@@ -59,49 +59,50 @@
   std::unique_ptr<LogManager> manager_;
 };
 
-TEST_F(LogManagerTest, LogSavePasswordProgressNoReceiver) {
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(_)).Times(0);
+TEST_F(LogManagerTest, LogTextMessageNoReceiver) {
+  EXPECT_CALL(receiver_, LogEntry(_)).Times(0);
   // Before attaching the receiver, no text should be passed.
-  manager_->LogSavePasswordProgress(kTestText);
+  manager_->LogTextMessage(kTestText);
   EXPECT_FALSE(manager_->IsLoggingActive());
 }
 
-TEST_F(LogManagerTest, LogSavePasswordProgressAttachReceiver) {
+TEST_F(LogManagerTest, LogTextMessageAttachReceiver) {
   EXPECT_FALSE(manager_->IsLoggingActive());
 
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
-  EXPECT_EQ(std::string(), router_.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router_.RegisterReceiver(&receiver_));
   EXPECT_TRUE(manager_->IsLoggingActive());
   // After attaching the logger, text should be passed.
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText));
-  manager_->LogSavePasswordProgress(kTestText);
+  base::Value log_entry = LogRouter::CreateEntryForText(kTestText);
+  EXPECT_CALL(receiver_, LogEntry(testing::Eq(testing::ByRef(log_entry))));
+  manager_->LogTextMessage(kTestText);
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
   router_.UnregisterReceiver(&receiver_);
   EXPECT_FALSE(manager_->IsLoggingActive());
 }
 
-TEST_F(LogManagerTest, LogSavePasswordProgressDetachReceiver) {
+TEST_F(LogManagerTest, LogTextMessageDetachReceiver) {
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
-  EXPECT_EQ(std::string(), router_.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router_.RegisterReceiver(&receiver_));
   EXPECT_TRUE(manager_->IsLoggingActive());
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
   router_.UnregisterReceiver(&receiver_);
   EXPECT_FALSE(manager_->IsLoggingActive());
 
   // After detaching the logger, no text should be passed.
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(_)).Times(0);
-  manager_->LogSavePasswordProgress(kTestText);
+  EXPECT_CALL(receiver_, LogEntry(_)).Times(0);
+  manager_->LogTextMessage(kTestText);
 }
 
 TEST_F(LogManagerTest, NullCallbackWillNotCrash) {
   manager_ = LogManager::Create(&router_, base::Closure());
-  EXPECT_EQ(std::string(), router_.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router_.RegisterReceiver(&receiver_));
   router_.UnregisterReceiver(&receiver_);
 }
 
 TEST_F(LogManagerTest, SetSuspended_WithActiveLogging) {
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
-  EXPECT_EQ(std::string(), router_.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router_.RegisterReceiver(&receiver_));
   EXPECT_TRUE(manager_->IsLoggingActive());
 
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
@@ -131,7 +132,7 @@
   manager_->SetSuspended(true);
   EXPECT_FALSE(manager_->IsLoggingActive());
 
-  EXPECT_EQ(std::string(), router_.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router_.RegisterReceiver(&receiver_));
   EXPECT_FALSE(manager_->IsLoggingActive());
 
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
@@ -147,7 +148,7 @@
   EXPECT_FALSE(manager_->IsLoggingActive());
 
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
-  EXPECT_EQ(std::string(), router_.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router_.RegisterReceiver(&receiver_));
   EXPECT_TRUE(manager_->IsLoggingActive());
 
   EXPECT_CALL(notified_object_, NotifyAboutLoggingActivity());
diff --git a/components/autofill/core/browser/logging/log_receiver.h b/components/autofill/core/browser/logging/log_receiver.h
index 64ef1d3..3c2e2b7c 100644
--- a/components/autofill/core/browser/logging/log_receiver.h
+++ b/components/autofill/core/browser/logging/log_receiver.h
@@ -5,8 +5,8 @@
 #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_RECEIVER_H_
 #define COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_RECEIVER_H_
 
-#include <string>
 #include "base/macros.h"
+#include "base/values.h"
 
 namespace autofill {
 
@@ -17,7 +17,7 @@
   LogReceiver() {}
   virtual ~LogReceiver() {}
 
-  virtual void LogSavePasswordProgress(const std::string& text) = 0;
+  virtual void LogEntry(const base::Value& entry) = 0;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(LogReceiver);
diff --git a/components/autofill/core/browser/logging/log_router.cc b/components/autofill/core/browser/logging/log_router.cc
index c6c1c2b6..3ab3a1b 100644
--- a/components/autofill/core/browser/logging/log_router.cc
+++ b/components/autofill/core/browser/logging/log_router.cc
@@ -5,8 +5,11 @@
 #include "components/autofill/core/browser/logging/log_router.h"
 
 #include "base/stl_util.h"
+#include "base/strings/string_split.h"
+#include "components/autofill/core/browser/logging/log_buffer.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
 #include "components/autofill/core/browser/logging/log_receiver.h"
+#include "net/base/escape.h"
 
 namespace autofill {
 
@@ -14,13 +17,29 @@
 
 LogRouter::~LogRouter() = default;
 
+// static
+base::Value LogRouter::CreateEntryForText(const std::string& text) {
+  LogBuffer buffer;
+  buffer << Tag{"div"};
+  for (const auto& line : base::SplitStringPiece(
+           text, "\n", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
+    buffer << line << Br{};
+  }
+  buffer << CTag{};
+  return buffer.RetrieveResult();
+}
+
 void LogRouter::ProcessLog(const std::string& text) {
+  ProcessLog(CreateEntryForText(text));
+}
+
+void LogRouter::ProcessLog(base::Value&& node) {
   // This may not be called when there are no receivers (i.e., the router is
   // inactive), because in that case the logs cannot be displayed.
   DCHECK(receivers_.might_have_observers());
-  accumulated_logs_.append(text);
+  accumulated_logs_.emplace_back(std::move(node));
   for (LogReceiver& receiver : receivers_)
-    receiver.LogSavePasswordProgress(text);
+    receiver.LogEntry(accumulated_logs_.back());
 }
 
 bool LogRouter::RegisterManager(LogManager* manager) {
@@ -34,7 +53,8 @@
   managers_.RemoveObserver(manager);
 }
 
-std::string LogRouter::RegisterReceiver(LogReceiver* receiver) {
+const std::vector<base::Value>& LogRouter::RegisterReceiver(
+    LogReceiver* receiver) {
   DCHECK(receiver);
   DCHECK(accumulated_logs_.empty() || receivers_.might_have_observers());
 
@@ -52,7 +72,7 @@
   if (!receivers_.might_have_observers()) {
     // |accumulated_logs_| can become very long; use the swap instead of clear()
     // to ensure that the memory is freed.
-    std::string().swap(accumulated_logs_);
+    std::vector<base::Value>().swap(accumulated_logs_);
     for (LogManager& manager : managers_)
       manager.OnLogRouterAvailabilityChanged(false);
   }
diff --git a/components/autofill/core/browser/logging/log_router.h b/components/autofill/core/browser/logging/log_router.h
index b9cb0eb8..f8ecd5d 100644
--- a/components/autofill/core/browser/logging/log_router.h
+++ b/components/autofill/core/browser/logging/log_router.h
@@ -5,12 +5,13 @@
 #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_ROUTER_H_
 #define COMPONENTS_AUTOFILL_CORE_BROWSER_LOGGING_LOG_ROUTER_H_
 
-#include <set>
 #include <string>
+#include <vector>
 
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/observer_list.h"
+#include "base/values.h"
 
 namespace autofill {
 
@@ -27,8 +28,12 @@
   LogRouter();
   ~LogRouter();
 
+  // Returns a JSON entry that can be fed into the logger.
+  static base::Value CreateEntryForText(const std::string& text);
+
   // Passes logs to the router. Only call when there are receivers registered.
   void ProcessLog(const std::string& text);
+  void ProcessLog(base::Value&& node);
 
   // All four (Unr|R)egister* methods below are safe to call from the
   // constructor of the registered object, because they do not call that object,
@@ -45,7 +50,8 @@
   // RegisterReceiver adds |receiver| to the right observer list, and returns
   // the logs accumulated so far. (It returns by value, not const ref, to
   // provide a snapshot as opposed to a link to |accumulated_logs_|.)
-  std::string RegisterReceiver(LogReceiver* receiver) WARN_UNUSED_RESULT;
+  const std::vector<base::Value>& RegisterReceiver(LogReceiver* receiver)
+      WARN_UNUSED_RESULT;
   // Remove |receiver| from the observers list.
   void UnregisterReceiver(LogReceiver* receiver);
 
@@ -57,7 +63,7 @@
   base::ObserverList<LogReceiver, true>::Unchecked receivers_;
 
   // Logs accumulated since the first receiver was registered.
-  std::string accumulated_logs_;
+  std::vector<base::Value> accumulated_logs_;
 
   DISALLOW_COPY_AND_ASSIGN(LogRouter);
 };
diff --git a/components/autofill/core/browser/logging/log_router_unittest.cc b/components/autofill/core/browser/logging/log_router_unittest.cc
index 1d50ede..26f6ea85 100644
--- a/components/autofill/core/browser/logging/log_router_unittest.cc
+++ b/components/autofill/core/browser/logging/log_router_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/autofill/core/browser/logging/log_router.h"
 
 #include "base/macros.h"
+#include "base/values.h"
 #include "components/autofill/core/browser/logging/log_receiver.h"
 #include "components/autofill/core/browser/logging/stub_log_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -22,7 +23,7 @@
  public:
   MockLogReceiver() = default;
 
-  MOCK_METHOD1(LogSavePasswordProgress, void(const std::string&));
+  MOCK_METHOD1(LogEntry, void(const base::Value&));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockLogReceiver);
@@ -49,47 +50,59 @@
 
 TEST_F(LogRouterTest, ProcessLog_NoReceiver) {
   LogRouter router;
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(1);
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
+  base::Value log_entry = LogRouter::CreateEntryForText(kTestText);
+  EXPECT_CALL(receiver_, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(1);
   router.ProcessLog(kTestText);
   router.UnregisterReceiver(&receiver_);
   // Without receivers, accumulated logs should not have been kept. That means
   // that on the registration of the first receiver, none are returned.
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
   router.UnregisterReceiver(&receiver_);
 }
 
 TEST_F(LogRouterTest, ProcessLog_OneReceiver) {
   LogRouter router;
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
   // Check that logs generated after activation are passed.
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(1);
+  base::Value log_entry = LogRouter::CreateEntryForText(kTestText);
+  EXPECT_CALL(receiver_, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(1);
   router.ProcessLog(kTestText);
   router.UnregisterReceiver(&receiver_);
 }
 
 TEST_F(LogRouterTest, ProcessLog_TwoReceiversAccumulatedLogsPassed) {
   LogRouter router;
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
 
   // Log something with only the first receiver, to accumulate some logs.
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(1);
-  EXPECT_CALL(receiver2_, LogSavePasswordProgress(kTestText)).Times(0);
+  base::Value log_entry = LogRouter::CreateEntryForText(kTestText);
+  EXPECT_CALL(receiver_, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(1);
+  EXPECT_CALL(receiver2_, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(0);
   router.ProcessLog(kTestText);
   // Accumulated logs get passed on registration.
-  EXPECT_EQ(kTestText, router.RegisterReceiver(&receiver2_));
+  std::vector<base::Value> expected_logs;
+  expected_logs.emplace_back(log_entry.Clone());
+  EXPECT_EQ(expected_logs, router.RegisterReceiver(&receiver2_));
   router.UnregisterReceiver(&receiver_);
   router.UnregisterReceiver(&receiver2_);
 }
 
 TEST_F(LogRouterTest, ProcessLog_TwoReceiversBothUpdated) {
   LogRouter router;
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver2_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver2_));
 
   // Check that both receivers get log updates.
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(1);
-  EXPECT_CALL(receiver2_, LogSavePasswordProgress(kTestText)).Times(1);
+  base::Value log_entry = LogRouter::CreateEntryForText(kTestText);
+  EXPECT_CALL(receiver_, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(1);
+  EXPECT_CALL(receiver2_, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(1);
   router.ProcessLog(kTestText);
   router.UnregisterReceiver(&receiver2_);
   router.UnregisterReceiver(&receiver_);
@@ -97,13 +110,15 @@
 
 TEST_F(LogRouterTest, ProcessLog_TwoReceiversNoUpdateAfterUnregistering) {
   LogRouter router;
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver2_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver2_));
 
   // Check that no logs are passed to an unregistered receiver.
   router.UnregisterReceiver(&receiver_);
-  EXPECT_CALL(receiver_, LogSavePasswordProgress(_)).Times(0);
-  EXPECT_CALL(receiver2_, LogSavePasswordProgress(kTestText)).Times(1);
+  EXPECT_CALL(receiver_, LogEntry(_)).Times(0);
+  base::Value log_entry = LogRouter::CreateEntryForText(kTestText);
+  EXPECT_CALL(receiver2_, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(1);
   router.ProcessLog(kTestText);
   router.UnregisterReceiver(&receiver2_);
 }
@@ -117,7 +132,7 @@
 TEST_F(LogRouterTest, RegisterManager_OneReceiverBeforeManager) {
   LogRouter router;
   // First register a receiver.
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
   // The manager should be told the LogRouter has some receivers.
   EXPECT_TRUE(router.RegisterManager(&manager_));
   // Now unregister the receiver. The manager should be told the LogRouter has
@@ -134,7 +149,7 @@
   EXPECT_FALSE(router.RegisterManager(&manager_));
   // Now register the receiver. The manager should be notified.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(true));
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
   // Now unregister the manager.
   router.UnregisterManager(&manager_);
   // Now unregister the receiver. The manager should not hear about it.
@@ -149,10 +164,10 @@
   EXPECT_FALSE(router.RegisterManager(&manager_));
   // Now register the 1st receiver. The manager should be notified.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(true));
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver_));
   // Now register the 2nd receiver. The manager should not be notified.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(true)).Times(0);
-  EXPECT_EQ(std::string(), router.RegisterReceiver(&receiver2_));
+  EXPECT_EQ(std::vector<base::Value>(), router.RegisterReceiver(&receiver2_));
   // Now unregister the 1st receiver. The manager should not hear about it.
   EXPECT_CALL(manager_, OnLogRouterAvailabilityChanged(false)).Times(0);
   router.UnregisterReceiver(&receiver_);
diff --git a/components/autofill/core/browser/logging/stub_log_manager.cc b/components/autofill/core/browser/logging/stub_log_manager.cc
index cf81f73..52ed346 100644
--- a/components/autofill/core/browser/logging/stub_log_manager.cc
+++ b/components/autofill/core/browser/logging/stub_log_manager.cc
@@ -10,7 +10,9 @@
 
 void StubLogManager::SetSuspended(bool suspended) {}
 
-void StubLogManager::LogSavePasswordProgress(const std::string& text) const {}
+void StubLogManager::LogTextMessage(const std::string& text) const {}
+
+void StubLogManager::LogEntry(base::Value&& entry) const {}
 
 bool StubLogManager::IsLoggingActive() const {
   return false;
diff --git a/components/autofill/core/browser/logging/stub_log_manager.h b/components/autofill/core/browser/logging/stub_log_manager.h
index f155c55..c8ec53e 100644
--- a/components/autofill/core/browser/logging/stub_log_manager.h
+++ b/components/autofill/core/browser/logging/stub_log_manager.h
@@ -22,7 +22,8 @@
   // LogManager
   void OnLogRouterAvailabilityChanged(bool router_can_be_used) override;
   void SetSuspended(bool suspended) override;
-  void LogSavePasswordProgress(const std::string& text) const override;
+  void LogTextMessage(const std::string& text) const override;
+  void LogEntry(base::Value&& entry) const override;
   bool IsLoggingActive() const override;
 
   DISALLOW_COPY_AND_ASSIGN(StubLogManager);
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc
index 5de4e63f..542fe87c 100644
--- a/components/autofill/core/common/save_password_progress_logger.cc
+++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -154,6 +154,7 @@
   bool conversion_to_string_successful = base::JSONWriter::WriteWithOptions(
       log, base::JSONWriter::OPTIONS_PRETTY_PRINT, &log_string);
   DCHECK(conversion_to_string_successful);
+  std::replace(log_string.begin(), log_string.end(), '"', ' ');
   SendLog(GetStringFromID(label) + ": " + log_string);
 }
 
diff --git a/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc b/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc
index 44bbea2..5d7d22e 100644
--- a/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/configure_bottom_sheet_action_unittest.cc
@@ -29,8 +29,7 @@
 class ConfigureBottomSheetActionTest : public testing::Test {
  public:
   ConfigureBottomSheetActionTest()
-      : task_env_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+      : task_env_(base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     ON_CALL(mock_action_delegate_, GetResizeViewport())
diff --git a/components/autofill_assistant/browser/actions/prompt_action_unittest.cc b/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
index a4761f51..46c09e09 100644
--- a/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
@@ -32,8 +32,7 @@
 class PromptActionTest : public testing::Test {
  public:
   PromptActionTest()
-      : task_env_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+      : task_env_(base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     ON_CALL(mock_web_controller_, OnElementCheck(_, _))
diff --git a/components/autofill_assistant/browser/controller_unittest.cc b/components/autofill_assistant/browser/controller_unittest.cc
index 119d6f4..8784d9dd 100644
--- a/components/autofill_assistant/browser/controller_unittest.cc
+++ b/components/autofill_assistant/browser/controller_unittest.cc
@@ -83,7 +83,8 @@
  public:
   ControllerTest()
       : RenderViewHostTestHarness(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME),
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         fake_client_(&mock_ui_controller_) {}
   ~ControllerTest() override {}
 
diff --git a/components/autofill_assistant/browser/element_area_unittest.cc b/components/autofill_assistant/browser/element_area_unittest.cc
index 1a8fc9b..b271af9 100644
--- a/components/autofill_assistant/browser/element_area_unittest.cc
+++ b/components/autofill_assistant/browser/element_area_unittest.cc
@@ -69,7 +69,7 @@
  protected:
   ElementAreaTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         element_area_(&delegate_) {
     delegate_.SetWebController(&mock_web_controller_);
     delegate_.GetMutableSettings()->element_position_update_interval =
diff --git a/components/autofill_assistant/browser/retry_timer_unittest.cc b/components/autofill_assistant/browser/retry_timer_unittest.cc
index 3fbd868..e467d15 100644
--- a/components/autofill_assistant/browser/retry_timer_unittest.cc
+++ b/components/autofill_assistant/browser/retry_timer_unittest.cc
@@ -24,7 +24,7 @@
  protected:
   RetryTimerTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void FastForwardOneSecond() {
     scoped_task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index 1109f217..b06f0e9 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -79,7 +79,7 @@
  protected:
   ScriptExecutorTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   // Implements ScriptExecutor::Listener
   void OnServerPayloadChanged(const std::string& global_payload,
diff --git a/components/background_task_scheduler/BUILD.gn b/components/background_task_scheduler/BUILD.gn
index 5923277f..7db9b4d 100644
--- a/components/background_task_scheduler/BUILD.gn
+++ b/components/background_task_scheduler/BUILD.gn
@@ -89,6 +89,7 @@
     java_files = [
       "android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java",
       "android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java",
+      "android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java",
       "android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerImplTest.java",
       "android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerPrefsTest.java",
       "android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUmaTest.java",
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
index b109980..46380ee7 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskService.java
@@ -13,6 +13,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
@@ -22,6 +23,13 @@
 public class BackgroundTaskGcmTaskService extends GcmTaskService {
     private static final String TAG = "BkgrdTaskGcmTS";
 
+    private BackgroundTaskSchedulerGcmNetworkManager.Clock mClock = System::currentTimeMillis;
+
+    @VisibleForTesting
+    void setClockForTesting(BackgroundTaskSchedulerGcmNetworkManager.Clock clock) {
+        mClock = clock;
+    }
+
     /** Class that waits for the processing to be done. */
     private static class Waiter {
         // Wakelock is only held for 3 minutes by default for GcmTaskService.
@@ -90,6 +98,12 @@
             return GcmNetworkManager.RESULT_FAILURE;
         }
 
+        Long deadlineTime =
+                BackgroundTaskSchedulerGcmNetworkManager.getDeadlineTimeFromTaskParams(params);
+        if (deadlineTime != null && mClock.currentTimeMillis() >= deadlineTime) {
+            return GcmNetworkManager.RESULT_FAILURE;
+        }
+
         final TaskParameters taskParams =
                 BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTaskParams(params);
         final Waiter waiter = new Waiter(Waiter.MAX_TIMEOUT_SECONDS);
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
index 83a038c4..f54aa98 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobService.java
@@ -12,6 +12,7 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
 import org.chromium.base.ThreadUtils;
+import org.chromium.base.VisibleForTesting;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -21,6 +22,13 @@
 public class BackgroundTaskJobService extends JobService {
     private static final String TAG = "BkgrdTaskJS";
 
+    private BackgroundTaskSchedulerJobService.Clock mClock = System::currentTimeMillis;
+
+    @VisibleForTesting
+    void setClockForTesting(BackgroundTaskSchedulerJobService.Clock clock) {
+        mClock = clock;
+    }
+
     private static class TaskFinishedCallbackJobService
             implements BackgroundTask.TaskFinishedCallback {
         private final BackgroundTaskJobService mJobService;
@@ -73,6 +81,12 @@
             return false;
         }
 
+        Long deadlineTime =
+                BackgroundTaskSchedulerJobService.getDeadlineTimeFromJobParameters(params);
+        if (deadlineTime != null && mClock.currentTimeMillis() >= deadlineTime) {
+            return false;
+        }
+
         mCurrentTasks.put(params.getJobId(), backgroundTask);
 
         TaskParameters taskParams =
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java
index 87538f9..b7c4d6ad 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerDelegate.java
@@ -6,12 +6,21 @@
 
 import android.content.Context;
 
+import org.chromium.base.VisibleForTesting;
+
 /**
  * The internal representation of a {@link BackgroundTaskScheduler} to make it possible to use
  * system APIs ({@link android.app.job.JobScheduler} on newer platforms and GCM
  * ({@link com.google.android.gms.gcm.GcmNetworkManager}) on older platforms.
  */
 interface BackgroundTaskSchedulerDelegate {
+    @VisibleForTesting
+    String BACKGROUND_TASK_CLASS_KEY = "_background_task_class";
+    @VisibleForTesting
+    String BACKGROUND_TASK_EXTRAS_KEY = "_background_task_extras";
+    @VisibleForTesting
+    String BACKGROUND_TASK_DEADLINE_KEY = "_background_task_deadline";
+
     /**
      * Schedules a background task. See {@link TaskInfo} for information on what types of tasks that
      * can be scheduled.
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
index bc759eb..5715890 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManager.java
@@ -29,10 +29,18 @@
 class BackgroundTaskSchedulerGcmNetworkManager implements BackgroundTaskSchedulerDelegate {
     private static final String TAG = "BkgrdTaskSchedGcmNM";
 
+    /** Delta time for expiration checks, after the end time. */
+    static final long DEADLINE_DELTA_MS = 1000;
+
+    /** Clock to use so we can mock time in tests. */
+    public interface Clock { long currentTimeMillis(); }
+
+    private static Clock sClock = System::currentTimeMillis;
+
     @VisibleForTesting
-    static final String BACKGROUND_TASK_CLASS_KEY = "_background_task_class";
-    @VisibleForTesting
-    static final String BACKGROUND_TASK_EXTRAS_KEY = "_background_task_extras";
+    static void setClockForTesting(Clock clock) {
+        sClock = clock;
+    }
 
     static BackgroundTask getBackgroundTaskFromTaskParams(@NonNull TaskParams taskParams) {
         String backgroundTaskClassName = getBackgroundTaskClassFromTaskParams(taskParams);
@@ -45,6 +53,19 @@
         return extras.getString(BACKGROUND_TASK_CLASS_KEY);
     }
 
+    static Long getDeadlineTimeFromTaskParams(@NonNull TaskParams taskParams) {
+        Bundle extras = taskParams.getExtras();
+        if (extras == null || !extras.containsKey(BACKGROUND_TASK_DEADLINE_KEY)) {
+            return null;
+        }
+        return extras.getLong(BACKGROUND_TASK_DEADLINE_KEY);
+    }
+
+    private static long getDeadlineTime(TaskInfo taskInfo) {
+        long windowEndTimeMs = taskInfo.getOneOffInfo().getWindowEndTimeMs();
+        return sClock.currentTimeMillis() + windowEndTimeMs;
+    }
+
     /**
      * Retrieves the {@link TaskParameters} from the {@link TaskParams}, which are passed as
      * one of the keys. Only values valid for {@link android.os.BaseBundle} are supported, and other
@@ -76,6 +97,9 @@
         Bundle taskExtras = new Bundle();
         taskExtras.putString(
                 BACKGROUND_TASK_CLASS_KEY, taskInfo.getBackgroundTaskClass().getName());
+        if (!taskInfo.isPeriodic() && taskInfo.getOneOffInfo().expiresAfterWindowEndTime()) {
+            taskExtras.putLong(BACKGROUND_TASK_DEADLINE_KEY, getDeadlineTime(taskInfo));
+        }
         taskExtras.putBundle(BACKGROUND_TASK_EXTRAS_KEY, taskInfo.getExtras());
 
         Task.Builder builder;
@@ -111,8 +135,12 @@
         long windowStartSeconds = oneOffInfo.hasWindowStartTimeConstraint()
                 ? TimeUnit.MILLISECONDS.toSeconds(oneOffInfo.getWindowStartTimeMs())
                 : 0;
-        builder.setExecutionWindow(windowStartSeconds,
-                TimeUnit.MILLISECONDS.toSeconds(oneOffInfo.getWindowEndTimeMs()));
+        long windowEndTimeMs = oneOffInfo.getWindowEndTimeMs();
+        if (oneOffInfo.expiresAfterWindowEndTime()) {
+            windowEndTimeMs += DEADLINE_DELTA_MS;
+        }
+        builder.setExecutionWindow(
+                windowStartSeconds, TimeUnit.MILLISECONDS.toSeconds(windowEndTimeMs));
         return builder;
     }
 
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
index 68380df..68d5299 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobService.java
@@ -27,9 +27,18 @@
 class BackgroundTaskSchedulerJobService implements BackgroundTaskSchedulerDelegate {
     private static final String TAG = "BkgrdTaskSchedulerJS";
 
-    private static final String BACKGROUND_TASK_CLASS_KEY = "_background_task_class";
+    /** Delta time to use expiration checks. Used to make checks after the end time. */
+    static final long DEADLINE_DELTA_MS = 1000;
+
+    /** Clock to use so we can mock time in tests. */
+    public interface Clock { long currentTimeMillis(); }
+
+    private static Clock sClock = System::currentTimeMillis;
+
     @VisibleForTesting
-    static final String BACKGROUND_TASK_EXTRAS_KEY = "_background_task_extras";
+    static void setClockForTesting(Clock clock) {
+        sClock = clock;
+    }
 
     static BackgroundTask getBackgroundTaskFromJobParameters(JobParameters jobParameters) {
         String backgroundTaskClassName = getBackgroundTaskClassFromJobParameters(jobParameters);
@@ -42,6 +51,19 @@
         return extras.getString(BACKGROUND_TASK_CLASS_KEY);
     }
 
+    static Long getDeadlineTimeFromJobParameters(JobParameters jobParameters) {
+        PersistableBundle extras = jobParameters.getExtras();
+        if (extras == null || !extras.containsKey(BACKGROUND_TASK_DEADLINE_KEY)) {
+            return null;
+        }
+        return extras.getLong(BACKGROUND_TASK_DEADLINE_KEY);
+    }
+
+    private static long getDeadlineTime(TaskInfo taskInfo) {
+        long windowEndTimeMs = taskInfo.getOneOffInfo().getWindowEndTimeMs();
+        return sClock.currentTimeMillis() + windowEndTimeMs;
+    }
+
     /**
      * Retrieves the {@link TaskParameters} from the {@link JobParameters}, which are passed as
      * one of the keys. Only values valid for {@link android.os.BaseBundle} are supported, and other
@@ -69,6 +91,10 @@
         PersistableBundle jobExtras = new PersistableBundle();
         jobExtras.putString(BACKGROUND_TASK_CLASS_KEY, taskInfo.getBackgroundTaskClass().getName());
 
+        if (!taskInfo.isPeriodic() && taskInfo.getOneOffInfo().expiresAfterWindowEndTime()) {
+            jobExtras.putLong(BACKGROUND_TASK_DEADLINE_KEY, getDeadlineTime(taskInfo));
+        }
+
         PersistableBundle persistableBundle = getTaskExtrasAsPersistableBundle(taskInfo);
         jobExtras.putPersistableBundle(BACKGROUND_TASK_EXTRAS_KEY, persistableBundle);
 
@@ -96,7 +122,11 @@
         if (oneOffInfo.hasWindowStartTimeConstraint()) {
             builder = builder.setMinimumLatency(oneOffInfo.getWindowStartTimeMs());
         }
-        return builder.setOverrideDeadline(oneOffInfo.getWindowEndTimeMs());
+        long windowEndTimeMs = oneOffInfo.getWindowEndTimeMs();
+        if (oneOffInfo.expiresAfterWindowEndTime()) {
+            windowEndTimeMs += DEADLINE_DELTA_MS;
+        }
+        return builder.setOverrideDeadline(windowEndTimeMs);
     }
 
     private static JobInfo.Builder getPeriodicJobInfo(JobInfo.Builder builder, TaskInfo taskInfo) {
diff --git a/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java b/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java
index 5aabb755..c10a8c6 100644
--- a/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java
+++ b/components/background_task_scheduler/android/javatests/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerJobServiceTest.java
@@ -14,6 +14,7 @@
 import android.support.test.filters.SmallTest;
 
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -45,67 +46,104 @@
         public void reschedule(Context context) {}
     }
 
+    private static final long CLOCK_TIME = 1415926535000L;
+    private static final long TIME_50_MIN_TO_MS = TimeUnit.MINUTES.toMillis(50);
+    private static final long TIME_100_MIN_TO_MS = TimeUnit.MINUTES.toMillis(100);
+    private static final long TIME_200_MIN_TO_MS = TimeUnit.MINUTES.toMillis(200);
+    private static final long END_TIME_WITH_DEADLINE_MS =
+            TIME_200_MIN_TO_MS + BackgroundTaskSchedulerJobService.DEADLINE_DELTA_MS;
+    private static final long DEADLINE_TIME_MS = CLOCK_TIME + TIME_200_MIN_TO_MS;
+
+    private BackgroundTaskSchedulerJobService.Clock mClock = () -> CLOCK_TIME;
+
+    @Before
+    public void setUp() {
+        BackgroundTaskSchedulerJobService.setClockForTesting(mClock);
+    }
+
     @Test
     @SmallTest
-    public void testOneOffTaskInfoWithDeadlineConversion() {
+    public void testOneOffTaskWithDeadline() {
         TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.MINUTES.toMillis(200))
+                                              TIME_200_MIN_TO_MS)
                                       .build();
         JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
                 InstrumentationRegistry.getTargetContext(), oneOffTask);
         Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId());
         Assert.assertFalse(jobInfo.isPeriodic());
-        Assert.assertEquals(oneOffTask.getOneOffInfo().getWindowEndTimeMs(),
-                jobInfo.getMaxExecutionDelayMillis());
+        Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getMaxExecutionDelayMillis());
     }
 
     @Test
     @SmallTest
-    public void testOneOffTaskInfoWithWindowConversion() {
-        TaskInfo oneOffTask =
-                TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                TimeUnit.MINUTES.toMillis(100), TimeUnit.MINUTES.toMillis(200))
-                        .build();
+    public void testOneOffTaskWithDeadlineAndExpiration() {
+        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                              TIME_200_MIN_TO_MS)
+                                      .setExpiresAfterWindowEndTime(true)
+                                      .build();
+        JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
+                InstrumentationRegistry.getTargetContext(), oneOffTask);
+        Assert.assertEquals(END_TIME_WITH_DEADLINE_MS, jobInfo.getMaxExecutionDelayMillis());
+        Assert.assertEquals(DEADLINE_TIME_MS,
+                jobInfo.getExtras().getLong(
+                        BackgroundTaskSchedulerJobService.BACKGROUND_TASK_DEADLINE_KEY));
+    }
+
+    @Test
+    @SmallTest
+    public void testOneOffTaskWithWindow() {
+        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                              TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
+                                      .build();
         JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
                 InstrumentationRegistry.getTargetContext(), oneOffTask);
         Assert.assertEquals(oneOffTask.getTaskId(), jobInfo.getId());
         Assert.assertFalse(jobInfo.isPeriodic());
-        Assert.assertEquals(
-                oneOffTask.getOneOffInfo().getWindowStartTimeMs(), jobInfo.getMinLatencyMillis());
-        Assert.assertEquals(oneOffTask.getOneOffInfo().getWindowEndTimeMs(),
-                jobInfo.getMaxExecutionDelayMillis());
+        Assert.assertEquals(TIME_100_MIN_TO_MS, jobInfo.getMinLatencyMillis());
+        Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getMaxExecutionDelayMillis());
     }
 
     @Test
     @SmallTest
-    public void testPeriodicTaskInfoWithoutFlexConversion() {
+    public void testOneOffTaskWithWindowAndExpiration() {
+        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                              TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
+                                      .setExpiresAfterWindowEndTime(true)
+                                      .build();
+        JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
+                InstrumentationRegistry.getTargetContext(), oneOffTask);
+        Assert.assertEquals(
+                oneOffTask.getOneOffInfo().getWindowStartTimeMs(), jobInfo.getMinLatencyMillis());
+        Assert.assertEquals(END_TIME_WITH_DEADLINE_MS, jobInfo.getMaxExecutionDelayMillis());
+        Assert.assertEquals(DEADLINE_TIME_MS,
+                jobInfo.getExtras().getLong(
+                        BackgroundTaskSchedulerJobService.BACKGROUND_TASK_DEADLINE_KEY));
+    }
+
+    @Test
+    @SmallTest
+    public void testPeriodicTaskWithoutFlex() {
         TaskInfo periodicTask = TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
-                                                TimeUnit.MINUTES.toMillis(200))
+                                                TIME_200_MIN_TO_MS)
                                         .build();
         JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
                 InstrumentationRegistry.getTargetContext(), periodicTask);
         Assert.assertEquals(periodicTask.getTaskId(), jobInfo.getId());
         Assert.assertTrue(jobInfo.isPeriodic());
-        Assert.assertEquals(
-                periodicTask.getPeriodicInfo().getIntervalMs(), jobInfo.getIntervalMillis());
+        Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getIntervalMillis());
     }
 
     @Test
     @SmallTest
-    public void testPeriodicTaskInfoWithFlexConversion() {
-        TaskInfo periodicTask =
-                TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
-                                TimeUnit.MINUTES.toMillis(200), TimeUnit.MINUTES.toMillis(50))
-                        .build();
+    public void testPeriodicTaskWithFlex() {
+        TaskInfo periodicTask = TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
+                                                TIME_200_MIN_TO_MS, TIME_50_MIN_TO_MS)
+                                        .build();
         JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
                 InstrumentationRegistry.getTargetContext(), periodicTask);
-        Assert.assertEquals(periodicTask.getTaskId(), jobInfo.getId());
-        Assert.assertTrue(jobInfo.isPeriodic());
-        Assert.assertEquals(
-                periodicTask.getPeriodicInfo().getIntervalMs(), jobInfo.getIntervalMillis());
+        Assert.assertEquals(TIME_200_MIN_TO_MS, jobInfo.getIntervalMillis());
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
-            Assert.assertEquals(
-                    periodicTask.getPeriodicInfo().getFlexMs(), jobInfo.getFlexMillis());
+            Assert.assertEquals(TIME_50_MIN_TO_MS, jobInfo.getFlexMillis());
         }
     }
 
@@ -117,7 +155,7 @@
         taskExtras.putBoolean("bools", true);
         taskExtras.putLong("longs", 1342543L);
         TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.MINUTES.toMillis(200))
+                                              TIME_200_MIN_TO_MS)
                                       .setExtras(taskExtras)
                                       .build();
         JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
@@ -136,7 +174,7 @@
     @SmallTest
     public void testTaskInfoWithManyConstraints() {
         TaskInfo.Builder taskBuilder = TaskInfo.createOneOffTask(
-                TaskIds.TEST, TestBackgroundTask.class, TimeUnit.MINUTES.toMillis(200));
+                TaskIds.TEST, TestBackgroundTask.class, TIME_200_MIN_TO_MS);
 
         JobInfo jobInfo = BackgroundTaskSchedulerJobService.createJobInfoFromTaskInfo(
                 InstrumentationRegistry.getTargetContext(),
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java
index 63cbf43..7a44dfd 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskGcmTaskServiceTest.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -37,6 +38,8 @@
     static TestBackgroundTaskWithParams sLastTask;
     static boolean sReturnThroughCallback;
     static boolean sNeedsRescheduling;
+    private static BackgroundTaskSchedulerGcmNetworkManager.Clock sClock = () -> 1415926535000L;
+    private static BackgroundTaskSchedulerGcmNetworkManager.Clock sZeroClock = () -> 0L;
     @Mock
     private BackgroundTaskSchedulerDelegate mDelegate;
     @Mock
@@ -77,10 +80,11 @@
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testOnRunTask() {
+    public void testStartsAnytimeWithoutDeadline() {
         Bundle taskExtras = new Bundle();
         taskExtras.putString("foo", "bar");
-        TaskParams taskParams = buildTaskParams(TestBackgroundTaskWithParams.class, taskExtras);
+        TaskParams taskParams =
+                buildTaskParams(TestBackgroundTaskWithParams.class, taskExtras, null);
 
         BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
         assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_SUCCESS);
@@ -96,9 +100,57 @@
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
+    public void testDoesNotStartExactlyAtDeadline() {
+        TaskParams taskParams = buildTaskParams(
+                TestBackgroundTaskWithParams.class, new Bundle(), sClock.currentTimeMillis());
+
+        BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+        taskService.setClockForTesting(sClock);
+        assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_FAILURE);
+
+        assertNull(sLastTask);
+
+        verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testDoesNotStartAfterDeadline() {
+        TaskParams taskParams = buildTaskParams(
+                TestBackgroundTaskWithParams.class, new Bundle(), sZeroClock.currentTimeMillis());
+
+        BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+        taskService.setClockForTesting(sClock);
+        assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_FAILURE);
+
+        assertNull(sLastTask);
+
+        verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testStartsBeforeDeadline() {
+        TaskParams taskParams = buildTaskParams(
+                TestBackgroundTaskWithParams.class, new Bundle(), sClock.currentTimeMillis());
+
+        BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
+        taskService.setClockForTesting(sZeroClock);
+        assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_SUCCESS);
+
+        assertNotNull(sLastTask);
+        TaskParameters parameters = sLastTask.getTaskParameters();
+
+        assertEquals(parameters.getTaskId(), TaskIds.TEST);
+
+        verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
     public void testOnRunTaskMissingConstructor() {
         TaskParams taskParams =
-                buildTaskParams(TestBackgroundTaskNoPublicConstructor.class, new Bundle());
+                buildTaskParams(TestBackgroundTaskNoPublicConstructor.class, new Bundle(), null);
 
         BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
         assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_FAILURE);
@@ -109,7 +161,8 @@
     public void testOnRuntaskNeedsReschedulingFromCallback() {
         sReturnThroughCallback = true;
         sNeedsRescheduling = true;
-        TaskParams taskParams = buildTaskParams(TestBackgroundTaskWithParams.class, new Bundle());
+        TaskParams taskParams =
+                buildTaskParams(TestBackgroundTaskWithParams.class, new Bundle(), null);
 
         BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
         assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_RESCHEDULE);
@@ -120,7 +173,8 @@
     public void testOnRuntaskDontRescheduleFromCallback() {
         sReturnThroughCallback = true;
         sNeedsRescheduling = false;
-        TaskParams taskParams = buildTaskParams(TestBackgroundTaskWithParams.class, new Bundle());
+        TaskParams taskParams =
+                buildTaskParams(TestBackgroundTaskWithParams.class, new Bundle(), null);
 
         BackgroundTaskGcmTaskService taskService = new BackgroundTaskGcmTaskService();
         assertEquals(taskService.onRunTask(taskParams), GcmNetworkManager.RESULT_SUCCESS);
@@ -155,12 +209,16 @@
         assertEquals(0, TestBackgroundTask.getRescheduleCalls());
     }
 
-    private TaskParams buildTaskParams(Class clazz, Bundle taskExtras) {
+    private static TaskParams buildTaskParams(Class clazz, Bundle taskExtras, Long deadlineTimeMs) {
         Bundle extras = new Bundle();
         extras.putBundle(
                 BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_EXTRAS_KEY, taskExtras);
         extras.putString(BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_CLASS_KEY,
                 clazz.getName());
+        if (deadlineTimeMs != null) {
+            extras.putLong(BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_DEADLINE_KEY,
+                    deadlineTimeMs);
+        }
 
         return new TaskParams(Integer.toString(TaskIds.TEST), extras);
     }
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java
new file mode 100644
index 0000000..6bfcfc2
--- /dev/null
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskJobServiceTest.java
@@ -0,0 +1,114 @@
+// 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.
+
+package org.chromium.components.background_task_scheduler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.job.JobParameters;
+import android.os.PersistableBundle;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.Feature;
+
+/** Unit tests for {@link BackgroundTaskJobService}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class BackgroundTaskJobServiceTest {
+    private static BackgroundTaskSchedulerJobService.Clock sClock = () -> 1415926535000L;
+    private static BackgroundTaskSchedulerJobService.Clock sZeroClock = () -> 0L;
+    @Mock
+    private BackgroundTaskSchedulerDelegate mDelegate;
+    @Mock
+    private BackgroundTaskSchedulerUma mBackgroundTaskSchedulerUma;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        BackgroundTaskSchedulerFactory.setSchedulerForTesting(
+                new BackgroundTaskSchedulerImpl(mDelegate));
+        BackgroundTaskSchedulerUma.setInstanceForTesting(mBackgroundTaskSchedulerUma);
+        TestBackgroundTask.reset();
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testTaskStartsAnytimeWithoutDeadline() {
+        JobParameters jobParameters = buildJobParameters(null);
+
+        BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+        assertFalse(jobService.onStartJob(jobParameters));
+
+        verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
+        assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testTaskDoesNotStartExactlyAtDeadline() {
+        JobParameters jobParameters = buildJobParameters(sClock.currentTimeMillis());
+
+        BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+        jobService.setClockForTesting(sClock);
+        assertFalse(jobService.onStartJob(jobParameters));
+
+        verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+        assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testTaskDoesNotStartAfterDeadline() {
+        JobParameters jobParameters = buildJobParameters(sZeroClock.currentTimeMillis());
+
+        BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+        jobService.setClockForTesting(sClock);
+        assertFalse(jobService.onStartJob(jobParameters));
+
+        verify(mBackgroundTaskSchedulerUma, times(0)).reportTaskStarted(eq(TaskIds.TEST));
+        assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testTaskStartsBeforeDeadline() {
+        JobParameters jobParameters = buildJobParameters(sClock.currentTimeMillis());
+
+        BackgroundTaskJobService jobService = new BackgroundTaskJobService();
+        jobService.setClockForTesting(sZeroClock);
+        assertFalse(jobService.onStartJob(jobParameters));
+
+        verify(mBackgroundTaskSchedulerUma, times(1)).reportTaskStarted(eq(TaskIds.TEST));
+        assertEquals(0, TestBackgroundTask.getRescheduleCalls());
+    }
+
+    private static JobParameters buildJobParameters(Long deadlineTime) {
+        PersistableBundle extras = new PersistableBundle();
+        extras.putString(BackgroundTaskSchedulerJobService.BACKGROUND_TASK_CLASS_KEY,
+                TestBackgroundTask.class.getName());
+        if (deadlineTime != null) {
+            extras.putLong(
+                    BackgroundTaskSchedulerJobService.BACKGROUND_TASK_DEADLINE_KEY, deadlineTime);
+        }
+        PersistableBundle taskExtras = new PersistableBundle();
+        extras.putPersistableBundle(
+                BackgroundTaskSchedulerJobService.BACKGROUND_TASK_EXTRAS_KEY, taskExtras);
+
+        return new JobParameters(null /* callback */, TaskIds.TEST, extras,
+                null /* transientExtras */, null /* clipData */, 0 /* clipGrantFlags */,
+                false /* overrideDeadlineExpired */, null /* triggeredContentUris */,
+                null /* triggeredContentAuthorities */, null /* network */);
+    }
+}
\ No newline at end of file
diff --git a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java
index cad5c84..e177fdd 100644
--- a/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java
+++ b/components/background_task_scheduler/android/junit/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerGcmNetworkManagerTest.java
@@ -45,77 +45,120 @@
 
     ShadowGcmNetworkManager mGcmNetworkManager;
 
+    private static final long CLOCK_TIME_MS = 1415926535000L;
+    private static final long TIME_100_MIN_TO_MS = TimeUnit.MINUTES.toMillis(100);
+    private static final long TIME_100_MIN_TO_S = TimeUnit.MINUTES.toSeconds(100);
+    private static final long TIME_200_MIN_TO_MS = TimeUnit.MINUTES.toMillis(200);
+    private static final long TIME_200_MIN_TO_S = TimeUnit.MINUTES.toSeconds(200);
+    private static final long TIME_24_H_TO_MS = TimeUnit.HOURS.toMillis(1);
+    private static final long END_TIME_WITH_DEADLINE_S =
+            (TIME_200_MIN_TO_MS + BackgroundTaskSchedulerGcmNetworkManager.DEADLINE_DELTA_MS)
+            / 1000;
+    private static final long DEADLINE_TIME_MS = CLOCK_TIME_MS + TIME_200_MIN_TO_MS;
+
+    private BackgroundTaskSchedulerGcmNetworkManager.Clock mClock = () -> CLOCK_TIME_MS;
+
     @Before
     public void setUp() {
-
         Shadows.shadowOf(GoogleApiAvailability.getInstance())
                 .setIsGooglePlayServicesAvailable(ConnectionResult.SUCCESS);
         mGcmNetworkManager = (ShadowGcmNetworkManager) Shadow.extract(
                 GcmNetworkManager.getInstance(ContextUtils.getApplicationContext()));
+        BackgroundTaskSchedulerGcmNetworkManager.setClockForTesting(mClock);
     }
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testOneOffTaskInfoWithDeadlineConversion() {
-        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.MINUTES.toMillis(200))
-                                      .build();
-        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTask);
+    public void testOneOffTaskWithDeadline() {
+        TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                                  TIME_200_MIN_TO_MS)
+                                          .build();
+        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
         assertTrue(task instanceof OneoffTask);
-        assertEquals(Integer.toString(oneOffTask.getTaskId()), task.getTag());
-        assertEquals(
-                TimeUnit.MILLISECONDS.toSeconds(oneOffTask.getOneOffInfo().getWindowEndTimeMs()),
-                ((OneoffTask) task).getWindowEnd());
-        assertEquals(0, ((OneoffTask) task).getWindowStart());
+        OneoffTask oneOffTask = (OneoffTask) task;
+        assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
+        assertEquals(TIME_200_MIN_TO_S, oneOffTask.getWindowEnd());
+        assertEquals(0, oneOffTask.getWindowStart());
     }
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testOneOffTaskInfoWithWindowConversion() {
-        TaskInfo oneOffTask =
-                TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                TimeUnit.MINUTES.toMillis(100), TimeUnit.MINUTES.toMillis(200))
-                        .build();
-        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTask);
+    public void testOneOffTaskWithDeadlineAndExpiration() {
+        TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                                  TIME_200_MIN_TO_MS)
+                                          .setExpiresAfterWindowEndTime(true)
+                                          .build();
+        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
         assertTrue(task instanceof OneoffTask);
-        assertEquals(Integer.toString(oneOffTask.getTaskId()), task.getTag());
-        assertEquals(
-                TimeUnit.MILLISECONDS.toSeconds(oneOffTask.getOneOffInfo().getWindowEndTimeMs()),
-                ((OneoffTask) task).getWindowEnd());
-        assertEquals(
-                TimeUnit.MILLISECONDS.toSeconds(oneOffTask.getOneOffInfo().getWindowStartTimeMs()),
-                ((OneoffTask) task).getWindowStart());
+        OneoffTask oneOffTask = (OneoffTask) task;
+        assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
+        assertEquals(END_TIME_WITH_DEADLINE_S, oneOffTask.getWindowEnd());
+        assertEquals(0, oneOffTask.getWindowStart());
+        assertEquals(DEADLINE_TIME_MS,
+                task.getExtras().getLong(
+                        BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_DEADLINE_KEY));
     }
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testPeriodicTaskInfoWithoutFlexConversion() {
-        TaskInfo periodicTask = TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
-                                                TimeUnit.MINUTES.toMillis(200))
-                                        .build();
-        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(periodicTask);
-        assertEquals(Integer.toString(periodicTask.getTaskId()), task.getTag());
+    public void testOneOffTaskWithWindow() {
+        TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                                  TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
+                                          .build();
+        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
+        assertTrue(task instanceof OneoffTask);
+        OneoffTask oneOffTask = (OneoffTask) task;
+        assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
+        assertEquals(TIME_200_MIN_TO_S, oneOffTask.getWindowEnd());
+        assertEquals(TIME_100_MIN_TO_S, oneOffTask.getWindowStart());
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testOneOffTaskWithWindowAndExpiration() {
+        TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                                  TIME_100_MIN_TO_MS, TIME_200_MIN_TO_MS)
+                                          .setExpiresAfterWindowEndTime(true)
+                                          .build();
+        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
+        assertTrue(task instanceof OneoffTask);
+        OneoffTask oneOffTask = (OneoffTask) task;
+        assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
+        assertEquals(END_TIME_WITH_DEADLINE_S, oneOffTask.getWindowEnd());
+        assertEquals(TIME_100_MIN_TO_S, oneOffTask.getWindowStart());
+        assertEquals(DEADLINE_TIME_MS,
+                task.getExtras().getLong(
+                        BackgroundTaskSchedulerGcmNetworkManager.BACKGROUND_TASK_DEADLINE_KEY));
+    }
+
+    @Test
+    @Feature({"BackgroundTaskScheduler"})
+    public void testPeriodicTaskWithoutFlex() {
+        TaskInfo periodicTaskInfo = TaskInfo.createPeriodicTask(TaskIds.TEST,
+                                                    TestBackgroundTask.class, TIME_200_MIN_TO_MS)
+                                            .build();
+        Task task =
+                BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(periodicTaskInfo);
+        assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
         assertTrue(task instanceof PeriodicTask);
-        assertEquals(
-                TimeUnit.MILLISECONDS.toSeconds(periodicTask.getPeriodicInfo().getIntervalMs()),
-                ((PeriodicTask) task).getPeriod());
+        PeriodicTask periodicTask = (PeriodicTask) task;
+        assertEquals(TIME_200_MIN_TO_S, periodicTask.getPeriod());
     }
 
     @Test
     @Feature({"BackgroundTaskScheduler"})
-    public void testPeriodicTaskInfoWithFlexConversion() {
-        TaskInfo periodicTask =
+    public void testPeriodicTaskWithFlex() {
+        TaskInfo periodicTaskInfo =
                 TaskInfo.createPeriodicTask(TaskIds.TEST, TestBackgroundTask.class,
-                                TimeUnit.MINUTES.toMillis(200), TimeUnit.MINUTES.toMillis(50))
+                                TIME_200_MIN_TO_MS, TimeUnit.MINUTES.toMillis(50))
                         .build();
-        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(periodicTask);
-        assertEquals(Integer.toString(periodicTask.getTaskId()), task.getTag());
+        Task task =
+                BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(periodicTaskInfo);
+        assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
         assertTrue(task instanceof PeriodicTask);
-        assertEquals(
-                TimeUnit.MILLISECONDS.toSeconds(periodicTask.getPeriodicInfo().getIntervalMs()),
-                ((PeriodicTask) task).getPeriod());
-        assertEquals(TimeUnit.MILLISECONDS.toSeconds(periodicTask.getPeriodicInfo().getFlexMs()),
-                ((PeriodicTask) task).getFlex());
+        PeriodicTask periodicTask = (PeriodicTask) task;
+        assertEquals(TIME_200_MIN_TO_S, periodicTask.getPeriod());
+        assertEquals(TimeUnit.MINUTES.toSeconds(50), periodicTask.getFlex());
     }
 
     @Test
@@ -125,13 +168,14 @@
         userExtras.putString("foo", "bar");
         userExtras.putBoolean("bools", true);
         userExtras.putLong("longs", 1342543L);
-        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.MINUTES.toMillis(200))
-                                      .setExtras(userExtras)
-                                      .build();
-        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTask);
-        assertEquals(Integer.toString(oneOffTask.getTaskId()), task.getTag());
+        TaskInfo oneOffTaskInfo = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
+                                                  TIME_200_MIN_TO_MS)
+                                          .setExtras(userExtras)
+                                          .build();
+        Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo);
+        assertEquals(Integer.toString(TaskIds.TEST), task.getTag());
         assertTrue(task instanceof OneoffTask);
+        OneoffTask oneOffTask = (OneoffTask) task;
 
         Bundle taskExtras = task.getExtras();
         Bundle bundle = taskExtras.getBundle(
@@ -146,7 +190,7 @@
     @Feature({"BackgroundTaskScheduler"})
     public void testTaskInfoWithManyConstraints() {
         TaskInfo.Builder taskBuilder = TaskInfo.createOneOffTask(
-                TaskIds.TEST, TestBackgroundTask.class, TimeUnit.MINUTES.toMillis(200));
+                TaskIds.TEST, TestBackgroundTask.class, TIME_200_MIN_TO_MS);
 
         Task task = BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(
                 taskBuilder.setIsPersisted(true).build());
@@ -174,8 +218,8 @@
 
         TaskParameters parameters =
                 BackgroundTaskSchedulerGcmNetworkManager.getTaskParametersFromTaskParams(params);
-        assertEquals(parameters.getTaskId(), TaskIds.TEST);
-        assertEquals(parameters.getExtras().getString("foo"), "bar");
+        assertEquals(TaskIds.TEST, parameters.getTaskId());
+        assertEquals("bar", parameters.getExtras().getString("foo"));
     }
 
     @Test
@@ -196,41 +240,39 @@
     @Test
     @Feature({"BackgroundTaskScheduler"})
     public void testSchedule() {
-        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.DAYS.toMillis(1))
-                                      .build();
+        TaskInfo oneOffTaskInfo =
+                TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
+                        .build();
 
         assertNull(mGcmNetworkManager.getScheduledTask());
 
         BackgroundTaskSchedulerDelegate delegate = new BackgroundTaskSchedulerGcmNetworkManager();
 
-        assertTrue(delegate.schedule(ContextUtils.getApplicationContext(), oneOffTask));
+        assertTrue(delegate.schedule(ContextUtils.getApplicationContext(), oneOffTaskInfo));
 
         // Check that a task was scheduled using GCM Network Manager.
         assertNotNull(mGcmNetworkManager.getScheduledTask());
 
         // Verify details of the scheduled task.
         Task scheduledTask = mGcmNetworkManager.getScheduledTask();
+        assertTrue(scheduledTask instanceof OneoffTask);
+        OneoffTask oneOffTask = (OneoffTask) scheduledTask;
 
-        assertEquals(Integer.toString(oneOffTask.getTaskId()), scheduledTask.getTag());
-        assertEquals(
-                TimeUnit.MILLISECONDS.toSeconds(oneOffTask.getOneOffInfo().getWindowEndTimeMs()),
-                ((OneoffTask) scheduledTask).getWindowEnd());
-        assertEquals(
-                TimeUnit.MILLISECONDS.toSeconds(oneOffTask.getOneOffInfo().getWindowStartTimeMs()),
-                ((OneoffTask) scheduledTask).getWindowStart());
+        assertEquals(Integer.toString(TaskIds.TEST), scheduledTask.getTag());
+        assertEquals(TimeUnit.HOURS.toSeconds(1), oneOffTask.getWindowEnd());
+        assertEquals(0, oneOffTask.getWindowStart());
     }
 
     @Test
     @Feature("BackgroundTaskScheduler")
     public void testScheduleNoPublicConstructor() {
-        TaskInfo oneOffTask =
+        TaskInfo oneOffTaskInfo =
                 TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTaskNoPublicConstructor.class,
-                                TimeUnit.DAYS.toMillis(1))
+                                TIME_24_H_TO_MS)
                         .build();
 
         assertFalse(new BackgroundTaskSchedulerGcmNetworkManager().schedule(
-                ContextUtils.getApplicationContext(), oneOffTask));
+                ContextUtils.getApplicationContext(), oneOffTaskInfo));
     }
 
     @Test
@@ -239,28 +281,28 @@
         Shadows.shadowOf(GoogleApiAvailability.getInstance())
                 .setIsGooglePlayServicesAvailable(ConnectionResult.SERVICE_MISSING);
 
-        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.DAYS.toMillis(1))
-                                      .build();
+        TaskInfo oneOffTaskInfo =
+                TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
+                        .build();
 
         assertFalse(new BackgroundTaskSchedulerGcmNetworkManager().schedule(
-                ContextUtils.getApplicationContext(), oneOffTask));
+                ContextUtils.getApplicationContext(), oneOffTaskInfo));
     }
 
     @Test
     @Feature("BackgroundTaskScheduler")
     public void testCancel() {
-        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.DAYS.toMillis(1))
-                                      .build();
+        TaskInfo oneOffTaskInfo =
+                TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
+                        .build();
 
         BackgroundTaskSchedulerDelegate delegate = new BackgroundTaskSchedulerGcmNetworkManager();
 
-        assertTrue(delegate.schedule(ContextUtils.getApplicationContext(), oneOffTask));
-        delegate.cancel(ContextUtils.getApplicationContext(), oneOffTask.getTaskId());
+        assertTrue(delegate.schedule(ContextUtils.getApplicationContext(), oneOffTaskInfo));
+        delegate.cancel(ContextUtils.getApplicationContext(), TaskIds.TEST);
 
         Task canceledTask = mGcmNetworkManager.getCanceledTask();
-        assertEquals(Integer.toString(oneOffTask.getTaskId()), canceledTask.getTag());
+        assertEquals(Integer.toString(TaskIds.TEST), canceledTask.getTag());
     }
 
     @Test
@@ -270,19 +312,19 @@
         Shadows.shadowOf(GoogleApiAvailability.getInstance())
                 .setIsGooglePlayServicesAvailable(ConnectionResult.SERVICE_MISSING);
 
-        TaskInfo oneOffTask = TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class,
-                                              TimeUnit.DAYS.toMillis(1))
-                                      .build();
+        TaskInfo oneOffTaskInfo =
+                TaskInfo.createOneOffTask(TaskIds.TEST, TestBackgroundTask.class, TIME_24_H_TO_MS)
+                        .build();
 
         // Ensure there was a previously scheduled task.
         mGcmNetworkManager.schedule(
-                BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTask));
+                BackgroundTaskSchedulerGcmNetworkManager.createTaskFromTaskInfo(oneOffTaskInfo));
 
         BackgroundTaskSchedulerDelegate delegate = new BackgroundTaskSchedulerGcmNetworkManager();
 
         // This call is expected to have no effect on GCM Network Manager, because Play Services are
         // not available.
-        delegate.cancel(ContextUtils.getApplicationContext(), oneOffTask.getTaskId());
+        delegate.cancel(ContextUtils.getApplicationContext(), TaskIds.TEST);
         assertNull(mGcmNetworkManager.getCanceledTask());
         assertNotNull(mGcmNetworkManager.getScheduledTask());
     }
diff --git a/components/cast_channel/cast_message_handler_unittest.cc b/components/cast_channel/cast_message_handler_unittest.cc
index 5acea0b..f835e3c6 100644
--- a/components/cast_channel/cast_message_handler_unittest.cc
+++ b/components/cast_channel/cast_message_handler_unittest.cc
@@ -74,7 +74,7 @@
  public:
   CastMessageHandlerTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         cast_socket_service_(new base::TestSimpleTaskRunner()),
         handler_(&cast_socket_service_,
                  /* connector */ nullptr,
diff --git a/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc b/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
index f9917a4..fc4188f 100644
--- a/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
+++ b/components/data_reduction_proxy/content/browser/data_reduction_proxy_pingback_client_impl_unittest.cc
@@ -110,7 +110,7 @@
  public:
   DataReductionProxyPingbackClientImplTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::ASYNC) {
   }
 
diff --git a/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc b/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
index a1a7a0e..9b52e956 100644
--- a/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/warmup_url_fetcher_unittest.cc
@@ -374,7 +374,7 @@
 
 TEST(WarmupURLFetcherTest, TestSuccessfulFetchWarmupURLWithDelay) {
   base::test::ScopedTaskEnvironment scoped_task_environment(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   network::TestURLLoaderFactory test_url_loader_factory;
 
   base::HistogramTester histogram_tester;
diff --git a/components/embedder_support/android/java/strings/web_contents_delegate_android_strings.grd b/components/embedder_support/android/java/strings/web_contents_delegate_android_strings.grd
index b438a13e..11a0cf0 100644
--- a/components/embedder_support/android/java/strings/web_contents_delegate_android_strings.grd
+++ b/components/embedder_support/android/java/strings/web_contents_delegate_android_strings.grd
@@ -22,7 +22,7 @@
     <output filename="values-tl/web_contents_delegate_android_strings.xml" lang="fil" type="android" />
     <output filename="values-fr/web_contents_delegate_android_strings.xml" lang="fr" type="android" />
     <output filename="values-gu/web_contents_delegate_android_strings.xml" lang="gu" type="android" />
-    <output filename="values-iw/web_contents_delegate_android_strings.xml" lang="he" type="android" />
+    <output filename="values-iw/web_contents_delegate_android_strings.xml" lang="iw" type="android" />
     <output filename="values-hi/web_contents_delegate_android_strings.xml" lang="hi" type="android" />
     <output filename="values-hr/web_contents_delegate_android_strings.xml" lang="hr" type="android" />
     <output filename="values-hu/web_contents_delegate_android_strings.xml" lang="hu" type="android" />
diff --git a/components/feed/core/feed_networking_host_unittest.cc b/components/feed/core/feed_networking_host_unittest.cc
index 875075c..e38d912 100644
--- a/components/feed/core/feed_networking_host_unittest.cc
+++ b/components/feed/core/feed_networking_host_unittest.cc
@@ -137,7 +137,7 @@
   network::TestURLLoaderFactory* test_factory() { return &test_factory_; }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
  private:
   identity::IdentityTestEnvironment identity_test_env_;
diff --git a/components/gcm_driver/gcm_client_impl_unittest.cc b/components/gcm_driver/gcm_client_impl_unittest.cc
index 7925c72..5d5649e 100644
--- a/components/gcm_driver/gcm_client_impl_unittest.cc
+++ b/components/gcm_driver/gcm_client_impl_unittest.cc
@@ -429,7 +429,7 @@
 
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
   // Must be declared first so that it is destroyed last. Injected to
   // GCM client.
diff --git a/components/language/content/browser/geo_language_model_unittest.cc b/components/language/content/browser/geo_language_model_unittest.cc
index a041ac9..36230f8 100644
--- a/components/language/content/browser/geo_language_model_unittest.cc
+++ b/components/language/content/browser/geo_language_model_unittest.cc
@@ -59,7 +59,7 @@
   GeoLanguageModel* language_model() { return &geo_language_model_; }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
  private:
   GeoLanguageProvider geo_language_provider_;
diff --git a/components/language/content/browser/geo_language_provider_unittest.cc b/components/language/content/browser/geo_language_provider_unittest.cc
index d1c89c89..a006532 100644
--- a/components/language/content/browser/geo_language_provider_unittest.cc
+++ b/components/language/content/browser/geo_language_provider_unittest.cc
@@ -82,7 +82,7 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
  private:
   // Object under test.
diff --git a/components/network_session_configurator/OWNERS b/components/network_session_configurator/OWNERS
index 6afd7be..1b18221a 100644
--- a/components/network_session_configurator/OWNERS
+++ b/components/network_session_configurator/OWNERS
@@ -1,2 +1,3 @@
 bnc@chromium.org
 rch@chromium.org
+# COMPONENT: Internals>Network
diff --git a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
index 72f56d5..948a8201 100644
--- a/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
+++ b/components/ntp_snippets/remote/remote_suggestions_fetcher_impl_unittest.cc
@@ -254,7 +254,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   std::map<std::string, std::string> default_variation_params_;
   identity::IdentityTestEnvironment identity_test_env_;
   network::TestURLLoaderFactory test_url_loader_factory_;
diff --git a/components/ntp_tiles/features.cc b/components/ntp_tiles/features.cc
index 0ea51f07..a5baa53 100644
--- a/components/ntp_tiles/features.cc
+++ b/components/ntp_tiles/features.cc
@@ -20,7 +20,4 @@
 const base::Feature kUsePopularSitesSuggestions{
     "UsePopularSitesSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kDefaultSearchShortcut{"DefaultSearchShortcut",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
-
 }  // namespace ntp_tiles
diff --git a/components/ntp_tiles/features.h b/components/ntp_tiles/features.h
index 39dc61d..d9e819607 100644
--- a/components/ntp_tiles/features.h
+++ b/components/ntp_tiles/features.h
@@ -26,9 +26,6 @@
 // If this feature is enabled, we enable popular sites in the suggestions UI.
 extern const base::Feature kUsePopularSitesSuggestions;
 
-// If enabled, show a Google search shortcut on the NTP by default.
-extern const base::Feature kDefaultSearchShortcut;
-
 }  // namespace ntp_tiles
 
 #endif  // COMPONENTS_NTP_TILES_FEATURES_H_
diff --git a/components/ntp_tiles/metrics.cc b/components/ntp_tiles/metrics.cc
index 8b97fa2..a942354 100644
--- a/components/ntp_tiles/metrics.cc
+++ b/components/ntp_tiles/metrics.cc
@@ -28,7 +28,6 @@
 const char kHistogramHomepageName[] = "homepage";
 const char kHistogramCustomLinksName[] = "custom_links";
 const char kHistogramExploreName[] = "explore";
-const char kHistogramSearchName[] = "search_page";
 
 // Suffixes for the various icon types.
 const char kTileTypeSuffixIconColor[] = "IconsColor";
@@ -61,8 +60,6 @@
       return kHistogramCustomLinksName;
     case TileSource::EXPLORE:
       return kHistogramExploreName;
-    case TileSource::SEARCH_PAGE:
-      return kHistogramSearchName;
   }
   NOTREACHED();
   return std::string();
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index 4a0d141c..f25abd58 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -17,7 +17,6 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
-#include "components/google/core/common/google_util.h"
 #include "components/history/core/browser/top_sites.h"
 #include "components/ntp_tiles/constants.h"
 #include "components/ntp_tiles/features.h"
@@ -26,8 +25,6 @@
 #include "components/ntp_tiles/switches.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/base/l10n/l10n_util.h"
 
 using history::TopSites;
 using suggestions::ChromeSuggestion;
@@ -185,12 +182,6 @@
       return custom_links_ != nullptr;
     case TileSource::EXPLORE:
       return explore_sites_client_ != nullptr;
-    case TileSource::SEARCH_PAGE:
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-      return true;
-#else
-      return false;
-#endif
   }
   NOTREACHED();
   return false;
@@ -741,51 +732,6 @@
   return explore_sites_tile;
 }
 
-NTPTilesVector MostVisitedSites::InsertSearchTile(NTPTilesVector tiles) const {
-  DCHECK_GT(max_num_sites_, 0u);
-
-#if defined(OS_ANDROID)
-  return tiles;
-#else
-  NTPTilesVector new_tiles;
-  const GURL search_url(l10n_util::GetStringUTF16(IDS_NTP_DEFAULT_SEARCH_URL));
-  bool search_tile_added = false;
-
-  for (auto& tile : tiles) {
-    if (new_tiles.size() >= max_num_sites_) {
-      break;
-    }
-
-    // If there's a tile has the same host name with the search page, insert
-    // the tile to the first position of the list. This is also a deduplication.
-    if (google_util::IsGoogleHomePageUrl(tile.url) && !search_tile_added) {
-      tile.source = TileSource::SEARCH_PAGE;
-      search_tile_added = true;
-      new_tiles.insert(new_tiles.begin(), std::move(tile));
-      continue;
-    }
-    new_tiles.push_back(std::move(tile));
-  }
-
-  if (!search_tile_added) {
-    // Make room for the search tile.
-    if (new_tiles.size() >= max_num_sites_) {
-      new_tiles.pop_back();
-    }
-    NTPTile search_tile;
-    search_tile.url = search_url;
-    search_tile.title = l10n_util::GetStringUTF16(IDS_NTP_DEFAULT_SEARCH_TITLE);
-    search_tile.source = TileSource::SEARCH_PAGE;
-    search_tile.title_source = TileTitleSource::TITLE_TAG;
-
-    // Always insert |search_tile| to the front of |new_tiles| to ensure it's
-    // the first tile.
-    new_tiles.insert(new_tiles.begin(), std::move(search_tile));
-  }
-  return new_tiles;
-#endif
-}
-
 void MostVisitedSites::OnCustomLinksChanged() {
   DCHECK(custom_links_);
   if (!custom_links_enabled_)
@@ -841,9 +787,6 @@
     // copy of new tiles.
     new_tiles = InsertHomeTile(std::move(new_tiles), base::string16());
   }
-  if (base::FeatureList::IsEnabled(ntp_tiles::kDefaultSearchShortcut)) {
-    new_tiles = InsertSearchTile(std::move(new_tiles));
-  }
   MergeMostVisitedTiles(std::move(new_tiles));
 }
 
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h
index ade20009..537213f 100644
--- a/components/ntp_tiles/most_visited_sites.h
+++ b/components/ntp_tiles/most_visited_sites.h
@@ -326,11 +326,6 @@
   // the front of the list.
   base::Optional<NTPTile> CreateExploreSitesTile();
 
-  // Adds the Google Search page as first tile to |tiles| and returns them as
-  // new vector. Drops existing tiles with the same host as the Google Search
-  // page and tiles that would exceed the maximum.
-  NTPTilesVector InsertSearchTile(NTPTilesVector tiles) const;
-
   void OnHomepageTitleDetermined(NTPTilesVector tiles,
                                  const base::Optional<base::string16>& title);
 
diff --git a/components/ntp_tiles/most_visited_sites_unittest.cc b/components/ntp_tiles/most_visited_sites_unittest.cc
index a46e3a9..e099000 100644
--- a/components/ntp_tiles/most_visited_sites_unittest.cc
+++ b/components/ntp_tiles/most_visited_sites_unittest.cc
@@ -93,11 +93,6 @@
          testing::PrintToString(static_cast<int>(source));
 }
 
-MATCHER_P3(NotMatchesTile, title, url, source, PrintTile(title, url, source)) {
-  return arg.title != base::ASCIIToUTF16(title) && arg.url != GURL(url) &&
-         arg.source != source;
-}
-
 MATCHER_P3(MatchesTile, title, url, source, PrintTile(title, url, source)) {
   return arg.title == base::ASCIIToUTF16(title) && arg.url == GURL(url) &&
          arg.source == source;
@@ -2255,95 +2250,4 @@
                       TileSource::EXPLORE)));
 }
 
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-
-TEST_P(MostVisitedSitesTest, ShouldIncludeTileForSearchPage) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled=*/{ntp_tiles::kDefaultSearchShortcut}, /*disabled=*/{});
-  DisableRemoteSuggestions();
-  EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
-      .WillRepeatedly(InvokeCallbackArgument<0>(MostVisitedURLList{}));
-  EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
-  EXPECT_CALL(*mock_top_sites_,
-              IsBlacklisted(Eq(GURL("https://www.google.com"))))
-      .Times(AnyNumber())
-      .WillRepeatedly(Return(false));
-  EXPECT_CALL(mock_observer_, OnURLsAvailable(FirstPersonalizedTileIs(
-                                  "Google", "https://www.google.com/",
-                                  TileSource::SEARCH_PAGE)));
-  most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
-                                                  /*num_sites=*/3);
-  base::RunLoop().RunUntilIdle();
-}
-
-TEST_P(MostVisitedSitesTest, ShouldHaveSearchPageFirstInListWhenFull) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled=*/{ntp_tiles::kDefaultSearchShortcut}, /*disabled=*/{});
-  DisableRemoteSuggestions();
-  EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
-      .WillRepeatedly(InvokeCallbackArgument<0>((MostVisitedURLList{
-          MakeMostVisitedURL("Site 1", "http://site1/"),
-          MakeMostVisitedURL("Site 2", "http://site2/"),
-          MakeMostVisitedURL("Site 3", "http://site3/"),
-          MakeMostVisitedURL("Site 4", "http://site4/"),
-          MakeMostVisitedURL("Site 5", "http://site5/"),
-      })));
-  EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
-  EXPECT_CALL(*mock_top_sites_,
-              IsBlacklisted(Eq(GURL("https://www.gooogle.com/"))))
-      .Times(AnyNumber())
-      .WillRepeatedly(Return(false));
-  std::map<SectionType, NTPTilesVector> sections;
-  EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
-      .WillOnce(SaveArg<0>(&sections));
-  most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
-                                                  /*num_sites=*/4);
-  base::RunLoop().RunUntilIdle();
-  ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
-  NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
-  ASSERT_THAT(tiles.size(), Ge(4ul));
-  // Assert that the search page is appended as the first tile.
-  EXPECT_THAT(tiles[0], MatchesTile("Google", "https://www.google.com",
-                                    TileSource::SEARCH_PAGE));
-}
-
-TEST_P(MostVisitedSitesTest, DedupesSearchPage) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      /*enabled=*/{ntp_tiles::kDefaultSearchShortcut}, /*disabled=*/{});
-  DisableRemoteSuggestions();
-  EXPECT_CALL(*mock_top_sites_, GetMostVisitedURLs(_))
-      .WillRepeatedly(InvokeCallbackArgument<0>((MostVisitedURLList{
-          MakeMostVisitedURL("Site 1", "http://site1/"),
-          MakeMostVisitedURL("Google", "https://www.google.com"),
-          MakeMostVisitedURL("Site 3", "http://site3/"),
-          MakeMostVisitedURL("Site 4", "http://site4/"),
-      })));
-  EXPECT_CALL(*mock_top_sites_, SyncWithHistory());
-  EXPECT_CALL(*mock_top_sites_,
-              IsBlacklisted(Eq(GURL("https://www.gooogle.com/"))))
-      .Times(AnyNumber())
-      .WillRepeatedly(Return(false));
-  std::map<SectionType, NTPTilesVector> sections;
-  EXPECT_CALL(mock_observer_, OnURLsAvailable(_))
-      .WillOnce(SaveArg<0>(&sections));
-  most_visited_sites_->SetMostVisitedURLsObserver(&mock_observer_,
-                                                  /*num_sites=*/4);
-  base::RunLoop().RunUntilIdle();
-  ASSERT_THAT(sections, Contains(Key(SectionType::PERSONALIZED)));
-  NTPTilesVector tiles = sections.at(SectionType::PERSONALIZED);
-  ASSERT_THAT(tiles.size(), Ge(4ul));
-  // Assert that the search page is appended as the first tile.
-  EXPECT_THAT(tiles[0], MatchesTile("Google", "https://www.google.com/",
-                                    TileSource::SEARCH_PAGE));
-  for (auto i = 1u; i < tiles.size(); ++i) {
-    EXPECT_THAT(tiles[i], NotMatchesTile("Google", "https://www.google.com/",
-                                         TileSource::SEARCH_PAGE));
-  }
-}
-
-#endif
-
 }  // namespace ntp_tiles
diff --git a/components/ntp_tiles/tile_source.h b/components/ntp_tiles/tile_source.h
index c06f81d1..d4670041 100644
--- a/components/ntp_tiles/tile_source.h
+++ b/components/ntp_tiles/tile_source.h
@@ -28,10 +28,8 @@
   HOMEPAGE,
   // Tile comes from explore sites list.
   EXPLORE,
-  // Tile containing the Google Search page.
-  SEARCH_PAGE,
 
-  LAST = SEARCH_PAGE
+  LAST = EXPLORE
 };
 
 }  // namespace ntp_tiles
diff --git a/components/omnibox/browser/location_bar_model_impl.cc b/components/omnibox/browser/location_bar_model_impl.cc
index 0e5355f..8da79e2 100644
--- a/components/omnibox/browser/location_bar_model_impl.cc
+++ b/components/omnibox/browser/location_bar_model_impl.cc
@@ -74,6 +74,8 @@
 
 base::string16 LocationBarModelImpl::GetFormattedURL(
     url_formatter::FormatUrlTypes format_types) const {
+  if (!ShouldDisplayURL())
+    return base::string16{};
   GURL url(GetURL());
   // Note that we can't unescape spaces here, because if the user copies this
   // and pastes it into another program, that program may think the URL ends at
@@ -95,7 +97,9 @@
 
 GURL LocationBarModelImpl::GetURL() const {
   GURL url;
-  return delegate_->GetURL(&url) ? url : GURL(url::kAboutBlankURL);
+  return (ShouldDisplayURL() && delegate_->GetURL(&url))
+             ? url
+             : GURL(url::kAboutBlankURL);
 }
 
 security_state::SecurityLevel LocationBarModelImpl::GetSecurityLevel() const {
diff --git a/components/optimization_guide/BUILD.gn b/components/optimization_guide/BUILD.gn
index 5bf351c..02d2176 100644
--- a/components/optimization_guide/BUILD.gn
+++ b/components/optimization_guide/BUILD.gn
@@ -4,6 +4,8 @@
 
 static_library("optimization_guide") {
   sources = [
+    "bloom_filter.cc",
+    "bloom_filter.h",
     "hint_cache.cc",
     "hint_cache.h",
     "hint_cache_store.cc",
@@ -17,6 +19,8 @@
     "hints_fetcher.h",
     "hints_processing_util.cc",
     "hints_processing_util.h",
+    "host_filter.cc",
+    "host_filter.h",
     "optimization_guide_constants.cc",
     "optimization_guide_constants.h",
     "optimization_guide_features.cc",
@@ -41,6 +45,7 @@
     "//google_apis",
     "//net:net",
     "//services/network/public/cpp",
+    "//third_party/smhasher:murmurhash3",
     "//url:url",
   ]
 }
@@ -65,12 +70,14 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
+    "bloom_filter_unittest.cc",
     "hint_cache_store_unittest.cc",
     "hint_cache_unittest.cc",
     "hint_update_data_unittest.cc",
     "hints_component_util_unittest.cc",
     "hints_fetcher_unittest.cc",
     "hints_processing_util_unittest.cc",
+    "host_filter_unittest.cc",
     "optimization_guide_features_unittest.cc",
     "optimization_guide_service_unittest.cc",
     "url_pattern_with_wildcards_unittest.cc",
diff --git a/components/optimization_guide/DEPS b/components/optimization_guide/DEPS
index 5096bbb..f2c9a00 100644
--- a/components/optimization_guide/DEPS
+++ b/components/optimization_guide/DEPS
@@ -4,4 +4,5 @@
   "+google_apis",
   "+net",
   "+services/network",
+  "+third_party/smhasher",
 ]
diff --git a/components/previews/core/bloom_filter.cc b/components/optimization_guide/bloom_filter.cc
similarity index 92%
rename from components/previews/core/bloom_filter.cc
rename to components/optimization_guide/bloom_filter.cc
index 38436cc..4be1766 100644
--- a/components/previews/core/bloom_filter.cc
+++ b/components/optimization_guide/bloom_filter.cc
@@ -1,8 +1,8 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
+// 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/previews/core/bloom_filter.h"
+#include "components/optimization_guide/bloom_filter.h"
 
 #include <stddef.h>
 #include <stdint.h>
@@ -10,7 +10,7 @@
 #include "base/logging.h"
 #include "third_party/smhasher/src/MurmurHash3.h"
 
-namespace previews {
+namespace optimization_guide {
 
 namespace {
 
@@ -77,4 +77,4 @@
   }
 }
 
-}  // namespace previews
+}  // namespace optimization_guide
diff --git a/components/previews/core/bloom_filter.h b/components/optimization_guide/bloom_filter.h
similarity index 88%
rename from components/previews/core/bloom_filter.h
rename to components/optimization_guide/bloom_filter.h
index f820d87..8c3895bc 100644
--- a/components/previews/core/bloom_filter.h
+++ b/components/optimization_guide/bloom_filter.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 COMPONENTS_PREVIEWS_CORE_BLOOM_FILTER_H_
-#define COMPONENTS_PREVIEWS_CORE_BLOOM_FILTER_H_
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_BLOOM_FILTER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_BLOOM_FILTER_H_
 
 #include <stdint.h>
 #include <string>
@@ -12,7 +12,7 @@
 #include "base/macros.h"
 #include "base/sequence_checker.h"
 
-namespace previews {
+namespace optimization_guide {
 
 // A vector of bytes (or 8-bit integers).
 typedef std::vector<uint8_t> ByteVector;
@@ -59,6 +59,6 @@
   DISALLOW_COPY_AND_ASSIGN(BloomFilter);
 };
 
-}  // namespace previews
+}  // namespace optimization_guide
 
-#endif  // COMPONENTS_PREVIEWS_CORE_BLOOM_FILTER_H_
+#endif  // COMPONENTS_OPTIMIZATION_GUIDE_BLOOM_FILTER_H_
diff --git a/components/previews/core/bloom_filter_unittest.cc b/components/optimization_guide/bloom_filter_unittest.cc
similarity index 96%
rename from components/previews/core/bloom_filter_unittest.cc
rename to components/optimization_guide/bloom_filter_unittest.cc
index e6d7fa86..aa041b2 100644
--- a/components/previews/core/bloom_filter_unittest.cc
+++ b/components/optimization_guide/bloom_filter_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 "components/previews/core/bloom_filter.h"
+#include "components/optimization_guide/bloom_filter.h"
 
 #include <stdint.h>
 #include <string>
@@ -10,7 +10,7 @@
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace previews {
+namespace optimization_guide {
 
 namespace {
 
@@ -115,4 +115,4 @@
 }
 #endif
 
-}  // namespace previews
+}  // namespace optimization_guide
diff --git a/components/previews/core/host_filter.cc b/components/optimization_guide/host_filter.cc
similarity index 92%
rename from components/previews/core/host_filter.cc
rename to components/optimization_guide/host_filter.cc
index c29b547..20636e7 100644
--- a/components/previews/core/host_filter.cc
+++ b/components/optimization_guide/host_filter.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/previews/core/host_filter.h"
+#include "components/optimization_guide/host_filter.h"
 
 #include <string>
 
-namespace previews {
+namespace optimization_guide {
 
 // Maximum number of suffixes to check per url.
 const int kMaxSuffixCount = 5;
@@ -50,4 +50,4 @@
   return false;
 }
 
-}  // namespace previews
+}  // namespace optimization_guide
diff --git a/components/previews/core/host_filter.h b/components/optimization_guide/host_filter.h
similarity index 82%
rename from components/previews/core/host_filter.h
rename to components/optimization_guide/host_filter.h
index 3b0ec94..b74da202 100644
--- a/components/previews/core/host_filter.h
+++ b/components/optimization_guide/host_filter.h
@@ -2,15 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PREVIEWS_CORE_HOST_FILTER_H_
-#define COMPONENTS_PREVIEWS_CORE_HOST_FILTER_H_
+#ifndef COMPONENTS_OPTIMIZATION_GUIDE_HOST_FILTER_H_
+#define COMPONENTS_OPTIMIZATION_GUIDE_HOST_FILTER_H_
 
 #include "base/macros.h"
 #include "base/sequence_checker.h"
-#include "components/previews/core/bloom_filter.h"
+#include "components/optimization_guide/bloom_filter.h"
 #include "url/gurl.h"
 
-namespace previews {
+namespace optimization_guide {
 
 // HostFilter is a simple Host filter for keeping track of a set of strings
 // that are represented by a Bloom filter.
@@ -46,6 +46,6 @@
   DISALLOW_COPY_AND_ASSIGN(HostFilter);
 };
 
-}  // namespace previews
+}  // namespace optimization_guide
 
-#endif  // COMPONENTS_PREVIEWS_CORE_BLOOM_FILTER_H_
+#endif  // COMPONENTS_OPTIMIZATION_GUIDE_HOST_FILTER_H_
diff --git a/components/previews/core/host_filter_unittest.cc b/components/optimization_guide/host_filter_unittest.cc
similarity index 92%
rename from components/previews/core/host_filter_unittest.cc
rename to components/optimization_guide/host_filter_unittest.cc
index aa34944..8c49bd1c 100644
--- a/components/previews/core/host_filter_unittest.cc
+++ b/components/optimization_guide/host_filter_unittest.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/previews/core/host_filter.h"
+#include "components/optimization_guide/host_filter.h"
 
 #include "base/macros.h"
-#include "components/previews/core/bloom_filter.h"
+#include "components/optimization_guide/bloom_filter.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "url/gurl.h"
 
-namespace previews {
+namespace optimization_guide {
 
 namespace {
 
@@ -61,4 +61,4 @@
 
 }  // namespace
 
-}  // namespace previews
+}  // namespace optimization_guide
diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc
index f6317c9..969be7e 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.cc
+++ b/components/password_manager/content/browser/content_password_manager_driver.cc
@@ -283,7 +283,7 @@
 
 void ContentPasswordManagerDriver::RecordSavePasswordProgress(
     const std::string& log) {
-  client_->GetLogManager()->LogSavePasswordProgress(log);
+  client_->GetLogManager()->LogTextMessage(log);
 }
 
 void ContentPasswordManagerDriver::UserModifiedPasswordField() {
diff --git a/components/password_manager/content/browser/password_manager_internals_service_factory_unittest.cc b/components/password_manager/content/browser/password_manager_internals_service_factory_unittest.cc
index a5f91bb..76b4f7c 100644
--- a/components/password_manager/content/browser/password_manager_internals_service_factory_unittest.cc
+++ b/components/password_manager/content/browser/password_manager_internals_service_factory_unittest.cc
@@ -23,7 +23,7 @@
  public:
   MockLogReceiver() {}
 
-  MOCK_METHOD1(LogSavePasswordProgress, void(const std::string&));
+  MOCK_METHOD1(LogEntry, void(const base::Value&));
 };
 
 }  // namespace
@@ -54,9 +54,11 @@
   testing::StrictMock<MockLogReceiver> receiver;
 
   ASSERT_TRUE(service);
-  EXPECT_EQ(std::string(), service->RegisterReceiver(&receiver));
+  EXPECT_EQ(std::vector<base::Value>(), service->RegisterReceiver(&receiver));
 
-  EXPECT_CALL(receiver, LogSavePasswordProgress(kTestText)).Times(1);
+  base::Value log_entry = autofill::LogRouter::CreateEntryForText(kTestText);
+  EXPECT_CALL(receiver, LogEntry(testing::Eq(testing::ByRef(log_entry))))
+      .Times(1);
   service->ProcessLog(kTestText);
 
   service->UnregisterReceiver(&receiver);
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
index b4dc57e..e52c611 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -268,7 +268,7 @@
 }
 
 void BrowserSavePasswordProgressLogger::SendLog(const std::string& log) {
-  log_manager_->LogSavePasswordProgress(log);
+  log_manager_->LogTextMessage(log);
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc b/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
index ff2282a..fcd90fe 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
@@ -39,7 +39,7 @@
 
 class MockLogManager : public autofill::StubLogManager {
  public:
-  MOCK_CONST_METHOD1(LogSavePasswordProgress, void(const std::string& text));
+  MOCK_CONST_METHOD1(LogTextMessage, void(const std::string& text));
 };
 
 class BrowserSavePasswordProgressLoggerTest : public testing::Test {
diff --git a/components/password_manager/core/browser/credential_manager_logger.cc b/components/password_manager/core/browser/credential_manager_logger.cc
index db63288..cc7373ce 100644
--- a/components/password_manager/core/browser/credential_manager_logger.cc
+++ b/components/password_manager/core/browser/credential_manager_logger.cc
@@ -42,7 +42,7 @@
   for (const GURL& federation_provider : federations)
     s += SavePasswordProgressLogger::ScrubURL(federation_provider) + ", ";
 
-  log_manager_->LogSavePasswordProgress(s);
+  log_manager_->LogTextMessage(s);
 }
 
 void CredentialManagerLogger::LogSendCredential(const GURL& url,
@@ -50,7 +50,7 @@
   std::string s("CM API send a credential: origin=" +
                 SavePasswordProgressLogger::ScrubURL(url));
   s += ", CredentialType=" + CredentialTypeToString(type);
-  log_manager_->LogSavePasswordProgress(s);
+  log_manager_->LogTextMessage(s);
 }
 
 void CredentialManagerLogger::LogStoreCredential(const GURL& url,
@@ -58,13 +58,13 @@
   std::string s("CM API save a credential: origin=" +
                 SavePasswordProgressLogger::ScrubURL(url));
   s += ", CredentialType=" + CredentialTypeToString(type);
-  log_manager_->LogSavePasswordProgress(s);
+  log_manager_->LogTextMessage(s);
 }
 
 void CredentialManagerLogger::LogPreventSilentAccess(const GURL& url) {
   std::string s("CM API sign out: origin=" +
                 SavePasswordProgressLogger::ScrubURL(url));
-  log_manager_->LogSavePasswordProgress(s);
+  log_manager_->LogTextMessage(s);
 }
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/credential_manager_logger_unittest.cc b/components/password_manager/core/browser/credential_manager_logger_unittest.cc
index 194a0668..1a3f07a 100644
--- a/components/password_manager/core/browser/credential_manager_logger_unittest.cc
+++ b/components/password_manager/core/browser/credential_manager_logger_unittest.cc
@@ -23,7 +23,7 @@
   MockLogManager() = default;
   ~MockLogManager() override = default;
 
-  MOCK_CONST_METHOD1(LogSavePasswordProgress, void(const std::string& text));
+  MOCK_CONST_METHOD1(LogTextMessage, void(const std::string& text));
 
  private:
   DISALLOW_COPY_AND_ASSIGN(MockLogManager);
@@ -51,7 +51,7 @@
 
 TEST_F(CredentialManagerLoggerTest, LogRequestCredential) {
   EXPECT_CALL(log_manager(),
-              LogSavePasswordProgress(
+              LogTextMessage(
                   AllOf(HasSubstr(kSiteOrigin), HasSubstr(kFederationOrigin))));
   logger().LogRequestCredential(GURL(kSiteOrigin),
                                 CredentialMediationRequirement::kSilent,
@@ -59,19 +59,19 @@
 }
 
 TEST_F(CredentialManagerLoggerTest, LogSendCredential) {
-  EXPECT_CALL(log_manager(), LogSavePasswordProgress(HasSubstr(kSiteOrigin)));
+  EXPECT_CALL(log_manager(), LogTextMessage(HasSubstr(kSiteOrigin)));
   logger().LogSendCredential(GURL(kSiteOrigin),
                              CredentialType::CREDENTIAL_TYPE_PASSWORD);
 }
 
 TEST_F(CredentialManagerLoggerTest, LogStoreCredential) {
-  EXPECT_CALL(log_manager(), LogSavePasswordProgress(HasSubstr(kSiteOrigin)));
+  EXPECT_CALL(log_manager(), LogTextMessage(HasSubstr(kSiteOrigin)));
   logger().LogStoreCredential(GURL(kSiteOrigin),
                               CredentialType::CREDENTIAL_TYPE_PASSWORD);
 }
 
 TEST_F(CredentialManagerLoggerTest, LogPreventSilentAccess) {
-  EXPECT_CALL(log_manager(), LogSavePasswordProgress(HasSubstr(kSiteOrigin)));
+  EXPECT_CALL(log_manager(), LogTextMessage(HasSubstr(kSiteOrigin)));
   logger().LogPreventSilentAccess(GURL(kSiteOrigin));
 }
 
diff --git a/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc b/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc
index 54b483b8..9ec93ad52 100644
--- a/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc
+++ b/components/password_manager/core/browser/generation/password_requirements_spec_fetcher_unittest.cc
@@ -208,7 +208,7 @@
     base::HistogramTester histogram_tester;
 
     base::test::ScopedTaskEnvironment environment(
-        base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+        base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
     network::TestURLLoaderFactory loader_factory;
     loader_factory.AddResponse(test.requested_url, test.response_content,
                                test.response_status);
@@ -263,7 +263,7 @@
     shard.SerializeToString(&serialized_shard);
 
     base::test::ScopedTaskEnvironment environment(
-        base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+        base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
     network::TestURLLoaderFactory loader_factory;
 
     // Target into which data will be written by the callback.
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index 8b752c4..86062ec5 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -321,22 +321,34 @@
 }
 
 bool IsNewFormParsingForFillingEnabled() {
+#if defined(OS_IOS)
+  return true;
+#else
   return base::FeatureList::IsEnabled(features::kNewPasswordFormParsing);
+#endif
 }
 
 bool IsNewFormParsingForSavingEnabled() {
+#if defined(OS_IOS)
+  return true;
+#else
   return base::FeatureList::IsEnabled(
              features::kNewPasswordFormParsingForSaving) &&
          base::FeatureList::IsEnabled(features::kNewPasswordFormParsing);
+#endif
 }
 
 // Returns true if it is turned off using PasswordFormManager in
 // PasswordManager.
 bool IsOnlyNewParserEnabled() {
+#if defined(OS_IOS)
+  return true;
+#else
   return base::FeatureList::IsEnabled(
              features::kNewPasswordFormParsingForSaving) &&
          base::FeatureList::IsEnabled(features::kNewPasswordFormParsing) &&
          base::FeatureList::IsEnabled(features::kOnlyNewParser);
+#endif
 }
 
 }  // namespace
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index 3a5744eba..9ecc1678 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -739,6 +739,7 @@
   form_manager_to_save->Save();
 }
 
+#if !defined(OS_IOS)
 TEST_F(PasswordManagerTest, BestMatchFormToManager) {
   base::test::ScopedFeatureList scoped_feature_list;
   // This test does not make sense for NewPasswordFormManager:
@@ -857,6 +858,7 @@
   EXPECT_EQ(changed_form.form_data.name,
             form_manager->GetSubmittedForm()->form_data.name);
 }
+#endif
 
 // Tests that a credential wouldn't be saved if it is already in the store.
 TEST_F(PasswordManagerTest, DontSaveAlreadySavedCredential) {
@@ -1725,6 +1727,7 @@
   task_runner_->FastForwardUntilNoTasksRemain();
 }
 
+#if !defined(OS_IOS)
 // If kNewPasswordFormParsing is disabled, "similar" is governed by
 // PasswordFormManager::DoesManage and is related to actual similarity of the
 // forms, including having the same signon realm (and hence origin). Should a
@@ -1752,6 +1755,7 @@
   EXPECT_CALL(*store_, GetLogins(_, _)).Times(0);
   manager()->OnPasswordFormsParsed(&driver_b, {same_form});
 }
+#endif
 
 TEST_F(PasswordManagerTest, SameDocumentNavigation) {
   // Test that observing a newly submitted form shows the save password bar on
@@ -1809,6 +1813,7 @@
   EXPECT_TRUE(form_manager_to_save->IsBlacklisted());
 }
 
+#if !defined(OS_IOS)
 TEST_F(PasswordManagerTest, SavingSignupForms_NoHTMLMatch) {
   base::test::ScopedFeatureList scoped_feature_list;
   // This test does not make sense for NewPasswordFormManager:
@@ -1968,6 +1973,7 @@
   ASSERT_TRUE(form_manager_to_save);
   form_manager_to_save->Save();
 }
+#endif
 
 TEST_F(PasswordManagerTest, FormSubmittedUnchangedNotifiesClient) {
   // This tests verifies that if the observed forms and provisionally saved
@@ -2355,6 +2361,7 @@
   EXPECT_TRUE(form_manager->HasGeneratedPassword());
 }
 
+#if !defined(OS_IOS)
 TEST_F(PasswordManagerTest,
        PasswordGenerationNoCorrespondingPasswordFormManager) {
   base::test::ScopedFeatureList scoped_feature_list;
@@ -2383,6 +2390,7 @@
 
   EXPECT_FALSE(form_manager->HasGeneratedPassword());
 }
+#endif
 
 TEST_F(PasswordManagerTest, UpdateFormManagers) {
     // Seeing a form should result in creating PasswordFormManager and
@@ -2397,6 +2405,7 @@
     manager()->UpdateFormManagers();
 }
 
+#if !defined(OS_IOS)
 TEST_F(PasswordManagerTest, DropFormManagers) {
   // This test doesn't make sense for the new parser, because
   // NewPasswordFormManager is created on submission if it is missing.
@@ -2423,6 +2432,7 @@
   manager()->OnPasswordFormsParsed(&driver_, observed);
   manager()->OnPasswordFormsRendered(&driver_, observed, true);
 }
+#endif
 
 TEST_F(PasswordManagerTest, AutofillingOfAffiliatedCredentials) {
   PasswordForm android_form(MakeAndroidCredential());
@@ -2975,6 +2985,7 @@
   EXPECT_EQ(1u, manager()->form_managers().size());
 }
 
+#if !defined(OS_IOS)
 TEST_F(PasswordManagerTest,
        ShowManualFallbacksDontChangeProvisionalSaveManager) {
   base::test::ScopedFeatureList scoped_feature_list;
@@ -3012,6 +3023,7 @@
   EXPECT_EQ(last_provisional_save_manager,
             manager()->provisional_save_manager());
 }
+#endif
 
 // Tests that processing normal HTML form submissions works properly with the
 // new parsing. For details see scheme 1 in comments before
@@ -3129,6 +3141,7 @@
   manager()->OnPasswordFormSubmittedNoChecks(&driver_, form);
 }
 
+#if !defined(OS_IOS)
 // Tests that PasswordFormManager and NewPasswordFormManager for the same form
 // have the same metrics recorder.
 TEST_F(PasswordManagerTest, CheckMetricsRecorder) {
@@ -3160,6 +3173,7 @@
   EXPECT_EQ(password_form_managers[0]->GetMetricsRecorder(),
             new_password_form_managers[0]->GetMetricsRecorder());
 }
+#endif
 
 TEST_F(PasswordManagerTest, MetricForSchemeOfSuccessfulLogins) {
   for (bool origin_is_secure : {false, true}) {
@@ -3233,6 +3247,7 @@
   manager()->HideManualFallbackForSaving();
 }
 
+#if !defined(OS_IOS)
 // Check that some value for the ParsingOnSavingDifference UKM metric is emitted
 // on a successful login.
 TEST_F(PasswordManagerTest, ParsingOnSavingMetricRecorded) {
@@ -3267,6 +3282,7 @@
                      ukm::builders::PasswordForm::kEntryName),
       ukm::builders::PasswordForm::kParsingOnSavingDifferenceName));
 }
+#endif
 
 TEST_F(PasswordManagerTest, NoSavePromptWhenPasswordManagerDisabled) {
   base::test::ScopedFeatureList scoped_feature_list;
@@ -3554,8 +3570,13 @@
     EXPECT_CALL(client_, IsSavingAndFillingEnabled(_))
         .WillRepeatedly(Return(test_case.saving ==
                                MissingFormManagerTestCase::Saving::Enabled));
+    std::vector<bool> only_new_parser_options(1, true);
+#if !defined(OS_IOS)
+    // The old parser is not present on iOS anymore.
+    only_new_parser_options.push_back(false);
+#endif
 
-    for (bool only_new_parser : {false, true}) {
+    for (bool only_new_parser : only_new_parser_options) {
       if ((only_new_parser && !test_case.run_for_new_parser) ||
           (!only_new_parser && !test_case.run_for_old_parser)) {
         continue;
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc
index 7f83ea58..9e4e1ab0 100644
--- a/components/password_manager/core/common/password_manager_features.cc
+++ b/components/password_manager/core/common/password_manager_features.cc
@@ -86,6 +86,10 @@
 const base::Feature kGenerationNoOverwrites = {
     "GenerationNoOverwrites", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables support of filling and saving on username first flow.
+const base::Feature kUsernameFirstFlow = {"UsernameFirstFlow",
+                                          base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Field trial identifier for password generation requirements.
 const char* kGenerationRequirementsFieldTrial =
     "PasswordGenerationRequirements";
diff --git a/components/password_manager/core/common/password_manager_features.h b/components/password_manager/core/common/password_manager_features.h
index 43cc7a7..fec5465 100644
--- a/components/password_manager/core/common/password_manager_features.h
+++ b/components/password_manager/core/common/password_manager_features.h
@@ -33,6 +33,7 @@
 extern const base::Feature kRecoverPasswordsForSyncUsers;
 extern const base::Feature kTouchToFillAndroid;
 extern const base::Feature kGenerationNoOverwrites;
+extern const base::Feature kUsernameFirstFlow;
 
 // Field trial and corresponding parameters.
 // To manually override this, start Chrome with the following parameters:
diff --git a/components/policy/core/common/cloud/component_cloud_policy_updater_unittest.cc b/components/policy/core/common/cloud/component_cloud_policy_updater_unittest.cc
index 62449b52..8b781b4 100644
--- a/components/policy/core/common/cloud/component_cloud_policy_updater_unittest.cc
+++ b/components/policy/core/common/cloud/component_cloud_policy_updater_unittest.cc
@@ -96,7 +96,7 @@
 };
 
 ComponentCloudPolicyUpdaterTest::ComponentCloudPolicyUpdaterTest()
-    : task_env_(base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+    : task_env_(base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
   builder_.SetDefaultSigningKey();
   builder_.policy_data().set_policy_type(
       dm_protocol::kChromeExtensionPolicyType);
diff --git a/components/policy/proto/chrome_device_policy.proto b/components/policy/proto/chrome_device_policy.proto
index a71b482..951f6cfc 100644
--- a/components/policy/proto/chrome_device_policy.proto
+++ b/components/policy/proto/chrome_device_policy.proto
@@ -403,6 +403,8 @@
     // An account that serves as a container for a single full-screen
     // Android app.
     ACCOUNT_TYPE_KIOSK_ANDROID_APP = 2;
+    // SAML public session account
+    ACCOUNT_TYPE_SAML_PUBLIC_SESSION = 3;
   }
 
   // The account type.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 20a7a37..9ad77e6 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -15246,7 +15246,7 @@
       When this policy is unset it is not possible to verify Parent Access Code on child user's device.'''
     },
     {
-      'name': 'CertificateManagementAllowed',
+      'name': 'ClientCertificateManagementAllowed',
       'type': 'int-enum',
       'schema': {
         'type': 'integer',
@@ -15277,8 +15277,8 @@
       },
       'example_value': 1,
       'id': 518,
-      'caption': '''Allow users to manage installed certificates.''',
-      'desc': '''This policy controls whether user are able to import and remove certificates via Certificate Manager.
+      'caption': '''Allow users to manage installed client certificates.''',
+      'desc': '''This policy controls whether user are able to import and remove client certificates via Certificate Manager.
 
       If this policy is set to ''Allow users to manage all certificates'' or left not set, users will be able to manage certificates.
 
diff --git a/components/policy/tools/template_writers/policy_template_generator.py b/components/policy/tools/template_writers/policy_template_generator.py
index bedb927..43f38b6a6 100755
--- a/components/policy/tools/template_writers/policy_template_generator.py
+++ b/components/policy/tools/template_writers/policy_template_generator.py
@@ -22,12 +22,8 @@
 
   def _ImportMessage(self, msg_txt):
     msg_txt = msg_txt.decode('utf-8')
-    # Replace the placeholder of app name.
-    msg_txt = msg_txt.replace('$1', self._config['app_name'])
-    msg_txt = msg_txt.replace('$2', self._config['os_name'])
-    msg_txt = msg_txt.replace('$3', self._config['frame_name'])
-
     lines = msg_txt.split('\n')
+
     # Strip any extra leading spaces, but keep useful indentation:
     min_leading_spaces = min(list(self._IterateLeadingSpaces(lines)) or [0])
     if min_leading_spaces > 0:
diff --git a/components/policy/tools/template_writers/policy_template_generator_unittest.py b/components/policy/tools/template_writers/policy_template_generator_unittest.py
index 9b5fd3e..b6570eb 100755
--- a/components/policy/tools/template_writers/policy_template_generator_unittest.py
+++ b/components/policy/tools/template_writers/policy_template_generator_unittest.py
@@ -257,44 +257,6 @@
 
     self.do_test(policy_defs_mock, LocalMockWriter())
 
-  def testPolicyTexts(self):
-    # Test that GUI messages of policies all get placeholders replaced.
-    policy_data_mock = {
-        'policy_definitions': [
-            {
-                'name': 'Group1',
-                'type': 'group',
-                'desc': '',
-                'caption': '',
-                'policies': ['Policy1'],
-            },
-            {
-                'name': 'Policy1',
-                'caption': '1. app_name -- $1',
-                'label': '2. os_name -- $2',
-                'desc': '3. frame_name -- $3',
-                'type': 'string',
-                'supported_on': []
-            },
-        ]
-    }
-
-    class LocalMockWriter(mock_writer.MockWriter):
-
-      def WritePolicy(self, policy):
-        if policy['name'] == 'Policy1':
-          self.tester.assertEquals(policy['caption'],
-                                   '1. app_name -- _app_name')
-          self.tester.assertEquals(policy['label'], '2. os_name -- _os_name')
-          self.tester.assertEquals(policy['desc'],
-                                   '3. frame_name -- _frame_name')
-        elif policy['name'] == 'Group1':
-          pass
-        else:
-          self.tester.fail()
-
-    self.do_test(policy_data_mock, LocalMockWriter())
-
   def testIntEnumTexts(self):
     # Test that GUI messages are assigned correctly to int-enums
     # (aka dropdown menus).
diff --git a/components/policy/tools/template_writers/writers/plist_strings_writer_unittest.py b/components/policy/tools/template_writers/writers/plist_strings_writer_unittest.py
index 83bdf789..91c39f43 100755
--- a/components/policy/tools/template_writers/writers/plist_strings_writer_unittest.py
+++ b/components/policy/tools/template_writers/writers/plist_strings_writer_unittest.py
@@ -26,7 +26,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': '$1 preferen"ces',
+            'text': 'Chromium preferen"ces',
             'desc': 'blah'
           }
         }
@@ -48,7 +48,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': '$1 preferen"ces',
+            'text': 'Chromium preferen"ces',
             'desc': 'blah'
           }
         }
@@ -88,7 +88,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': 'Preferences of $1',
+            'text': 'Preferences of Google Chrome',
             'desc': 'blah'
           }
         }
@@ -131,7 +131,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': 'Preferences of $1',
+            'text': 'Preferences of Chromium',
             'desc': 'blah'
           }
         }
@@ -176,7 +176,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': 'Preferences of $1',
+            'text': 'Preferences of Chromium',
             'desc': 'blah'
           }
         }
@@ -233,7 +233,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': 'Preferences of $1',
+            'text': 'Preferences of Chromium',
             'desc': 'blah'
           }
         }
@@ -286,7 +286,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': '$1 preferences',
+            'text': 'Google Chrome preferences',
             'desc': 'blah'
           }
         }
@@ -340,7 +340,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': '$1 preferences',
+            'text': 'Google Chrome preferences',
             'desc': 'blah'
           }
         }
@@ -383,7 +383,7 @@
         'placeholders': [],
         'messages': {
           'mac_chrome_preferences': {
-            'text': '$1 preferences',
+            'text': 'Google Chrome preferences',
             'desc': 'blah'
           }
         }
diff --git a/components/previews/content/previews_hints.cc b/components/previews/content/previews_hints.cc
index 00e0d23..4c3cb21 100644
--- a/components/previews/content/previews_hints.cc
+++ b/components/previews/content/previews_hints.cc
@@ -12,11 +12,11 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/strings/stringprintf.h"
+#include "components/optimization_guide/bloom_filter.h"
 #include "components/optimization_guide/hint_update_data.h"
 #include "components/optimization_guide/hints_component_info.h"
 #include "components/optimization_guide/hints_component_util.h"
 #include "components/optimization_guide/hints_processing_util.h"
-#include "components/previews/core/bloom_filter.h"
 #include "components/previews/core/previews_features.h"
 #include "url/gurl.h"
 
@@ -366,11 +366,13 @@
             PreviewsOptimizationFilterStatus::kFailedServerBlacklistTooBig);
         continue;
       }
-      std::unique_ptr<BloomFilter> bloom_filter = std::make_unique<BloomFilter>(
-          bloom_filter_proto.num_hash_functions(),
-          bloom_filter_proto.num_bits(), bloom_filter_proto.data());
+      std::unique_ptr<optimization_guide::BloomFilter> bloom_filter =
+          std::make_unique<optimization_guide::BloomFilter>(
+              bloom_filter_proto.num_hash_functions(),
+              bloom_filter_proto.num_bits(), bloom_filter_proto.data());
       lite_page_redirect_blacklist_ =
-          std::make_unique<HostFilter>(std::move(bloom_filter));
+          std::make_unique<optimization_guide::HostFilter>(
+              std::move(bloom_filter));
       RecordOptimizationFilterStatus(
           previews_type.value(),
           PreviewsOptimizationFilterStatus::kCreatedServerBlacklist);
diff --git a/components/previews/content/previews_hints.h b/components/previews/content/previews_hints.h
index 023f4cb..aa01f64a 100644
--- a/components/previews/content/previews_hints.h
+++ b/components/previews/content/previews_hints.h
@@ -13,9 +13,9 @@
 #include "base/sequence_checker.h"
 #include "components/optimization_guide/hint_cache.h"
 #include "components/optimization_guide/hints_processing_util.h"
+#include "components/optimization_guide/host_filter.h"
 #include "components/optimization_guide/proto/hints.pb.h"
 #include "components/previews/content/previews_user_data.h"
-#include "components/previews/core/host_filter.h"
 #include "net/nqe/effective_connection_type.h"
 
 class GURL;
@@ -114,7 +114,7 @@
   std::unique_ptr<optimization_guide::HintUpdateData> component_update_data_;
 
   // Blacklist of host suffixes for LITE_PAGE_REDIRECT Previews.
-  std::unique_ptr<HostFilter> lite_page_redirect_blacklist_;
+  std::unique_ptr<optimization_guide::HostFilter> lite_page_redirect_blacklist_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
diff --git a/components/previews/content/previews_hints_unittest.cc b/components/previews/content/previews_hints_unittest.cc
index 80608f9..c9999edbaa 100644
--- a/components/previews/content/previews_hints_unittest.cc
+++ b/components/previews/content/previews_hints_unittest.cc
@@ -14,10 +14,12 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
+#include "components/optimization_guide/bloom_filter.h"
 #include "components/optimization_guide/hint_cache.h"
 #include "components/optimization_guide/hint_cache_store.h"
 #include "components/optimization_guide/hint_update_data.h"
 #include "components/optimization_guide/hints_component_info.h"
+#include "components/optimization_guide/host_filter.h"
 #include "components/optimization_guide/optimization_guide_features.h"
 #include "components/optimization_guide/proto/hints.pb.h"
 #include "components/optimization_guide/proto_database_provider_test_base.h"
@@ -32,12 +34,13 @@
 const int kBlackBlacklistBloomFilterNumHashFunctions = 7;
 const int kBlackBlacklistBloomFilterNumBits = 511;
 
-void PopulateBlackBlacklistBloomFilter(BloomFilter* bloom_filter) {
+void PopulateBlackBlacklistBloomFilter(
+    optimization_guide::BloomFilter* bloom_filter) {
   bloom_filter->Add("black.com");
 }
 
 void AddBlacklistBloomFilterToConfig(
-    const BloomFilter& blacklist_bloom_filter,
+    const optimization_guide::BloomFilter& blacklist_bloom_filter,
     int num_hash_functions,
     int num_bits,
     optimization_guide::proto::Configuration* config) {
@@ -57,7 +60,7 @@
 
 }  // namespace
 
-class TestHostFilter : public previews::HostFilter {
+class TestHostFilter : public optimization_guide::HostFilter {
  public:
   explicit TestHostFilter(std::string single_host_match)
       : HostFilter(nullptr), single_host_match_(single_host_match) {}
@@ -290,8 +293,9 @@
   base::test::ScopedFeatureList scoped_list;
   scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
 
-  BloomFilter blacklist_bloom_filter(kBlackBlacklistBloomFilterNumHashFunctions,
-                                     kBlackBlacklistBloomFilterNumBits);
+  optimization_guide::BloomFilter blacklist_bloom_filter(
+      kBlackBlacklistBloomFilterNumHashFunctions,
+      kBlackBlacklistBloomFilterNumBits);
   PopulateBlackBlacklistBloomFilter(&blacklist_bloom_filter);
 
   optimization_guide::proto::Configuration config;
@@ -316,8 +320,9 @@
   base::test::ScopedFeatureList scoped_list;
   scoped_list.InitAndEnableFeature(features::kLitePageServerPreviews);
 
-  BloomFilter blacklist_bloom_filter(kBlackBlacklistBloomFilterNumHashFunctions,
-                                     kBlackBlacklistBloomFilterNumBits);
+  optimization_guide::BloomFilter blacklist_bloom_filter(
+      kBlackBlacklistBloomFilterNumHashFunctions,
+      kBlackBlacklistBloomFilterNumBits);
   PopulateBlackBlacklistBloomFilter(&blacklist_bloom_filter);
 
   // Set num_bits in config to one more than the size of the data.
@@ -351,8 +356,8 @@
           8 +
       1;
 
-  BloomFilter blacklist_bloom_filter(kBlackBlacklistBloomFilterNumHashFunctions,
-                                     too_many_bits);
+  optimization_guide::BloomFilter blacklist_bloom_filter(
+      kBlackBlacklistBloomFilterNumHashFunctions, too_many_bits);
   PopulateBlackBlacklistBloomFilter(&blacklist_bloom_filter);
 
   optimization_guide::proto::Configuration config;
diff --git a/components/previews/content/previews_optimization_guide_unittest.cc b/components/previews/content/previews_optimization_guide_unittest.cc
index 8050c2e..c2f3cbb 100644
--- a/components/previews/content/previews_optimization_guide_unittest.cc
+++ b/components/previews/content/previews_optimization_guide_unittest.cc
@@ -24,6 +24,7 @@
 #include "base/test/simple_test_clock.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
+#include "components/optimization_guide/bloom_filter.h"
 #include "components/optimization_guide/hints_component_info.h"
 #include "components/optimization_guide/hints_fetcher.h"
 #include "components/optimization_guide/optimization_guide_features.h"
@@ -37,7 +38,6 @@
 #include "components/prefs/testing_pref_service.h"
 #include "components/previews/content/previews_hints.h"
 #include "components/previews/content/previews_user_data.h"
-#include "components/previews/core/bloom_filter.h"
 #include "components/previews/core/previews_experiments.h"
 #include "components/previews/core/previews_features.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
@@ -204,7 +204,8 @@
  public:
   PreviewsOptimizationGuideTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::MainThreadType::UI,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   ~PreviewsOptimizationGuideTest() override {}
 
@@ -525,7 +526,7 @@
 }
 
 void PreviewsOptimizationGuideTest::InitializeWithLitePageRedirectBlacklist() {
-  previews::BloomFilter blacklist_bloom_filter(7, 511);
+  optimization_guide::BloomFilter blacklist_bloom_filter(7, 511);
   blacklist_bloom_filter.Add("blacklisteddomain.com");
   blacklist_bloom_filter.Add("blacklistedsubdomain.maindomain.co.in");
   std::string blacklist_data((char*)&blacklist_bloom_filter.bytes()[0],
diff --git a/components/previews/core/BUILD.gn b/components/previews/core/BUILD.gn
index bc54e154..886262a 100644
--- a/components/previews/core/BUILD.gn
+++ b/components/previews/core/BUILD.gn
@@ -4,10 +4,6 @@
 
 static_library("core") {
   sources = [
-    "bloom_filter.cc",
-    "bloom_filter.h",
-    "host_filter.cc",
-    "host_filter.h",
     "previews_black_list.cc",
     "previews_black_list.h",
     "previews_constants.cc",
@@ -32,7 +28,6 @@
     "//components/variations",
     "//net:net",
     "//third_party/re2",
-    "//third_party/smhasher:murmurhash3",
     "//url:url",
   ]
 }
@@ -58,8 +53,6 @@
 source_set("unit_tests") {
   testonly = true
   sources = [
-    "bloom_filter_unittest.cc",
-    "host_filter_unittest.cc",
     "previews_black_list_unittest.cc",
     "previews_experiments_unittest.cc",
     "previews_lite_page_redirect_unittest.cc",
diff --git a/components/previews/core/DEPS b/components/previews/core/DEPS
index 776d207..9f3afce 100644
--- a/components/previews/core/DEPS
+++ b/components/previews/core/DEPS
@@ -3,5 +3,4 @@
   "+components/variations",
   "+net",
   "+third_party/re2",
-  "+third_party/smhasher"
 ]
diff --git a/components/printing/resources/OWNERS b/components/printing/resources/OWNERS
index c05db2e..4acba5a 100644
--- a/components/printing/resources/OWNERS
+++ b/components/printing/resources/OWNERS
@@ -1,2 +1,4 @@
 # For trivial or mechanical horizontal JS/CSS/HTML changes.
 file://ui/webui/PLATFORM_OWNERS
+
+# COMPONENT: Internals>Printing
diff --git a/components/safe_browsing/db/allowlist_checker_client_unittest.cc b/components/safe_browsing/db/allowlist_checker_client_unittest.cc
index 5d386f7..37e27371 100644
--- a/components/safe_browsing/db/allowlist_checker_client_unittest.cc
+++ b/components/safe_browsing/db/allowlist_checker_client_unittest.cc
@@ -51,7 +51,7 @@
  public:
   AllowlistCheckerClientTest()
       : thread_bundle_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         target_url_("https://example.test") {}
 
   void SetUp() override {
diff --git a/components/safe_search_api/OWNERS b/components/safe_search_api/OWNERS
index 408a9bd..7411752 100644
--- a/components/safe_search_api/OWNERS
+++ b/components/safe_search_api/OWNERS
@@ -1,2 +1,4 @@
 michaelpg@chromium.org
 treib@chromium.org
+
+# COMPONENT: FamilyLink
diff --git a/components/security_interstitials/content/BUILD.gn b/components/security_interstitials/content/BUILD.gn
index 1657464..c7a16c9 100644
--- a/components/security_interstitials/content/BUILD.gn
+++ b/components/security_interstitials/content/BUILD.gn
@@ -37,6 +37,7 @@
     "//components/strings:components_strings_grit",
     "//content/public/browser",
     "//content/public/common",
+    "//services/network/public/cpp:cpp",
   ]
 }
 
diff --git a/components/security_interstitials/content/DEPS b/components/security_interstitials/content/DEPS
index 84d5909..26f2c68 100644
--- a/components/security_interstitials/content/DEPS
+++ b/components/security_interstitials/content/DEPS
@@ -9,4 +9,5 @@
   "+content/public/test",
   "+net",
   "+net/test",
+  "+services/network/public/cpp",
 ]
diff --git a/components/security_interstitials/content/origin_policy_interstitial_page.cc b/components/security_interstitials/content/origin_policy_interstitial_page.cc
index 5008b3d..5f42a34 100644
--- a/components/security_interstitials/content/origin_policy_interstitial_page.cc
+++ b/components/security_interstitials/content/origin_policy_interstitial_page.cc
@@ -24,7 +24,7 @@
     content::WebContents* web_contents,
     const GURL& request_url,
     std::unique_ptr<SecurityInterstitialControllerClient> controller,
-    content::OriginPolicyErrorReason error_reason)
+    network::OriginPolicyState error_reason)
     : SecurityInterstitialPage(web_contents,
                                request_url,
                                std::move(controller)),
@@ -45,18 +45,18 @@
   // User may choose to ignore the warning & proceed to the site.
   load_time_data->SetBoolean("overridable", true);
 
-  // Custom messages depending on the OriginPolicyErrorReason:
+  // Custom messages depending on the OriginPolicyState:
   int explanation_paragraph_id = IDS_ORIGIN_POLICY_EXPLANATION_OTHER;
   switch (error_reason_) {
-    case content::OriginPolicyErrorReason::kCannotLoadPolicy:
+    case network::OriginPolicyState::kCannotLoadPolicy:
       explanation_paragraph_id = IDS_ORIGIN_POLICY_EXPLANATION_CANNOT_LOAD;
       break;
-    case content::OriginPolicyErrorReason::kPolicyShouldNotRedirect:
+    case network::OriginPolicyState::kInvalidRedirect:
       explanation_paragraph_id =
           IDS_ORIGIN_POLICY_EXPLANATION_SHOULD_NOT_REDIRECT;
       break;
-    case content::OriginPolicyErrorReason::kOther:
-      explanation_paragraph_id = IDS_ORIGIN_POLICY_EXPLANATION_OTHER;
+    default:
+      NOTREACHED();
       break;
   }
 
diff --git a/components/security_interstitials/content/origin_policy_interstitial_page.h b/components/security_interstitials/content/origin_policy_interstitial_page.h
index 87d43c3..00a47af 100644
--- a/components/security_interstitials/content/origin_policy_interstitial_page.h
+++ b/components/security_interstitials/content/origin_policy_interstitial_page.h
@@ -12,7 +12,7 @@
 #include "components/security_interstitials/content/security_interstitial_controller_client.h"
 #include "components/security_interstitials/content/security_interstitial_page.h"
 #include "content/public/browser/interstitial_page_delegate.h"
-#include "content/public/browser/origin_policy_error_reason.h"
+#include "services/network/public/cpp/origin_policy.h"
 
 #include "url/gurl.h"
 
@@ -29,7 +29,7 @@
       content::WebContents* web_contents,
       const GURL& request_url,
       std::unique_ptr<SecurityInterstitialControllerClient> controller,
-      content::OriginPolicyErrorReason error_reason);
+      network::OriginPolicyState error_reason);
 
   ~OriginPolicyInterstitialPage() override;
 
@@ -44,7 +44,7 @@
   void PopulateInterstitialStrings(base::DictionaryValue*) override;
 
  private:
-  content::OriginPolicyErrorReason error_reason_;
+  network::OriginPolicyState error_reason_;
 
   DISALLOW_COPY_AND_ASSIGN(OriginPolicyInterstitialPage);
 };
diff --git a/components/security_interstitials/content/origin_policy_ui.cc b/components/security_interstitials/content/origin_policy_ui.cc
index 5ed3836f..3f9efea 100644
--- a/components/security_interstitials/content/origin_policy_ui.cc
+++ b/components/security_interstitials/content/origin_policy_ui.cc
@@ -13,6 +13,7 @@
 #include "components/security_interstitials/content/security_interstitial_tab_helper.h"
 #include "components/security_interstitials/core/metrics_helper.h"
 #include "content/public/browser/navigation_handle.h"
+#include "services/network/public/cpp/origin_policy.h"
 #include "url/gurl.h"
 
 namespace security_interstitials {
@@ -20,7 +21,7 @@
 namespace {
 
 std::unique_ptr<SecurityInterstitialPage> GetErrorPageImpl(
-    content::OriginPolicyErrorReason error_reason,
+    network::OriginPolicyState error_reason,
     content::WebContents* web_contents,
     const GURL& url) {
   MetricsHelper::ReportDetails report_details;
@@ -38,7 +39,7 @@
 }  // namespace
 
 base::Optional<std::string> OriginPolicyUI::GetErrorPageAsHTML(
-    content::OriginPolicyErrorReason error_reason,
+    network::OriginPolicyState error_reason,
     content::NavigationHandle* handle) {
   DCHECK(handle);
   std::unique_ptr<SecurityInterstitialPage> page(GetErrorPageImpl(
@@ -54,7 +55,7 @@
 }
 
 SecurityInterstitialPage* OriginPolicyUI::GetBlockingPage(
-    content::OriginPolicyErrorReason error_reason,
+    network::OriginPolicyState error_reason,
     content::WebContents* web_contents,
     const GURL& url) {
   return GetErrorPageImpl(error_reason, web_contents, url).release();
diff --git a/components/security_interstitials/content/origin_policy_ui.h b/components/security_interstitials/content/origin_policy_ui.h
index 06a27c5..1d1f245 100644
--- a/components/security_interstitials/content/origin_policy_ui.h
+++ b/components/security_interstitials/content/origin_policy_ui.h
@@ -17,9 +17,12 @@
 namespace content {
 class NavigationHandle;
 class WebContents;
-enum class OriginPolicyErrorReason;
 }  // namespace content
 
+namespace network {
+enum class OriginPolicyState;
+}
+
 namespace security_interstitials {
 class SecurityInterstitialPage;
 
@@ -29,13 +32,13 @@
   // Create the error page for the given NavigationHandle.
   // This is intended to implement the ContentBrowserClient interface.
   static base::Optional<std::string> GetErrorPageAsHTML(
-      content::OriginPolicyErrorReason error_reason,
+      network::OriginPolicyState error_reason,
       content::NavigationHandle* handle);
 
   // Create the error page instance for the given WebContents + URL.
   // This is intended for use by debug functions (like chrome:://interstitials).
   static SecurityInterstitialPage* GetBlockingPage(
-      content::OriginPolicyErrorReason error_reason,
+      network::OriginPolicyState error_reason,
       content::WebContents* web_contents,
       const GURL& url);
 };
diff --git a/components/signin/public/identity_manager/identity_test_environment.h b/components/signin/public/identity_manager/identity_test_environment.h
index dce9c29..2babc39 100644
--- a/components/signin/public/identity_manager/identity_test_environment.h
+++ b/components/signin/public/identity_manager/identity_test_environment.h
@@ -16,7 +16,6 @@
 #include "components/signin/public/identity_manager/identity_test_utils.h"
 
 class FakeProfileOAuth2TokenService;
-class IdentityTestEnvironmentChromeBrowserStateAdaptor;
 class IdentityTestEnvironmentProfileAdaptor;
 class PrefService;
 class TestSigninClient;
@@ -275,7 +274,6 @@
   void SimulateMergeSessionFailure(const GoogleServiceAuthError& auth_error);
 
  private:
-  friend class ::IdentityTestEnvironmentChromeBrowserStateAdaptor;
   friend class ::IdentityTestEnvironmentProfileAdaptor;
 
   struct AccessTokenRequestState {
@@ -307,8 +305,8 @@
   // use the ProfileKeyedServiceFactory infrastructure).
   // NOTE: This constructor is for usage only in the special case of embedder
   // unittests that must use the IdentityManager instance associated with the
-  // Profile/ChromeBrowserState. If you think you have another use case for it,
-  // contact blundell@chromium.org.
+  // Profile. If you think you have another use case for it, contact
+  // blundell@chromium.org.
   IdentityTestEnvironment(IdentityManager* identity_manager);
 
   // IdentityManager::DiagnosticsObserver:
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
index df08d76..a0b99720 100644
--- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
+++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle.h
@@ -29,6 +29,12 @@
 // The throttle should only be instantiated for navigations occuring in
 // subframes owned by documents which already have filtering activated, and
 // therefore an associated (Async)DocumentSubresourceFilter.
+//
+// TODO(https://crbug.com/984562): With AdTagging enabled, this throttle delays
+// almost all subframe navigations. This delay is necessary in blocking mode due
+// to logic related to BLOCK_REQUEST_AND_COLLAPSE. However, there may be room
+// for optimization during AdTagging, or migrating BLOCK_REQUEST_AND_COLLAPSE to
+// be allowed during WillProcessResponse.
 class SubframeNavigationFilteringThrottle : public content::NavigationThrottle {
  public:
   class Delegate {
diff --git a/components/suggestions/suggestions_service_impl_unittest.cc b/components/suggestions/suggestions_service_impl_unittest.cc
index 8b2907c..2eaaa7d7 100644
--- a/components/suggestions/suggestions_service_impl_unittest.cc
+++ b/components/suggestions/suggestions_service_impl_unittest.cc
@@ -194,7 +194,7 @@
   }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
  private:
   identity::IdentityTestEnvironment identity_test_env_;
diff --git a/components/sync/driver/profile_sync_service_startup_unittest.cc b/components/sync/driver/profile_sync_service_startup_unittest.cc
index 4a6515fa..8d2e1bc 100644
--- a/components/sync/driver/profile_sync_service_startup_unittest.cc
+++ b/components/sync/driver/profile_sync_service_startup_unittest.cc
@@ -60,7 +60,7 @@
  public:
   ProfileSyncServiceStartupTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         sync_prefs_(profile_sync_service_bundle_.pref_service()) {
     profile_sync_service_bundle_.identity_test_env()
         ->SetAutomaticIssueOfAccessTokens(true);
diff --git a/components/test/data/OWNERS b/components/test/data/OWNERS
index 72e8ffc..feecc5c 100644
--- a/components/test/data/OWNERS
+++ b/components/test/data/OWNERS
@@ -1 +1,2 @@
 *
+# COMPONENT: Tests
diff --git a/components/test/data/payments/payment_request_bobpay_and_cards_test.html b/components/test/data/payments/payment_request_bobpay_and_cards_test.html
index 71a9c95..c4417e7 100644
--- a/components/test/data/payments/payment_request_bobpay_and_cards_test.html
+++ b/components/test/data/payments/payment_request_bobpay_and_cards_test.html
@@ -13,6 +13,7 @@
 </head>
 <body>
 <div><button onclick="buy()" id="buy">Bob Pay and Cards Test</button></div>
+<div><button onclick="testInstallableAppAndCard()" id="installable-app">Installable App</button></div>
 <pre id="result"></pre>
 <script src="util.js"></script>
 <script src="bobpay_and_cards.js"></script>
diff --git a/components/viz/common/hit_test/aggregated_hit_test_region.h b/components/viz/common/hit_test/aggregated_hit_test_region.h
index cdb4c29f..681bc56 100644
--- a/components/viz/common/hit_test/aggregated_hit_test_region.h
+++ b/components/viz/common/hit_test/aggregated_hit_test_region.h
@@ -83,6 +83,17 @@
     transform_ = transform;
   }
 
+  bool operator==(const AggregatedHitTestRegion& rhs) const {
+    return (frame_sink_id == rhs.frame_sink_id && flags == rhs.flags &&
+            async_hit_test_reasons == rhs.async_hit_test_reasons &&
+            rect == rhs.rect && child_count == rhs.child_count &&
+            transform_ == rhs.transform());
+  }
+
+  bool operator!=(const AggregatedHitTestRegion& other) const {
+    return !(*this == other);
+  }
+
  private:
   friend struct mojo::StructTraits<mojom::AggregatedHitTestRegionDataView,
                                    AggregatedHitTestRegion>;
diff --git a/components/viz/demo/service/demo_service.cc b/components/viz/demo/service/demo_service.cc
index 24a6724..cdfe9c7 100644
--- a/components/viz/demo/service/demo_service.cc
+++ b/components/viz/demo/service/demo_service.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/message_loop/message_loop.h"
 #include "components/viz/common/frame_sinks/begin_frame_source.h"
 #include "components/viz/service/main/viz_compositor_thread_runner.h"
 
@@ -20,7 +21,8 @@
   params->activation_deadline_in_frames = 0u;
   params->frame_sink_manager = std::move(request);
   params->frame_sink_manager_client = client.PassInterface();
-  runner_ = std::make_unique<viz::VizCompositorThreadRunner>();
+  runner_ = std::make_unique<viz::VizCompositorThreadRunner>(
+      base::MessageLoop::TYPE_DEFAULT);
   runner_->CreateFrameSinkManager(std::move(params));
 }
 
diff --git a/components/viz/host/hit_test/hit_test_query.h b/components/viz/host/hit_test/hit_test_query.h
index 1b1ce24..14d5bf2 100644
--- a/components/viz/host/hit_test/hit_test_query.h
+++ b/components/viz/host/hit_test/hit_test_query.h
@@ -13,10 +13,6 @@
 #include "components/viz/host/viz_host_export.h"
 #include "ui/gfx/geometry/point_f.h"
 
-namespace content {
-class HitTestRegionObserver;
-}
-
 namespace viz {
 
 struct Target {
@@ -110,6 +106,9 @@
 
   // Returns hit-test data, using indentation to visualize the tree structure.
   std::string PrintHitTestData() const;
+  const std::vector<AggregatedHitTestRegion>& GetHitTestData() const {
+    return hit_test_data_;
+  }
 
  protected:
   // The FindTargetForLocation() functions call into this.
@@ -123,8 +122,6 @@
       bool is_location_relative_to_parent) const;
 
  private:
-  friend class content::HitTestRegionObserver;
-
   // Helper function to find |target| for |location| in the |region_index|,
   // returns true if a target is found and false otherwise. If
   // |is_location_relative_to_parent| is true, |location| is in the coordinate
diff --git a/components/viz/service/main/viz_compositor_thread_runner.cc b/components/viz/service/main/viz_compositor_thread_runner.cc
index d4407ab..e6a6ef1c 100644
--- a/components/viz/service/main/viz_compositor_thread_runner.cc
+++ b/components/viz/service/main/viz_compositor_thread_runner.cc
@@ -32,16 +32,13 @@
 #include "components/ui_devtools/viz/overlay_agent_viz.h"
 #endif
 
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
 namespace viz {
 namespace {
 
 const char kThreadName[] = "VizCompositorThread";
 
-std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread() {
+std::unique_ptr<VizCompositorThreadType> CreateAndStartCompositorThread(
+    base::MessageLoop::Type message_loop_type) {
   const base::ThreadPriority thread_priority =
       base::FeatureList::IsEnabled(features::kGpuUseDisplayThreadPriority)
           ? base::ThreadPriority::DISPLAY
@@ -55,11 +52,7 @@
   auto thread = std::make_unique<base::Thread>(kThreadName);
 
   base::Thread::Options thread_options;
-#if defined(USE_OZONE)
-  // We may need a non-default message loop type for the platform surface.
-  thread_options.message_loop_type =
-      ui::OzonePlatform::GetInstance()->GetMessageLoopTypeForGpu();
-#endif
+  thread_options.message_loop_type = message_loop_type;
   thread_options.priority = thread_priority;
 
   CHECK(thread->StartWithOptions(thread_options));
@@ -69,8 +62,9 @@
 
 }  // namespace
 
-VizCompositorThreadRunner::VizCompositorThreadRunner()
-    : thread_(CreateAndStartCompositorThread()),
+VizCompositorThreadRunner::VizCompositorThreadRunner(
+    base::MessageLoop::Type message_loop_type)
+    : thread_(CreateAndStartCompositorThread(message_loop_type)),
       task_runner_(thread_->task_runner()) {}
 
 VizCompositorThreadRunner::~VizCompositorThreadRunner() {
diff --git a/components/viz/service/main/viz_compositor_thread_runner.h b/components/viz/service/main/viz_compositor_thread_runner.h
index 8f2d2fd..a491185 100644
--- a/components/viz/service/main/viz_compositor_thread_runner.h
+++ b/components/viz/service/main/viz_compositor_thread_runner.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 #include "services/network/public/mojom/tcp_socket.mojom.h"
 #include "services/viz/privileged/interfaces/viz_main.mojom.h"
@@ -48,7 +49,7 @@
 // and then stop the thread.
 class VizCompositorThreadRunner {
  public:
-  VizCompositorThreadRunner();
+  explicit VizCompositorThreadRunner(base::MessageLoop::Type message_loop_type);
   // Performs teardown on thread and then stops thread.
   ~VizCompositorThreadRunner();
 
diff --git a/components/viz/service/main/viz_main_impl.cc b/components/viz/service/main/viz_main_impl.cc
index 8b1cde48..884d7d0 100644
--- a/components/viz/service/main/viz_main_impl.cc
+++ b/components/viz/service/main/viz_main_impl.cc
@@ -83,8 +83,8 @@
   if (!dependencies_.io_thread_task_runner)
     io_thread_ = CreateAndStartIOThread();
   if (dependencies_.create_display_compositor) {
-    viz_compositor_thread_runner_ =
-        std::make_unique<VizCompositorThreadRunner>();
+    viz_compositor_thread_runner_ = std::make_unique<VizCompositorThreadRunner>(
+        gpu_init_->gpu_preferences().message_loop_type);
     if (delegate_) {
       delegate_->PostCompositorThreadCreated(
           viz_compositor_thread_runner_->task_runner());
diff --git a/components/wifi/OWNERS b/components/wifi/OWNERS
index fb59c70..7e5ec6e 100644
--- a/components/wifi/OWNERS
+++ b/components/wifi/OWNERS
@@ -1 +1,3 @@
 file://net/OWNERS
+# COMPONENT: Internals>Network
+# TEAM: net-dev@chromium.org
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index d92e37c..866b6ea 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -804,19 +804,10 @@
     "display_cutout/display_cutout_constants.h",
     "display_cutout/display_cutout_host_impl.cc",
     "display_cutout/display_cutout_host_impl.h",
-    "dom_storage/dom_storage_area.cc",
-    "dom_storage/dom_storage_area.h",
-    "dom_storage/dom_storage_context_impl.cc",
-    "dom_storage/dom_storage_context_impl.h",
     "dom_storage/dom_storage_context_wrapper.cc",
     "dom_storage/dom_storage_context_wrapper.h",
     "dom_storage/dom_storage_database.cc",
     "dom_storage/dom_storage_database.h",
-    "dom_storage/dom_storage_database_adapter.h",
-    "dom_storage/dom_storage_host.cc",
-    "dom_storage/dom_storage_host.h",
-    "dom_storage/dom_storage_namespace.cc",
-    "dom_storage/dom_storage_namespace.h",
     "dom_storage/dom_storage_task_runner.cc",
     "dom_storage/dom_storage_task_runner.h",
     "dom_storage/local_storage_context_mojo.cc",
@@ -827,10 +818,6 @@
     "dom_storage/session_storage_context_mojo.h",
     "dom_storage/session_storage_data_map.cc",
     "dom_storage/session_storage_data_map.h",
-    "dom_storage/session_storage_database.cc",
-    "dom_storage/session_storage_database.h",
-    "dom_storage/session_storage_database_adapter.cc",
-    "dom_storage/session_storage_database_adapter.h",
     "dom_storage/session_storage_metadata.cc",
     "dom_storage/session_storage_metadata.h",
     "dom_storage/session_storage_namespace_impl.cc",
diff --git a/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index 2be6bb1..c311f31 100644
--- a/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -149,7 +149,7 @@
     if (base::LowerCaseEqualsASCII(module_name, "fsdomsrv.dll"))
       jaws = true;
     if (base::LowerCaseEqualsASCII(module_name, "vbufbackend_gecko_ia2.dll") ||
-        base::LowerCaseEqualsASCII(module_name, "nvdaHelperRemote.dll"))
+        base::LowerCaseEqualsASCII(module_name, "nvdahelperremote.dll"))
       nvda = true;
     if (base::LowerCaseEqualsASCII(module_name, "stsaw32.dll"))
       satogo = true;
diff --git a/content/browser/background_sync/background_sync_context_impl.cc b/content/browser/background_sync/background_sync_context_impl.cc
index 905e2642..9d4de6a 100644
--- a/content/browser/background_sync/background_sync_context_impl.cc
+++ b/content/browser/background_sync/background_sync_context_impl.cc
@@ -141,6 +141,7 @@
 
 void BackgroundSyncContextImpl::GetSoonestWakeupDelta(
     blink::mojom::BackgroundSyncType sync_type,
+    base::Time last_browser_wakeup_for_periodic_sync,
     base::OnceCallback<void(base::TimeDelta)> callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -148,13 +149,14 @@
       FROM_HERE, {BrowserThread::IO},
       base::BindOnce(
           &BackgroundSyncContextImpl::GetSoonestWakeupDeltaOnIOThread, this,
-          sync_type),
+          sync_type, last_browser_wakeup_for_periodic_sync),
       base::BindOnce(&BackgroundSyncContextImpl::DidGetSoonestWakeupDelta, this,
                      std::move(callback)));
 }
 
 base::TimeDelta BackgroundSyncContextImpl::GetSoonestWakeupDeltaOnIOThread(
-    blink::mojom::BackgroundSyncType sync_type) {
+    blink::mojom::BackgroundSyncType sync_type,
+    base::Time last_browser_wakeup_for_periodic_sync) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
   if (!test_wakeup_delta_.is_max())
@@ -163,7 +165,7 @@
     return base::TimeDelta::Max();
 
   return background_sync_manager_->GetSoonestWakeupDelta(
-      sync_type, /* apply_browser_wakeup_limit= */ true);
+      sync_type, last_browser_wakeup_for_periodic_sync);
 }
 
 void BackgroundSyncContextImpl::DidGetSoonestWakeupDelta(
diff --git a/content/browser/background_sync/background_sync_context_impl.h b/content/browser/background_sync/background_sync_context_impl.h
index f082965..ba54a87 100644
--- a/content/browser/background_sync/background_sync_context_impl.h
+++ b/content/browser/background_sync/background_sync_context_impl.h
@@ -72,6 +72,7 @@
                                 base::OnceClosure done_closure) override;
   void GetSoonestWakeupDelta(
       blink::mojom::BackgroundSyncType sync_type,
+      base::Time last_browser_wakeup_for_periodic_sync,
       base::OnceCallback<void(base::TimeDelta)> callback) override;
 
  protected:
@@ -107,7 +108,8 @@
   void ShutdownOnIO();
 
   base::TimeDelta GetSoonestWakeupDeltaOnIOThread(
-      blink::mojom::BackgroundSyncType sync_type);
+      blink::mojom::BackgroundSyncType sync_type,
+      base::Time last_browser_wakeup_for_periodic_sync);
   void DidGetSoonestWakeupDelta(
       base::OnceCallback<void(base::TimeDelta)> callback,
       base::TimeDelta soonest_wakeup_delta);
diff --git a/content/browser/background_sync/background_sync_launcher.cc b/content/browser/background_sync/background_sync_launcher.cc
index b8aebd2..0f9c401 100644
--- a/content/browser/background_sync/background_sync_launcher.cc
+++ b/content/browser/background_sync/background_sync_launcher.cc
@@ -144,16 +144,17 @@
   DCHECK(sync_context);
 
   sync_context->GetSoonestWakeupDelta(
-      sync_type, base::BindOnce(
-                     [](base::OnceClosure done_closure,
-                        base::TimeDelta* soonest_wakeup_delta,
-                        base::TimeDelta wakeup_delta) {
-                       DCHECK_CURRENTLY_ON(BrowserThread::UI);
-                       *soonest_wakeup_delta =
-                           std::min(*soonest_wakeup_delta, wakeup_delta);
-                       std::move(done_closure).Run();
-                     },
-                     std::move(done_closure), &soonest_wakeup_delta_));
+      sync_type, last_browser_wakeup_for_periodic_sync_,
+      base::BindOnce(
+          [](base::OnceClosure done_closure,
+             base::TimeDelta* soonest_wakeup_delta,
+             base::TimeDelta wakeup_delta) {
+            DCHECK_CURRENTLY_ON(BrowserThread::UI);
+            *soonest_wakeup_delta =
+                std::min(*soonest_wakeup_delta, wakeup_delta);
+            std::move(done_closure).Run();
+          },
+          std::move(done_closure), &soonest_wakeup_delta_));
 }
 
 void BackgroundSyncLauncher::SendSoonestWakeupDelta(
@@ -163,13 +164,4 @@
   std::move(callback).Run(soonest_wakeup_delta_);
 }
 
-#if defined(OS_ANDROID)
-base::TimeDelta
-BackgroundSyncLauncher::TimeSinceLastBrowserWakeUpForPeriodicSync() {
-  if (!time_since_last_browser_wakeup_for_testing_.is_max())
-    return time_since_last_browser_wakeup_for_testing_;
-  return base::Time::Now() - last_browser_wakeup_for_periodic_sync_;
-}
-#endif
-
 }  // namespace content
diff --git a/content/browser/background_sync/background_sync_launcher.h b/content/browser/background_sync/background_sync_launcher.h
index eff0757..39c06ba 100644
--- a/content/browser/background_sync/background_sync_launcher.h
+++ b/content/browser/background_sync/background_sync_launcher.h
@@ -65,11 +65,7 @@
       base::OnceCallback<void(base::TimeDelta)> callback);
 
   base::TimeDelta soonest_wakeup_delta_ = base::TimeDelta::Max();
-#if defined(OS_ANDROID)
   base::Time last_browser_wakeup_for_periodic_sync_;
-  base::TimeDelta time_since_last_browser_wakeup_for_testing_ =
-      base::TimeDelta::Max();
-#endif
   DISALLOW_COPY_AND_ASSIGN(BackgroundSyncLauncher);
 };
 
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index fc66fae..01c4233 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -1280,7 +1280,7 @@
 
 base::TimeDelta BackgroundSyncManager::GetSoonestWakeupDelta(
     BackgroundSyncType sync_type,
-    bool apply_browser_wakeup_limit) {
+    base::Time last_browser_wakeup_time) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   base::TimeDelta soonest_wakeup_delta = base::TimeDelta::Max();
   bool need_retries = false;
@@ -1318,27 +1318,27 @@
 
   // The browser may impose a hard limit on how often it can be woken up to
   // process periodic Background Sync registrations. This excludes retries.
-  if (sync_type == BackgroundSyncType::PERIODIC && !need_retries &&
-      apply_browser_wakeup_limit) {
-    soonest_wakeup_delta = ApplyBrowserWakeupCountLimit(soonest_wakeup_delta);
+  if (sync_type == BackgroundSyncType::PERIODIC && !need_retries) {
+    soonest_wakeup_delta = MaybeApplyBrowserWakeupCountLimit(
+        soonest_wakeup_delta, last_browser_wakeup_time);
   }
   return soonest_wakeup_delta;
 }
 
-base::TimeDelta BackgroundSyncManager::ApplyBrowserWakeupCountLimit(
-    base::TimeDelta soonest_wakeup_delta) {
+base::TimeDelta BackgroundSyncManager::MaybeApplyBrowserWakeupCountLimit(
+    base::TimeDelta soonest_wakeup_delta,
+    base::Time last_browser_wakeup_time) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  base::TimeDelta time_since_last_browser_wakeup = base::TimeDelta::Max();
-#if defined(OS_ANDROID)
-  time_since_last_browser_wakeup =
-      BackgroundSyncLauncher::Get()
-          ->TimeSinceLastBrowserWakeUpForPeriodicSync();
-#endif
-  if (time_since_last_browser_wakeup >=
-      parameters_->min_periodic_sync_events_interval)
+  if (last_browser_wakeup_time.is_null())
     return soonest_wakeup_delta;
 
+  base::TimeDelta time_since_last_browser_wakeup =
+      clock_->Now() - last_browser_wakeup_time;
+  if (time_since_last_browser_wakeup >=
+      parameters_->min_periodic_sync_events_interval) {
+    return soonest_wakeup_delta;
+  }
+
   base::TimeDelta time_till_next_allowed_browser_wakeup =
       parameters_->min_periodic_sync_events_interval -
       time_since_last_browser_wakeup;
@@ -1352,7 +1352,7 @@
   ResetAndScheduleDelayedSyncTask(
       sync_type,
       GetSoonestWakeupDelta(sync_type,
-                            /* apply_browser_wakeup_limit= */ false));
+                            /* last_browser_wakeup_time= */ base::Time()));
   proxy_.ScheduleBrowserWakeUp(sync_type);
 }
 
diff --git a/content/browser/background_sync/background_sync_manager.h b/content/browser/background_sync/background_sync_manager.h
index 7c52b17..87c2819 100644
--- a/content/browser/background_sync/background_sync_manager.h
+++ b/content/browser/background_sync/background_sync_manager.h
@@ -150,19 +150,21 @@
   // Only registrations of type |sync_type| are considered.
   // Browsers can have a hard limit on how often to wake themselves up to
   // process Periodic Background Sync registrations. We apply this limit if
-  // |apply_browser_wakeup_limit| is set to true.
+  // |last_browser_wakeup_time| is not null.
   // This limit is only applied when calculating the soonest wake up delta to
   // wake up Chrome. It's not applied when calculating the time after which a
   // delayed task should be run to process Background Sync registrations.
   virtual base::TimeDelta GetSoonestWakeupDelta(
       blink::mojom::BackgroundSyncType sync_type,
-      bool apply_browser_wakeup_limit);
+      base::Time last_browser_wakeup_time);
 
   // Browsers can have a hard limit on how often to wake themselves up to
   // process Periodic Background Sync registrations. If the browser can't be
   // woken up after |wakeup_delta| to do so, returns an updated delta after
   // which it's safe to wake the browser. This limit doesn't apply to retries.
-  base::TimeDelta ApplyBrowserWakeupCountLimit(base::TimeDelta wakeup_delta);
+  base::TimeDelta MaybeApplyBrowserWakeupCountLimit(
+      base::TimeDelta wakeup_delta,
+      base::Time last_browser_wakeup_time);
 
  protected:
   BackgroundSyncManager(
diff --git a/content/browser/background_sync/background_sync_manager_unittest.cc b/content/browser/background_sync/background_sync_manager_unittest.cc
index 6439ac6..ff1f498 100644
--- a/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -252,9 +252,9 @@
 
   base::TimeDelta GetSoonestWakeupDelta(
       blink::mojom::BackgroundSyncType sync_type,
-      bool apply_browser_wakeup_limit) {
+      base::Time last_browser_wakeup_for_periodic_sync) {
     return test_background_sync_manager()->GetSoonestWakeupDelta(
-        sync_type, apply_browser_wakeup_limit);
+        sync_type, last_browser_wakeup_for_periodic_sync);
   }
 
  protected:
@@ -630,13 +630,6 @@
     SetupBackgroundSyncManager();
   }
 
-  void SetTimeSinceLastWakeupOnAndroid(base::TimeDelta time_since_last_wakeup) {
-#if defined(OS_ANDROID)
-    BackgroundSyncLauncher::Get()->time_since_last_browser_wakeup_for_testing_ =
-        time_since_last_wakeup;
-#endif
-  }
-
   void FireReadyEvents() { test_background_sync_manager()->OnNetworkChanged(); }
 
   bool AreOptionConditionsMet() {
@@ -1650,11 +1643,13 @@
   EXPECT_TRUE(Register(sync_options_2_));
   EXPECT_TRUE(GetRegistration(sync_options_2_));
 
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::ONE_SHOT,
-                                  /* apply_browser_wakeup_limit= */ false),
+  EXPECT_EQ(GetSoonestWakeupDelta(
+                blink::mojom::BackgroundSyncType::ONE_SHOT,
+                /* last_browser_wakeup_for_periodic_sync= */ base::Time()),
             base::TimeDelta());
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ false),
+  EXPECT_EQ(GetSoonestWakeupDelta(
+                blink::mojom::BackgroundSyncType::PERIODIC,
+                /* last_browser_wakeup_for_periodic_sync= */ base::Time()),
             base::TimeDelta::FromMilliseconds(sync_options_2_.min_interval));
 }
 
@@ -1665,24 +1660,24 @@
   EXPECT_TRUE(Register(sync_options_2_));
   EXPECT_TRUE(GetRegistration(sync_options_2_));
 
-  base::TimeDelta soonest_wakeup_delta_1 =
-      GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                            /* apply_browser_wakeup_limit= */ false);
+  base::TimeDelta soonest_wakeup_delta_1 = GetSoonestWakeupDelta(
+      blink::mojom::BackgroundSyncType::PERIODIC,
+      /* last_browser_wakeup_for_periodic_sync= */ base::Time());
 
   test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
-  base::TimeDelta soonest_wakeup_delta_2 =
-      GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                            /* apply_browser_wakeup_limit= */ false);
+  base::TimeDelta soonest_wakeup_delta_2 = GetSoonestWakeupDelta(
+      blink::mojom::BackgroundSyncType::PERIODIC,
+      /* last_browser_wakeup_for_periodic_sync= */ base::Time());
 
   test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
-  base::TimeDelta soonest_wakeup_delta_3 =
-      GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                            /* apply_browser_wakeup_limit= */ false);
+  base::TimeDelta soonest_wakeup_delta_3 = GetSoonestWakeupDelta(
+      blink::mojom::BackgroundSyncType::PERIODIC,
+      /* last_browser_wakeup_for_periodic_sync= */ base::Time());
 
   test_clock_.Advance(base::TimeDelta::FromMilliseconds(thirteen_hours_ms));
-  base::TimeDelta soonest_wakeup_delta_4 =
-      GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                            /* apply_browser_wakeup_limit= */ false);
+  base::TimeDelta soonest_wakeup_delta_4 = GetSoonestWakeupDelta(
+      blink::mojom::BackgroundSyncType::PERIODIC,
+      /* last_browser_wakeup_for_periodic_sync= */ base::Time());
 
   EXPECT_GT(soonest_wakeup_delta_1, soonest_wakeup_delta_2);
   EXPECT_GT(soonest_wakeup_delta_2, soonest_wakeup_delta_3);
@@ -1699,58 +1694,33 @@
   sync_options_1_.min_interval = thirteen_hours.InMilliseconds();
   EXPECT_TRUE(Register(sync_options_1_));
   EXPECT_TRUE(GetRegistration(sync_options_1_));
-
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ false),
+  EXPECT_EQ(GetSoonestWakeupDelta(
+                blink::mojom::BackgroundSyncType::PERIODIC,
+                /* last_browser_wakeup_for_periodic_sync= */ base::Time()),
             thirteen_hours);
 
-  // Advance clock by an hour and add another registration.
+  // Advance the clock by an hour.
   // Hour 1. Expect soonest_wakeup_delta to now be 12.
   base::TimeDelta one_hour = base::TimeDelta::FromHours(1);
   test_clock_.Advance(one_hour);
-  sync_options_2_.min_interval = thirteen_hours.InMilliseconds();
-  EXPECT_TRUE(Register(sync_options_2_));
-  EXPECT_TRUE(GetRegistration(sync_options_2_));
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ false),
+  EXPECT_EQ(GetSoonestWakeupDelta(
+                blink::mojom::BackgroundSyncType::PERIODIC,
+                /* last_browser_wakeup_for_periodic_sync= */ base::Time()),
             twelve_hours);
-
-  test_clock_.Advance(base::TimeDelta::FromHours(2));
-  SetTimeSinceLastWakeupOnAndroid(base::TimeDelta::FromHours(3));
-#if defined(OS_ANDROID)
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ true),
-            base::TimeDelta::FromHours(10));
-#else
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ true),
-            base::TimeDelta::FromHours(10));
-#endif
-
-  // Advance further by 10 hours and update the first registration to have a 14
-  // hour interval. Set last wake up to be one hour ago.
-  // Hour 13. On Android, soonest wakeup delta should be 11 hours with the
-  // browser wakeup limit, and 1 hour without it.
-  test_clock_.Advance(base::TimeDelta::FromHours(10));
-  sync_options_1_.min_interval = 14 * 60 * 60 * 1000;  // 14 hours.
-  EXPECT_TRUE(Register(sync_options_1_));
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ false),
-            one_hour);
-
-  SetTimeSinceLastWakeupOnAndroid(one_hour);
-#if defined(OS_ANDROID)
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ true),
-            base::TimeDelta::FromHours(11));
-#else
-  EXPECT_EQ(GetSoonestWakeupDelta(blink::mojom::BackgroundSyncType::PERIODIC,
-                                  /* apply_browser_wakeup_limit= */ true),
-            one_hour);
-#endif
-
+  // Advance the clock by 12 hours. Hour 13.
+  test_clock_.Advance(base::TimeDelta::FromHours(9));
+  base::Time browser_wakeup_time = test_clock_.Now();
+  test_clock_.Advance(base::TimeDelta::FromHours(3));
+  EXPECT_EQ(
+      GetSoonestWakeupDelta(
+          blink::mojom::BackgroundSyncType::PERIODIC,
+          /* last_browser_wakeup_for_periodic_sync= */ browser_wakeup_time),
+      base::TimeDelta::FromHours(9));
+  EXPECT_EQ(GetSoonestWakeupDelta(
+                blink::mojom::BackgroundSyncType::PERIODIC,
+                /* last_browser_wakeup_for_periodic_sync= */ base::Time()),
+            base::TimeDelta());
   Unregister(sync_options_1_);
-  Unregister(sync_options_2_);
 }
 
 TEST_F(BackgroundSyncManagerTest, OneAttempt) {
diff --git a/content/browser/background_sync/one_shot_background_sync_browsertest.cc b/content/browser/background_sync/one_shot_background_sync_browsertest.cc
index 699ee64..6f06e654 100644
--- a/content/browser/background_sync/one_shot_background_sync_browsertest.cc
+++ b/content/browser/background_sync/one_shot_background_sync_browsertest.cc
@@ -4,8 +4,6 @@
 
 #include "content/browser/background_sync/background_sync_base_browsertest.h"
 
-#include <stdint.h>
-
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
@@ -56,15 +54,17 @@
 
 bool OneShotBackgroundSyncBrowserTest::Register(const std::string& tag) {
   std::string script_result;
-  EXPECT_TRUE(RunScript(BuildScriptString("register", tag), &script_result));
+  EXPECT_TRUE(
+      RunScript(BuildScriptString("registerOneShotSync", tag), &script_result));
   return script_result == BuildExpectedResult(tag, "registered");
 }
 
 bool OneShotBackgroundSyncBrowserTest::RegisterFromServiceWorker(
     const std::string& tag) {
   std::string script_result;
-  EXPECT_TRUE(RunScript(BuildScriptString("registerFromServiceWorker", tag),
-                        &script_result));
+  EXPECT_TRUE(
+      RunScript(BuildScriptString("registerOneShotSyncFromServiceWorker", tag),
+                &script_result));
   return script_result == BuildExpectedResult(tag, "register sent to SW");
 }
 
@@ -78,21 +78,23 @@
 
   GURL url = alt_server.GetURL(frame_url);
   return RunScript(
-      BuildScriptString("registerFromCrossOriginFrame", url.spec()),
+      BuildScriptString("registerOneShotSyncFromCrossOriginFrame", url.spec()),
       script_result);
 }
 
 bool OneShotBackgroundSyncBrowserTest::HasTag(const std::string& tag) {
   std::string script_result;
-  EXPECT_TRUE(RunScript(BuildScriptString("hasTag", tag), &script_result));
+  EXPECT_TRUE(
+      RunScript(BuildScriptString("hasOneShotSyncTag", tag), &script_result));
   return script_result == BuildExpectedResult(tag, "found");
 }
 
 bool OneShotBackgroundSyncBrowserTest::HasTagFromServiceWorker(
     const std::string& tag) {
   std::string script_result;
-  EXPECT_TRUE(RunScript(BuildScriptString("hasTagFromServiceWorker", tag),
-                        &script_result));
+  EXPECT_TRUE(
+      RunScript(BuildScriptString("hasOneShotSyncTagFromServiceWorker", tag),
+                &script_result));
   EXPECT_TRUE(script_result == "ok - hasTag sent to SW");
 
   return PopConsole(BuildExpectedResult(tag, "found"));
@@ -115,7 +117,7 @@
 bool OneShotBackgroundSyncBrowserTest::GetTags(
     const std::vector<std::string>& expected_tags) {
   std::string script_result;
-  EXPECT_TRUE(RunScript("getTags()", &script_result));
+  EXPECT_TRUE(RunScript("getOneShotSyncTags()", &script_result));
 
   return MatchTags(script_result, expected_tags);
 }
@@ -123,7 +125,8 @@
 bool OneShotBackgroundSyncBrowserTest::GetTagsFromServiceWorker(
     const std::vector<std::string>& expected_tags) {
   std::string script_result;
-  EXPECT_TRUE(RunScript("getTagsFromServiceWorker()", &script_result));
+  EXPECT_TRUE(
+      RunScript("getOneShotSyncTagsFromServiceWorker()", &script_result));
   EXPECT_TRUE(script_result == "ok - getTags sent to SW");
 
   return MatchTags(PopConsoleString(), expected_tags);
@@ -410,8 +413,9 @@
                        RegisterFromIFrameWithMainFrameHost) {
   std::string script_result;
   GURL url = https_server()->GetURL(kEmptyURL);
-  EXPECT_TRUE(RunScript(BuildScriptString("registerFromLocalFrame", url.spec()),
-                        &script_result));
+  EXPECT_TRUE(RunScript(
+      BuildScriptString("registerOneShotSyncFromLocalFrame", url.spec()),
+      &script_result));
   EXPECT_EQ(BuildExpectedResult("iframe", "registered sync"), script_result);
 }
 
diff --git a/content/browser/background_sync/periodic_background_sync_browsertest.cc b/content/browser/background_sync/periodic_background_sync_browsertest.cc
new file mode 100644
index 0000000..f7190fae
--- /dev/null
+++ b/content/browser/background_sync/periodic_background_sync_browsertest.cc
@@ -0,0 +1,179 @@
+// 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/test/scoped_feature_list.h"
+#include "base/test/simple_test_clock.h"
+#include "base/time/time.h"
+#include "content/browser/background_sync/background_sync_base_browsertest.h"
+#include "content/public/common/content_features.h"
+
+namespace content {
+
+class PeriodicBackgroundSyncBrowserTest : public BackgroundSyncBaseBrowserTest {
+ public:
+  PeriodicBackgroundSyncBrowserTest() {}
+  ~PeriodicBackgroundSyncBrowserTest() override {}
+
+  void SetUpOnMainThread() override;
+  bool Register(const std::string& tag, int min_interval_ms);
+  bool RegisterNoMinInterval(const std::string& tag);
+  bool RegisterFromServiceWorker(const std::string& tag, int min_interval_ms);
+  bool RegisterFromServiceWorkerNoMinInterval(const std::string& tag);
+  bool HasTag(const std::string& tag);
+  bool HasTagFromServiceWorker(const std::string& tag);
+  bool Unregister(const std::string& tag);
+  bool UnregisterFromServiceWorker(const std::string& tag);
+
+ protected:
+  base::SimpleTestClock clock_;
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+  DISALLOW_COPY_AND_ASSIGN(PeriodicBackgroundSyncBrowserTest);
+};
+
+void PeriodicBackgroundSyncBrowserTest::SetUpOnMainThread() {
+  scoped_feature_list_.InitAndEnableFeature(features::kPeriodicBackgroundSync);
+  BackgroundSyncBaseBrowserTest::SetUpOnMainThread();
+}
+
+bool PeriodicBackgroundSyncBrowserTest::Register(const std::string& tag,
+                                                 int min_interval_ms) {
+  std::string script_result;
+  EXPECT_TRUE(
+      RunScript(base::StringPrintf("%s('%s', %d);", "registerPeriodicSync",
+                                   tag.c_str(), min_interval_ms),
+                &script_result));
+  return script_result == BuildExpectedResult(tag, "registered");
+}
+
+bool PeriodicBackgroundSyncBrowserTest::RegisterNoMinInterval(
+    const std::string& tag) {
+  std::string script_result;
+  EXPECT_TRUE(RunScript(
+      base::StringPrintf("%s('%s');", "registerPeriodicSync", tag.c_str()),
+      &script_result));
+  return script_result == BuildExpectedResult(tag, "registered");
+}
+
+bool PeriodicBackgroundSyncBrowserTest::RegisterFromServiceWorker(
+    const std::string& tag,
+    int min_interval_ms) {
+  std::string script_result;
+  EXPECT_TRUE(
+      RunScript(base::StringPrintf("%s('%s', %d);",
+                                   "registerPeriodicSyncFromServiceWorker",
+                                   tag.c_str(), min_interval_ms),
+                &script_result));
+  return script_result == BuildExpectedResult(tag, "register sent to SW");
+}
+
+bool PeriodicBackgroundSyncBrowserTest::RegisterFromServiceWorkerNoMinInterval(
+    const std::string& tag) {
+  std::string script_result;
+  EXPECT_TRUE(
+      RunScript(BuildScriptString("registerPeriodicSyncFromServiceWorker", tag),
+                &script_result));
+  return script_result == BuildExpectedResult(tag, "register sent to SW");
+}
+
+bool PeriodicBackgroundSyncBrowserTest::HasTag(const std::string& tag) {
+  std::string script_result;
+  EXPECT_TRUE(
+      RunScript(BuildScriptString("hasPeriodicSyncTag", tag), &script_result));
+  return script_result == BuildExpectedResult(tag, "found");
+}
+
+bool PeriodicBackgroundSyncBrowserTest::HasTagFromServiceWorker(
+    const std::string& tag) {
+  std::string script_result;
+  EXPECT_TRUE(
+      RunScript(BuildScriptString("hasPeriodicSyncTagFromServiceWorker", tag),
+                &script_result));
+  return (script_result == "ok - hasTag sent to SW");
+}
+
+bool PeriodicBackgroundSyncBrowserTest::Unregister(const std::string& tag) {
+  std::string script_result;
+  EXPECT_TRUE(RunScript(BuildScriptString("unregister", tag), &script_result));
+  return script_result == BuildExpectedResult(tag, "unregistered");
+}
+
+bool PeriodicBackgroundSyncBrowserTest::UnregisterFromServiceWorker(
+    const std::string& tag) {
+  std::string script_result;
+  EXPECT_TRUE(RunScript(BuildScriptString("unregisterFromServiceWorker", tag),
+                        &script_result));
+  return script_result == BuildExpectedResult(tag, "unregister sent to SW");
+}
+
+IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
+                       RegisterFromControlledDocument) {
+  EXPECT_TRUE(RegisterServiceWorker());
+  EXPECT_TRUE(LoadTestPage(kDefaultTestURL));  // Control the page.
+
+  EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 1000));
+  EXPECT_TRUE(Unregister("foo"));
+}
+
+IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
+                       RegisterNoMinInterval) {
+  EXPECT_TRUE(RegisterServiceWorker());
+
+  EXPECT_TRUE(RegisterNoMinInterval("foo"));
+  EXPECT_TRUE(Unregister("foo"));
+}
+
+// Verify that Register works in a service worker
+IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
+                       RegisterFromServiceWorker) {
+  EXPECT_TRUE(RegisterServiceWorker());
+  EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
+
+  EXPECT_TRUE(RegisterFromServiceWorker("foo_sw", /* min_interval_ms= */ 10));
+  EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
+  EXPECT_TRUE(Unregister("foo"));
+}
+
+IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
+                       RegisterFromServiceWorkerNoMinInterval) {
+  EXPECT_TRUE(RegisterServiceWorker());
+  EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
+
+  EXPECT_TRUE(RegisterFromServiceWorkerNoMinInterval("foo_sw"));
+  EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
+  EXPECT_TRUE(Unregister("foo"));
+}
+
+IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest, FindATag) {
+  EXPECT_TRUE(RegisterServiceWorker());
+  EXPECT_TRUE(LoadTestPage(kDefaultTestURL));  // Control the page.
+
+  EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 1000));
+  EXPECT_TRUE(HasTag("foo"));
+  EXPECT_TRUE(Unregister("foo"));
+}
+
+IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
+                       FindATagFromServiceWorker) {
+  EXPECT_TRUE(RegisterServiceWorker());
+  EXPECT_TRUE(LoadTestPage(kDefaultTestURL));  // Control the page.
+
+  EXPECT_TRUE(Register("foo", /* min_interval_ms= */ 1000));
+  EXPECT_TRUE(HasTagFromServiceWorker("foo"));
+  EXPECT_TRUE(PopConsole("ok - foo found in SW"));
+}
+
+IN_PROC_BROWSER_TEST_F(PeriodicBackgroundSyncBrowserTest,
+                       UnregisterFromServiceWorker) {
+  EXPECT_TRUE(RegisterServiceWorker());
+  EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
+
+  EXPECT_TRUE(RegisterNoMinInterval("foo"));
+  EXPECT_TRUE(HasTag("foo"));
+  EXPECT_TRUE(UnregisterFromServiceWorker("foo"));
+  EXPECT_TRUE(PopConsole("ok - foo unregistered in SW"));
+}
+
+}  // namespace content
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc
index 348c92a1..4ead353 100644
--- a/content/browser/browser_main_loop.cc
+++ b/content/browser/browser_main_loop.cc
@@ -64,7 +64,6 @@
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/compositor/surface_utils.h"
 #include "content/browser/compositor/viz_process_transport_factory.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
 #include "content/browser/dom_storage/storage_area_impl.h"
 #include "content/browser/download/download_resource_handler.h"
 #include "content/browser/download/save_file_manager.h"
@@ -767,7 +766,6 @@
           switches::kEnableAggressiveDOMStorageFlushing)) {
     TRACE_EVENT0("startup",
                  "BrowserMainLoop::Subsystem:EnableAggressiveCommitDelay");
-    DOMStorageArea::EnableAggressiveCommitDelay();
     StorageAreaImpl::EnableAggressiveCommitDelay();
   }
 
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index 803d06c..5bb9bc2 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/debug/dump_without_crashing.h"
+#include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/task/post_task.h"
 #include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
@@ -189,7 +190,8 @@
 
     // GPU process access is disabled. Start a new thread to run the display
     // compositor in-process and connect HostFrameSinkManager to it.
-    viz_compositor_thread_ = std::make_unique<viz::VizCompositorThreadRunner>();
+    viz_compositor_thread_ = std::make_unique<viz::VizCompositorThreadRunner>(
+        base::MessageLoop::TYPE_DEFAULT);
 
     viz::mojom::FrameSinkManagerParamsPtr params =
         viz::mojom::FrameSinkManagerParams::New();
diff --git a/content/browser/dom_storage/dom_storage_area.cc b/content/browser/dom_storage/dom_storage_area.cc
deleted file mode 100644
index 4fdd70a7..0000000
--- a/content/browser/dom_storage/dom_storage_area.cc
+++ /dev/null
@@ -1,671 +0,0 @@
-// Copyright 2013 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/dom_storage/dom_storage_area.h"
-
-#include <inttypes.h>
-
-#include <algorithm>
-#include <cctype>  // for std::isalnum
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/process/process_info.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "build/build_config.h"
-#include "content/browser/dom_storage/dom_storage_namespace.h"
-#include "content/browser/dom_storage/dom_storage_task_runner.h"
-#include "content/browser/dom_storage/session_storage_database.h"
-#include "content/browser/dom_storage/session_storage_database_adapter.h"
-#include "content/common/dom_storage/dom_storage_map.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-#include "content/public/browser/browser_thread.h"
-#include "storage/browser/database/database_util.h"
-#include "storage/common/database/database_identifier.h"
-#include "storage/common/fileapi/file_system_util.h"
-
-using storage::DatabaseUtil;
-
-namespace content {
-
-namespace {
-
-// To avoid excessive IO we apply limits to the amount of data being written
-// and the frequency of writes. The specific values used are somewhat arbitrary.
-constexpr int kMaxBytesPerHour = kPerStorageAreaQuota;
-constexpr int kMaxCommitsPerHour = 60;
-
-}  // namespace
-
-bool DOMStorageArea::s_aggressive_flushing_enabled_ = false;
-
-DOMStorageArea::RateLimiter::RateLimiter(size_t desired_rate,
-                                         base::TimeDelta time_quantum)
-    : rate_(desired_rate), samples_(0), time_quantum_(time_quantum) {
-  DCHECK_GT(desired_rate, 0ul);
-}
-
-base::TimeDelta DOMStorageArea::RateLimiter::ComputeTimeNeeded() const {
-  return time_quantum_ * (samples_ / rate_);
-}
-
-base::TimeDelta DOMStorageArea::RateLimiter::ComputeDelayNeeded(
-    const base::TimeDelta elapsed_time) const {
-  base::TimeDelta time_needed = ComputeTimeNeeded();
-  if (time_needed > elapsed_time)
-    return time_needed - elapsed_time;
-  return base::TimeDelta();
-}
-
-DOMStorageArea::CommitBatch::CommitBatch() : clear_all_first(false) {}
-DOMStorageArea::CommitBatch::~CommitBatch() {}
-
-size_t DOMStorageArea::CommitBatch::GetDataSize() const {
-  return DOMStorageMap::CountBytes(changed_values);
-}
-
-DOMStorageArea::CommitBatchHolder::CommitBatchHolder(
-    Type type,
-    scoped_refptr<CommitBatch> batch)
-    : type(type), batch(batch) {}
-DOMStorageArea::CommitBatchHolder::CommitBatchHolder(
-    const DOMStorageArea::CommitBatchHolder& other) = default;
-DOMStorageArea::CommitBatchHolder::~CommitBatchHolder() {}
-
-// static
-const base::FilePath::CharType DOMStorageArea::kDatabaseFileExtension[] =
-    FILE_PATH_LITERAL(".localstorage");
-
-// static
-base::FilePath DOMStorageArea::DatabaseFileNameFromOrigin(
-    const url::Origin& origin) {
-  std::string filename = storage::GetIdentifierFromOrigin(origin);
-  // There is no base::FilePath.AppendExtension() method, so start with just the
-  // extension as the filename, and then InsertBeforeExtension the desired
-  // name.
-  return base::FilePath().Append(kDatabaseFileExtension).
-      InsertBeforeExtensionASCII(filename);
-}
-
-// static
-url::Origin DOMStorageArea::OriginFromDatabaseFileName(
-    const base::FilePath& name) {
-  DCHECK(name.MatchesExtension(kDatabaseFileExtension));
-  std::string origin_id =
-      name.BaseName().RemoveExtension().MaybeAsASCII();
-  return storage::GetOriginFromIdentifier(origin_id);
-}
-
-void DOMStorageArea::EnableAggressiveCommitDelay() {
-  s_aggressive_flushing_enabled_ = true;
-}
-
-DOMStorageArea::DOMStorageArea(const std::string& namespace_id,
-                               std::vector<std::string> original_namespace_ids,
-                               const url::Origin& origin,
-                               SessionStorageDatabase* session_storage_backing,
-                               DOMStorageTaskRunner* task_runner)
-    : namespace_id_(namespace_id),
-      original_namespace_ids_(std::move(original_namespace_ids)),
-      origin_(origin),
-      task_runner_(task_runner),
-#if defined(OS_ANDROID)
-      desired_load_state_(session_storage_backing ? LOAD_STATE_KEYS_ONLY
-                                                  : LOAD_STATE_KEYS_AND_VALUES),
-#else
-      desired_load_state_(LOAD_STATE_KEYS_AND_VALUES),
-#endif
-      load_state_(session_storage_backing ? LOAD_STATE_UNLOADED
-                                          : LOAD_STATE_KEYS_AND_VALUES),
-      map_(new DOMStorageMap(
-          kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
-          desired_load_state_ == LOAD_STATE_KEYS_ONLY)),
-      session_storage_backing_(session_storage_backing),
-      is_shutdown_(false),
-      start_time_(base::TimeTicks::Now()),
-      data_rate_limiter_(kMaxBytesPerHour, base::TimeDelta::FromHours(1)),
-      commit_rate_limiter_(kMaxCommitsPerHour, base::TimeDelta::FromHours(1)) {
-  DCHECK(!namespace_id.empty());
-  if (session_storage_backing) {
-    backing_.reset(
-        new SessionStorageDatabaseAdapter(session_storage_backing, namespace_id,
-                                          original_namespace_ids_, origin));
-  }
-}
-
-DOMStorageArea::~DOMStorageArea() {
-}
-
-void DOMStorageArea::ExtractValues(DOMStorageValuesMap* map) {
-  if (is_shutdown_)
-    return;
-
-  if (load_state_ == LOAD_STATE_KEYS_AND_VALUES) {
-    map_->ExtractValues(map);
-    return;
-  }
-  LoadMapAndApplyUncommittedChangesIfNeeded(map);
-}
-
-unsigned DOMStorageArea::Length() {
-  if (is_shutdown_)
-    return 0;
-  LoadMapAndApplyUncommittedChangesIfNeeded(nullptr);
-  return map_->Length();
-}
-
-base::NullableString16 DOMStorageArea::Key(unsigned index) {
-  if (is_shutdown_)
-    return base::NullableString16();
-  LoadMapAndApplyUncommittedChangesIfNeeded(nullptr);
-  return map_->Key(index);
-}
-
-base::NullableString16 DOMStorageArea::GetItem(const base::string16& key) {
-  if (is_shutdown_)
-    return base::NullableString16();
-  LoadMapAndApplyUncommittedChangesIfNeeded(nullptr);
-  return map_->GetItem(key);
-}
-
-bool DOMStorageArea::SetItem(const base::string16& key,
-                             const base::string16& value,
-                             const base::NullableString16& client_old_value,
-                             base::NullableString16* old_value) {
-  if (is_shutdown_)
-    return false;
-  LoadMapAndApplyUncommittedChangesIfNeeded(nullptr);
-  if (!map_->HasOneRef())
-    map_ = map_->DeepCopy();
-  bool success = map_->SetItem(key, value, old_value);
-  if (map_->has_only_keys())
-    *old_value = client_old_value;
-  if (success && backing_ &&
-      (old_value->is_null() || old_value->string() != value)) {
-    CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
-    if (load_state_ == LOAD_STATE_KEYS_AND_VALUES) {
-      // Values are populated later to avoid holding duplicate memory.
-      commit_batch->changed_values[key] = base::NullableString16();
-    } else {
-      commit_batch->changed_values[key] = base::NullableString16(value, false);
-    }
-  }
-  return success;
-}
-
-bool DOMStorageArea::RemoveItem(const base::string16& key,
-                                const base::NullableString16& client_old_value,
-                                base::string16* old_value) {
-  if (is_shutdown_)
-    return false;
-  LoadMapAndApplyUncommittedChangesIfNeeded(nullptr);
-  if (!map_->HasOneRef())
-    map_ = map_->DeepCopy();
-  bool success = map_->RemoveItem(key, old_value);
-  if (map_->has_only_keys()) {
-    DCHECK(!client_old_value.is_null());
-    *old_value = client_old_value.string();
-  }
-  if (success && backing_) {
-    CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
-    commit_batch->changed_values[key] = base::NullableString16();
-  }
-  return success;
-}
-
-bool DOMStorageArea::Clear() {
-  if (is_shutdown_)
-    return false;
-  LoadMapAndApplyUncommittedChangesIfNeeded(nullptr);
-  if (map_->Length() == 0)
-    return false;
-
-  map_ = new DOMStorageMap(
-      kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
-      desired_load_state_ == LOAD_STATE_KEYS_ONLY);
-
-  if (backing_) {
-    CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
-    commit_batch->clear_all_first = true;
-    commit_batch->changed_values.clear();
-  }
-
-  return true;
-}
-
-void DOMStorageArea::FastClear() {
-  if (is_shutdown_)
-    return;
-
-  map_ = new DOMStorageMap(
-      kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
-      desired_load_state_ == LOAD_STATE_KEYS_ONLY);
-  // This ensures no load will happen while we're waiting to clear the data
-  // from the database.
-  load_state_ = desired_load_state_;
-
-  if (backing_) {
-    CommitBatch* commit_batch = CreateCommitBatchIfNeeded();
-    commit_batch->clear_all_first = true;
-    commit_batch->changed_values.clear();
-  }
-}
-
-DOMStorageArea* DOMStorageArea::ShallowCopy(
-    const std::string& destination_namespace_id) {
-  DCHECK(!namespace_id_.empty());
-  DCHECK(!destination_namespace_id.empty());
-
-  std::vector<std::string> original_namespace_ids;
-  original_namespace_ids.push_back(namespace_id_);
-  original_namespace_ids.insert(original_namespace_ids.end(),
-                                original_namespace_ids_.begin(),
-                                original_namespace_ids_.end());
-  DOMStorageArea* copy = new DOMStorageArea(
-      destination_namespace_id, std::move(original_namespace_ids), origin_,
-      session_storage_backing_.get(), task_runner_.get());
-  copy->desired_load_state_ = desired_load_state_;
-  copy->load_state_ = load_state_;
-  copy->map_ = map_;
-  copy->is_shutdown_ = is_shutdown_;
-
-  // All the uncommitted changes to this area need to happen before the actual
-  // shallow copy is made (scheduled by the upper layer sometime after return).
-  if (GetCurrentCommitBatch())
-    ScheduleImmediateCommit();
-  if (load_state_ != LOAD_STATE_KEYS_AND_VALUES) {
-    copy->commit_batches_ = commit_batches_;
-    for (auto& it : copy->commit_batches_)
-      it.type = CommitBatchHolder::TYPE_CLONE;
-  }
-  return copy;
-}
-
-bool DOMStorageArea::HasUncommittedChanges() const {
-  return !commit_batches_.empty();
-}
-
-void DOMStorageArea::ScheduleImmediateCommit() {
-  DCHECK(HasUncommittedChanges());
-  PostCommitTask();
-}
-
-void DOMStorageArea::ClearShallowCopiedCommitBatches() {
-  if (is_shutdown_)
-    return;
-  while (!commit_batches_.empty() &&
-         commit_batches_.back().type == CommitBatchHolder::TYPE_CLONE) {
-    commit_batches_.pop_back();
-  }
-  original_namespace_ids_.clear();
-}
-
-void DOMStorageArea::SetCacheOnlyKeys(bool only_keys) {
-  LoadState new_desired_state =
-      only_keys ? LOAD_STATE_KEYS_ONLY : LOAD_STATE_KEYS_AND_VALUES;
-  if (is_shutdown_ || !backing_ || desired_load_state_ == new_desired_state)
-    return;
-
-  desired_load_state_ = new_desired_state;
-  // Do not clear values immediately when desired state is set to keys only.
-  // Either commit timer or a purge call will clear the map, in case new process
-  // tries to open again. When values are desired it is ok to clear the map
-  // immediately. The reload only happens when required.
-  if (!map_->Length() || desired_load_state_ == LOAD_STATE_KEYS_AND_VALUES)
-    UnloadMapIfDesired();
-}
-
-void DOMStorageArea::PurgeMemory() {
-  DCHECK(!is_shutdown_);
-
-  if (load_state_ == LOAD_STATE_UNLOADED ||  // We're not using any memory.
-      !backing_.get() ||                     // We can't purge anything.
-      HasUncommittedChanges())  // We leave things alone with changes pending.
-    return;
-
-  // Recreate the database object, this frees up the open sqlite connection
-  // and its page cache.
-  backing_->Reset();
-
-  // Do not set load_state_ to |LOAD_STATE_UNLOADED| if map is empty since
-  // FastClear is efficient with no reloads while waiting for clearing database.
-  if (!map_ || !map_->Length())
-    return;
-
-  // Drop the in memory cache, we'll reload when needed.
-  load_state_ = LOAD_STATE_UNLOADED;
-  map_ = new DOMStorageMap(
-      kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
-      desired_load_state_ == LOAD_STATE_KEYS_ONLY);
-}
-
-void DOMStorageArea::UnloadMapIfDesired() {
-  if (load_state_ == LOAD_STATE_UNLOADED || load_state_ == desired_load_state_)
-    return;
-
-  // Do not clear the map if there are uncommitted changes since the commit
-  // batch might not have the values populated.
-  if (!backing_ || HasUncommittedChanges())
-    return;
-
-  if (load_state_ == LOAD_STATE_KEYS_AND_VALUES) {
-    scoped_refptr<DOMStorageMap> keys_values = map_;
-    map_ = new DOMStorageMap(
-        kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
-        desired_load_state_ == LOAD_STATE_KEYS_ONLY);
-    map_->TakeKeysFrom(keys_values->keys_values());
-    load_state_ = LOAD_STATE_KEYS_ONLY;
-    return;
-  }
-
-  map_ = new DOMStorageMap(
-      kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
-      desired_load_state_ == LOAD_STATE_KEYS_ONLY);
-  load_state_ = LOAD_STATE_UNLOADED;
-}
-
-void DOMStorageArea::Shutdown() {
-  if (is_shutdown_)
-    return;
-  is_shutdown_ = true;
-
-  if (GetCurrentCommitBatch()) {
-    DCHECK(backing_);
-    PopulateCommitBatchValues();
-  }
-
-  map_ = nullptr;
-  if (!backing_)
-    return;
-
-  bool success = task_runner_->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
-      base::BindOnce(&DOMStorageArea::ShutdownInCommitSequence, this));
-  DCHECK(success);
-}
-
-bool DOMStorageArea::IsMapReloadNeeded() {
-  return load_state_ < desired_load_state_;
-}
-
-void DOMStorageArea::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd) {
-  task_runner_->AssertIsRunningOnPrimarySequence();
-  if (is_shutdown_ || load_state_ == LOAD_STATE_UNLOADED)
-    return;
-
-  // Limit the url length to 50 and strip special characters.
-  std::string url = origin_.GetURL().spec().substr(0, 50);
-  for (size_t index = 0; index < url.size(); ++index) {
-    if (!std::isalnum(url[index]))
-      url[index] = '_';
-  }
-  std::string name =
-      base::StringPrintf("site_storage/%s/0x%" PRIXPTR, url.c_str(),
-                         reinterpret_cast<uintptr_t>(this));
-
-  const char* system_allocator_name =
-      base::trace_event::MemoryDumpManager::GetInstance()
-          ->system_allocator_pool_name();
-  if (!commit_batches_.empty()) {
-    size_t commit_batches_size = 0;
-    for (const auto& it : commit_batches_)
-      commit_batches_size += it.batch->GetDataSize();
-    auto* commit_batch_mad = pmd->CreateAllocatorDump(name + "/commit_batch");
-    commit_batch_mad->AddScalar(
-        base::trace_event::MemoryAllocatorDump::kNameSize,
-        base::trace_event::MemoryAllocatorDump::kUnitsBytes,
-        commit_batches_size);
-    if (system_allocator_name)
-      pmd->AddSuballocation(commit_batch_mad->guid(), system_allocator_name);
-  }
-
-  // Do not add storage map usage if less than 1KB.
-  if (map_->memory_used() < 1024)
-    return;
-
-  auto* map_mad = pmd->CreateAllocatorDump(name + "/storage_map");
-  map_mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
-                     base::trace_event::MemoryAllocatorDump::kUnitsBytes,
-                     map_->memory_used());
-  if (system_allocator_name)
-    pmd->AddSuballocation(map_mad->guid(), system_allocator_name);
-}
-
-void DOMStorageArea::LoadMapAndApplyUncommittedChangesIfNeeded(
-    DOMStorageValuesMap* map) {
-  if (!backing_ || (!IsMapReloadNeeded() && !map))
-    return;
-
-  DOMStorageValuesMap read_values;
-  auto most_recent_clear_all_iter = commit_batches_.begin();
-  while (most_recent_clear_all_iter != commit_batches_.end()) {
-    if (most_recent_clear_all_iter->batch->clear_all_first)
-      break;
-    ++most_recent_clear_all_iter;
-  }
-
-  if (most_recent_clear_all_iter == commit_batches_.end()) {
-    base::TimeTicks before = base::TimeTicks::Now();
-    backing_->ReadAllValues(&read_values);
-
-    base::TimeDelta time_to_prime = base::TimeTicks::Now() - before;
-    UMA_HISTOGRAM_TIMES("LocalStorage.BrowserTimeToPrimeLocalStorage",
-                        time_to_prime);
-
-    size_t local_storage_size_kb =
-        DOMStorageMap::CountBytes(read_values) / 1024;
-    // Track localStorage size, from 0-6MB. Note that the maximum size should be
-    // 5MB, but we add some slop since we want to make sure the max size is
-    // always above what we see in practice, since histograms can't change.
-    UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageSizeInKB",
-                                local_storage_size_kb, 1, 6 * 1024, 50);
-    if (local_storage_size_kb < 100) {
-      UMA_HISTOGRAM_TIMES(
-          "LocalStorage.BrowserTimeToPrimeLocalStorageUnder100KB",
-          time_to_prime);
-    } else if (local_storage_size_kb < 1000) {
-      UMA_HISTOGRAM_TIMES(
-          "LocalStorage.BrowserTimeToPrimeLocalStorage100KBTo1MB",
-          time_to_prime);
-    } else {
-      UMA_HISTOGRAM_TIMES("LocalStorage.BrowserTimeToPrimeLocalStorage1MBTo5MB",
-                          time_to_prime);
-    }
-  }
-
-  // Apply changes in reverse order of commit batches starting from the most
-  // recent commit batch with clear all flag. It is possible that the changes in
-  // one or more of the commit batches have already been written to the database
-  // and reflected in the map returned by ReadAllValues(). It is okay to
-  // re-apply these changes.
-  auto it = most_recent_clear_all_iter == commit_batches_.end()
-                ? commit_batches_.end()
-                : ++most_recent_clear_all_iter;
-  while (it != commit_batches_.begin()) {
-    --it;
-    for (const auto& item : it->batch->changed_values) {
-      if (item.second.is_null())
-        read_values.erase(item.first);
-      else
-        read_values[item.first] = item.second;
-    }
-  }
-
-  if (!IsMapReloadNeeded()) {
-    map->swap(read_values);
-    return;
-  }
-
-  map_ = new DOMStorageMap(
-      kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
-      desired_load_state_ == LOAD_STATE_KEYS_ONLY);
-  if (desired_load_state_ == LOAD_STATE_KEYS_ONLY) {
-    map_->TakeKeysFrom(read_values);
-    if (map)
-      map->swap(read_values);
-  } else {
-    map_->SwapValues(&read_values);
-    if (map)
-      map_->ExtractValues(map);
-  }
-  load_state_ = desired_load_state_;
-}
-
-DOMStorageArea::CommitBatch* DOMStorageArea::CreateCommitBatchIfNeeded() {
-  DCHECK(!is_shutdown_);
-  DCHECK(backing_);
-  if (!GetCurrentCommitBatch()) {
-    commit_batches_.emplace_front(CommitBatchHolder(
-        CommitBatchHolder::TYPE_CURRENT_BATCH, new CommitBatch()));
-    StartCommitTimer();
-  }
-  return GetCurrentCommitBatch()->batch.get();
-}
-
-const DOMStorageArea::CommitBatchHolder* DOMStorageArea::GetCurrentCommitBatch()
-    const {
-  return (!commit_batches_.empty() &&
-          commit_batches_.front().type == CommitBatchHolder::TYPE_CURRENT_BATCH)
-             ? &commit_batches_.front()
-             : nullptr;
-}
-
-bool DOMStorageArea::HasCommitBatchInFlight() const {
-  for (const auto& batch : commit_batches_) {
-    if (batch.type == CommitBatchHolder::TYPE_IN_FLIGHT)
-      return true;
-  }
-  return false;
-}
-
-void DOMStorageArea::PopulateCommitBatchValues() {
-  task_runner_->AssertIsRunningOnPrimarySequence();
-  if (load_state_ != LOAD_STATE_KEYS_AND_VALUES)
-    return;
-  CommitBatch* current_batch = GetCurrentCommitBatch()->batch.get();
-  for (auto& key_value : current_batch->changed_values)
-    key_value.second = map_->GetItem(key_value.first);
-}
-
-void DOMStorageArea::StartCommitTimer() {
-  if (is_shutdown_ || !GetCurrentCommitBatch())
-    return;
-
-  // Start a timer to commit any changes that accrue in the batch, but only if
-  // no commits are currently in flight. In that case the timer will be
-  // started after the commits have happened.
-  if (HasCommitBatchInFlight())
-    return;
-
-  task_runner_->PostDelayedTask(
-      FROM_HERE, base::BindOnce(&DOMStorageArea::OnCommitTimer, this),
-      ComputeCommitDelay());
-}
-
-base::TimeDelta DOMStorageArea::ComputeCommitDelay() const {
-  if (s_aggressive_flushing_enabled_)
-    return base::TimeDelta::FromSeconds(1);
-
-  // Delay for a moment after a value is set in anticipation
-  // of other values being set, so changes are batched.
-  static constexpr base::TimeDelta kCommitDefaultDelaySecs =
-      base::TimeDelta::FromSeconds(5);
-
-  base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time_;
-  base::TimeDelta delay =
-      std::max(kCommitDefaultDelaySecs,
-               std::max(commit_rate_limiter_.ComputeDelayNeeded(elapsed_time),
-                        data_rate_limiter_.ComputeDelayNeeded(elapsed_time)));
-  UMA_HISTOGRAM_LONG_TIMES("LocalStorage.CommitDelay", delay);
-  return delay;
-}
-
-void DOMStorageArea::OnCommitTimer() {
-  if (is_shutdown_)
-    return;
-
-  // It's possible that there is nothing to commit if an immediate
-  // commit occured after the timer was scheduled but before it fired.
-  if (!GetCurrentCommitBatch())
-    return;
-
-  PostCommitTask();
-}
-
-void DOMStorageArea::PostCommitTask() {
-  if (is_shutdown_ || !GetCurrentCommitBatch())
-    return;
-
-  DCHECK(backing_.get());
-  CommitBatchHolder& current_batch = commit_batches_.front();
-  PopulateCommitBatchValues();
-  current_batch.type = CommitBatchHolder::TYPE_IN_FLIGHT;
-
-  commit_rate_limiter_.add_samples(1);
-  data_rate_limiter_.add_samples(current_batch.batch->GetDataSize());
-
-  // This method executes on the primary sequence, we schedule
-  // a task for immediate execution on the commit sequence.
-  task_runner_->AssertIsRunningOnPrimarySequence();
-  bool success = task_runner_->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
-      base::BindOnce(&DOMStorageArea::CommitChanges, this,
-                     base::RetainedRef(current_batch.batch)));
-  DCHECK(success);
-}
-
-void DOMStorageArea::CommitChanges(const CommitBatch* commit_batch) {
-  // This method executes on the commit sequence.
-  task_runner_->AssertIsRunningOnCommitSequence();
-  backing_->CommitChanges(commit_batch->clear_all_first,
-                          commit_batch->changed_values);
-  // TODO(michaeln): what if CommitChanges returns false (e.g., we're trying to
-  // commit to a DB which is in an inconsistent state?)
-  task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&DOMStorageArea::OnCommitComplete, this));
-}
-
-void DOMStorageArea::OnCommitComplete() {
-  // We're back on the primary sequence in this method.
-  task_runner_->AssertIsRunningOnPrimarySequence();
-  if (is_shutdown_)
-    return;
-
-  DCHECK_EQ(CommitBatchHolder::TYPE_IN_FLIGHT, commit_batches_.back().type);
-  commit_batches_.pop_back();
-  if (GetCurrentCommitBatch() && !HasCommitBatchInFlight()) {
-    // More changes have accrued, restart the timer.
-    task_runner_->PostDelayedTask(
-        FROM_HERE, base::BindOnce(&DOMStorageArea::OnCommitTimer, this),
-        ComputeCommitDelay());
-  } else {
-    // When the desired load state is changed, the unload of map is deferred
-    // when there are uncommitted changes. So, try again after committing.
-    UnloadMapIfDesired();
-  }
-}
-
-void DOMStorageArea::ShutdownInCommitSequence() {
-  // This method executes on the commit sequence.
-  task_runner_->AssertIsRunningOnCommitSequence();
-  DCHECK(backing_.get());
-  if (GetCurrentCommitBatch()) {
-    CommitBatch* batch = GetCurrentCommitBatch()->batch.get();
-    // Commit any changes that accrued prior to the timer firing.
-    bool success =
-        backing_->CommitChanges(batch->clear_all_first, batch->changed_values);
-    DCHECK(success);
-  }
-  commit_batches_.clear();
-  backing_.reset();
-  session_storage_backing_ = nullptr;
-}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/dom_storage_area.h b/content/browser/dom_storage/dom_storage_area.h
deleted file mode 100644
index ad96a81e..0000000
--- a/content/browser/dom_storage/dom_storage_area.h
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2013 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_DOM_STORAGE_DOM_STORAGE_AREA_H_
-#define CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_AREA_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <list>
-#include <memory>
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/nullable_string16.h"
-#include "base/strings/string16.h"
-#include "content/common/content_export.h"
-#include "content/common/dom_storage/dom_storage_map.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-#include "url/origin.h"
-
-namespace base {
-namespace trace_event {
-class ProcessMemoryDump;
-}
-}
-
-namespace content {
-
-class DOMStorageDatabaseAdapter;
-class DOMStorageTaskRunner;
-class SessionStorageDatabase;
-
-// Container for a per-origin Map of key/value pairs potentially
-// backed by storage on disk and lazily commits changes to disk.
-// See class comments for DOMStorageContextImpl for a larger overview.
-class CONTENT_EXPORT DOMStorageArea
-    : public base::RefCountedThreadSafe<DOMStorageArea> {
-
- public:
-  static const base::FilePath::CharType kDatabaseFileExtension[];
-  static base::FilePath DatabaseFileNameFromOrigin(const url::Origin& origin);
-  static url::Origin OriginFromDatabaseFileName(
-      const base::FilePath& file_name);
-
-  // Commence aggressive flushing. This should be called early in the startup -
-  // before any localStorage writing. Currently scheduled writes will not be
-  // rescheduled and will be flushed at the scheduled time after which
-  // aggressive flushing will commence.
-  static void EnableAggressiveCommitDelay();
-
-  // Session storage. Backed on disk if |session_storage_backing| is not NULL.
-  DOMStorageArea(const std::string& namespace_id,
-                 std::vector<std::string> original_namespace_ids,
-                 const url::Origin& origin,
-                 SessionStorageDatabase* session_storage_backing,
-                 DOMStorageTaskRunner* task_runner);
-
-  const url::Origin& origin() const { return origin_; }
-  const std::string& namespace_id() const { return namespace_id_; }
-  size_t map_memory_used() const { return map_ ? map_->memory_used() : 0; }
-
-  // Writes a copy of the current set of values in the area to the |map|.
-  void ExtractValues(DOMStorageValuesMap* map);
-
-  unsigned Length();
-  base::NullableString16 Key(unsigned index);
-  base::NullableString16 GetItem(const base::string16& key);
-  bool SetItem(const base::string16& key,
-               const base::string16& value,
-               const base::NullableString16& client_old_value,
-               base::NullableString16* old_value);
-  bool RemoveItem(const base::string16& key,
-                  const base::NullableString16& client_old_value,
-                  base::string16* old_value);
-  bool Clear();
-  void FastClear();
-
-  DOMStorageArea* ShallowCopy(const std::string& destination_namespace_id);
-
-  bool HasUncommittedChanges() const;
-  void ScheduleImmediateCommit();
-  void ClearShallowCopiedCommitBatches();
-
-  // Stores only the keys in the in-memory cache when set to true. Changing this
-  // behavior will reload the cache only when needed and not immediately.
-  // Note: Do not use ExtractValues() frequently since will have a disk access
-  // when only keys are stored.
-  void SetCacheOnlyKeys(bool value);
-
-  // Frees up memory when possible. Typically, this method returns
-  // the object to its just constructed state, however if uncommitted
-  // changes are pending, it does nothing.
-  void PurgeMemory();
-
-  // Schedules the commit of any unsaved changes and enters a
-  // shutdown state such that the value getters and setters will
-  // no longer do anything.
-  void Shutdown();
-
-  // Returns true if data needs to be loaded in memory.
-  bool IsMapReloadNeeded();
-
-  // Adds memory statistics to |pmd| for chrome://tracing.
-  void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd);
-
- private:
-  friend class DOMStorageAreaTest;
-  friend class DOMStorageAreaMock;
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaParamTest, DOMStorageAreaBasics);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaTest, BackingDatabaseOpened);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaParamTest, ShallowCopyWithBacking);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaTest, SetCacheOnlyKeysWithoutBacking);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaTest, SetCacheOnlyKeysWithBacking);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaTest, TestDatabaseFilePath);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaParamTest, CommitTasks);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaParamTest,
-                           ChangesDuringInflightCommitGetCommitted);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaParamTest, CommitChangesAtShutdown);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaParamTest, PurgeMemory);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageAreaTest, RateLimiter);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageContextImplTest, PersistentIds);
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageContextImplTest, PurgeMemory);
-  friend class base::RefCountedThreadSafe<DOMStorageArea>;
-
-  enum LoadState {
-    LOAD_STATE_UNLOADED = 0,
-    LOAD_STATE_KEYS_ONLY = 1,
-    LOAD_STATE_KEYS_AND_VALUES = 2
-  };
-
-  // Used to rate limit commits.
-  class CONTENT_EXPORT RateLimiter {
-   public:
-    RateLimiter(size_t desired_rate, base::TimeDelta time_quantum);
-
-    void add_samples(size_t samples) {
-      samples_ += samples;
-    }
-
-    // Computes the total time needed to process the total samples seen
-    // at the desired rate.
-    base::TimeDelta ComputeTimeNeeded() const;
-
-    // Given the elapsed time since the start of the rate limiting session,
-    // computes the delay needed to mimic having processed the total samples
-    // seen at the desired rate.
-    base::TimeDelta ComputeDelayNeeded(
-        const base::TimeDelta elapsed_time) const;
-
-   private:
-    float rate_;
-    float samples_;
-    base::TimeDelta time_quantum_;
-  };
-
-  struct CONTENT_EXPORT CommitBatch
-      : public base::RefCountedThreadSafe<CommitBatch> {
-    bool clear_all_first;
-    DOMStorageValuesMap changed_values;
-
-    CommitBatch();
-    size_t GetDataSize() const;
-
-   private:
-    friend class base::RefCountedThreadSafe<CommitBatch>;
-    ~CommitBatch();
-  };
-
-  struct CONTENT_EXPORT CommitBatchHolder {
-    enum Type { TYPE_CURRENT_BATCH, TYPE_IN_FLIGHT, TYPE_CLONE };
-    Type type;
-    scoped_refptr<CommitBatch> batch;
-
-    CommitBatchHolder(Type, scoped_refptr<CommitBatch>);
-    CommitBatchHolder(const CommitBatchHolder& other);
-    ~CommitBatchHolder();
-  };
-
-  virtual ~DOMStorageArea();
-
-  // Loads the map for this origin into the |map_| if desired load state is not
-  // met and into the |map| if it's not null.
-  void LoadMapAndApplyUncommittedChangesIfNeeded(DOMStorageValuesMap* map);
-
-  // If the cache state is inconsistent with the map storage, purges the map and
-  // updates with new data if possible without reading from database. Noop if
-  // the area has uncommitted changes.
-  void UnloadMapIfDesired();
-
-  // Post tasks to defer writing a batch of changed values to
-  // disk on the commit sequence, and to call back on the primary
-  // task sequence when complete.
-  CommitBatch* CreateCommitBatchIfNeeded();
-  const CommitBatchHolder* GetCurrentCommitBatch() const;
-  bool HasCommitBatchInFlight() const;
-  void PopulateCommitBatchValues();
-  void StartCommitTimer();
-  virtual void OnCommitTimer();
-  void PostCommitTask();
-  void CommitChanges(const CommitBatch* commit_batch);
-  void OnCommitComplete();
-  base::TimeDelta ComputeCommitDelay() const;
-
-  void ShutdownInCommitSequence();
-
-  static bool s_aggressive_flushing_enabled_;
-
-  std::string namespace_id_;
-  std::vector<std::string> original_namespace_ids_;
-  url::Origin origin_;
-  scoped_refptr<DOMStorageTaskRunner> task_runner_;
-  LoadState desired_load_state_;
-  LoadState load_state_;
-  scoped_refptr<DOMStorageMap> map_;
-  std::unique_ptr<DOMStorageDatabaseAdapter> backing_;
-  scoped_refptr<SessionStorageDatabase> session_storage_backing_;
-  bool is_shutdown_;
-  std::list<CommitBatchHolder> commit_batches_;
-  base::TimeTicks start_time_;
-  RateLimiter data_rate_limiter_;
-  RateLimiter commit_rate_limiter_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMStorageArea);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_AREA_H_
diff --git a/content/browser/dom_storage/dom_storage_area_unittest.cc b/content/browser/dom_storage/dom_storage_area_unittest.cc
deleted file mode 100644
index f638eeb0..0000000
--- a/content/browser/dom_storage/dom_storage_area_unittest.cc
+++ /dev/null
@@ -1,607 +0,0 @@
-// Copyright 2013 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 <stddef.h>
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
-#include "content/browser/dom_storage/dom_storage_database_adapter.h"
-#include "content/browser/dom_storage/dom_storage_task_runner.h"
-#include "content/browser/dom_storage/session_storage_database.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/origin.h"
-
-using base::ASCIIToUTF16;
-using ::testing::Invoke;
-
-namespace content {
-
-class DOMStorageAreaMock : public DOMStorageArea {
- public:
-  DOMStorageAreaMock(const std::string& namespace_id,
-                     std::vector<std::string> original_namespace_ids,
-                     const url::Origin& origin,
-                     SessionStorageDatabase* session_storage_backing,
-                     DOMStorageTaskRunner* task_runner)
-      : DOMStorageArea(namespace_id,
-                       std::move(original_namespace_ids),
-                       origin,
-                       session_storage_backing,
-                       task_runner) {}
-
-  MOCK_METHOD0(AfterOnCommitTimerCalled, void());
-
-  void ReadAllValuesFromBackingStore(DOMStorageValuesMap* result) {
-    backing_->ReadAllValues(result);
-  }
-
- private:
-  ~DOMStorageAreaMock() override {}
-
-  void OnCommitTimer() override {
-    DOMStorageArea::OnCommitTimer();
-    AfterOnCommitTimerCalled();
-  }
-};
-
-class DOMStorageAreaTest : public testing::Test {
- public:
-  DOMStorageAreaTest()
-      : kOrigin(url::Origin::Create(GURL("http://dom_storage/"))),
-        kKey(ASCIIToUTF16("key")),
-        kValue(ASCIIToUTF16("value")),
-        kKey2(ASCIIToUTF16("key2")),
-        kValue2(ASCIIToUTF16("value2")) {}
-
-  const url::Origin kOrigin;
-  const base::string16 kKey;
-  const base::string16 kValue;
-  const base::string16 kKey2;
-  const base::string16 kValue2;
-
- protected:
-  TestBrowserThreadBundle test_browser_thread_bundle_;
-};
-
-class DOMStorageAreaParamTest : public DOMStorageAreaTest,
-                                public testing::WithParamInterface<bool> {
- public:
-  DOMStorageAreaParamTest() {}
-  ~DOMStorageAreaParamTest() override {}
-};
-
-INSTANTIATE_TEST_SUITE_P(_, DOMStorageAreaParamTest, ::testing::Bool());
-
-TEST_P(DOMStorageAreaParamTest, DOMStorageAreaBasics) {
-  const std::string kFirstNamespaceId = "id1";
-  const std::string kSecondNamespaceId = "id2";
-  scoped_refptr<DOMStorageArea> area(
-      new DOMStorageArea(kFirstNamespaceId, std::vector<std::string>(), kOrigin,
-                         nullptr, nullptr));
-  const bool values_cached = GetParam();
-  area->SetCacheOnlyKeys(!values_cached);
-  base::string16 old_value;
-  base::NullableString16 old_nullable_value;
-  scoped_refptr<DOMStorageArea> copy;
-
-  // We don't focus on the underlying DOMStorageMap functionality
-  // since that's covered by seperate unit tests.
-  EXPECT_EQ(kOrigin, area->origin());
-  EXPECT_EQ(kFirstNamespaceId, area->namespace_id());
-  EXPECT_EQ(0u, area->Length());
-  EXPECT_TRUE(
-      area->SetItem(kKey, kValue, old_nullable_value, &old_nullable_value));
-  EXPECT_TRUE(
-      area->SetItem(kKey2, kValue2, old_nullable_value, &old_nullable_value));
-  EXPECT_FALSE(area->HasUncommittedChanges());
-
-  // Verify that a copy shares the same map.
-  copy = area->ShallowCopy(kSecondNamespaceId);
-  EXPECT_EQ(kOrigin, copy->origin());
-  EXPECT_EQ(kSecondNamespaceId, copy->namespace_id());
-  EXPECT_EQ(area->Length(), copy->Length());
-  if (values_cached)
-    EXPECT_EQ(area->GetItem(kKey).string(), copy->GetItem(kKey).string());
-  EXPECT_EQ(area->Key(0).string(), copy->Key(0).string());
-  EXPECT_EQ(copy->map_.get(), area->map_.get());
-  copy->ClearShallowCopiedCommitBatches();
-
-  // But will deep copy-on-write as needed.
-  old_nullable_value = base::NullableString16(kValue, false);
-  EXPECT_TRUE(area->RemoveItem(kKey, old_nullable_value, &old_value));
-  EXPECT_EQ(kValue, old_value);
-  EXPECT_NE(copy->map_.get(), area->map_.get());
-  copy = area->ShallowCopy(kSecondNamespaceId);
-  EXPECT_EQ(copy->map_.get(), area->map_.get());
-  EXPECT_TRUE(
-      area->SetItem(kKey, kValue, old_nullable_value, &old_nullable_value));
-  EXPECT_NE(copy->map_.get(), area->map_.get());
-  copy = area->ShallowCopy(kSecondNamespaceId);
-  EXPECT_EQ(copy->map_.get(), area->map_.get());
-  EXPECT_NE(0u, area->Length());
-  EXPECT_TRUE(area->Clear());
-  EXPECT_EQ(0u, area->Length());
-  EXPECT_NE(copy->map_.get(), area->map_.get());
-
-  // Verify that once Shutdown(), behaves that way.
-  area->Shutdown();
-  EXPECT_TRUE(area->is_shutdown_);
-  EXPECT_FALSE(area->map_.get());
-  EXPECT_EQ(0u, area->Length());
-  EXPECT_TRUE(area->Key(0).is_null());
-  if (values_cached)
-    EXPECT_TRUE(area->GetItem(kKey).is_null());
-  EXPECT_FALSE(
-      area->SetItem(kKey, kValue, old_nullable_value, &old_nullable_value));
-  EXPECT_FALSE(area->RemoveItem(kKey, old_nullable_value, &old_value));
-  EXPECT_FALSE(area->Clear());
-}
-
-TEST_F(DOMStorageAreaTest, BackingDatabaseOpened) {
-  const std::string kSessionStorageNamespaceId = "id1";
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  const base::FilePath kExpectedOriginFilePath = temp_dir.GetPath().Append(
-      DOMStorageArea::DatabaseFileNameFromOrigin(kOrigin));
-
-  // Valid directory and origin but no session storage backing. Backing should
-  // be null.
-  {
-    scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
-        kSessionStorageNamespaceId, std::vector<std::string>(), kOrigin,
-        nullptr, nullptr));
-    EXPECT_EQ(nullptr, area->backing_.get());
-
-    base::NullableString16 old_value;
-    EXPECT_TRUE(area->SetItem(kKey, kValue, old_value, &old_value));
-    ASSERT_TRUE(old_value.is_null());
-
-    // Check that saving a value has still left us without a backing database.
-    EXPECT_EQ(nullptr, area->backing_.get());
-    EXPECT_FALSE(base::PathExists(kExpectedOriginFilePath));
-  }
-}
-
-TEST_P(DOMStorageAreaParamTest, ShallowCopyWithBacking) {
-  const std::string kFirstNamespaceId = "id1";
-  const std::string kSecondNamespaceId = "id2";
-  const std::string kThirdNamespaceId = "id3";
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  scoped_refptr<SessionStorageDatabase> db = new SessionStorageDatabase(
-      temp_dir.GetPath(), base::ThreadTaskRunnerHandle::Get());
-  scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
-      kFirstNamespaceId, std::vector<std::string>(), kOrigin, db.get(),
-      new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
-  EXPECT_TRUE(area->backing_.get());
-  EXPECT_TRUE(area->session_storage_backing_);
-  const bool values_cached = GetParam();
-  area->SetCacheOnlyKeys(!values_cached);
-
-  scoped_refptr<DOMStorageArea> temp_copy;
-  temp_copy = area->ShallowCopy(kSecondNamespaceId);
-  EXPECT_TRUE(temp_copy->commit_batches_.empty());
-  temp_copy->ClearShallowCopiedCommitBatches();
-
-  // Check if shallow copy is consistent.
-  base::string16 old_value;
-  base::NullableString16 old_nullable_value;
-  scoped_refptr<DOMStorageArea> copy;
-  EXPECT_TRUE(
-      area->SetItem(kKey, kValue, old_nullable_value, &old_nullable_value));
-  EXPECT_TRUE(area->HasUncommittedChanges());
-  EXPECT_EQ(DOMStorageArea::CommitBatchHolder::TYPE_CURRENT_BATCH,
-            area->commit_batches_.front().type);
-  copy = area->ShallowCopy(kThirdNamespaceId);
-  EXPECT_EQ(copy->map_.get(), area->map_.get());
-  EXPECT_EQ(1u, copy->original_namespace_ids_.size());
-  EXPECT_EQ(kFirstNamespaceId, copy->original_namespace_ids_[0]);
-  if (!values_cached) {
-    EXPECT_EQ(area->commit_batches_.front().batch,
-              copy->commit_batches_.front().batch);
-    EXPECT_EQ(DOMStorageArea::CommitBatchHolder::TYPE_IN_FLIGHT,
-              area->commit_batches_.front().type);
-    EXPECT_EQ(DOMStorageArea::CommitBatchHolder::TYPE_CLONE,
-              copy->commit_batches_.front().type);
-  } else {
-    EXPECT_TRUE(copy->commit_batches_.empty());
-  }
-
-  DOMStorageValuesMap map;
-  copy->ExtractValues(&map);
-  EXPECT_EQ(1u, map.size());
-  EXPECT_EQ(kValue, map[kKey].string());
-
-  // Check if copy on write works.
-  EXPECT_TRUE(
-      copy->SetItem(kKey2, kValue2, old_nullable_value, &old_nullable_value));
-  EXPECT_TRUE(copy->GetCurrentCommitBatch());
-  EXPECT_FALSE(copy->commit_batches_.front().type);
-  if (!values_cached)
-    EXPECT_EQ(DOMStorageArea::CommitBatchHolder::TYPE_CLONE,
-              copy->commit_batches_.back().type);
-  else
-    EXPECT_FALSE(copy->HasCommitBatchInFlight());
-  EXPECT_EQ(1u, area->Length());
-
-  // Check clearing of cloned batches.
-  area->ClearShallowCopiedCommitBatches();
-  copy->ClearShallowCopiedCommitBatches();
-  EXPECT_EQ(DOMStorageArea::CommitBatchHolder::TYPE_IN_FLIGHT,
-            area->commit_batches_.front().type);
-  EXPECT_FALSE(copy->HasCommitBatchInFlight());
-}
-
-TEST_F(DOMStorageAreaTest, SetCacheOnlyKeysWithoutBacking) {
-  const std::string kFirstNamespaceId = "id1";
-  scoped_refptr<DOMStorageArea> area(
-      new DOMStorageArea(kFirstNamespaceId, std::vector<std::string>(), kOrigin,
-                         nullptr, nullptr));
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_AND_VALUES,
-            area->desired_load_state_);
-  EXPECT_FALSE(area->map_->has_only_keys());
-  base::NullableString16 old_value;
-  EXPECT_TRUE(area->SetItem(kKey, kValue, old_value, &old_value));
-  DOMStorageValuesMap map;
-  area->ExtractValues(&map);
-  EXPECT_EQ(1u, map.size());
-
-  area->SetCacheOnlyKeys(true);
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_AND_VALUES,
-            area->desired_load_state_);  // cannot be disabled without backing.
-  area->SetItem(kKey, kValue2, old_value, &old_value);
-  EXPECT_FALSE(area->map_->has_only_keys());
-  EXPECT_EQ(kValue, old_value.string());
-  area->ExtractValues(&map);
-  EXPECT_EQ(kValue2, map[kKey].string());
-  EXPECT_EQ(1u, map.size());
-}
-
-TEST_F(DOMStorageAreaTest, SetCacheOnlyKeysWithBacking) {
-  const std::string kNamespaceId = "id1";
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  scoped_refptr<SessionStorageDatabase> db = new SessionStorageDatabase(
-      temp_dir.GetPath(), base::ThreadTaskRunnerHandle::Get());
-  scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
-      kNamespaceId, std::vector<std::string>(), kOrigin, db.get(),
-      new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
-
-  EXPECT_TRUE(area->backing_.get());
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_UNLOADED, area->load_state_);
-
-#if !defined(OS_ANDROID)
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_AND_VALUES,
-            area->desired_load_state_);
-  area->SetCacheOnlyKeys(true);
-#endif
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_ONLY, area->desired_load_state_);
-  base::NullableString16 old_value;
-  EXPECT_TRUE(area->SetItem(kKey, kValue, old_value, &old_value));
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_ONLY, area->load_state_);
-  EXPECT_TRUE(area->GetCurrentCommitBatch());
-
-  base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(area->GetCurrentCommitBatch());
-  EXPECT_EQ(1u, area->Length());
-
-  // Fill the current batch and in flight batch.
-  EXPECT_TRUE(area->SetItem(kKey2, kValue, old_value, &old_value));
-  area->PostCommitTask();
-  EXPECT_FALSE(area->GetCurrentCommitBatch());
-  EXPECT_TRUE(area->HasCommitBatchInFlight());
-  EXPECT_TRUE(area->SetItem(kKey2, kValue2, old_value, &old_value));
-  EXPECT_TRUE(area->GetCurrentCommitBatch());
-
-  // The values must be imported from the backing, and from the commit batches.
-  area->SetCacheOnlyKeys(false);
-  EXPECT_EQ(2u, area->Length());
-  EXPECT_EQ(kValue, area->GetItem(kKey).string());
-  EXPECT_EQ(kValue2, area->GetItem(kKey2).string());
-
-  // Check if disabling cache clears the cache after committing only.
-  area->SetCacheOnlyKeys(true);
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_ONLY, area->desired_load_state_);
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_AND_VALUES, area->load_state_);
-  ASSERT_FALSE(area->map_->has_only_keys());
-
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_ONLY, area->load_state_);
-  EXPECT_TRUE(area->map_->has_only_keys());
-  EXPECT_FALSE(area->HasCommitBatchInFlight());
-
-  // Check if Clear() works as expected when values are desired.
-  area->Clear();
-  EXPECT_TRUE(area->SetItem(kKey2, kValue2, old_value, &old_value));
-  area->PostCommitTask();
-  EXPECT_TRUE(area->SetItem(kKey, kValue, old_value, &old_value));
-  EXPECT_EQ(2u, area->Length());
-  area->Clear();
-  EXPECT_TRUE(area->SetItem(kKey2, kValue, old_value, &old_value));
-  EXPECT_TRUE(area->GetCurrentCommitBatch()->batch->clear_all_first);
-  EXPECT_TRUE(area->commit_batches_.back().batch->clear_all_first);
-  area->SetCacheOnlyKeys(false);
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_ONLY, area->load_state_);
-
-  // Unload only after commit.
-  base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_UNLOADED, area->load_state_);
-  EXPECT_EQ(1u, area->Length());
-  EXPECT_EQ(kValue, area->GetItem(kKey2).string());
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_KEYS_AND_VALUES, area->load_state_);
-}
-
-TEST_P(DOMStorageAreaParamTest, CommitTasks) {
-  const std::string kNamespaceId = "id1";
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  scoped_refptr<SessionStorageDatabase> db = new SessionStorageDatabase(
-      temp_dir.GetPath(), base::ThreadTaskRunnerHandle::Get());
-  scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
-      kNamespaceId, std::vector<std::string>(), kOrigin, db.get(),
-      new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
-
-  area->SetCacheOnlyKeys(GetParam());
-
-  // Unrelated to commits, but while we're here, see that querying Length()
-  // causes the backing database to be opened and presumably read from.
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_UNLOADED, area->load_state_);
-  EXPECT_EQ(0u, area->Length());
-  EXPECT_EQ(area->desired_load_state_, area->load_state_);
-
-  DOMStorageValuesMap values;
-  base::NullableString16 old_value;
-
-  // See that changes are batched up.
-  EXPECT_FALSE(area->GetCurrentCommitBatch());
-  EXPECT_TRUE(area->SetItem(kKey, kValue, old_value, &old_value));
-  EXPECT_TRUE(area->HasUncommittedChanges());
-  EXPECT_TRUE(area->GetCurrentCommitBatch());
-  EXPECT_FALSE(area->GetCurrentCommitBatch()->batch->clear_all_first);
-  EXPECT_EQ(1u, area->GetCurrentCommitBatch()->batch->changed_values.size());
-  EXPECT_TRUE(area->SetItem(kKey2, kValue2, old_value, &old_value));
-  EXPECT_FALSE(area->GetCurrentCommitBatch()->batch->clear_all_first);
-  EXPECT_EQ(2u, area->GetCurrentCommitBatch()->batch->changed_values.size());
-  base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(area->HasUncommittedChanges());
-  EXPECT_FALSE(area->GetCurrentCommitBatch());
-  EXPECT_FALSE(area->HasCommitBatchInFlight());
-  // Verify the changes made it to the database.
-  values.clear();
-  area->backing_->ReadAllValues(&values);
-  EXPECT_EQ(2u, values.size());
-  EXPECT_EQ(kValue, values[kKey].string());
-  EXPECT_EQ(kValue2, values[kKey2].string());
-
-  // See that clear is handled properly.
-  EXPECT_TRUE(area->Clear());
-  EXPECT_TRUE(area->GetCurrentCommitBatch());
-  EXPECT_TRUE(area->GetCurrentCommitBatch()->batch->clear_all_first);
-  EXPECT_TRUE(area->GetCurrentCommitBatch()->batch->changed_values.empty());
-  base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(area->GetCurrentCommitBatch());
-  EXPECT_FALSE(area->HasCommitBatchInFlight());
-  // Verify the changes made it to the database.
-  values.clear();
-  area->backing_->ReadAllValues(&values);
-  EXPECT_TRUE(values.empty());
-}
-
-TEST_P(DOMStorageAreaParamTest, ChangesDuringInflightCommitGetCommitted) {
-  const std::string kNamespaceId = "id1";
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  scoped_refptr<SessionStorageDatabase> db = new SessionStorageDatabase(
-      temp_dir.GetPath(), base::ThreadTaskRunnerHandle::Get());
-  scoped_refptr<DOMStorageAreaMock> area(new DOMStorageAreaMock(
-      kNamespaceId, std::vector<std::string>(), kOrigin, db.get(),
-      new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
-  area->SetCacheOnlyKeys(GetParam());
-
-  DOMStorageValuesMap values;
-  base::NullableString16 old_value;
-
-  EXPECT_CALL(*area, AfterOnCommitTimerCalled)
-      .WillOnce(Invoke([&]() {
-        // At this point the OnCommitTimer has run.
-        // Verify that it put a commit in flight.
-        EXPECT_TRUE(area->HasCommitBatchInFlight());
-        EXPECT_FALSE(area->GetCurrentCommitBatch());
-        EXPECT_TRUE(area->HasUncommittedChanges());
-        // Make additional change and verify that a new commit batch
-        // is created for that change.
-        base::NullableString16 old_value;
-        EXPECT_TRUE(area->SetItem(kKey2, kValue2, old_value, &old_value));
-        EXPECT_TRUE(area->GetCurrentCommitBatch());
-        EXPECT_TRUE(area->HasCommitBatchInFlight());
-        EXPECT_TRUE(area->HasUncommittedChanges());
-      }))
-      .WillOnce(Invoke([&]() {
-        // At this point the OnCommitTimer has run.
-        // Verify that it put a commit in flight.
-        EXPECT_TRUE(area->HasCommitBatchInFlight());
-        EXPECT_FALSE(area->GetCurrentCommitBatch());
-        EXPECT_TRUE(area->HasUncommittedChanges());
-      }));
-
-  // See that if changes accrue while a commit is "in flight"
-  // those will also get committed.
-  EXPECT_TRUE(area->SetItem(kKey, kValue, old_value, &old_value));
-  EXPECT_TRUE(area->HasUncommittedChanges());
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(area->HasOneRef());
-  EXPECT_FALSE(area->HasUncommittedChanges());
-  // Verify the changes made it to the database.
-  values.clear();
-  area->ReadAllValuesFromBackingStore(&values);
-  EXPECT_EQ(2u, values.size());
-  EXPECT_EQ(kValue, values[kKey].string());
-  EXPECT_EQ(kValue2, values[kKey2].string());
-}
-
-TEST_P(DOMStorageAreaParamTest, CommitChangesAtShutdown) {
-  const std::string kNamespaceId = "id1";
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  scoped_refptr<SessionStorageDatabase> db = new SessionStorageDatabase(
-      temp_dir.GetPath(), base::ThreadTaskRunnerHandle::Get());
-  scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
-      kNamespaceId, std::vector<std::string>(), kOrigin, db.get(),
-      new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
-
-  area->SetCacheOnlyKeys(GetParam());
-
-  DOMStorageValuesMap values;
-  base::NullableString16 old_value;
-  EXPECT_TRUE(area->SetItem(kKey, kValue, old_value, &old_value));
-  EXPECT_TRUE(area->HasUncommittedChanges());
-  area->backing_->ReadAllValues(&values);
-  EXPECT_TRUE(values.empty());  // not committed yet
-  area->Shutdown();
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(area->HasOneRef());
-  EXPECT_FALSE(area->backing_.get());
-
-  // Verify changes were committed.
-  db->ReadAreaValues(kNamespaceId, std::vector<std::string>(), kOrigin,
-                     &values);
-  EXPECT_EQ(1u, values.size());
-  EXPECT_EQ(kValue, values[kKey].string());
-
-  // A second Shutdown call should be safe.
-  area->Shutdown();
-}
-
-TEST_P(DOMStorageAreaParamTest, PurgeMemory) {
-  const std::string kNamespaceId = "id1";
-  base::ScopedTempDir temp_dir;
-  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-  scoped_refptr<SessionStorageDatabase> db = new SessionStorageDatabase(
-      temp_dir.GetPath(), base::ThreadTaskRunnerHandle::Get());
-  scoped_refptr<DOMStorageArea> area(new DOMStorageArea(
-      kNamespaceId, std::vector<std::string>(), kOrigin, db.get(),
-      new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get())));
-  area->SetCacheOnlyKeys(GetParam());
-
-  // Unowned ptr we use to verify that 'purge' has happened.
-  DOMStorageMap* original_map = area->map_.get();
-
-  // Should do no harm when called on a newly constructed object.
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_UNLOADED, area->load_state_);
-  area->PurgeMemory();
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_UNLOADED, area->load_state_);
-  EXPECT_EQ(original_map, area->map_.get());
-
-  // Should not do anything when commits are pending.
-  base::NullableString16 old_value;
-  area->SetItem(kKey, kValue, old_value, &old_value);
-  original_map = area->map_.get();  // importing creates new map.
-  EXPECT_EQ(area->desired_load_state_, area->load_state_);
-  EXPECT_TRUE(area->HasUncommittedChanges());
-  area->PurgeMemory();
-  EXPECT_EQ(area->desired_load_state_, area->load_state_);
-  EXPECT_TRUE(area->HasUncommittedChanges());
-  EXPECT_EQ(original_map, area->map_.get());
-
-  // Commit the changes from above,
-  base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(area->HasUncommittedChanges());
-  EXPECT_EQ(original_map, area->map_.get());
-
-  // Should drop caches and reset database connections
-  // when invoked on an area that's loaded up primed.
-  area->PurgeMemory();
-  EXPECT_EQ(DOMStorageArea::LOAD_STATE_UNLOADED, area->load_state_);
-  EXPECT_NE(original_map, area->map_.get());
-}
-
-TEST_F(DOMStorageAreaTest, DatabaseFileNames) {
-  struct {
-    const char* origin;
-    const char* file_name;
-  } kCases[] = {
-      {"https://www.google.com/", "https_www.google.com_0.localstorage"},
-      {"http://www.google.com:8080/", "http_www.google.com_8080.localstorage"},
-      {"file:///", "file__0.localstorage"},
-  };
-
-  for (size_t i = 0; i < base::size(kCases); ++i) {
-    url::Origin origin =
-        url::Origin::Create(GURL(kCases[i].origin).GetOrigin());
-    base::FilePath file_name =
-        base::FilePath().AppendASCII(kCases[i].file_name);
-
-    EXPECT_EQ(file_name,
-              DOMStorageArea::DatabaseFileNameFromOrigin(origin));
-    EXPECT_EQ(origin,
-              DOMStorageArea::OriginFromDatabaseFileName(file_name));
-  }
-}
-
-TEST_F(DOMStorageAreaTest, RateLimiter) {
-  // Limit to 1000 samples per second
-  DOMStorageArea::RateLimiter rate_limiter(
-      1000, base::TimeDelta::FromSeconds(1));
-
-  // No samples have been added so no time/delay should be needed.
-  EXPECT_EQ(base::TimeDelta(),
-            rate_limiter.ComputeTimeNeeded());
-  EXPECT_EQ(base::TimeDelta(),
-            rate_limiter.ComputeDelayNeeded(base::TimeDelta()));
-  EXPECT_EQ(base::TimeDelta(),
-            rate_limiter.ComputeDelayNeeded(base::TimeDelta::FromDays(1)));
-
-  // Add a seconds worth of samples.
-  rate_limiter.add_samples(1000);
-  EXPECT_EQ(base::TimeDelta::FromSeconds(1),
-            rate_limiter.ComputeTimeNeeded());
-  EXPECT_EQ(base::TimeDelta::FromSeconds(1),
-            rate_limiter.ComputeDelayNeeded(base::TimeDelta()));
-  EXPECT_EQ(base::TimeDelta(),
-            rate_limiter.ComputeDelayNeeded(base::TimeDelta::FromSeconds(1)));
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(250),
-            rate_limiter.ComputeDelayNeeded(
-                base::TimeDelta::FromMilliseconds(750)));
-  EXPECT_EQ(base::TimeDelta(),
-            rate_limiter.ComputeDelayNeeded(
-                base::TimeDelta::FromDays(1)));
-
-  // And another half seconds worth.
-  rate_limiter.add_samples(500);
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
-            rate_limiter.ComputeTimeNeeded());
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(1500),
-            rate_limiter.ComputeDelayNeeded(base::TimeDelta()));
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(500),
-            rate_limiter.ComputeDelayNeeded(base::TimeDelta::FromSeconds(1)));
-  EXPECT_EQ(base::TimeDelta::FromMilliseconds(750),
-            rate_limiter.ComputeDelayNeeded(
-                base::TimeDelta::FromMilliseconds(750)));
-  EXPECT_EQ(base::TimeDelta(),
-            rate_limiter.ComputeDelayNeeded(
-                base::TimeDelta::FromMilliseconds(1500)));
-  EXPECT_EQ(base::TimeDelta(),
-            rate_limiter.ComputeDelayNeeded(
-                base::TimeDelta::FromDays(1)));
-}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/dom_storage_browsertest.cc b/content/browser/dom_storage/dom_storage_browsertest.cc
index 6d1d861b..fe6046b 100644
--- a/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -6,12 +6,10 @@
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_restrictions.h"
 #include "build/build_config.h"
 #include "components/services/leveldb/public/cpp/util.h"
 #include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
 #include "content/browser/dom_storage/dom_storage_database.h"
 #include "content/browser/dom_storage/dom_storage_task_runner.h"
@@ -192,7 +190,7 @@
 
 IN_PROC_BROWSER_TEST_F(DOMStorageBrowserTest, DataMigrates) {
   base::FilePath db_path = legacy_localstorage_path().Append(
-      DOMStorageArea::DatabaseFileNameFromOrigin(
+      LocalStorageContextMojo::LegacyDatabaseFileNameFromOrigin(
           url::Origin::Create(GetTestUrl("dom_storage", "store_data.html"))));
   {
     base::ScopedAllowBlockingForTesting allow_blocking;
diff --git a/content/browser/dom_storage/dom_storage_context_impl.cc b/content/browser/dom_storage/dom_storage_context_impl.cc
deleted file mode 100644
index 78ade68..0000000
--- a/content/browser/dom_storage/dom_storage_context_impl.cc
+++ /dev/null
@@ -1,499 +0,0 @@
-// Copyright (c) 2012 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/dom_storage/dom_storage_context_impl.h"
-
-#include <inttypes.h>
-#include <stddef.h>
-#include <stdlib.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_util.h"
-#include "base/guid.h"
-#include "base/location.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/system/sys_info.h"
-#include "base/time/time.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
-#include "content/browser/dom_storage/dom_storage_database.h"
-#include "content/browser/dom_storage/dom_storage_namespace.h"
-#include "content/browser/dom_storage/dom_storage_task_runner.h"
-#include "content/browser/dom_storage/session_storage_database.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-#include "content/public/browser/dom_storage_context.h"
-#include "content/public/browser/session_storage_usage_info.h"
-#include "content/public/browser/storage_usage_info.h"
-#include "storage/browser/quota/special_storage_policy.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-namespace content {
-namespace {
-
-// Limits on the cache size and number of areas in memory, over which the areas
-// are purged.
-#if defined(OS_ANDROID)
-const unsigned kMaxDomStorageAreaCount = 20;
-const size_t kMaxDomStorageCacheSize = 2 * 1024 * 1024;
-#else
-const unsigned kMaxDomStorageAreaCount = 100;
-const size_t kMaxDomStorageCacheSize = 20 * 1024 * 1024;
-#endif
-
-const int kSessionStoraceScavengingSeconds = 60;
-
-// Aggregates statistics from all the namespaces.
-DOMStorageNamespace::UsageStatistics GetTotalNamespaceStatistics(
-    const DOMStorageContextImpl::StorageNamespaceMap& namespace_map) {
-  DOMStorageNamespace::UsageStatistics total_stats = {0};
-  for (const auto& it : namespace_map) {
-    DOMStorageNamespace::UsageStatistics stats =
-        it.second->GetUsageStatistics();
-    total_stats.total_cache_size += stats.total_cache_size;
-    total_stats.total_area_count += stats.total_area_count;
-    total_stats.inactive_area_count += stats.inactive_area_count;
-  }
-  return total_stats;
-}
-
-}  // namespace
-
-DOMStorageContextImpl::DOMStorageContextImpl(
-    const base::FilePath& sessionstorage_directory,
-    storage::SpecialStoragePolicy* special_storage_policy,
-    scoped_refptr<DOMStorageTaskRunner> task_runner)
-    : sessionstorage_directory_(sessionstorage_directory),
-      task_runner_(std::move(task_runner)),
-      is_shutdown_(false),
-      force_keep_session_state_(false),
-      special_storage_policy_(special_storage_policy),
-      scavenging_started_(false),
-      is_low_end_device_(base::SysInfo::IsLowEndDevice()) {
-  // Tests may run without task runners.
-  if (task_runner_) {
-    // Registering dump provider is safe even outside the task runner.
-    base::trace_event::MemoryDumpManager::GetInstance()
-        ->RegisterDumpProviderWithSequencedTaskRunner(
-            this, "DOMStorage", task_runner_->GetSequencedTaskRunner(
-                                    DOMStorageTaskRunner::PRIMARY_SEQUENCE),
-            base::trace_event::MemoryDumpProvider::Options());
-  }
-}
-
-DOMStorageContextImpl::~DOMStorageContextImpl() {
-  DCHECK(is_shutdown_);
-  if (session_storage_database_.get()) {
-    // SessionStorageDatabase shouldn't be deleted right away: deleting it will
-    // potentially involve waiting in leveldb::DBImpl::~DBImpl, and waiting
-    // shouldn't happen on this thread.
-    SessionStorageDatabase* to_release = session_storage_database_.get();
-    to_release->AddRef();
-    session_storage_database_ = nullptr;
-    task_runner_->PostShutdownBlockingTask(
-        FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
-        base::BindOnce(&SessionStorageDatabase::Release,
-                       base::Unretained(to_release)));
-  }
-}
-
-DOMStorageNamespace* DOMStorageContextImpl::GetStorageNamespace(
-    const std::string& namespace_id) {
-  if (is_shutdown_)
-    return nullptr;
-  auto found = namespaces_.find(namespace_id);
-  if (found == namespaces_.end())
-    return nullptr;
-  return found->second.get();
-}
-
-void DOMStorageContextImpl::GetSessionStorageUsage(
-    std::vector<SessionStorageUsageInfo>* infos) {
-  if (!session_storage_database_.get()) {
-    for (const auto& entry : namespaces_) {
-      std::vector<url::Origin> origins;
-      entry.second->GetOriginsWithAreas(&origins);
-      for (const url::Origin& origin : origins) {
-        SessionStorageUsageInfo info;
-        info.namespace_id = entry.second->namespace_id();
-        info.origin = origin.GetURL();
-        infos->push_back(info);
-      }
-    }
-    return;
-  }
-
-  std::map<std::string, std::vector<url::Origin>> namespaces_and_origins;
-  session_storage_database_->ReadNamespacesAndOrigins(
-      &namespaces_and_origins);
-  for (auto it = namespaces_and_origins.cbegin();
-       it != namespaces_and_origins.cend(); ++it) {
-    for (auto origin_it = it->second.cbegin(); origin_it != it->second.cend();
-         ++origin_it) {
-      SessionStorageUsageInfo info;
-      info.namespace_id = it->first;
-      info.origin = origin_it->GetURL();
-      infos->push_back(info);
-    }
-  }
-}
-
-void DOMStorageContextImpl::DeleteSessionStorage(
-    const SessionStorageUsageInfo& usage_info) {
-  DCHECK(!is_shutdown_);
-  DOMStorageNamespace* dom_storage_namespace = nullptr;
-
-  auto it = namespaces_.find(usage_info.namespace_id);
-  if (it != namespaces_.end()) {
-    dom_storage_namespace = it->second.get();
-  } else {
-    CreateSessionNamespace(usage_info.namespace_id);
-    dom_storage_namespace = GetStorageNamespace(usage_info.namespace_id);
-  }
-  dom_storage_namespace->DeleteSessionStorageOrigin(
-      url::Origin::Create(usage_info.origin));
-  // Synthesize a 'cleared' event if the area is open so CachedAreas in
-  // renderers get emptied out too.
-  DOMStorageArea* area = dom_storage_namespace->GetOpenStorageArea(
-      url::Origin::Create(usage_info.origin));
-  if (area)
-    NotifyAreaCleared(area, usage_info.origin);
-}
-
-void DOMStorageContextImpl::Flush() {
-  for (auto& entry : namespaces_)
-    entry.second->Flush();
-}
-
-void DOMStorageContextImpl::Shutdown() {
-  if (task_runner_)
-    task_runner_->AssertIsRunningOnPrimarySequence();
-  is_shutdown_ = true;
-  StorageNamespaceMap::const_iterator it = namespaces_.begin();
-  for (; it != namespaces_.end(); ++it)
-    it->second->Shutdown();
-
-  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
-      this);
-
-  if (!session_storage_database_.get())
-    return;
-
-  // Respect the content policy settings about what to
-  // keep and what to discard.
-  if (force_keep_session_state_)
-    return;  // Keep everything.
-
-  bool has_session_only_origins =
-      special_storage_policy_.get() &&
-      special_storage_policy_->HasSessionOnlyOrigins();
-
-  if (has_session_only_origins) {
-    // We may have to delete something. We continue on the
-    // commit sequence after area shutdown tasks have cycled
-    // thru that sequence (and closed their database files).
-    bool success = task_runner_->PostShutdownBlockingTask(
-        FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
-        base::BindOnce(&DOMStorageContextImpl::ClearSessionOnlyOrigins, this));
-    DCHECK(success);
-  }
-}
-
-void DOMStorageContextImpl::AddEventObserver(EventObserver* observer) {
-  event_observers_.AddObserver(observer);
-}
-
-void DOMStorageContextImpl::RemoveEventObserver(EventObserver* observer) {
-  event_observers_.RemoveObserver(observer);
-}
-
-void DOMStorageContextImpl::NotifyItemSet(
-    const DOMStorageArea* area,
-    const base::string16& key,
-    const base::string16& new_value,
-    const base::NullableString16& old_value,
-    const GURL& page_url) {
-  for (auto& observer : event_observers_)
-    observer.OnDOMStorageItemSet(area, key, new_value, old_value, page_url);
-}
-
-void DOMStorageContextImpl::NotifyItemRemoved(
-    const DOMStorageArea* area,
-    const base::string16& key,
-    const base::string16& old_value,
-    const GURL& page_url) {
-  for (auto& observer : event_observers_)
-    observer.OnDOMStorageItemRemoved(area, key, old_value, page_url);
-}
-
-void DOMStorageContextImpl::NotifyAreaCleared(
-    const DOMStorageArea* area,
-    const GURL& page_url) {
-  for (auto& observer : event_observers_)
-    observer.OnDOMStorageAreaCleared(area, page_url);
-}
-
-// Used to diagnose unknown namespace_ids given to the ipc message filter.
-base::Optional<bad_message::BadMessageReason>
-DOMStorageContextImpl::DiagnoseSessionNamespaceId(
-    const std::string& namespace_id) {
-  if (base::Contains(recently_deleted_session_ids_, namespace_id))
-    return bad_message::DSH_DELETED_SESSION_ID;
-  return bad_message::DSH_NOT_ALLOCATED_SESSION_ID;
-}
-
-void DOMStorageContextImpl::CreateSessionNamespace(
-    const std::string& namespace_id) {
-  if (is_shutdown_)
-    return;
-  DCHECK(!namespace_id.empty());
-  // There are many browser tests that 'quit and restore' the browser but not
-  // the profile (and instead just reuse the old profile). This is unfortunate
-  // and doesn't actually test the 'restore' feature of session storage.
-  if (namespaces_.find(namespace_id) != namespaces_.end())
-    return;
-  namespaces_[namespace_id] = new DOMStorageNamespace(
-      namespace_id, session_storage_database_.get(), task_runner_.get());
-}
-
-void DOMStorageContextImpl::DeleteSessionNamespace(
-    const std::string& namespace_id,
-    bool should_persist_data) {
-  DCHECK(!namespace_id.empty());
-  StorageNamespaceMap::const_iterator it = namespaces_.find(namespace_id);
-  if (it == namespaces_.end())
-    return;
-  if (session_storage_database_.get()) {
-    if (!should_persist_data) {
-      task_runner_->PostShutdownBlockingTask(
-          FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
-          base::BindOnce(
-              base::IgnoreResult(&SessionStorageDatabase::DeleteNamespace),
-              session_storage_database_, namespace_id));
-    } else {
-      // Ensure that the data gets committed before we shut down.
-      it->second->Shutdown();
-      if (!scavenging_started_) {
-        // Protect the persistent namespace ID from scavenging.
-        protected_session_ids_.insert(namespace_id);
-      }
-    }
-  }
-  namespaces_.erase(namespace_id);
-
-  recently_deleted_session_ids_.push_back(namespace_id);
-  if (recently_deleted_session_ids_.size() > 10)
-    recently_deleted_session_ids_.pop_front();
-}
-
-void DOMStorageContextImpl::CloneSessionNamespace(
-    const std::string& existing_id,
-    const std::string& new_id) {
-  if (is_shutdown_)
-    return;
-  DCHECK(!existing_id.empty());
-  DCHECK(!new_id.empty());
-  auto found = namespaces_.find(existing_id);
-  if (found != namespaces_.end()) {
-    namespaces_[new_id] = found->second->Clone(new_id);
-    return;
-  }
-  CreateSessionNamespace(new_id);
-}
-
-void DOMStorageContextImpl::ClearSessionOnlyOrigins() {
-  if (session_storage_database_.get()) {
-    std::vector<SessionStorageUsageInfo> infos;
-    GetSessionStorageUsage(&infos);
-    for (size_t i = 0; i < infos.size(); ++i) {
-      const url::Origin& origin = url::Origin::Create(infos[i].origin);
-      if (special_storage_policy_->IsStorageProtected(origin.GetURL()))
-        continue;
-      if (!special_storage_policy_->IsStorageSessionOnly(origin.GetURL()))
-        continue;
-      session_storage_database_->DeleteArea(infos[i].namespace_id, origin);
-    }
-  }
-}
-
-void DOMStorageContextImpl::SetSaveSessionStorageOnDisk() {
-  DCHECK(namespaces_.empty());
-  if (!sessionstorage_directory_.empty()) {
-    session_storage_database_ = new SessionStorageDatabase(
-        sessionstorage_directory_, task_runner_->GetSequencedTaskRunner(
-                                       DOMStorageTaskRunner::COMMIT_SEQUENCE));
-  }
-}
-
-void DOMStorageContextImpl::StartScavengingUnusedSessionStorage() {
-  if (session_storage_database_.get()) {
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&DOMStorageContextImpl::FindUnusedNamespaces, this),
-        base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
-  }
-}
-
-void DOMStorageContextImpl::PurgeMemory(PurgeOption purge_option) {
-  if (is_shutdown_)
-    return;
-
-  DOMStorageNamespace::UsageStatistics initial_stats =
-      GetTotalNamespaceStatistics(namespaces_);
-  if (!initial_stats.total_area_count)
-    return;
-
-  // Track the total localStorage cache size.
-  UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageCacheSizeInKB",
-                              initial_stats.total_cache_size / 1024, 1, 100000,
-                              50);
-
-  const char* purge_reason = nullptr;
-  if (purge_option == PURGE_IF_NEEDED) {
-    // Purging is done based on the cache sizes without including the database
-    // size since it can be expensive trying to estimate the sqlite usage for
-    // all databases. For low end devices purge all inactive areas.
-    if (initial_stats.total_cache_size > kMaxDomStorageCacheSize)
-      purge_reason = "SizeLimitExceeded";
-    else if (initial_stats.total_area_count > kMaxDomStorageAreaCount)
-      purge_reason = "AreaCountLimitExceeded";
-    else if (is_low_end_device_)
-      purge_reason = "InactiveOnLowEndDevice";
-    if (!purge_reason)
-      return;
-
-    purge_option = PURGE_UNOPENED;
-  } else {
-    if (purge_option == PURGE_AGGRESSIVE)
-      purge_reason = "AggressivePurgeTriggered";
-    else
-      purge_reason = "ModeratePurgeTriggered";
-  }
-
-  // Return if no areas can be purged with the given option.
-  bool aggressively = purge_option == PURGE_AGGRESSIVE;
-  if (!aggressively && !initial_stats.inactive_area_count) {
-    return;
-  }
-  for (const auto& it : namespaces_)
-    it.second->PurgeMemory(aggressively);
-
-  // Track the size of cache purged.
-  size_t purged_size_kib =
-      (initial_stats.total_cache_size -
-       GetTotalNamespaceStatistics(namespaces_).total_cache_size) /
-      1024;
-  std::string full_histogram_name =
-      std::string("LocalStorage.BrowserLocalStorageCachePurgedInKB.") +
-      purge_reason;
-  base::HistogramBase* histogram = base::Histogram::FactoryGet(
-      full_histogram_name, 1, 100000, 50,
-      base::HistogramBase::kUmaTargetedHistogramFlag);
-  if (histogram)
-    histogram->Add(purged_size_kib);
-  UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.BrowserLocalStorageCachePurgedInKB",
-                              purged_size_kib, 1, 100000, 50);
-}
-
-bool DOMStorageContextImpl::OnMemoryDump(
-    const base::trace_event::MemoryDumpArgs& args,
-    base::trace_event::ProcessMemoryDump* pmd) {
-  if (session_storage_database_)
-    session_storage_database_->OnMemoryDump(pmd);
-  if (args.level_of_detail ==
-      base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
-    DOMStorageNamespace::UsageStatistics total_stats =
-        GetTotalNamespaceStatistics(namespaces_);
-    auto* mad = pmd->CreateAllocatorDump(base::StringPrintf(
-        "site_storage/session_storage/0x%" PRIXPTR "/cache_size",
-        reinterpret_cast<uintptr_t>(this)));
-    mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
-                   base::trace_event::MemoryAllocatorDump::kUnitsBytes,
-                   total_stats.total_cache_size);
-    mad->AddScalar("inactive_areas",
-                   base::trace_event::MemoryAllocatorDump::kUnitsObjects,
-                   total_stats.inactive_area_count);
-    mad->AddScalar("total_areas",
-                   base::trace_event::MemoryAllocatorDump::kUnitsObjects,
-                   total_stats.total_area_count);
-    return true;
-  }
-  for (const auto& it : namespaces_) {
-    it.second->OnMemoryDump(pmd);
-  }
-  return true;
-}
-
-void DOMStorageContextImpl::FindUnusedNamespaces() {
-  DCHECK(session_storage_database_.get());
-  if (scavenging_started_)
-    return;
-  scavenging_started_ = true;
-  std::set<std::string> namespace_ids_in_use;
-  for (StorageNamespaceMap::const_iterator it = namespaces_.begin();
-       it != namespaces_.end(); ++it)
-    namespace_ids_in_use.insert(it->second->namespace_id());
-  std::set<std::string> protected_session_ids;
-  protected_session_ids.swap(protected_session_ids_);
-  task_runner_->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
-      base::BindOnce(
-          &DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence, this,
-          namespace_ids_in_use, protected_session_ids));
-}
-
-void DOMStorageContextImpl::FindUnusedNamespacesInCommitSequence(
-    const std::set<std::string>& namespace_ids_in_use,
-    const std::set<std::string>& protected_session_ids) {
-  DCHECK(session_storage_database_.get());
-  // Delete all namespaces which don't have an associated DOMStorageNamespace
-  // alive.
-  std::map<std::string, std::vector<url::Origin>> namespaces_and_origins;
-  session_storage_database_->ReadNamespacesAndOrigins(&namespaces_and_origins);
-  for (auto it = namespaces_and_origins.cbegin();
-       it != namespaces_and_origins.cend(); ++it) {
-    if (namespace_ids_in_use.find(it->first) == namespace_ids_in_use.end() &&
-        protected_session_ids.find(it->first) == protected_session_ids.end()) {
-      deletable_namespace_ids_.push_back(it->first);
-    }
-  }
-  if (!deletable_namespace_ids_.empty()) {
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&DOMStorageContextImpl::DeleteNextUnusedNamespace, this),
-        base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
-  }
-}
-
-void DOMStorageContextImpl::DeleteNextUnusedNamespace() {
-  if (is_shutdown_)
-    return;
-  task_runner_->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::COMMIT_SEQUENCE,
-      base::BindOnce(
-          &DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence,
-          this));
-}
-
-void DOMStorageContextImpl::DeleteNextUnusedNamespaceInCommitSequence() {
-  if (deletable_namespace_ids_.empty())
-    return;
-  const std::string& persistent_id = deletable_namespace_ids_.back();
-  session_storage_database_->DeleteNamespace(persistent_id);
-  deletable_namespace_ids_.pop_back();
-  if (!deletable_namespace_ids_.empty()) {
-    task_runner_->PostDelayedTask(
-        FROM_HERE,
-        base::BindOnce(&DOMStorageContextImpl::DeleteNextUnusedNamespace, this),
-        base::TimeDelta::FromSeconds(kSessionStoraceScavengingSeconds));
-  }
-}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/dom_storage_context_impl.h b/content/browser/dom_storage/dom_storage_context_impl.h
deleted file mode 100644
index 2c1e6c8..0000000
--- a/content/browser/dom_storage/dom_storage_context_impl.h
+++ /dev/null
@@ -1,244 +0,0 @@
-// Copyright (c) 2012 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_DOM_STORAGE_DOM_STORAGE_CONTEXT_IMPL_H_
-#define CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_CONTEXT_IMPL_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/atomicops.h"
-#include "base/containers/circular_deque.h"
-#include "base/files/file_path.h"
-#include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/observer_list.h"
-#include "base/optional.h"
-#include "base/time/time.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "content/browser/bad_message.h"
-#include "content/common/content_export.h"
-#include "url/gurl.h"
-
-namespace base {
-class FilePath;
-class NullableString16;
-}
-
-namespace storage {
-class SpecialStoragePolicy;
-}
-
-namespace content {
-
-class DOMStorageArea;
-class DOMStorageNamespace;
-class DOMStorageSession;
-class DOMStorageTaskRunner;
-class SessionStorageDatabase;
-struct SessionStorageUsageInfo;
-
-// The Context is the root of an object containment hierarchy for
-// Namespaces and Areas related to the owning profile.
-// One instance is allocated in the main process for each profile,
-// instance methods should be called serially in the background as
-// determined by the task_runner. Specifically not on chrome's non-blocking
-// IO thread since these methods can result in blocking file io.
-//
-// In general terms, the DOMStorage object relationships are...
-//   Contexts (per-profile) own Namespaces which own Areas which share Maps.
-//   Hosts(per-renderer) refer to Namespaces and Areas open in its renderer.
-//   Sessions (per-tab) cause the creation and deletion of session Namespaces.
-//
-// Session Namespaces are cloned by initially making a shallow copy of
-// all contained Areas, the shallow copies refer to the same refcounted Map,
-// and does a deep copy-on-write if needed.
-//
-// Classes intended to be used by an embedder are DOMStorageContextImpl,
-// DOMStorageHost, and DOMStorageSession. The other classes are for
-// internal consumption.
-class CONTENT_EXPORT DOMStorageContextImpl
-    : public base::RefCountedThreadSafe<DOMStorageContextImpl>,
-      public base::trace_event::MemoryDumpProvider {
- public:
-  typedef std::map<std::string, scoped_refptr<DOMStorageNamespace>>
-      StorageNamespaceMap;
-
-  // An interface for observing Local and Session Storage events on the
-  // background thread.
-  class EventObserver {
-   public:
-    // |old_value| may be null on initial insert.
-    virtual void OnDOMStorageItemSet(
-        const DOMStorageArea* area,
-        const base::string16& key,
-        const base::string16& new_value,
-        const base::NullableString16& old_value,
-        const GURL& page_url) = 0;
-    virtual void OnDOMStorageItemRemoved(
-        const DOMStorageArea* area,
-        const base::string16& key,
-        const base::string16& old_value,
-        const GURL& page_url) = 0;
-    virtual void OnDOMStorageAreaCleared(
-        const DOMStorageArea* area,
-        const GURL& page_url) = 0;
-
-   protected:
-    virtual ~EventObserver() {}
-  };
-
-  // Option for PurgeMemory.
-  enum PurgeOption {
-    // Determines if purging is required based on the usage and the platform.
-    PURGE_IF_NEEDED,
-
-    // Purge unopened areas only.
-    PURGE_UNOPENED,
-
-    // Purge aggressively, i.e. discard cache even for areas that have
-    // non-zero open count.
-    PURGE_AGGRESSIVE,
-  };
-
-  // |sessionstorage_directory| may be empty for incognito browser contexts.
-  DOMStorageContextImpl(const base::FilePath& sessionstorage_directory,
-                        storage::SpecialStoragePolicy* special_storage_policy,
-                        scoped_refptr<DOMStorageTaskRunner> task_runner);
-
-  // Returns the directory path for sessionStorage, or an empty directory, if
-  // there is no backing on disk.
-  const base::FilePath& sessionstorage_directory() {
-    return sessionstorage_directory_;
-  }
-
-  DOMStorageTaskRunner* task_runner() const { return task_runner_.get(); }
-  DOMStorageNamespace* GetStorageNamespace(const std::string& namespace_id);
-
-  void GetSessionStorageUsage(std::vector<SessionStorageUsageInfo>* infos);
-  void DeleteSessionStorage(const SessionStorageUsageInfo& usage_info);
-
-  // Used by content settings to alter the behavior around
-  // what data to keep and what data to discard at shutdown.
-  // The policy is not so straight forward to describe, see
-  // the implementation for details.
-  void SetForceKeepSessionState() {
-    force_keep_session_state_ = true;
-  }
-
-  // Called when the owning BrowserContext is ending.
-  // Schedules the commit of any unsaved changes and will delete
-  // and keep data on disk per the content settings and special storage
-  // policies. Contained areas and namespaces will stop functioning after
-  // this method has been called.
-  void Shutdown();
-
-  // Initiate the process of flushing (writing - not sync'ing) any unwritten
-  // data managed by this instance. Flushing will start "soon".
-  void Flush();
-
-  // Methods to add, remove, and notify EventObservers.
-  void AddEventObserver(EventObserver* observer);
-  void RemoveEventObserver(EventObserver* observer);
-  void NotifyItemSet(
-      const DOMStorageArea* area,
-      const base::string16& key,
-      const base::string16& new_value,
-      const base::NullableString16& old_value,
-      const GURL& page_url);
-  void NotifyItemRemoved(
-      const DOMStorageArea* area,
-      const base::string16& key,
-      const base::string16& old_value,
-      const GURL& page_url);
-  void NotifyAreaCleared(
-      const DOMStorageArea* area,
-      const GURL& page_url);
-
-  // Must be called on the background thread.
-  base::Optional<bad_message::BadMessageReason> DiagnoseSessionNamespaceId(
-      const std::string& namespace_id);
-
-  // Must be called on the background thread.
-  void CreateSessionNamespace(const std::string& namespace_id);
-  void DeleteSessionNamespace(const std::string& namespace_id,
-                              bool should_persist_data);
-  void CloneSessionNamespace(const std::string& existing_id,
-                             const std::string& new_id);
-
-  // Starts backing sessionStorage on disk. This function must be called right
-  // after DOMStorageContextImpl is created, before it's used.
-  void SetSaveSessionStorageOnDisk();
-
-  // Deletes all namespaces which don't have an associated DOMStorageNamespace
-  // alive. This function is used for deleting possible leftover data after an
-  // unclean exit.
-  void StartScavengingUnusedSessionStorage();
-
-  // Frees up memory when possible. Purges caches and schedules commits
-  // depending on the given |purge_option|.
-  void PurgeMemory(PurgeOption purge_option);
-
-  // base::trace_event::MemoryDumpProvider implementation.
-  bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
-                    base::trace_event::ProcessMemoryDump* pmd) override;
-
- private:
-  friend class DOMStorageContextImplTest;
-  FRIEND_TEST_ALL_PREFIXES(DOMStorageContextImplTest, Basics);
-  friend class base::RefCountedThreadSafe<DOMStorageContextImpl>;
-
-  ~DOMStorageContextImpl() override;
-
-  void ClearSessionOnlyOrigins();
-
-  // For scavenging unused sessionStorages.
-  void FindUnusedNamespaces();
-  void FindUnusedNamespacesInCommitSequence(
-      const std::set<std::string>& namespace_ids_in_use,
-      const std::set<std::string>& protected_persistent_session_ids);
-  void DeleteNextUnusedNamespace();
-  void DeleteNextUnusedNamespaceInCommitSequence();
-
-  // Collection of namespaces keyed by id.
-  StorageNamespaceMap namespaces_;
-
-  // Where sessionstorage data is stored, maybe empty for the incognito use
-  // case. Always empty until the file-backed session storage feature is
-  // implemented.
-  base::FilePath sessionstorage_directory_;
-
-  // Used to schedule sequenced background tasks.
-  scoped_refptr<DOMStorageTaskRunner> task_runner_;
-
-  // List of objects observing local storage events.
-  base::ObserverList<EventObserver>::Unchecked event_observers_;
-
-  // For diagnostic purposes.
-  base::circular_deque<std::string> recently_deleted_session_ids_;
-
-  bool is_shutdown_;
-  bool force_keep_session_state_;
-  scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
-  scoped_refptr<SessionStorageDatabase> session_storage_database_;
-
-  // For cleaning up unused namespaces gradually.
-  bool scavenging_started_;
-  std::vector<std::string> deletable_namespace_ids_;
-
-  // Persistent namespace IDs to protect from gradual deletion (they will
-  // be needed for session restore).
-  std::set<std::string> protected_session_ids_;
-
-  // For cleaning up unused databases more aggressively.
-  bool is_low_end_device_;
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_CONTEXT_IMPL_H_
diff --git a/content/browser/dom_storage/dom_storage_context_impl_unittest.cc b/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
deleted file mode 100644
index eee1d66..0000000
--- a/content/browser/dom_storage/dom_storage_context_impl_unittest.cc
+++ /dev/null
@@ -1,171 +0,0 @@
-// Copyright 2013 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/dom_storage/dom_storage_context_impl.h"
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
-#include "content/browser/dom_storage/dom_storage_namespace.h"
-#include "content/browser/dom_storage/dom_storage_task_runner.h"
-#include "content/public/browser/session_storage_usage_info.h"
-#include "content/public/browser/storage_usage_info.h"
-#include "content/public/test/test_browser_thread_bundle.h"
-#include "storage/browser/test/mock_special_storage_policy.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-using base::ASCIIToUTF16;
-
-namespace content {
-
-class DOMStorageContextImplTest : public testing::Test {
- public:
-  DOMStorageContextImplTest()
-      : kOrigin(url::Origin::Create(GURL("http://dom_storage/"))),
-        kKey(ASCIIToUTF16("key")),
-        kValue(ASCIIToUTF16("value")),
-        kDontIncludeFileInfo(false),
-        kDoIncludeFileInfo(true) {}
-
-  const url::Origin kOrigin;
-  const base::string16 kKey;
-  const base::string16 kValue;
-  const bool kDontIncludeFileInfo;
-  const bool kDoIncludeFileInfo;
-
-  void SetUp() override {
-    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-    storage_policy_ = new MockSpecialStoragePolicy;
-    task_runner_ =
-        new MockDOMStorageTaskRunner(base::ThreadTaskRunnerHandle::Get().get());
-    context_ = new DOMStorageContextImpl(
-        base::FilePath(), storage_policy_.get(), task_runner_.get());
-  }
-
-  void TearDown() override {
-    if (context_)
-      context_->Shutdown();
-    base::RunLoop().RunUntilIdle();
-  }
-
- protected:
-  TestBrowserThreadBundle test_browser_thread_bundle_;
-  base::ScopedTempDir temp_dir_;
-  scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
-  scoped_refptr<MockDOMStorageTaskRunner> task_runner_;
-  scoped_refptr<DOMStorageContextImpl> context_;
-  DISALLOW_COPY_AND_ASSIGN(DOMStorageContextImplTest);
-};
-
-TEST_F(DOMStorageContextImplTest, Basics) {
-  // This test doesn't do much, checks that the constructor
-  // initializes members properly and that invoking methods
-  // on a newly created object w/o any data on disk do no harm.
-  EXPECT_EQ(base::FilePath(), context_->sessionstorage_directory());
-  EXPECT_EQ(storage_policy_.get(), context_->special_storage_policy_.get());
-  context_->Shutdown();
-}
-
-TEST_F(DOMStorageContextImplTest, PersistentIds) {
-  const std::string kFirstNamespaceId = "persistent";
-  context_->CreateSessionNamespace(kFirstNamespaceId);
-  DOMStorageNamespace* dom_namespace =
-      context_->GetStorageNamespace(kFirstNamespaceId);
-  ASSERT_TRUE(dom_namespace);
-  EXPECT_EQ(kFirstNamespaceId, dom_namespace->namespace_id());
-  // Verify that the areas inherit the persistent ID.
-  DOMStorageArea* area = dom_namespace->OpenStorageArea(kOrigin);
-  EXPECT_EQ(kFirstNamespaceId, area->namespace_id_);
-
-  // Verify that the persistent IDs are handled correctly when cloning.
-  const std::string kSecondNamespaceId = "cloned";
-  context_->CloneSessionNamespace(kFirstNamespaceId, kSecondNamespaceId);
-  DOMStorageNamespace* cloned_dom_namespace =
-      context_->GetStorageNamespace(kSecondNamespaceId);
-  ASSERT_TRUE(dom_namespace);
-  EXPECT_EQ(kSecondNamespaceId, cloned_dom_namespace->namespace_id());
-  // Verify that the areas inherit the persistent ID.
-  DOMStorageArea* cloned_area = cloned_dom_namespace->OpenStorageArea(kOrigin);
-  EXPECT_EQ(kSecondNamespaceId, cloned_area->namespace_id_);
-}
-
-// Disable this test on Android as on Android we always delete our old session
-// storage on startup. This is because we don't do any session restoration for
-// the android system. See crbug.com/770307.
-#if defined(OS_ANDROID)
-TEST_F(DOMStorageContextImplTest, DISABLED_DeleteSessionStorage) {
-#else
-TEST_F(DOMStorageContextImplTest, DeleteSessionStorage) {
-#endif
-  // Create a DOMStorageContextImpl which will save sessionStorage on disk.
-  context_->Shutdown();
-  context_ = new DOMStorageContextImpl(
-      temp_dir_.GetPath(), storage_policy_.get(), task_runner_.get());
-  context_->SetSaveSessionStorageOnDisk();
-  ASSERT_EQ(temp_dir_.GetPath(), context_->sessionstorage_directory());
-
-  // Write data.
-  const std::string kFirstNamespaceId = "persistent";
-  context_->CreateSessionNamespace(kFirstNamespaceId);
-  DOMStorageNamespace* dom_namespace =
-      context_->GetStorageNamespace(kFirstNamespaceId);
-  DOMStorageArea* area = dom_namespace->OpenStorageArea(kOrigin);
-  const base::string16 kKey(ASCIIToUTF16("foo"));
-  const base::string16 kValue(ASCIIToUTF16("bar"));
-  base::NullableString16 old_nullable_value;
-  area->SetItem(kKey, kValue, old_nullable_value, &old_nullable_value);
-  dom_namespace->CloseStorageArea(area);
-
-  // Destroy and recreate the DOMStorageContextImpl.
-  context_->Shutdown();
-  context_ = nullptr;
-  base::RunLoop().RunUntilIdle();
-  context_ = new DOMStorageContextImpl(
-      temp_dir_.GetPath(), storage_policy_.get(), task_runner_.get());
-  context_->SetSaveSessionStorageOnDisk();
-
-  // Read the data back.
-  context_->CreateSessionNamespace(kFirstNamespaceId);
-  dom_namespace = context_->GetStorageNamespace(kFirstNamespaceId);
-  area = dom_namespace->OpenStorageArea(kOrigin);
-  base::NullableString16 read_value;
-  EXPECT_EQ(kKey, area->Key(0).string());
-  dom_namespace->CloseStorageArea(area);
-
-  SessionStorageUsageInfo info;
-  info.origin = kOrigin.GetURL();
-  info.namespace_id = kFirstNamespaceId;
-  context_->DeleteSessionStorage(info);
-
-  // Destroy and recreate again.
-  context_->Shutdown();
-  context_ = nullptr;
-  base::RunLoop().RunUntilIdle();
-  context_ = new DOMStorageContextImpl(
-      temp_dir_.GetPath(), storage_policy_.get(), task_runner_.get());
-  context_->SetSaveSessionStorageOnDisk();
-
-  // Now there should be no data.
-  context_->CreateSessionNamespace(kFirstNamespaceId);
-  dom_namespace = context_->GetStorageNamespace(kFirstNamespaceId);
-  area = dom_namespace->OpenStorageArea(kOrigin);
-
-  EXPECT_EQ(0u, area->Length());
-  dom_namespace->CloseStorageArea(area);
-  context_->Shutdown();
-  context_ = nullptr;
-  base::RunLoop().RunUntilIdle();
-}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.cc b/content/browser/dom_storage/dom_storage_context_wrapper.cc
index ff06e2d4..599e7dd 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -21,8 +21,6 @@
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
-#include "content/browser/dom_storage/dom_storage_context_impl.h"
 #include "content/browser/dom_storage/dom_storage_task_runner.h"
 #include "content/browser/dom_storage/local_storage_context_mojo.h"
 #include "content/browser/dom_storage/session_storage_context_mojo.h"
@@ -54,10 +52,12 @@
                                   base::FileEnumerator::FILES);
   for (base::FilePath path = enumerator.Next(); !path.empty();
        path = enumerator.Next()) {
-    if (path.MatchesExtension(DOMStorageArea::kDatabaseFileExtension)) {
+    if (path.MatchesExtension(
+            LocalStorageContextMojo::kLegacyDatabaseFileExtension)) {
       base::FileEnumerator::FileInfo find_info = enumerator.GetInfo();
-      infos.emplace_back(DOMStorageArea::OriginFromDatabaseFileName(path),
-                         find_info.GetSize(), find_info.GetLastModifiedTime());
+      infos.emplace_back(
+          LocalStorageContextMojo::OriginFromLegacyDatabaseFileName(path),
+          find_info.GetSize(), find_info.GetLastModifiedTime());
     }
   }
   reply_task_runner->PostTask(
@@ -70,16 +70,6 @@
   std::move(callback).Run(*infos);
 }
 
-void GetSessionStorageUsageHelper(
-    base::SingleThreadTaskRunner* reply_task_runner,
-    DOMStorageContextImpl* context,
-    DOMStorageContext::GetSessionStorageUsageCallback callback) {
-  std::vector<SessionStorageUsageInfo> infos;
-  context->GetSessionStorageUsage(&infos);
-  reply_task_runner->PostTask(
-      FROM_HERE, base::BindOnce(std::move(callback), std::move(infos)));
-}
-
 void CollectLocalStorageUsage(std::vector<StorageUsageInfo>* out_info,
                               base::OnceClosure done_callback,
                               const std::vector<StorageUsageInfo>& in_info) {
@@ -128,14 +118,6 @@
       base::CreateSequencedTaskRunnerWithTraits(
           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
            base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-
-  scoped_refptr<DOMStorageContextImpl> old_context_impl =
-      base::MakeRefCounted<DOMStorageContextImpl>(
-          data_path.empty() ? data_path
-                            : data_path.AppendASCII(kSessionStorageDirectory),
-          special_storage_policy,
-          new DOMStorageWorkerPoolTaskRunner(std::move(primary_sequence),
-                                             std::move(commit_sequence)));
   auto mojo_task_runner =
       base::CreateSingleThreadTaskRunnerWithTraits({BrowserThread::IO});
 
@@ -147,41 +129,39 @@
           ? base::FilePath()
           : local_partition_path.AppendASCII(kLocalStorageDirectory);
   LocalStorageContextMojo* mojo_local_state = new LocalStorageContextMojo(
-      mojo_task_runner, connector, old_context_impl->task_runner(),
+      mojo_task_runner, connector,
+      new DOMStorageWorkerPoolTaskRunner(std::move(primary_sequence),
+                                         std::move(commit_sequence)),
       legacy_localstorage_path, new_localstorage_path, special_storage_policy);
   SessionStorageContextMojo* mojo_session_state = nullptr;
-  if (base::FeatureList::IsEnabled(blink::features::kOnionSoupDOMStorage)) {
-    mojo_session_state = new SessionStorageContextMojo(
-        mojo_task_runner, connector,
+  mojo_session_state = new SessionStorageContextMojo(
+      mojo_task_runner, connector,
 #if defined(OS_ANDROID)
-        // On Android there is no support for session storage restoring, and
-        // since the restoring code is responsible for database cleanup, we must
-        // manually delete the old database here before we open it.
-        SessionStorageContextMojo::BackingMode::kClearDiskStateOnOpen,
+      // On Android there is no support for session storage restoring, and
+      // since the restoring code is responsible for database cleanup, we must
+      // manually delete the old database here before we open it.
+      SessionStorageContextMojo::BackingMode::kClearDiskStateOnOpen,
 #else
-        profile_path.empty()
-            ? SessionStorageContextMojo::BackingMode::kNoDisk
-            : SessionStorageContextMojo::BackingMode::kRestoreDiskState,
+      profile_path.empty()
+          ? SessionStorageContextMojo::BackingMode::kNoDisk
+          : SessionStorageContextMojo::BackingMode::kRestoreDiskState,
 #endif
-        local_partition_path, std::string(kSessionStorageDirectory));
-  }
+      local_partition_path, std::string(kSessionStorageDirectory));
 
   return base::WrapRefCounted(new DOMStorageContextWrapper(
-      std::move(legacy_localstorage_path), std::move(old_context_impl),
-      mojo_task_runner, mojo_local_state, mojo_session_state));
+      std::move(legacy_localstorage_path), mojo_task_runner, mojo_local_state,
+      mojo_session_state));
 }
 
 DOMStorageContextWrapper::DOMStorageContextWrapper(
     base::FilePath legacy_local_storage_path,
-    scoped_refptr<DOMStorageContextImpl> context_impl,
     scoped_refptr<base::SequencedTaskRunner> mojo_task_runner,
     LocalStorageContextMojo* mojo_local_storage_context,
     SessionStorageContextMojo* mojo_session_storage_context)
     : mojo_state_(mojo_local_storage_context),
       mojo_session_state_(mojo_session_storage_context),
       mojo_task_runner_(std::move(mojo_task_runner)),
-      legacy_localstorage_path_(std::move(legacy_local_storage_path)),
-      context_(std::move(context_impl)) {
+      legacy_localstorage_path_(std::move(legacy_local_storage_path)) {
   memory_pressure_listener_.reset(new base::MemoryPressureListener(
       base::BindRepeating(&DOMStorageContextWrapper::OnMemoryPressure,
                           base::Unretained(this))));
@@ -195,7 +175,11 @@
 
 void DOMStorageContextWrapper::GetLocalStorageUsage(
     GetLocalStorageUsageCallback callback) {
-  DCHECK(context_.get());
+  if (!mojo_state_) {
+    // Shutdown() has been called.
+    std::move(callback).Run(std::vector<StorageUsageInfo>());
+    return;
+  }
   auto infos = std::make_unique<std::vector<StorageUsageInfo>>();
   auto* infos_ptr = infos.get();
   base::RepeatingClosure got_local_storage_usage = base::BarrierClosure(
@@ -214,7 +198,7 @@
                      base::BindOnce(&GotMojoLocalStorageUsage,
                                     base::ThreadTaskRunnerHandle::Get(),
                                     collect_callback)));
-  context_->task_runner()->PostShutdownBlockingTask(
+  mojo_state_->legacy_task_runner()->PostShutdownBlockingTask(
       FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
       base::BindOnce(&GetLegacyLocalStorageUsage, legacy_localstorage_path_,
                      base::ThreadTaskRunnerHandle::Get(),
@@ -223,40 +207,32 @@
 
 void DOMStorageContextWrapper::GetSessionStorageUsage(
     GetSessionStorageUsageCallback callback) {
-  if (mojo_session_state_) {
-    // base::Unretained is safe here, because the mojo_session_state_ won't be
-    // deleted until a ShutdownAndDelete task has been ran on the
-    // mojo_task_runner_, and as soon as that task is posted,
-    // mojo_session_state_ is set to null, preventing further tasks from being
-    // queued.
-    mojo_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&SessionStorageContextMojo::GetStorageUsage,
-                       base::Unretained(mojo_session_state_),
-                       base::BindOnce(&GotMojoSessionStorageUsage,
-                                      base::ThreadTaskRunnerHandle::Get(),
-                                      std::move(callback))));
+  if (!mojo_session_state_) {
+    // Shutdown() has been called.
+    std::move(callback).Run(std::vector<SessionStorageUsageInfo>());
     return;
   }
-  DCHECK(context_.get());
-  context_->task_runner()->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
-      base::BindOnce(&GetSessionStorageUsageHelper,
-                     base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
-                     base::RetainedRef(context_), std::move(callback)));
+  // base::Unretained is safe here, because the mojo_session_state_ won't be
+  // deleted until a ShutdownAndDelete task has been ran on the
+  // mojo_task_runner_, and as soon as that task is posted,
+  // mojo_session_state_ is set to null, preventing further tasks from being
+  // queued.
+  mojo_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&SessionStorageContextMojo::GetStorageUsage,
+                     base::Unretained(mojo_session_state_),
+                     base::BindOnce(&GotMojoSessionStorageUsage,
+                                    base::ThreadTaskRunnerHandle::Get(),
+                                    std::move(callback))));
 }
 
 void DOMStorageContextWrapper::DeleteLocalStorage(const url::Origin& origin,
                                                   base::OnceClosure callback) {
-  DCHECK(context_.get());
   DCHECK(callback);
-  if (!legacy_localstorage_path_.empty()) {
-    context_->task_runner()->PostShutdownBlockingTask(
-        FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
-        base::BindOnce(
-            base::IgnoreResult(&sql::Database::Delete),
-            legacy_localstorage_path_.Append(
-                DOMStorageArea::DatabaseFileNameFromOrigin(origin))));
+  if (!mojo_state_) {
+    // Shutdown() has been called.
+    std::move(callback).Run();
+    return;
   }
   // base::Unretained is safe here, because the mojo_state_ won't be deleted
   // until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
@@ -269,11 +245,19 @@
           base::Unretained(mojo_state_), origin,
           base::BindOnce(&GotMojoCallback, base::ThreadTaskRunnerHandle::Get(),
                          std::move(callback))));
+  if (!legacy_localstorage_path_.empty()) {
+    mojo_state_->legacy_task_runner()->PostShutdownBlockingTask(
+        FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
+        base::BindOnce(
+            base::IgnoreResult(&sql::Database::Delete),
+            legacy_localstorage_path_.Append(
+                LocalStorageContextMojo::LegacyDatabaseFileNameFromOrigin(
+                    origin))));
+  }
 }
 
 void DOMStorageContextWrapper::PerformLocalStorageCleanup(
     base::OnceClosure callback) {
-  DCHECK(context_.get());
   DCHECK(callback);
   if (!mojo_state_) {
     // Shutdown() has been called.
@@ -292,51 +276,39 @@
 void DOMStorageContextWrapper::DeleteSessionStorage(
     const SessionStorageUsageInfo& usage_info,
     base::OnceClosure callback) {
-  if (mojo_session_state_) {
-    // base::Unretained is safe here, because the mojo_session_state_ won't be
-    // deleted until a ShutdownAndDelete task has been ran on the
-    // mojo_task_runner_, and as soon as that task is posted,
-    // mojo_session_state_ is set to null, preventing further tasks from being
-    // queued.
-    mojo_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&SessionStorageContextMojo::DeleteStorage,
-                       base::Unretained(mojo_session_state_),
-                       url::Origin::Create(usage_info.origin),
-                       usage_info.namespace_id, std::move(callback)));
-    return;
+  if (!mojo_session_state_) {
+    // Shutdown() has been called.
+    std::move(callback).Run();
   }
-  DCHECK(context_.get());
-  context_->task_runner()->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
-      base::BindOnce(&DOMStorageContextImpl::DeleteSessionStorage, context_,
-                     usage_info));
-  std::move(callback).Run();
+  // base::Unretained is safe here, because the mojo_session_state_ won't be
+  // deleted until a ShutdownAndDelete task has been ran on the
+  // mojo_task_runner_, and as soon as that task is posted,
+  // mojo_session_state_ is set to null, preventing further tasks from being
+  // queued.
+  mojo_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&SessionStorageContextMojo::DeleteStorage,
+                                base::Unretained(mojo_session_state_),
+                                url::Origin::Create(usage_info.origin),
+                                usage_info.namespace_id, std::move(callback)));
 }
 
 void DOMStorageContextWrapper::PerformSessionStorageCleanup(
     base::OnceClosure callback) {
-  DCHECK(context_.get());
   DCHECK(callback);
-  if (mojo_session_state_) {
-    // base::Unretained is safe here, because the mojo_session_state_ won't be
-    // deleted until a ShutdownAndDelete task has been ran on the
-    // mojo_task_runner_, and as soon as that task is posted,
-    // mojo_session_state_ is set to null, preventing further tasks from being
-    // queued.
-    mojo_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&SessionStorageContextMojo::PerformStorageCleanup,
-                       base::Unretained(mojo_session_state_),
-                       std::move(callback)));
-    return;
+  if (!mojo_session_state_) {
+    // Shutdown() has been called.
+    std::move(callback).Run();
   }
-  std::move(callback).Run();
-}
-
-void DOMStorageContextWrapper::SetSaveSessionStorageOnDisk() {
-  DCHECK(context_.get());
-  context_->SetSaveSessionStorageOnDisk();
+  // base::Unretained is safe here, because the mojo_session_state_ won't be
+  // deleted until a ShutdownAndDelete task has been ran on the
+  // mojo_task_runner_, and as soon as that task is posted,
+  // mojo_session_state_ is set to null, preventing further tasks from being
+  // queued.
+  mojo_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&SessionStorageContextMojo::PerformStorageCleanup,
+                     base::Unretained(mojo_session_state_),
+                     std::move(callback)));
 }
 
 scoped_refptr<SessionStorageNamespace>
@@ -346,33 +318,28 @@
 }
 
 void DOMStorageContextWrapper::StartScavengingUnusedSessionStorage() {
-  if (mojo_session_state_) {
-    // base::Unretained is safe here, because the mojo_session_state_ won't be
-    // deleted until a ShutdownAndDelete task has been ran on the
-    // mojo_task_runner_, and as soon as that task is posted,
-    // mojo_session_state_ is set to null, preventing further tasks from being
-    // queued.
-    mojo_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&SessionStorageContextMojo::ScavengeUnusedNamespaces,
-                       base::Unretained(mojo_session_state_),
-                       base::OnceClosure()));
+  if (!mojo_session_state_) {
+    // Shutdown() has been called.
     return;
   }
-  DCHECK(context_.get());
-  context_->task_runner()->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
-      base::BindOnce(
-          &DOMStorageContextImpl::StartScavengingUnusedSessionStorage,
-          context_));
+  // base::Unretained is safe here, because the mojo_session_state_ won't be
+  // deleted until a ShutdownAndDelete task has been ran on the
+  // mojo_task_runner_, and as soon as that task is posted,
+  // mojo_session_state_ is set to null, preventing further tasks from being
+  // queued.
+  mojo_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&SessionStorageContextMojo::ScavengeUnusedNamespaces,
+                     base::Unretained(mojo_session_state_),
+                     base::OnceClosure()));
 }
 
 void DOMStorageContextWrapper::SetForceKeepSessionState() {
-  DCHECK(context_.get());
-  context_->task_runner()->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
-      base::BindOnce(&DOMStorageContextImpl::SetForceKeepSessionState,
-                     context_));
+  if (!mojo_session_state_) {
+    // Shutdown() has been called.
+    return;
+  }
+
   // base::Unretained is safe here, because the mojo_state_ won't be deleted
   // until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
   // as soon as that task is posted, mojo_state_ is set to null, preventing
@@ -397,26 +364,18 @@
     mojo_session_state_ = nullptr;
   }
   memory_pressure_listener_.reset();
-  if (context_) {
-    context_->task_runner()->PostShutdownBlockingTask(
-        FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
-        base::BindOnce(&DOMStorageContextImpl::Shutdown, context_));
-  }
 }
 
 void DOMStorageContextWrapper::Flush() {
-  DCHECK(context_.get());
-
-  context_->task_runner()->PostShutdownBlockingTask(
-      FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
-      base::BindOnce(&DOMStorageContextImpl::Flush, context_));
-  // base::Unretained is safe here, because the mojo_state_ won't be deleted
-  // until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
-  // as soon as that task is posted, mojo_state_ is set to null, preventing
-  // further tasks from being queued.
-  mojo_task_runner_->PostTask(FROM_HERE,
-                              base::BindOnce(&LocalStorageContextMojo::Flush,
-                                             base::Unretained(mojo_state_)));
+  if (mojo_state_) {
+    // base::Unretained is safe here, because the mojo_state_ won't be deleted
+    // until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
+    // as soon as that task is posted, mojo_state_ is set to null, preventing
+    // further tasks from being queued.
+    mojo_task_runner_->PostTask(FROM_HERE,
+                                base::BindOnce(&LocalStorageContextMojo::Flush,
+                                               base::Unretained(mojo_state_)));
+  }
   if (mojo_session_state_) {
     // base::Unretained is safe here, because the mojo_session_state_ won't be
     // deleted until a ShutdownAndDelete task has been ran on the
@@ -448,8 +407,7 @@
     const std::string& namespace_id,
     mojo::ReportBadMessageCallback bad_message_callback,
     blink::mojom::SessionStorageNamespaceRequest request) {
-  if (!mojo_session_state_)
-    return;
+  DCHECK(mojo_session_state_);
   // The bad message callback must be called on the same sequenced task runner
   // as the binding set. It cannot be called from our own mojo task runner.
   auto wrapped_bad_message_callback = base::BindOnce(
@@ -509,21 +467,20 @@
 
 void DOMStorageContextWrapper::OnMemoryPressure(
     base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) {
-  DOMStorageContextImpl::PurgeOption purge_option =
-      DOMStorageContextImpl::PURGE_UNOPENED;
+  PurgeOption purge_option = PURGE_UNOPENED;
   if (memory_pressure_level ==
       base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
-    purge_option = DOMStorageContextImpl::PURGE_AGGRESSIVE;
+    purge_option = PURGE_AGGRESSIVE;
   }
   PurgeMemory(purge_option);
 }
 
-void DOMStorageContextWrapper::PurgeMemory(DOMStorageContextImpl::PurgeOption
-    purge_option) {
-  context_->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&DOMStorageContextImpl::PurgeMemory, context_,
-                                purge_option));
-  if (mojo_state_ && purge_option == DOMStorageContextImpl::PURGE_AGGRESSIVE) {
+void DOMStorageContextWrapper::PurgeMemory(PurgeOption purge_option) {
+  if (!mojo_state_) {
+    // Shutdown was called.
+    return;
+  }
+  if (purge_option == PURGE_AGGRESSIVE) {
     // base::Unretained is safe here, because the mojo_state_ won't be deleted
     // until a ShutdownAndDelete task has been ran on the mojo_task_runner_, and
     // as soon as that task is posted, mojo_state_ is set to null, preventing
@@ -531,10 +488,6 @@
     mojo_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&LocalStorageContextMojo::PurgeMemory,
                                   base::Unretained(mojo_state_)));
-  }
-
-  if (mojo_session_state_ &&
-      purge_option == DOMStorageContextImpl::PURGE_AGGRESSIVE) {
     // base::Unretained is safe here, because the mojo_session_state_ won't be
     // deleted until a ShutdownAndDelete task has been ran on the
     // mojo_task_runner_, and as soon as that task is posted,
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper.h b/content/browser/dom_storage/dom_storage_context_wrapper.h
index d562833..687c8c5b 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -15,7 +15,6 @@
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
-#include "content/browser/dom_storage/dom_storage_context_impl.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/dom_storage_context.h"
 #include "mojo/public/cpp/bindings/message.h"
@@ -36,17 +35,31 @@
 
 namespace content {
 
-class DOMStorageContextImpl;
 class LocalStorageContextMojo;
 class SessionStorageContextMojo;
 class SessionStorageNamespaceImpl;
 
 // This is owned by Storage Partition and encapsulates all its dom storage
 // state.
+// Can only be accessed on the UI thread, except for the AddNamespace and
+// RemoveNamespace methods.
 class CONTENT_EXPORT DOMStorageContextWrapper
     : public DOMStorageContext,
       public base::RefCountedThreadSafe<DOMStorageContextWrapper> {
  public:
+  // Option for PurgeMemory.
+  enum PurgeOption {
+    // Determines if purging is required based on the usage and the platform.
+    PURGE_IF_NEEDED,
+
+    // Purge unopened areas only.
+    PURGE_UNOPENED,
+
+    // Purge aggressively, i.e. discard cache even for areas that have
+    // non-zero open count.
+    PURGE_AGGRESSIVE,
+  };
+
   // If |profile_path| is empty, nothing will be saved to disk.
   static scoped_refptr<DOMStorageContextWrapper> Create(
       service_manager::Connector* connector,
@@ -56,7 +69,6 @@
 
   DOMStorageContextWrapper(
       base::FilePath legacy_local_storage_path,
-      scoped_refptr<DOMStorageContextImpl> context_impl,
       scoped_refptr<base::SequencedTaskRunner> mojo_task_runner,
       LocalStorageContextMojo* mojo_local_storage_context,
       SessionStorageContextMojo* mojo_session_storage_context);
@@ -70,7 +82,6 @@
   void DeleteSessionStorage(const SessionStorageUsageInfo& usage_info,
                             base::OnceClosure callback) override;
   void PerformSessionStorageCleanup(base::OnceClosure callback) override;
-  void SetSaveSessionStorageOnDisk() override;
   scoped_refptr<SessionStorageNamespace> RecreateSessionStorage(
       const std::string& namespace_id) override;
   void StartScavengingUnusedSessionStorage() override;
@@ -108,7 +119,6 @@
   friend class DOMStorageBrowserTest;
 
   ~DOMStorageContextWrapper() override;
-  DOMStorageContextImpl* context() const { return context_.get(); }
 
   base::SequencedTaskRunner* mojo_task_runner() {
     return mojo_task_runner_.get();
@@ -128,7 +138,7 @@
   void OnMemoryPressure(
       base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level);
 
-  void PurgeMemory(DOMStorageContextImpl::PurgeOption purge_option);
+  void PurgeMemory(PurgeOption purge_option);
 
   // Keep all mojo-ish details together and not bleed them through the public
   // interface. The |mojo_state_| object is owned by this object, but destroyed
@@ -156,8 +166,6 @@
   // To receive memory pressure signals.
   std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
 
-  scoped_refptr<DOMStorageContextImpl> context_;
-
   DISALLOW_IMPLICIT_CONSTRUCTORS(DOMStorageContextWrapper);
 };
 
diff --git a/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc b/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc
index 71b1cc8..284b949 100644
--- a/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc
+++ b/content/browser/dom_storage/dom_storage_context_wrapper_unittest.cc
@@ -9,7 +9,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
-#include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/test/test_simple_task_runner.h"
 #include "base/threading/sequenced_task_runner_handle.h"
@@ -24,16 +23,13 @@
 
 class DOMStorageContextWrapperTest : public testing::Test {
  public:
-  DOMStorageContextWrapperTest() {
-    feature_list_.InitAndEnableFeature(blink::features::kOnionSoupDOMStorage);
-  }
+  DOMStorageContextWrapperTest() = default;
 
   void SetUp() override {
     storage_policy_ = new MockSpecialStoragePolicy();
     fake_mojo_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>();
     context_ = new DOMStorageContextWrapper(
-        /*legacy_local_storage_path=*/base::FilePath(),
-        /*context_impl=*/nullptr, fake_mojo_task_runner_,
+        /*legacy_local_storage_path=*/base::FilePath(), fake_mojo_task_runner_,
         /*mojo_local_storage_context=*/nullptr,
         new SessionStorageContextMojo(
             fake_mojo_task_runner_, /*connector=*/nullptr,
@@ -50,7 +46,6 @@
   }
 
  protected:
-  base::test::ScopedFeatureList feature_list_;
   base::test::ScopedTaskEnvironment task_environment_;
   scoped_refptr<base::TestSimpleTaskRunner> fake_mojo_task_runner_;
   scoped_refptr<MockSpecialStoragePolicy> storage_policy_;
diff --git a/content/browser/dom_storage/dom_storage_host.cc b/content/browser/dom_storage/dom_storage_host.cc
deleted file mode 100644
index f674cbd..0000000
--- a/content/browser/dom_storage/dom_storage_host.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2013 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/dom_storage/dom_storage_host.h"
-
-#include "content/browser/dom_storage/dom_storage_area.h"
-#include "content/browser/dom_storage/dom_storage_context_impl.h"
-#include "content/browser/dom_storage/dom_storage_namespace.h"
-#include "url/gurl.h"
-#include "url/origin.h"
-
-namespace content {
-
-DOMStorageHost::DOMStorageHost(DOMStorageContextImpl* context)
-    : context_(context) {
-}
-
-DOMStorageHost::~DOMStorageHost() {
-  // Clear connections prior to releasing the context_.
-  while (!connections_.empty())
-    CloseStorageArea(connections_.begin()->first);
-}
-
-base::Optional<bad_message::BadMessageReason> DOMStorageHost::OpenStorageArea(
-    int connection_id,
-    const std::string& namespace_id,
-    const url::Origin& origin) {
-  if (HasConnection(connection_id))
-    return bad_message::DSH_DUPLICATE_CONNECTION_ID;
-  NamespaceAndArea references;
-  references.namespace_ = context_->GetStorageNamespace(namespace_id);
-  if (!references.namespace_.get())
-    return context_->DiagnoseSessionNamespaceId(namespace_id);
-
-  // namespace->OpenStorageArea() is called only once per process
-  // (areas_open_count[area] is 0).
-  references.area_ = references.namespace_->GetOpenStorageArea(origin);
-  if (!references.area_ || !areas_open_count_[references.area_.get()]) {
-    references.area_ = references.namespace_->OpenStorageArea(origin);
-    DCHECK(references.area_.get());
-    DCHECK_EQ(0, areas_open_count_[references.area_.get()]);
-  }
-  ++areas_open_count_[references.area_.get()];
-  connections_[connection_id] = references;
-  return base::nullopt;
-}
-
-void DOMStorageHost::CloseStorageArea(int connection_id) {
-  const auto found = connections_.find(connection_id);
-  if (found == connections_.end())
-    return;
-  DOMStorageArea* area = found->second.area_.get();
-  DCHECK(areas_open_count_[area]);
-
-  // namespace->CloseStorageArea() is called only once per process
-  // (areas_open_count[area] becomes 0).
-  if (--areas_open_count_[area] == 0) {
-    found->second.namespace_->CloseStorageArea(area);
-    areas_open_count_.erase(area);
-  }
-  connections_.erase(found);
-}
-
-bool DOMStorageHost::ExtractAreaValues(
-    int connection_id, DOMStorageValuesMap* map) {
-  map->clear();
-  DOMStorageArea* area = GetOpenArea(connection_id);
-  if (!area)
-    return false;
-  if (area->IsMapReloadNeeded()) {
-    DOMStorageNamespace* ns = GetNamespace(connection_id);
-    DCHECK(ns);
-    context_->PurgeMemory(DOMStorageContextImpl::PURGE_IF_NEEDED);
-  }
-  area->ExtractValues(map);
-  return true;
-}
-
-unsigned DOMStorageHost::GetAreaLength(int connection_id) {
-  DOMStorageArea* area = GetOpenArea(connection_id);
-  if (!area)
-    return 0;
-  return area->Length();
-}
-
-base::NullableString16 DOMStorageHost::GetAreaKey(int connection_id,
-                                                  unsigned index) {
-  DOMStorageArea* area = GetOpenArea(connection_id);
-  if (!area)
-    return base::NullableString16();
-  return area->Key(index);
-}
-
-base::NullableString16 DOMStorageHost::GetAreaItem(int connection_id,
-                                                   const base::string16& key) {
-  DOMStorageArea* area = GetOpenArea(connection_id);
-  if (!area)
-    return base::NullableString16();
-  return area->GetItem(key);
-}
-
-bool DOMStorageHost::SetAreaItem(int connection_id,
-                                 const base::string16& key,
-                                 const base::string16& value,
-                                 const base::NullableString16& client_old_value,
-                                 const GURL& page_url) {
-  DOMStorageArea* area = GetOpenArea(connection_id);
-  if (!area)
-    return false;
-  base::NullableString16 old_value;
-  if (!area->SetItem(key, value, client_old_value, &old_value))
-    return false;
-  if (old_value.is_null() || old_value.string() != value)
-    context_->NotifyItemSet(area, key, value, old_value, page_url);
-  return true;
-}
-
-bool DOMStorageHost::RemoveAreaItem(
-    int connection_id,
-    const base::string16& key,
-    const base::NullableString16& client_old_value,
-    const GURL& page_url) {
-  DOMStorageArea* area = GetOpenArea(connection_id);
-  if (!area)
-    return false;
-  base::string16 old_value;
-  if (!area->RemoveItem(key, client_old_value, &old_value))
-    return false;
-  context_->NotifyItemRemoved(area, key, old_value, page_url);
-  return true;
-}
-
-bool DOMStorageHost::ClearArea(int connection_id, const GURL& page_url) {
-  DOMStorageArea* area = GetOpenArea(connection_id);
-  if (!area)
-    return false;
-  if (!area->Clear())
-    return false;
-  context_->NotifyAreaCleared(area, page_url);
-  return true;
-}
-
-bool DOMStorageHost::HasAreaOpen(const std::string& namespace_id,
-                                 const url::Origin& origin) const {
-  for (const auto& it : connections_) {
-    if (namespace_id == it.second.namespace_->namespace_id() &&
-        origin == it.second.area_->origin()) {
-      return true;
-    }
-  }
-  return false;
-}
-
-DOMStorageArea* DOMStorageHost::GetOpenArea(int connection_id) const {
-  const auto found = connections_.find(connection_id);
-  if (found == connections_.end())
-    return nullptr;
-  return found->second.area_.get();
-}
-
-DOMStorageNamespace* DOMStorageHost::GetNamespace(int connection_id) const {
-  const auto found = connections_.find(connection_id);
-  if (found == connections_.end())
-    return nullptr;
-  return found->second.namespace_.get();
-}
-
-// NamespaceAndArea
-
-DOMStorageHost::NamespaceAndArea::NamespaceAndArea() {}
-DOMStorageHost::NamespaceAndArea::NamespaceAndArea(
-    const NamespaceAndArea& other) = default;
-DOMStorageHost::NamespaceAndArea::~NamespaceAndArea() {}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/dom_storage_host.h b/content/browser/dom_storage/dom_storage_host.h
deleted file mode 100644
index 9cc5e7d..0000000
--- a/content/browser/dom_storage/dom_storage_host.h
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2013 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_DOM_STORAGE_DOM_STORAGE_HOST_H_
-#define CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_HOST_H_
-
-#include <map>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/optional.h"
-#include "base/strings/nullable_string16.h"
-#include "base/strings/string16.h"
-#include "content/browser/bad_message.h"
-#include "content/common/content_export.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-
-class GURL;
-
-namespace url {
-class Origin;
-}
-
-namespace content {
-
-class DOMStorageContextImpl;
-class DOMStorageHost;
-class DOMStorageNamespace;
-class DOMStorageArea;
-
-// One instance is allocated in the main process for each client process.
-// Used by DOMStorageMessageFilter in Chrome.
-// This class is single threaded, and performs blocking file reads/writes,
-// so it shouldn't be used on chrome's IO thread.
-// See class comments for DOMStorageContextImpl for a larger overview.
-class CONTENT_EXPORT DOMStorageHost {
- public:
-  explicit DOMStorageHost(DOMStorageContextImpl* context);
-  ~DOMStorageHost();
-
-  base::Optional<bad_message::BadMessageReason> OpenStorageArea(
-      int connection_id,
-      const std::string& namespace_id,
-      const url::Origin& origin);
-  void CloseStorageArea(int connection_id);
-  bool ExtractAreaValues(int connection_id, DOMStorageValuesMap* map);
-  unsigned GetAreaLength(int connection_id);
-  base::NullableString16 GetAreaKey(int connection_id, unsigned index);
-  base::NullableString16 GetAreaItem(int connection_id,
-                                     const base::string16& key);
-  bool SetAreaItem(int connection_id,
-                   const base::string16& key,
-                   const base::string16& value,
-                   const base::NullableString16& client_old_value,
-                   const GURL& page_url);
-  bool RemoveAreaItem(int connection_id,
-                      const base::string16& key,
-                      const base::NullableString16& client_old_value,
-                      const GURL& page_url);
-  bool ClearArea(int connection_id, const GURL& page_url);
-  bool HasAreaOpen(const std::string& namespace_id,
-                   const url::Origin& origin) const;
-  bool HasConnection(int connection_id) const {
-    return !!GetOpenArea(connection_id);
-  }
-
- private:
-  // Struct to hold references needed for areas that are open
-  // within our associated client process.
-  struct NamespaceAndArea {
-    scoped_refptr<DOMStorageNamespace> namespace_;
-    scoped_refptr<DOMStorageArea> area_;
-    NamespaceAndArea();
-    NamespaceAndArea(const NamespaceAndArea& other);
-    ~NamespaceAndArea();
-  };
-  typedef std::map<int, NamespaceAndArea > AreaMap;
-
-  DOMStorageArea* GetOpenArea(int connection_id) const;
-  DOMStorageNamespace* GetNamespace(int connection_id) const;
-
-  scoped_refptr<DOMStorageContextImpl> context_;
-  AreaMap connections_;
-  std::map<DOMStorageArea*, int> areas_open_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(DOMStorageHost);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_HOST_H_
diff --git a/content/browser/dom_storage/dom_storage_namespace.cc b/content/browser/dom_storage/dom_storage_namespace.cc
deleted file mode 100644
index 2f1f8559..0000000
--- a/content/browser/dom_storage/dom_storage_namespace.cc
+++ /dev/null
@@ -1,220 +0,0 @@
-// Copyright 2013 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/dom_storage/dom_storage_namespace.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
-#include "content/browser/dom_storage/dom_storage_task_runner.h"
-#include "content/browser/dom_storage/session_storage_database.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-#include "url/origin.h"
-
-namespace content {
-
-DOMStorageNamespace::DOMStorageNamespace(
-    const std::string& namespace_id,
-    SessionStorageDatabase* session_storage_database,
-    DOMStorageTaskRunner* task_runner)
-    : namespace_id_(namespace_id),
-      task_runner_(task_runner),
-      session_storage_database_(session_storage_database) {
-  DCHECK(!namespace_id_.empty());
-}
-
-DOMStorageNamespace::~DOMStorageNamespace() {
-}
-
-DOMStorageArea* DOMStorageNamespace::OpenStorageArea(
-    const url::Origin& origin) {
-  if (AreaHolder* holder = GetAreaHolder(origin)) {
-    ++(holder->open_count_);
-#if defined(OS_ANDROID)
-    if (holder->open_count_ > 1)
-      holder->area_->SetCacheOnlyKeys(false);
-#endif
-    return holder->area_.get();
-  }
-  DOMStorageArea* area;
-  area =
-      new DOMStorageArea(namespace_id_, std::vector<std::string>(), origin,
-                         session_storage_database_.get(), task_runner_.get());
-  areas_[origin] = AreaHolder(area, 1);
-  return area;
-}
-
-void DOMStorageNamespace::CloseStorageArea(DOMStorageArea* area) {
-  AreaHolder* holder = GetAreaHolder(area->origin());
-  DCHECK(holder);
-  DCHECK_EQ(holder->area_.get(), area);
-  --(holder->open_count_);
-  // TODO(ssid): disable caching when the open count goes to 0 and it's safe,
-  // crbug.com/743187.
-}
-
-DOMStorageArea* DOMStorageNamespace::GetOpenStorageArea(
-    const url::Origin& origin) {
-  AreaHolder* holder = GetAreaHolder(origin);
-  if (holder && holder->open_count_)
-    return holder->area_.get();
-  return nullptr;
-}
-
-scoped_refptr<DOMStorageNamespace> DOMStorageNamespace::Clone(
-    const std::string& clone_namespace_id) {
-  DCHECK(!namespace_id_.empty());
-  DCHECK(!clone_namespace_id.empty());
-  auto clone = base::MakeRefCounted<DOMStorageNamespace>(
-      clone_namespace_id, session_storage_database_.get(), task_runner_.get());
-  AreaMap::const_iterator it = areas_.begin();
-  // Clone the in-memory structures.
-  for (; it != areas_.end(); ++it) {
-    DOMStorageArea* area = it->second.area_->ShallowCopy(clone_namespace_id);
-    clone->areas_[it->first] = AreaHolder(area, 0);
-  }
-  // And clone the on-disk structures, too.
-  if (session_storage_database_) {
-    auto clone_task = base::BindOnce(
-        base::IgnoreResult(&SessionStorageDatabase::CloneNamespace),
-        session_storage_database_, namespace_id_, clone_namespace_id);
-    auto callback =
-        base::BindOnce(&DOMStorageNamespace::OnCloneStorageDone, clone);
-    task_runner_->GetSequencedTaskRunner(DOMStorageTaskRunner::COMMIT_SEQUENCE)
-        ->PostTaskAndReply(FROM_HERE, std::move(clone_task),
-                           std::move(callback));
-  }
-  return clone;
-}
-
-void DOMStorageNamespace::DeleteSessionStorageOrigin(
-    const url::Origin& origin) {
-  DOMStorageArea* area = OpenStorageArea(origin);
-  area->FastClear();
-  CloseStorageArea(area);
-}
-
-void DOMStorageNamespace::PurgeMemory(bool aggressively) {
-  auto it = areas_.begin();
-  while (it != areas_.end()) {
-    const AreaHolder& holder = it->second;
-
-    // We can't purge if there are changes pending.
-    if (holder.area_->HasUncommittedChanges()) {
-      if (holder.open_count_ == 0) {
-         // Schedule an immediate commit so the next time we're asked to purge,
-         // we can drop it from memory.
-         holder.area_->ScheduleImmediateCommit();
-      }
-      ++it;
-      continue;
-    }
-
-    // If not in use, we can shut it down and remove
-    // it from our collection entirely.
-    if (holder.open_count_ == 0) {
-      holder.area_->Shutdown();
-      areas_.erase(it++);
-      continue;
-    }
-
-    if (aggressively) {
-      // If aggressive is true, we clear caches and such
-      // for opened areas.
-      holder.area_->PurgeMemory();
-    }
-
-    ++it;
-  }
-}
-
-void DOMStorageNamespace::Shutdown() {
-  AreaMap::const_iterator it = areas_.begin();
-  for (; it != areas_.end(); ++it)
-    it->second.area_->Shutdown();
-}
-
-void DOMStorageNamespace::Flush() {
-  for (auto& entry : areas_) {
-    if (!entry.second.area_->HasUncommittedChanges())
-      continue;
-    entry.second.area_->ScheduleImmediateCommit();
-  }
-}
-
-DOMStorageNamespace::UsageStatistics DOMStorageNamespace::GetUsageStatistics()
-    const {
-  UsageStatistics stats = {0};
-  for (auto it = areas_.begin(); it != areas_.end(); ++it) {
-    if (it->second.area_->map_memory_used()) {
-      stats.total_cache_size += it->second.area_->map_memory_used();
-      ++stats.total_area_count;
-      if (it->second.open_count_ == 0)
-        ++stats.inactive_area_count;
-    }
-  }
-  return stats;
-}
-
-void DOMStorageNamespace::OnMemoryDump(
-    base::trace_event::ProcessMemoryDump* pmd) {
-  task_runner_->AssertIsRunningOnPrimarySequence();
-  for (const auto& it : areas_)
-    it.second.area_->OnMemoryDump(pmd);
-}
-
-void DOMStorageNamespace::GetOriginsWithAreas(
-    std::vector<url::Origin>* origins) const {
-  origins->clear();
-  for (const auto& entry : areas_)
-    origins->push_back(entry.first);
-}
-
-int DOMStorageNamespace::GetAreaOpenCount(const url::Origin& origin) const {
-  const auto& found = areas_.find(origin);
-  if (found == areas_.end())
-    return 0;
-  return found->second.open_count_;
-}
-
-DOMStorageNamespace::AreaHolder* DOMStorageNamespace::GetAreaHolder(
-    const url::Origin& origin) {
-  auto found = areas_.find(origin);
-  if (found == areas_.end())
-    return nullptr;
-  return &(found->second);
-}
-
-void DOMStorageNamespace::OnCloneStorageDone() {
-  task_runner_->AssertIsRunningOnPrimarySequence();
-  // Shallow copy of commit batches are no longer needed since the database is
-  // cloned.
-  for (AreaMap::const_iterator it = areas_.begin(); it != areas_.end(); ++it)
-    it->second.area_->ClearShallowCopiedCommitBatches();
-}
-
-// AreaHolder
-
-DOMStorageNamespace::AreaHolder::AreaHolder()
-    : open_count_(0) {
-}
-
-DOMStorageNamespace::AreaHolder::AreaHolder(
-    DOMStorageArea* area, int count)
-    : area_(area), open_count_(count) {
-}
-
-DOMStorageNamespace::AreaHolder& DOMStorageNamespace::AreaHolder::operator=(
-    AreaHolder&& other) {
-  area_ = std::move(other.area_);
-  open_count_ = other.open_count_;
-  return *this;
-}
-
-DOMStorageNamespace::AreaHolder::~AreaHolder() {
-}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/dom_storage_namespace.h b/content/browser/dom_storage/dom_storage_namespace.h
deleted file mode 100644
index fc2a5c68..0000000
--- a/content/browser/dom_storage/dom_storage_namespace.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2013 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_DOM_STORAGE_DOM_STORAGE_NAMESPACE_H_
-#define CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_NAMESPACE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "content/common/content_export.h"
-#include "url/gurl.h"
-
-namespace base {
-namespace trace_event {
-class ProcessMemoryDump;
-}
-}
-
-namespace url {
-class Origin;
-}
-
-namespace content {
-
-class DOMStorageArea;
-class DOMStorageTaskRunner;
-class SessionStorageDatabase;
-
-// Container for the set of per-origin Areas.
-// See class comments for DOMStorageContextImpl for a larger overview.
-class CONTENT_EXPORT DOMStorageNamespace
-    : public base::RefCountedThreadSafe<DOMStorageNamespace> {
- public:
-  // Struct to hold statistics about the areas in the namespace.
-  struct UsageStatistics {
-    size_t total_cache_size;
-    unsigned total_area_count;
-    unsigned inactive_area_count;  // areas with open count 0.
-  };
-
-  // Constructor for a SessionStorage namespace with the given namespace id and
-  // an optional backing on disk via |session_storage_database| (may be NULL).
-  DOMStorageNamespace(const std::string& namespace_id,
-                      SessionStorageDatabase* session_storage_database,
-                      DOMStorageTaskRunner* task_runner);
-
-  const std::string& namespace_id() const { return namespace_id_; }
-
-  // Returns the storage area for the given origin,
-  // creating instance if needed. Each call to open
-  // must be balanced with a call to CloseStorageArea.
-  DOMStorageArea* OpenStorageArea(const url::Origin& origin);
-  void CloseStorageArea(DOMStorageArea* area);
-
-  // Returns the area for |origin| if it's open, otherwise NULL.
-  DOMStorageArea* GetOpenStorageArea(const url::Origin& origin);
-
-  // Creates a clone of |this| namespace including
-  // shallow copies of all contained areas.
-  // Should only be called for session storage namespaces.
-  scoped_refptr<DOMStorageNamespace> Clone(
-      const std::string& clone_namespace_id);
-
-  void DeleteSessionStorageOrigin(const url::Origin& origin);
-  void PurgeMemory(bool aggressively);
-  void Shutdown();
-  void Flush();
-
-  // Returns statistics about the areas in the namespace.
-  UsageStatistics GetUsageStatistics() const;
-
-  // Adds memory statistics to |pmd| for chrome://tracing.
-  void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd);
-
-  void GetOriginsWithAreas(std::vector<url::Origin>* origins) const;
-
-  int GetAreaOpenCount(const url::Origin& origin) const;
-
- private:
-  friend class base::RefCountedThreadSafe<DOMStorageNamespace>;
-
-  // Struct to hold references to our contained areas and
-  // to keep track of how many tabs have a given area open.
-  struct AreaHolder {
-    scoped_refptr<DOMStorageArea> area_;
-    int open_count_;
-
-    AreaHolder();
-    AreaHolder(DOMStorageArea* area, int count);
-    AreaHolder& operator=(AreaHolder&& other);
-    ~AreaHolder();
-    DISALLOW_COPY_AND_ASSIGN(AreaHolder);
-  };
-  typedef std::map<url::Origin, AreaHolder> AreaMap;
-
-  ~DOMStorageNamespace();
-
-  // Returns a pointer to the area holder in our map or NULL.
-  AreaHolder* GetAreaHolder(const url::Origin& origin);
-
-  void OnCloneStorageDone();
-
-  const std::string namespace_id_;
-  AreaMap areas_;
-  const scoped_refptr<DOMStorageTaskRunner> task_runner_;
-  const scoped_refptr<SessionStorageDatabase> session_storage_database_;
-};
-
-}  // namespace content
-
-
-#endif  // CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_NAMESPACE_H_
diff --git a/content/browser/dom_storage/local_storage_context_mojo.cc b/content/browser/dom_storage/local_storage_context_mojo.cc
index 00c0b11..24912064 100644
--- a/content/browser/dom_storage/local_storage_context_mojo.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo.cc
@@ -25,9 +25,7 @@
 #include "build/build_config.h"
 #include "components/services/leveldb/public/cpp/util.h"
 #include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
 #include "content/browser/dom_storage/dom_storage_database.h"
-#include "content/browser/dom_storage/dom_storage_task_runner.h"
 #include "content/browser/dom_storage/local_storage_database.pb.h"
 #include "content/browser/dom_storage/storage_area_impl.h"
 #include "content/common/dom_storage/dom_storage_types.h"
@@ -36,6 +34,7 @@
 #include "services/service_manager/public/cpp/connector.h"
 #include "sql/database.h"
 #include "storage/browser/quota/special_storage_policy.h"
+#include "storage/common/database/database_identifier.h"
 #include "third_party/leveldatabase/env_chromium.h"
 #include "third_party/leveldatabase/leveldb_chrome.h"
 
@@ -357,7 +356,7 @@
     if (context_->old_localstorage_path_.empty())
       return base::FilePath();
     return context_->old_localstorage_path_.Append(
-        DOMStorageArea::DatabaseFileNameFromOrigin(origin_));
+        LocalStorageContextMojo::LegacyDatabaseFileNameFromOrigin(origin_));
   }
 
   LocalStorageContextMojo* context_;
@@ -372,6 +371,30 @@
   bool has_bindings_ = false;
 };
 
+const base::FilePath::CharType
+    LocalStorageContextMojo::kLegacyDatabaseFileExtension[] =
+        FILE_PATH_LITERAL(".localstorage");
+
+// static
+base::FilePath LocalStorageContextMojo::LegacyDatabaseFileNameFromOrigin(
+    const url::Origin& origin) {
+  std::string filename = storage::GetIdentifierFromOrigin(origin);
+  // There is no base::FilePath.AppendExtension() method, so start with just the
+  // extension as the filename, and then InsertBeforeExtension the desired
+  // name.
+  return base::FilePath()
+      .Append(kLegacyDatabaseFileExtension)
+      .InsertBeforeExtensionASCII(filename);
+}
+
+// static
+url::Origin LocalStorageContextMojo::OriginFromLegacyDatabaseFileName(
+    const base::FilePath& name) {
+  DCHECK(name.MatchesExtension(kLegacyDatabaseFileExtension));
+  std::string origin_id = name.BaseName().RemoveExtension().MaybeAsASCII();
+  return storage::GetOriginFromIdentifier(origin_id);
+}
+
 LocalStorageContextMojo::LocalStorageContextMojo(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     service_manager::Connector* connector,
diff --git a/content/browser/dom_storage/local_storage_context_mojo.h b/content/browser/dom_storage/local_storage_context_mojo.h
index 84634b3b..78dc38f8 100644
--- a/content/browser/dom_storage/local_storage_context_mojo.h
+++ b/content/browser/dom_storage/local_storage_context_mojo.h
@@ -17,6 +17,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/trace_event/memory_dump_provider.h"
 #include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
+#include "content/browser/dom_storage/dom_storage_task_runner.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
 #include "services/file/public/mojom/file_system.mojom.h"
@@ -48,6 +49,13 @@
   using GetStorageUsageCallback =
       base::OnceCallback<void(std::vector<StorageUsageInfo>)>;
 
+  static const base::FilePath::CharType kLegacyDatabaseFileExtension[];
+
+  static base::FilePath LegacyDatabaseFileNameFromOrigin(
+      const url::Origin& origin);
+  static url::Origin OriginFromLegacyDatabaseFileName(
+      const base::FilePath& file_name);
+
   LocalStorageContextMojo(
       scoped_refptr<base::SequencedTaskRunner> task_runner,
       service_manager::Connector* connector,
@@ -96,6 +104,10 @@
   // Converts a string from the old storage format to the new storage format.
   static std::vector<uint8_t> MigrateString(const base::string16& input);
 
+  scoped_refptr<DOMStorageTaskRunner> legacy_task_runner() {
+    return task_runner_;
+  }
+
  private:
   friend class DOMStorageBrowserTest;
 
diff --git a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
index 762dadb..177718dde 100644
--- a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -16,10 +16,7 @@
 #include "build/build_config.h"
 #include "components/services/filesystem/public/interfaces/file_system.mojom.h"
 #include "components/services/leveldb/public/cpp/util.h"
-#include "content/browser/dom_storage/dom_storage_area.h"
-#include "content/browser/dom_storage/dom_storage_context_impl.h"
 #include "content/browser/dom_storage/dom_storage_database.h"
-#include "content/browser/dom_storage/dom_storage_namespace.h"
 #include "content/browser/dom_storage/dom_storage_task_runner.h"
 #include "content/browser/dom_storage/test/fake_leveldb_database_error_on_write.h"
 #include "content/browser/dom_storage/test/fake_leveldb_service.h"
@@ -51,9 +48,6 @@
 using test::FakeLevelDBService;
 using test::FakeLevelDBDatabaseErrorOnWrite;
 
-// An empty namespace is the local storage namespace.
-constexpr const char kLocalStorageNamespaceId[] = "";
-
 void GetStorageUsageCallback(const base::RepeatingClosure& callback,
                              std::vector<StorageUsageInfo>* out_result,
                              std::vector<StorageUsageInfo> result) {
@@ -122,13 +116,9 @@
             base::ThreadTaskRunnerHandle::Get().get())),
         mock_special_storage_policy_(new MockSpecialStoragePolicy()) {
     EXPECT_TRUE(temp_path_.CreateUniqueTempDir());
-    dom_storage_context_ =
-        new DOMStorageContextImpl(base::FilePath(), nullptr, task_runner_);
   }
 
   ~LocalStorageContextMojoTest() override {
-    if (dom_storage_context_)
-      dom_storage_context_->Shutdown();
     if (context_)
       ShutdownContext();
   }
@@ -154,10 +144,6 @@
     base::RunLoop().RunUntilIdle();
   }
 
-  DOMStorageNamespace* local_storage_namespace() {
-    return dom_storage_context_->GetStorageNamespace(kLocalStorageNamespaceId);
-  }
-
   MockSpecialStoragePolicy* special_storage_policy() {
     return mock_special_storage_policy_.get();
   }
@@ -206,7 +192,6 @@
   mojo::AssociatedBinding<leveldb::mojom::LevelDBDatabase> db_binding_;
 
   scoped_refptr<MockDOMStorageTaskRunner> task_runner_;
-  scoped_refptr<DOMStorageContextImpl> dom_storage_context_;
 
   LocalStorageContextMojo* context_ = nullptr;
 
@@ -631,8 +616,8 @@
   key2.push_back(0xd83d);
   key2.push_back(0xde00);
 
-  base::FilePath old_db_path =
-      TempPath().Append(DOMStorageArea::DatabaseFileNameFromOrigin(origin1));
+  base::FilePath old_db_path = TempPath().Append(
+      LocalStorageContextMojo::LegacyDatabaseFileNameFromOrigin(origin1));
   {
     DOMStorageDatabase db(old_db_path);
     DOMStorageValuesMap data;
diff --git a/content/browser/dom_storage/session_storage_context_mojo.cc b/content/browser/dom_storage/session_storage_context_mojo.cc
index c67f792..4a0c263 100644
--- a/content/browser/dom_storage/session_storage_context_mojo.cc
+++ b/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -111,7 +111,6 @@
       memory_dump_id_(base::StringPrintf("SessionStorage/0x%" PRIXPTR,
                                          reinterpret_cast<uintptr_t>(this))),
       is_low_end_device_(base::SysInfo::IsLowEndDevice()) {
-  DCHECK(base::FeatureList::IsEnabled(blink::features::kOnionSoupDOMStorage));
   base::trace_event::MemoryDumpManager::GetInstance()
       ->RegisterDumpProviderWithSequencedTaskRunner(
           this, "SessionStorage", std::move(memory_dump_task_runner),
@@ -769,7 +768,6 @@
 
 void SessionStorageContextMojo::OnMojoConnectionDestroyed() {
   UMA_HISTOGRAM_BOOLEAN("SessionStorageContext.OnConnectionDestroyed", true);
-  LOG(ERROR) << "Lost connection to database";
   for (const auto& it : data_maps_)
     it.second->storage_area()->CancelAllPendingRequests();
 
@@ -1029,7 +1027,6 @@
 
 void SessionStorageContextMojo::LogDatabaseOpenResult(OpenResult result) {
   if (result != OpenResult::kSuccess) {
-    LOG(ERROR) << "Got error when opening: " << static_cast<int>(result);
     UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.OpenError", result);
   }
   if (open_result_histogram_) {
diff --git a/content/browser/dom_storage/session_storage_context_mojo_unittest.cc b/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
index 615fa47e..c211108 100644
--- a/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
+++ b/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
@@ -17,7 +17,6 @@
 #include "base/sequenced_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
-#include "base/test/scoped_feature_list.h"
 #include "components/services/leveldb/public/cpp/util.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/dom_storage/session_storage_database.h"
@@ -63,7 +62,6 @@
   }
 
   void SetUp() override {
-    features_.InitAndEnableFeature(blink::features::kOnionSoupDOMStorage);
     mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
         &SessionStorageContextMojoTest::OnBadMessage, base::Unretained(this)));
 
@@ -167,7 +165,6 @@
   TestBrowserContext browser_context_;
   SessionStorageContextMojo::BackingMode backing_mode_ =
       SessionStorageContextMojo::BackingMode::kRestoreDiskState;
-  base::test::ScopedFeatureList features_;
   SessionStorageContextMojo* context_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(SessionStorageContextMojoTest);
diff --git a/content/browser/dom_storage/session_storage_database.h b/content/browser/dom_storage/session_storage_database.h
index c541d53..991caf0e 100644
--- a/content/browser/dom_storage/session_storage_database.h
+++ b/content/browser/dom_storage/session_storage_database.h
@@ -22,7 +22,6 @@
 #include "base/sequenced_task_runner.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
-#include "content/common/content_export.h"
 #include "content/common/dom_storage/dom_storage_types.h"
 #include "third_party/leveldatabase/src/include/leveldb/status.h"
 
@@ -51,7 +50,7 @@
 // This class is not thread safe. Read-only methods (ReadAreaValues,
 // ReadNamespacesAndOrigins, and OnMemoryDump) may be called on any thread.
 // Methods that modify the database must be called on the same thread.
-class CONTENT_EXPORT SessionStorageDatabase
+class SessionStorageDatabase
     : public base::RefCountedDeleteOnSequence<SessionStorageDatabase> {
  public:
   // |file_path| is the path to the directory where the database will be
diff --git a/content/browser/dom_storage/session_storage_database_adapter.cc b/content/browser/dom_storage/session_storage_database_adapter.cc
deleted file mode 100644
index fb29b8a..0000000
--- a/content/browser/dom_storage/session_storage_database_adapter.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2013 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/dom_storage/session_storage_database_adapter.h"
-
-#include "content/browser/dom_storage/session_storage_database.h"
-
-namespace content {
-
-SessionStorageDatabaseAdapter::SessionStorageDatabaseAdapter(
-    SessionStorageDatabase* db,
-    const std::string& permanent_namespace_id,
-    const std::vector<std::string>& original_permanent_namespace_ids,
-    const url::Origin& origin)
-    : db_(db),
-      permanent_namespace_id_(permanent_namespace_id),
-      original_permanent_namespace_ids_(original_permanent_namespace_ids),
-      origin_(origin) {}
-
-SessionStorageDatabaseAdapter::~SessionStorageDatabaseAdapter() { }
-
-void SessionStorageDatabaseAdapter::ReadAllValues(DOMStorageValuesMap* result) {
-  db_->ReadAreaValues(permanent_namespace_id_,
-                      original_permanent_namespace_ids_, origin_, result);
-}
-
-bool SessionStorageDatabaseAdapter::CommitChanges(
-    bool clear_all_first, const DOMStorageValuesMap& changes) {
-  return db_->CommitAreaChanges(permanent_namespace_id_, origin_,
-                                clear_all_first, changes);
-}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/session_storage_database_adapter.h b/content/browser/dom_storage/session_storage_database_adapter.h
deleted file mode 100644
index b1c5fb67..0000000
--- a/content/browser/dom_storage/session_storage_database_adapter.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 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_DOM_STORAGE_SESSION_STORAGE_DATABASE_ADAPTER_H_
-#define CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATABASE_ADAPTER_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/browser/dom_storage/dom_storage_database_adapter.h"
-#include "url/origin.h"
-
-namespace content {
-
-class SessionStorageDatabase;
-
-class SessionStorageDatabaseAdapter : public DOMStorageDatabaseAdapter {
- public:
-  SessionStorageDatabaseAdapter(
-      SessionStorageDatabase* db,
-      const std::string& permanent_namespace_id,
-      const std::vector<std::string>& original_permanent_namespace_ids,
-      const url::Origin& origin);
-  ~SessionStorageDatabaseAdapter() override;
-  void ReadAllValues(DOMStorageValuesMap* result) override;
-  bool CommitChanges(bool clear_all_first,
-                     const DOMStorageValuesMap& changes) override;
-
- private:
-  scoped_refptr<SessionStorageDatabase> db_;
-  std::string permanent_namespace_id_;
-  // IDs of original databases in order of ShallowCopy(s).
-  std::vector<std::string> original_permanent_namespace_ids_;
-  url::Origin origin_;
-
-  DISALLOW_COPY_AND_ASSIGN(SessionStorageDatabaseAdapter);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_BROWSER_DOM_STORAGE_SESSION_STORAGE_DATABASE_ADAPTER_H_
diff --git a/content/browser/dom_storage/session_storage_database_unittest.cc b/content/browser/dom_storage/session_storage_database_unittest.cc
deleted file mode 100644
index c8f00281..0000000
--- a/content/browser/dom_storage/session_storage_database_unittest.cc
+++ /dev/null
@@ -1,848 +0,0 @@
-// Copyright 2013 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/dom_storage/session_storage_database.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <map>
-#include <string>
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "content/browser/dom_storage/session_storage_metadata.h"
-#include "content/common/dom_storage/dom_storage_types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/leveldatabase/src/include/leveldb/db.h"
-#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
-#include "third_party/leveldatabase/src/include/leveldb/options.h"
-#include "url/origin.h"
-
-namespace content {
-
-class SessionStorageDatabaseTest : public testing::Test {
- public:
-  SessionStorageDatabaseTest();
-  ~SessionStorageDatabaseTest() override;
-  void SetUp() override;
-
- protected:
-  typedef std::map<std::string, std::string> DataMap;
-
-  // Helpers.
-  static bool IsNamespaceKey(const std::string& key,
-                             std::string* namespace_id);
-  static bool IsNamespaceOriginKey(const std::string& key,
-                                   std::string* namespace_id);
-  static bool IsMapRefCountKey(const std::string& key, int64_t* map_id);
-  static bool IsMapValueKey(const std::string& key, int64_t* map_id);
-  void ResetDatabase();
-  void ReadData(DataMap* data) const;
-  void CheckDatabaseConsistency() const;
-  void CheckEmptyDatabase() const;
-  void DumpData() const;
-  void CheckAreaData(const std::string& namespace_id,
-                     const url::Origin& origin,
-                     const DOMStorageValuesMap& reference) const;
-  void CompareValuesMaps(const DOMStorageValuesMap& map1,
-                         const DOMStorageValuesMap& map2) const;
-  void CheckNamespaceIds(
-      const std::set<std::string>& expected_namespace_ids) const;
-  void CheckOrigins(const std::string& namespace_id,
-                    const std::set<url::Origin>& expected_origins) const;
-  std::string GetMapForArea(const std::string& namespace_id,
-                            const url::Origin& origin) const;
-  int64_t GetMapRefCount(const std::string& map_id) const;
-
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  base::ScopedTempDir temp_dir_;
-  scoped_refptr<SessionStorageDatabase> db_;
-
-  // Test data.
-  const url::Origin kOrigin1;
-  const url::Origin kOrigin2;
-  const std::string kNamespace1;
-  const std::string kNamespace2;
-  const std::string kNamespaceClone;
-  const base::string16 kKey1;
-  const base::string16 kKey2;
-  const base::string16 kKey3;
-  const base::NullableString16 kValue1;
-  const base::NullableString16 kValue2;
-  const base::NullableString16 kValue3;
-  const base::NullableString16 kValue4;
-  const base::NullableString16 kValueNull;
-
-  DISALLOW_COPY_AND_ASSIGN(SessionStorageDatabaseTest);
-};
-
-SessionStorageDatabaseTest::SessionStorageDatabaseTest()
-    : kOrigin1(url::Origin::Create(GURL("http://www.origin1.com"))),
-      kOrigin2(url::Origin::Create(GURL("http://www.origin2.com"))),
-      kNamespace1("namespace1"),
-      kNamespace2("namespace2"),
-      kNamespaceClone("wascloned"),
-      kKey1(base::ASCIIToUTF16("key1")),
-      kKey2(base::ASCIIToUTF16("key2")),
-      kKey3(base::ASCIIToUTF16("key3")),
-      kValue1(base::ASCIIToUTF16("value1"), false),
-      kValue2(base::ASCIIToUTF16("value2"), false),
-      kValue3(base::ASCIIToUTF16("value3"), false),
-      kValue4(base::ASCIIToUTF16("value4"), false) {}
-
-SessionStorageDatabaseTest::~SessionStorageDatabaseTest() { }
-
-void SessionStorageDatabaseTest::SetUp() {
-  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  ResetDatabase();
-}
-
-void SessionStorageDatabaseTest::ResetDatabase() {
-  db_ = new SessionStorageDatabase(temp_dir_.GetPath(),
-                                   base::ThreadTaskRunnerHandle::Get());
-  ASSERT_TRUE(db_->LazyOpen(true));
-}
-
-// static
-bool SessionStorageDatabaseTest::IsNamespaceKey(const std::string& key,
-                                                std::string* namespace_id) {
-  std::string namespace_prefix = SessionStorageDatabase::NamespacePrefix();
-  if (!base::StartsWith(key, namespace_prefix, base::CompareCase::SENSITIVE))
-    return false;
-  if (key == namespace_prefix)
-    return false;
-
-  size_t second_dash = key.find('-', namespace_prefix.length());
-  if (second_dash != key.length() - 1)
-    return false;
-
-  // Key is of the form "namespace-<namespaceid>-".
-  *namespace_id = key.substr(
-      namespace_prefix.length(),
-      second_dash - namespace_prefix.length());
-  return true;
-}
-
-// static
-bool SessionStorageDatabaseTest::IsNamespaceOriginKey(
-    const std::string& key,
-    std::string* namespace_id) {
-  std::string namespace_prefix = SessionStorageDatabase::NamespacePrefix();
-  if (!base::StartsWith(key, namespace_prefix, base::CompareCase::SENSITIVE))
-    return false;
-  size_t second_dash = key.find('-', namespace_prefix.length());
-  if (second_dash == std::string::npos || second_dash == key.length() - 1)
-    return false;
-
-  // Key is of the form "namespace-<namespaceid>-<origin>", and the value
-  // is the map id.
-  *namespace_id = key.substr(
-      namespace_prefix.length(),
-      second_dash - namespace_prefix.length());
-  return true;
-}
-
-// static
-bool SessionStorageDatabaseTest::IsMapRefCountKey(const std::string& key,
-                                                  int64_t* map_id) {
-  std::string map_prefix = "map-";
-  if (!base::StartsWith(key, map_prefix, base::CompareCase::SENSITIVE))
-    return false;
-  size_t second_dash = key.find('-', map_prefix.length());
-  if (second_dash != key.length() - 1)
-    return false;
-  // Key is of the form "map-<mapid>-" and the value is the ref count.
-  std::string map_id_str = key.substr(map_prefix.length(),
-                                      second_dash - map_prefix.length());
-  bool conversion_ok = base::StringToInt64(map_id_str, map_id);
-  EXPECT_TRUE(conversion_ok);
-  return true;
-}
-
-// static
-bool SessionStorageDatabaseTest::IsMapValueKey(const std::string& key,
-                                               int64_t* map_id) {
-  std::string map_prefix = "map-";
-  if (!base::StartsWith(key, map_prefix, base::CompareCase::SENSITIVE))
-    return false;
-  size_t second_dash = key.find('-', map_prefix.length());
-  if (second_dash == std::string::npos || second_dash == key.length() - 1)
-    return false;
-  // Key is of the form "map-<mapid>-key".
-  std::string map_id_str = key.substr(map_prefix.length(),
-                                      second_dash - map_prefix.length());
-  bool conversion_ok = base::StringToInt64(map_id_str, map_id);
-  EXPECT_TRUE(conversion_ok);
-  return true;
-}
-
-void SessionStorageDatabaseTest::ReadData(DataMap* data) const {
-  leveldb::DB* leveldb = db_->db_.get();
-  std::unique_ptr<leveldb::Iterator> it(
-      leveldb->NewIterator(leveldb::ReadOptions()));
-  for (it->SeekToFirst(); it->Valid(); it->Next()) {
-    (*data)[it->key().ToString()] = it->value().ToString();
-  }
-}
-
-void SessionStorageDatabaseTest::CheckDatabaseConsistency() const {
-  DataMap data;
-  ReadData(&data);
-  // Empty db is ok.
-  if (data.empty())
-    return;
-
-  // For detecting rubbish keys.
-  size_t valid_keys = 0;
-
-  std::string next_map_id_key = SessionStorageDatabase::NextMapIdKey();
-  // Check the namespace start key.
-  if (data.find(SessionStorageDatabase::NamespacePrefix()) == data.end()) {
-    // If there is no namespace start key, the database may contain only counter
-    // keys.
-    for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) {
-      ASSERT_TRUE(it->first == next_map_id_key);
-    }
-    return;
-  }
-  ++valid_keys;
-
-  // Iterate the "namespace-" keys.
-  std::set<std::string> found_namespace_ids;
-  std::set<std::string> namespaces_with_areas;
-  std::map<int64_t, int64_t> expected_map_refcounts;
-  int64_t max_map_id = -1;
-
-  for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) {
-    std::string namespace_id;
-    if (IsNamespaceKey(it->first, &namespace_id)) {
-      found_namespace_ids.insert(namespace_id);
-      ++valid_keys;
-    } else if (IsNamespaceOriginKey(
-        it->first, &namespace_id)) {
-      // Check that the corresponding "namespace-<namespaceid>-" key exists. It
-      // has been read by now, since the keys are stored in order.
-      ASSERT_TRUE(found_namespace_ids.find(namespace_id) !=
-                  found_namespace_ids.end());
-      namespaces_with_areas.insert(namespace_id);
-      int64_t map_id;
-      bool conversion_ok = base::StringToInt64(it->second, &map_id);
-      ASSERT_TRUE(conversion_ok);
-      ASSERT_GE(map_id, 0);
-      ++expected_map_refcounts[map_id];
-      max_map_id = std::max(map_id, max_map_id);
-      ++valid_keys;
-    }
-  }
-  // Check that there are no leftover "namespace-namespaceid-" keys without
-  // associated areas.
-  ASSERT_EQ(found_namespace_ids.size(), namespaces_with_areas.size());
-
-  if (max_map_id != -1) {
-    // The database contains maps.
-    ASSERT_TRUE(data.find(next_map_id_key) != data.end());
-    int64_t next_map_id;
-    bool conversion_ok =
-        base::StringToInt64(data[next_map_id_key], &next_map_id);
-    ASSERT_TRUE(conversion_ok);
-    ASSERT_GT(next_map_id, max_map_id);
-  }
-
-  // Iterate the "map-" keys.
-  std::set<int64_t> found_map_ids;
-  for (DataMap::const_iterator it = data.begin(); it != data.end(); ++it) {
-    int64_t map_id;
-    if (IsMapRefCountKey(it->first, &map_id)) {
-      int64_t ref_count;
-      bool conversion_ok = base::StringToInt64(it->second, &ref_count);
-      ASSERT_TRUE(conversion_ok);
-      // Check that the map is not stale.
-      ASSERT_GT(ref_count, 0);
-      ASSERT_TRUE(expected_map_refcounts.find(map_id) !=
-                  expected_map_refcounts.end());
-      ASSERT_EQ(expected_map_refcounts[map_id], ref_count);
-      // Mark the map as existing.
-      expected_map_refcounts.erase(map_id);
-      found_map_ids.insert(map_id);
-      ++valid_keys;
-    } else if (IsMapValueKey(it->first, &map_id)) {
-      ASSERT_TRUE(found_map_ids.find(map_id) != found_map_ids.end());
-      ++valid_keys;
-    }
-  }
-  // Check that all maps referred to exist.
-  ASSERT_TRUE(expected_map_refcounts.empty());
-
-  if (data.find(next_map_id_key) != data.end())
-    ++valid_keys;
-
-  ASSERT_EQ(data.size(), valid_keys);
-}
-
-void SessionStorageDatabaseTest::CheckEmptyDatabase() const {
-  DataMap data;
-  ReadData(&data);
-  size_t valid_keys = 0;
-  if (data.find(SessionStorageDatabase::NamespacePrefix()) != data.end())
-    ++valid_keys;
-  if (data.find(SessionStorageDatabase::NextMapIdKey()) != data.end())
-    ++valid_keys;
-  EXPECT_EQ(valid_keys, data.size());
-}
-
-void SessionStorageDatabaseTest::DumpData() const {
-  LOG(WARNING) << "---- Session storage contents";
-  std::unique_ptr<leveldb::Iterator> it(
-      db_->db_->NewIterator(leveldb::ReadOptions()));
-  for (it->SeekToFirst(); it->Valid(); it->Next()) {
-    int64_t dummy_map_id;
-    if (IsMapValueKey(it->key().ToString(), &dummy_map_id)) {
-      // Convert the value back to base::string16.
-      base::string16 value;
-      size_t len = it->value().size() / sizeof(base::char16);
-      value.resize(len);
-      value.assign(
-          reinterpret_cast<const base::char16*>(it->value().data()), len);
-      LOG(WARNING) << it->key().ToString() << ": " << value;
-    } else {
-      LOG(WARNING) << it->key().ToString() << ": " << it->value().ToString();
-    }
-  }
-  LOG(WARNING) << "----";
-}
-
-void SessionStorageDatabaseTest::CheckAreaData(
-    const std::string& namespace_id,
-    const url::Origin& origin,
-    const DOMStorageValuesMap& reference) const {
-  DOMStorageValuesMap values;
-  db_->ReadAreaValues(namespace_id, std::vector<std::string>(), origin,
-                      &values);
-  CompareValuesMaps(values, reference);
-}
-
-void SessionStorageDatabaseTest::CompareValuesMaps(
-    const DOMStorageValuesMap& map1,
-    const DOMStorageValuesMap& map2) const {
-  ASSERT_EQ(map2.size(), map1.size());
-  for (auto it = map1.begin(); it != map1.end(); ++it) {
-    base::string16 key = it->first;
-    ASSERT_TRUE(map2.find(key) != map2.end());
-    base::NullableString16 val1 = it->second;
-    base::NullableString16 val2 = map2.find(key)->second;
-    EXPECT_EQ(val2.is_null(), val1.is_null());
-    EXPECT_EQ(val2.string(), val1.string());
-  }
-}
-
-void SessionStorageDatabaseTest::CheckNamespaceIds(
-    const std::set<std::string>& expected_namespace_ids) const {
-  std::map<std::string, std::vector<url::Origin>> namespaces_and_origins;
-  EXPECT_TRUE(db_->ReadNamespacesAndOrigins(&namespaces_and_origins));
-  EXPECT_EQ(expected_namespace_ids.size(), namespaces_and_origins.size());
-  for (auto it = namespaces_and_origins.cbegin();
-       it != namespaces_and_origins.cend(); ++it) {
-    EXPECT_TRUE(expected_namespace_ids.find(it->first) !=
-                expected_namespace_ids.end());
-  }
-}
-
-void SessionStorageDatabaseTest::CheckOrigins(
-    const std::string& namespace_id,
-    const std::set<url::Origin>& expected_origins) const {
-  std::map<std::string, std::vector<url::Origin>> namespaces_and_origins;
-  EXPECT_TRUE(db_->ReadNamespacesAndOrigins(&namespaces_and_origins));
-  const std::vector<url::Origin>& origins =
-      namespaces_and_origins[namespace_id];
-  EXPECT_EQ(expected_origins.size(), origins.size());
-  for (auto it = origins.cbegin(); it != origins.cend(); ++it) {
-    EXPECT_TRUE(expected_origins.find(*it) != expected_origins.end());
-  }
-}
-
-std::string SessionStorageDatabaseTest::GetMapForArea(
-    const std::string& namespace_id,
-    const url::Origin& origin) const {
-  bool exists;
-  std::string map_id;
-  // GetURL().spec() should used here rather than Serialize() to ensure
-  // backwards compatibility with older data. The serializations are
-  // subtly different, e.g. Origin does not include a trailing "/".
-  // Origin without a  trailing "/" should not exist.
-  EXPECT_TRUE(db_->GetMapForArea(namespace_id, origin.Serialize(),
-                                 leveldb::ReadOptions(), &exists, &map_id));
-  EXPECT_FALSE(exists);
-
-  EXPECT_TRUE(db_->GetMapForArea(namespace_id, origin.GetURL().spec(),
-                                 leveldb::ReadOptions(), &exists, &map_id));
-  EXPECT_TRUE(exists);
-  return map_id;
-}
-
-int64_t SessionStorageDatabaseTest::GetMapRefCount(
-    const std::string& map_id) const {
-  int64_t ref_count;
-  EXPECT_TRUE(db_->GetMapRefCount(map_id, &ref_count));
-  return ref_count;
-}
-
-TEST_F(SessionStorageDatabaseTest, EmptyDatabaseSanityCheck) {
-  // An empty database should be valid.
-  CheckDatabaseConsistency();
-}
-
-TEST_F(SessionStorageDatabaseTest, WriteDataForOneOrigin) {
-  // Keep track on what the values should look like.
-  DOMStorageValuesMap reference;
-  // Write data.
-  {
-    DOMStorageValuesMap changes;
-    changes[kKey1] = kValue1;
-    changes[kKey2] = kValue2;
-    changes[kKey3] = kValue3;
-    reference[kKey1] = kValue1;
-    reference[kKey2] = kValue2;
-    reference[kKey3] = kValue3;
-    EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, changes));
-  }
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, reference);
-
-  // Overwrite and delete values.
-  {
-    DOMStorageValuesMap changes;
-    changes[kKey1] = kValue4;
-    changes[kKey3] = kValueNull;
-    reference[kKey1] = kValue4;
-    reference.erase(kKey3);
-    EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, changes));
-  }
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, reference);
-
-  // Clear data before writing.
-  {
-    DOMStorageValuesMap changes;
-    changes[kKey2] = kValue2;
-    reference.erase(kKey1);
-    reference[kKey2] = kValue2;
-    EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, true, changes));
-  }
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, reference);
-}
-
-TEST_F(SessionStorageDatabaseTest, WriteDataForTwoOrigins) {
-  // Write data.
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-
-  DOMStorageValuesMap data2;
-  data2[kKey1] = kValue4;
-  data2[kKey2] = kValue1;
-  data2[kKey3] = kValue2;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, data1);
-  CheckAreaData(kNamespace1, kOrigin2, data2);
-}
-
-TEST_F(SessionStorageDatabaseTest, WriteDataForTwoNamespaces) {
-  // Write data.
-  DOMStorageValuesMap data11;
-  data11[kKey1] = kValue1;
-  data11[kKey2] = kValue2;
-  data11[kKey3] = kValue3;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data11));
-  DOMStorageValuesMap data12;
-  data12[kKey2] = kValue4;
-  data12[kKey3] = kValue3;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data12));
-  DOMStorageValuesMap data21;
-  data21[kKey1] = kValue2;
-  data21[kKey2] = kValue4;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespace2, kOrigin1, false, data21));
-  DOMStorageValuesMap data22;
-  data22[kKey2] = kValue1;
-  data22[kKey3] = kValue2;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespace2, kOrigin2, false, data22));
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, data11);
-  CheckAreaData(kNamespace1, kOrigin2, data12);
-  CheckAreaData(kNamespace2, kOrigin1, data21);
-  CheckAreaData(kNamespace2, kOrigin2, data22);
-}
-
-TEST_F(SessionStorageDatabaseTest, ShallowCopy) {
-  // Write data for a namespace, for 2 origins.
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  DOMStorageValuesMap data2;
-  data2[kKey1] = kValue2;
-  data2[kKey3] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-
-  // Check if passing original id before cloning returns the original's data.
-  DOMStorageValuesMap values;
-  std::vector<std::string> original_ids;
-  original_ids.push_back(kNamespace1);
-  db_->ReadAreaValues(kNamespaceClone, original_ids, kOrigin1, &values);
-  CompareValuesMaps(values, data1);
-
-  original_ids.insert(original_ids.begin(), kNamespace2);
-  values.clear();
-  db_->ReadAreaValues(kNamespaceClone, original_ids, kOrigin1, &values);
-  CompareValuesMaps(values, data1);
-
-  // Make a shallow copy.
-  EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-  // Now both namespaces should have the same data.
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, data1);
-  CheckAreaData(kNamespace1, kOrigin2, data2);
-  CheckAreaData(kNamespaceClone, kOrigin1, data1);
-  CheckAreaData(kNamespaceClone, kOrigin2, data2);
-  // Both the namespaces refer to the same maps.
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
-            GetMapForArea(kNamespaceClone, kOrigin1));
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
-            GetMapForArea(kNamespaceClone, kOrigin2));
-  EXPECT_EQ(2, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin1)));
-  EXPECT_EQ(2, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin2)));
-}
-
-TEST_F(SessionStorageDatabaseTest, WriteIntoShallowCopy) {
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-
-  // Write data into a shallow copy.
-  DOMStorageValuesMap changes;
-  DOMStorageValuesMap reference;
-  changes[kKey1] = kValueNull;
-  changes[kKey2] = kValue4;
-  changes[kKey3] = kValue4;
-  reference[kKey2] = kValue4;
-  reference[kKey3] = kValue4;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespaceClone, kOrigin1, false,
-                                     changes));
-
-  // Values in the original namespace were not changed.
-  CheckAreaData(kNamespace1, kOrigin1, data1);
-  // But values in the copy were.
-  CheckAreaData(kNamespaceClone, kOrigin1, reference);
-
-  // The namespaces no longer refer to the same map.
-  EXPECT_NE(GetMapForArea(kNamespace1, kOrigin1),
-            GetMapForArea(kNamespaceClone, kOrigin1));
-  EXPECT_EQ(1, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin1)));
-  EXPECT_EQ(1, GetMapRefCount(GetMapForArea(kNamespaceClone, kOrigin1)));
-}
-
-TEST_F(SessionStorageDatabaseTest, ManyShallowCopies) {
-  // Write data for a namespace, for 2 origins.
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  DOMStorageValuesMap data2;
-  data2[kKey1] = kValue2;
-  data2[kKey3] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-
-  // Make a two shallow copies.
-  EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-  std::string another_clone("another_cloned");
-  EXPECT_TRUE(db_->CloneNamespace(kNamespace1, another_clone));
-
-  // Make a shallow copy of a shallow copy.
-  std::string clone_of_clone("clone_of_clone");
-  EXPECT_TRUE(db_->CloneNamespace(another_clone, clone_of_clone));
-
-  // Now all namespaces should have the same data.
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, data1);
-  CheckAreaData(kNamespaceClone, kOrigin1, data1);
-  CheckAreaData(another_clone, kOrigin1, data1);
-  CheckAreaData(clone_of_clone, kOrigin1, data1);
-  CheckAreaData(kNamespace1, kOrigin2, data2);
-  CheckAreaData(kNamespaceClone, kOrigin2, data2);
-  CheckAreaData(another_clone, kOrigin2, data2);
-  CheckAreaData(clone_of_clone, kOrigin2, data2);
-
-  // All namespaces refer to the same maps.
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
-            GetMapForArea(kNamespaceClone, kOrigin1));
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
-            GetMapForArea(kNamespaceClone, kOrigin2));
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
-            GetMapForArea(another_clone, kOrigin1));
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
-            GetMapForArea(another_clone, kOrigin2));
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin1),
-            GetMapForArea(clone_of_clone, kOrigin1));
-  EXPECT_EQ(GetMapForArea(kNamespace1, kOrigin2),
-            GetMapForArea(clone_of_clone, kOrigin2));
-
-  // Check the ref counts.
-  EXPECT_EQ(4, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin1)));
-  EXPECT_EQ(4, GetMapRefCount(GetMapForArea(kNamespace1, kOrigin2)));
-}
-
-TEST_F(SessionStorageDatabaseTest, DisassociateShallowCopy) {
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-
-  // Disassoaciate the shallow copy.
-  EXPECT_TRUE(db_->DeleteArea(kNamespaceClone, kOrigin1));
-  CheckDatabaseConsistency();
-
-  // Now new data can be written to that map.
-  DOMStorageValuesMap reference;
-  DOMStorageValuesMap changes;
-  changes[kKey1] = kValueNull;
-  changes[kKey2] = kValue4;
-  changes[kKey3] = kValue4;
-  reference[kKey2] = kValue4;
-  reference[kKey3] = kValue4;
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespaceClone, kOrigin1, false,
-                                     changes));
-
-  // Values in the original map were not changed.
-  CheckAreaData(kNamespace1, kOrigin1, data1);
-
-  // But values in the disassociated map were.
-  CheckAreaData(kNamespaceClone, kOrigin1, reference);
-}
-
-TEST_F(SessionStorageDatabaseTest, DeleteNamespace) {
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  DOMStorageValuesMap data2;
-  data2[kKey2] = kValue4;
-  data2[kKey3] = kValue3;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-  EXPECT_TRUE(db_->DeleteNamespace(kNamespace1));
-  CheckDatabaseConsistency();
-  CheckEmptyDatabase();
-}
-
-TEST_F(SessionStorageDatabaseTest, DeleteNamespaceWithShallowCopy) {
-  // Write data for a namespace, for 2 origins.
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  DOMStorageValuesMap data2;
-  data2[kKey1] = kValue2;
-  data2[kKey3] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-
-  // Make a shallow copy and delete the original namespace.
-  EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-  EXPECT_TRUE(db_->DeleteNamespace(kNamespace1));
-
-  // The original namespace has no data.
-  CheckDatabaseConsistency();
-  CheckAreaData(kNamespace1, kOrigin1, DOMStorageValuesMap());
-  CheckAreaData(kNamespace1, kOrigin2, DOMStorageValuesMap());
-  // But the copy persists.
-  CheckAreaData(kNamespaceClone, kOrigin1, data1);
-  CheckAreaData(kNamespaceClone, kOrigin2, data2);
-}
-
-TEST_F(SessionStorageDatabaseTest, DeleteArea) {
-  // Write data for a namespace, for 2 origins.
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  DOMStorageValuesMap data2;
-  data2[kKey1] = kValue2;
-  data2[kKey3] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-
-  EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2));
-  CheckDatabaseConsistency();
-  // The data for the non-deleted origin persists.
-  CheckAreaData(kNamespace1, kOrigin1, data1);
-  // The data for the deleted origin is gone.
-  CheckAreaData(kNamespace1, kOrigin2, DOMStorageValuesMap());
-}
-
-TEST_F(SessionStorageDatabaseTest, DeleteAreaWithShallowCopy) {
-  // Write data for a namespace, for 2 origins.
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  DOMStorageValuesMap data2;
-  data2[kKey1] = kValue2;
-  data2[kKey3] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-
-  // Make a shallow copy and delete an origin from the original namespace.
-  EXPECT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-  EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin1));
-  CheckDatabaseConsistency();
-
-  // The original namespace has data for only the non-deleted origin.
-  CheckAreaData(kNamespace1, kOrigin1, DOMStorageValuesMap());
-  CheckAreaData(kNamespace1, kOrigin2, data2);
-  // But the copy persists.
-  CheckAreaData(kNamespaceClone, kOrigin1, data1);
-  CheckAreaData(kNamespaceClone, kOrigin2, data2);
-}
-
-TEST_F(SessionStorageDatabaseTest, WriteRawBytes) {
-  // Write data which is not valid utf8 and contains null bytes.
-  unsigned char raw_data[10] = {255, 0, 0, 0, 1, 2, 3, 4, 5, 0};
-  DOMStorageValuesMap changes;
-  base::string16 string_with_raw_data;
-  string_with_raw_data.assign(reinterpret_cast<base::char16*>(raw_data), 5);
-  changes[kKey1] = base::NullableString16(string_with_raw_data, false);
-  EXPECT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, changes));
-  CheckDatabaseConsistency();
-  DOMStorageValuesMap values;
-  db_->ReadAreaValues(kNamespace1, std::vector<std::string>(), kOrigin1,
-                      &values);
-  const unsigned char* data =
-      reinterpret_cast<const unsigned char*>(values[kKey1].string().data());
-  for (int i = 0; i < 10; ++i)
-    EXPECT_EQ(raw_data[i], data[i]);
-}
-
-TEST_F(SessionStorageDatabaseTest, DeleteNamespaceConfusion) {
-  // Regression test for a bug where a namespace with id 10 prevented deleting
-  // the namespace with id 1.
-
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges("foobar", kOrigin1, false, data1));
-  ASSERT_TRUE(db_->CommitAreaChanges("foobarbaz", kOrigin1, false, data1));
-
-  // Delete the namespace with ID 1.
-  EXPECT_TRUE(db_->DeleteNamespace("foobar"));
-}
-
-TEST_F(SessionStorageDatabaseTest, ReadNamespaceIds) {
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-  std::set<std::string> expected_namespace_ids;
-
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  expected_namespace_ids.insert(kNamespace1);
-  CheckNamespaceIds(expected_namespace_ids);
-
-  ASSERT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-  expected_namespace_ids.insert(kNamespaceClone);
-  CheckNamespaceIds(expected_namespace_ids);
-
-  ASSERT_TRUE(db_->DeleteNamespace(kNamespace1));
-  expected_namespace_ids.erase(kNamespace1);
-  CheckNamespaceIds(expected_namespace_ids);
-
-  CheckDatabaseConsistency();
-}
-
-TEST_F(SessionStorageDatabaseTest, ReadNamespaceIdsInEmptyDatabase) {
-  std::set<std::string> expected_namespace_ids;
-  CheckNamespaceIds(expected_namespace_ids);
-}
-
-TEST_F(SessionStorageDatabaseTest, ReadOriginsInNamespace) {
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  data1[kKey2] = kValue2;
-  data1[kKey3] = kValue3;
-
-  std::set<url::Origin> expected_origins1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data1));
-  expected_origins1.insert(kOrigin1);
-  expected_origins1.insert(kOrigin2);
-  CheckOrigins(kNamespace1, expected_origins1);
-
-  std::set<url::Origin> expected_origins2;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace2, kOrigin2, false, data1));
-  expected_origins2.insert(kOrigin2);
-  CheckOrigins(kNamespace2, expected_origins2);
-
-  ASSERT_TRUE(db_->CloneNamespace(kNamespace1, kNamespaceClone));
-  CheckOrigins(kNamespaceClone, expected_origins1);
-
-  ASSERT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2));
-  expected_origins1.erase(kOrigin2);
-  CheckOrigins(kNamespace1, expected_origins1);
-
-  CheckDatabaseConsistency();
-}
-
-TEST_F(SessionStorageDatabaseTest, DeleteAllOrigins) {
-  // Write data for a namespace, for 2 origins.
-  DOMStorageValuesMap data1;
-  data1[kKey1] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data1));
-  DOMStorageValuesMap data2;
-  data2[kKey1] = kValue2;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin2, false, data2));
-
-  EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin1));
-  EXPECT_TRUE(db_->DeleteArea(kNamespace1, kOrigin2));
-  // Check that also the namespace start key was deleted.
-  CheckDatabaseConsistency();
-}
-
-TEST_F(SessionStorageDatabaseTest, WipeDBOnNewVersion) {
-  // Write data for a namespace.
-  DOMStorageValuesMap data;
-  data[kKey1] = kValue1;
-  ASSERT_TRUE(db_->CommitAreaChanges(kNamespace1, kOrigin1, false, data));
-  CheckDatabaseConsistency();
-
-  leveldb::Slice version_key =
-      leveldb::Slice(reinterpret_cast<const char*>(
-                         SessionStorageMetadata::kDatabaseVersionBytes),
-                     sizeof(SessionStorageMetadata::kDatabaseVersionBytes));
-  db_->db()->Put(leveldb::WriteOptions(), version_key, "something");
-  ResetDatabase();
-
-  CheckDatabaseConsistency();
-  CheckEmptyDatabase();
-  data.clear();
-  CheckAreaData(kNamespace1, kOrigin1, data);
-}
-
-}  // namespace content
diff --git a/content/browser/dom_storage/session_storage_namespace_impl.cc b/content/browser/dom_storage/session_storage_namespace_impl.cc
index 720da73..12ed30e6 100644
--- a/content/browser/dom_storage/session_storage_namespace_impl.cc
+++ b/content/browser/dom_storage/session_storage_namespace_impl.cc
@@ -12,7 +12,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task/post_task.h"
-#include "content/browser/dom_storage/dom_storage_context_impl.h"
 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
 #include "content/browser/dom_storage/dom_storage_task_runner.h"
 #include "content/browser/dom_storage/session_storage_context_mojo.h"
@@ -38,23 +37,14 @@
       context->MaybeGetExistingNamespace(namespace_id);
   if (existing)
     return existing;
-  if (context->mojo_session_state()) {
-    DCHECK(base::FeatureList::IsEnabled(blink::features::kOnionSoupDOMStorage));
-    auto result = base::WrapRefCounted(
-        new SessionStorageNamespaceImpl(context, std::move(namespace_id)));
-    result->mojo_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&SessionStorageContextMojo::CreateSessionNamespace,
-                       base::Unretained(context->mojo_session_state()),
-                       result->namespace_id_));
-    return result;
-  }
-  scoped_refptr<DOMStorageContextImpl> context_impl = context->context();
-  context_impl->task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&DOMStorageContextImpl::CreateSessionNamespace,
-                                context_impl, namespace_id));
-  return base::WrapRefCounted(new SessionStorageNamespaceImpl(
-      std::move(context), std::move(context_impl), std::move(namespace_id)));
+  auto result = base::WrapRefCounted(
+      new SessionStorageNamespaceImpl(context, std::move(namespace_id)));
+  result->mojo_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&SessionStorageContextMojo::CreateSessionNamespace,
+                     base::Unretained(context->mojo_session_state()),
+                     result->namespace_id_));
+  return result;
 }
 
 // static
@@ -64,28 +54,18 @@
     std::string namespace_id,
     const std::string& namespace_id_to_clone,
     bool immediately) {
-  if (context->mojo_session_state()) {
-    DCHECK(base::FeatureList::IsEnabled(blink::features::kOnionSoupDOMStorage));
-    auto result = base::WrapRefCounted(
-        new SessionStorageNamespaceImpl(context, std::move(namespace_id)));
-    result->mojo_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&SessionStorageContextMojo::CloneSessionNamespace,
-                       base::Unretained(context->mojo_session_state()),
-                       namespace_id_to_clone, result->namespace_id_,
-                       immediately
-                           ? SessionStorageContextMojo::CloneType::kImmediate
-                           : SessionStorageContextMojo::CloneType::
-                                 kWaitForCloneOnNamespace));
-    return result;
-  }
-  scoped_refptr<DOMStorageContextImpl> context_impl = context->context();
-  context_impl->task_runner()->PostTask(
+  auto result = base::WrapRefCounted(
+      new SessionStorageNamespaceImpl(context, std::move(namespace_id)));
+  result->mojo_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&DOMStorageContextImpl::CloneSessionNamespace,
-                     context_impl, namespace_id_to_clone, namespace_id));
-  return base::WrapRefCounted(new SessionStorageNamespaceImpl(
-      std::move(context), std::move(context_impl), std::move(namespace_id)));
+      base::BindOnce(&SessionStorageContextMojo::CloneSessionNamespace,
+                     base::Unretained(context->mojo_session_state()),
+                     namespace_id_to_clone, result->namespace_id_,
+                     immediately
+                         ? SessionStorageContextMojo::CloneType::kImmediate
+                         : SessionStorageContextMojo::CloneType::
+                               kWaitForCloneOnNamespace));
+  return result;
 }
 
 const std::string& SessionStorageNamespaceImpl::id() {
@@ -112,18 +92,6 @@
 }
 
 SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
-    scoped_refptr<DOMStorageContextWrapper> context_wrapper,
-    scoped_refptr<DOMStorageContextImpl> context,
-    std::string namespace_id)
-    : context_(std::move(context)),
-      context_wrapper_(std::move(context_wrapper)),
-      namespace_id_(std::move(namespace_id)),
-      should_persist_(false) {
-  context_wrapper_->AddNamespace(namespace_id_, this);
-  DCHECK(!base::FeatureList::IsEnabled(blink::features::kOnionSoupDOMStorage));
-}
-
-SessionStorageNamespaceImpl::SessionStorageNamespaceImpl(
     scoped_refptr<DOMStorageContextWrapper> context,
     std::string namespace_id)
     : context_wrapper_(std::move(context)),
@@ -131,30 +99,23 @@
       namespace_id_(std::move(namespace_id)),
       should_persist_(false) {
   context_wrapper_->AddNamespace(namespace_id_, this);
-  DCHECK(base::FeatureList::IsEnabled(blink::features::kOnionSoupDOMStorage));
 }
 
 SessionStorageNamespaceImpl::~SessionStorageNamespaceImpl() {
-  DCHECK(context_ || mojo_task_runner_);
+  DCHECK(mojo_task_runner_);
   context_wrapper_->RemoveNamespace(namespace_id_);
-  if (context_) {
-    context_->task_runner()->PostTask(
-        FROM_HERE,
-        base::BindOnce(&DOMStorageContextImpl::DeleteSessionNamespace, context_,
-                       namespace_id_, should_persist_));
-  }
-  if (IsMojoSessionStorage()) {
-    base::ScopedClosureRunner deleteNamespaceRunner =
-        base::ScopedClosureRunner(base::BindOnce(
-            &SessionStorageNamespaceImpl::DeleteSessionNamespaceFromUIThread,
-            std::move(mojo_task_runner_), std::move(context_wrapper_),
-            std::move(namespace_id_), should_persist_));
-    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
-      // If this fails to post then that's fine, as the mojo state should
-      // already be destructed.
-      base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
-                               deleteNamespaceRunner.Release());
-    }
+  // We must hop the the UI thread, as the context_wrapper_ can only be
+  // accessed on that thread.
+  base::ScopedClosureRunner deleteNamespaceRunner =
+      base::ScopedClosureRunner(base::BindOnce(
+          &SessionStorageNamespaceImpl::DeleteSessionNamespaceFromUIThread,
+          std::move(mojo_task_runner_), std::move(context_wrapper_),
+          std::move(namespace_id_), should_persist_));
+  if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
+    // If this fails to post then that's fine, as the mojo state should
+    // already be destructed.
+    base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
+                             deleteNamespaceRunner.Release());
   }
 }
 
diff --git a/content/browser/dom_storage/session_storage_namespace_impl.h b/content/browser/dom_storage/session_storage_namespace_impl.h
index 70cf707..21731cd 100644
--- a/content/browser/dom_storage/session_storage_namespace_impl.h
+++ b/content/browser/dom_storage/session_storage_namespace_impl.h
@@ -20,7 +20,6 @@
 }
 
 namespace content {
-class DOMStorageContextImpl;
 class DOMStorageContextWrapper;
 
 class SessionStorageNamespaceImpl : public SessionStorageNamespace {
@@ -56,17 +55,10 @@
   void SetShouldPersist(bool should_persist) override;
   bool should_persist() override;
 
-  bool IsMojoSessionStorage() { return context_.get(); }
-
   scoped_refptr<SessionStorageNamespaceImpl> Clone();
   bool IsFromContext(DOMStorageContextWrapper* context);
 
  private:
-  // Creates the non-mojo version.
-  SessionStorageNamespaceImpl(
-      scoped_refptr<DOMStorageContextWrapper> context_wrapper,
-      scoped_refptr<DOMStorageContextImpl> context_impl,
-      std::string namespace_id);
   // Creates a mojo version.
   SessionStorageNamespaceImpl(scoped_refptr<DOMStorageContextWrapper> context,
                               std::string namespace_id);
@@ -79,7 +71,6 @@
       std::string namespace_id,
       bool should_persist);
 
-  scoped_refptr<DOMStorageContextImpl> context_;
   scoped_refptr<DOMStorageContextWrapper> context_wrapper_;
   scoped_refptr<base::SequencedTaskRunner> mojo_task_runner_;
   std::string namespace_id_;
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 53e6163..2a465d3e 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -1700,42 +1700,9 @@
   // Mark the fetch_start (Navigation Timing API).
   commit_params_.navigation_timing.fetch_start = base::TimeTicks::Now();
 
-  GURL base_url;
-#if defined(OS_ANDROID)
-  // On Android, a base URL can be set for the frame. If this the case, it is
-  // the URL to use for cookies.
-  NavigationEntry* last_committed_entry =
-      frame_tree_node_->navigator()->GetController()->GetLastCommittedEntry();
-  if (last_committed_entry)
-    base_url = last_committed_entry->GetBaseURLForDataURL();
-#endif
-  const GURL& top_document_url =
-      !base_url.is_empty()
-          ? base_url
-          : frame_tree_node_->frame_tree()->root()->current_url();
-
-  // Walk the ancestor chain to determine whether all frames are same-site. If
-  // not, the |site_for_cookies| is set to an empty URL.
-  //
-  // TODO(mkwst): This is incorrect. It ought to use the definition from
-  // 'Document::SiteForCookies()' in Blink, which special-cases extension
-  // URLs and a few other sharp edges.
-  const FrameTreeNode* current = frame_tree_node_->parent();
-  bool ancestors_are_same_site = true;
-  while (current && ancestors_are_same_site) {
-    if (!net::registry_controlled_domains::SameDomainOrHost(
-            top_document_url, current->current_url(),
-            net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
-      ancestors_are_same_site = false;
-    }
-    current = current->parent();
-  }
-
-  const GURL& site_for_cookies =
-      (ancestors_are_same_site || !base_url.is_empty())
-          ? (frame_tree_node_->IsMainFrame() ? common_params_.url
-                                             : top_document_url)
-          : GURL::EmptyGURL();
+  GURL site_for_cookies =
+      frame_tree_node_->current_frame_host()
+          ->ComputeSiteForCookiesForNavigation(common_params_.url);
   bool parent_is_main_frame = !frame_tree_node_->parent()
                                   ? false
                                   : frame_tree_node_->parent()->IsMainFrame();
diff --git a/content/browser/frame_host/origin_policy_throttle.cc b/content/browser/frame_host/origin_policy_throttle.cc
index 6832219..5a1721a 100644
--- a/content/browser/frame_host/origin_policy_throttle.cc
+++ b/content/browser/frame_host/origin_policy_throttle.cc
@@ -5,37 +5,22 @@
 #include "content/browser/frame_host/origin_policy_throttle.h"
 #include "content/public/browser/origin_policy_commands.h"
 
+#include <string>
 #include <utility>
 
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
-#include "base/no_destructor.h"
-#include "base/strings/strcat.h"
-#include "build/buildflag.h"
 #include "content/browser/frame_host/navigation_handle_impl.h"
 #include "content/browser/frame_host/navigation_request.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/browser_thread.h"
-#include "content/public/browser/navigation_handle.h"
-#include "content/public/browser/origin_policy_error_reason.h"
 #include "content/public/browser/storage_partition.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_request_headers.h"
-#include "net/http/http_util.h"
-#include "services/network/network_context.h"
-#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/mojom/origin_policy_manager.mojom.h"
 #include "url/origin.h"
 
-namespace {
-// Constants derived from the spec, https://github.com/WICG/origin-policy
-static constexpr const char* kDeletePolicy = "0";
-static constexpr const char* kReportTo = "report-to";
-static constexpr const char* kPolicy = "policy";
-}  // namespace
-
 namespace content {
 
 // Implement the public "API" from
@@ -119,7 +104,7 @@
   navigation_handle()->GetResponseHeaders()->GetNormalizedHeader(
       net::HttpRequestHeaders::kSecOriginPolicy, &header);
 
-  network::OriginPolicyManager::RetrieveOriginPolicyCallback
+  network::mojom::OriginPolicyManager::RetrieveOriginPolicyCallback
       origin_policy_manager_done = base::BindOnce(
           &OriginPolicyThrottle::OnOriginPolicyManagerRetrieveDone,
           weak_factory_.GetWeakPtr());
@@ -144,123 +129,25 @@
 OriginPolicyThrottle::OriginPolicyThrottle(NavigationHandle* handle)
     : NavigationThrottle(handle) {}
 
-// TODO(andypaicu): Remove when we have moved reporting logic to the network
-// service.
-OriginPolicyThrottle::PolicyVersionAndReportTo
-OriginPolicyThrottle::GetRequestedPolicyAndReportGroupFromHeader() const {
-  std::string header;
-  navigation_handle()->GetResponseHeaders()->GetNormalizedHeader(
-      net::HttpRequestHeaders::kSecOriginPolicy, &header);
-  return GetRequestedPolicyAndReportGroupFromHeaderString(header);
-}
-
-OriginPolicyThrottle::PolicyVersionAndReportTo
-OriginPolicyThrottle::GetRequestedPolicyAndReportGroupFromHeaderString(
-    const std::string& header) {
-  // Compatibility with early spec drafts, for safety reasons:
-  // A lonely "0" will be recognized, so that deletion of a policy always works.
-  if (net::HttpUtil::TrimLWS(header) == kDeletePolicy)
-    return PolicyVersionAndReportTo({kDeletePolicy, ""});
-
-  std::string policy;
-  std::string report_to;
-  bool valid = true;
-  net::HttpUtil::NameValuePairsIterator iter(header.cbegin(), header.cend(),
-                                             ',');
-  while (iter.GetNext()) {
-    std::string token_value =
-        net::HttpUtil::TrimLWS(iter.value_piece()).as_string();
-    bool is_token = net::HttpUtil::IsToken(token_value);
-    if (iter.name_piece() == kPolicy) {
-      valid &= is_token && policy.empty();
-      policy = token_value;
-    } else if (iter.name_piece() == kReportTo) {
-      valid &= is_token && report_to.empty();
-      report_to = token_value;
-    }
-  }
-  valid &= iter.valid();
-
-  if (!valid)
-    return PolicyVersionAndReportTo();
-  return PolicyVersionAndReportTo({policy, report_to});
-}
-
 const url::Origin OriginPolicyThrottle::GetRequestOrigin() const {
   return url::Origin::Create(navigation_handle()->GetURL());
 }
 
-void OriginPolicyThrottle::CancelNavigation(OriginPolicyErrorReason reason,
+void OriginPolicyThrottle::CancelNavigation(network::OriginPolicyState state,
                                             const GURL& policy_url) {
   base::Optional<std::string> error_page =
       GetContentClient()->browser()->GetOriginPolicyErrorPage(
-          reason, navigation_handle());
+          state, navigation_handle());
   CancelDeferredNavigation(NavigationThrottle::ThrottleCheckResult(
       NavigationThrottle::CANCEL, net::ERR_BLOCKED_BY_CLIENT, error_page));
-  Report(reason, policy_url);
 }
 
-#if BUILDFLAG(ENABLE_REPORTING)
-void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason,
-                                  const GURL& policy_url) {
-  const PolicyVersionAndReportTo header_values =
-      GetRequestedPolicyAndReportGroupFromHeader();
-  if (header_values.report_to.empty())
-    return;
-
-  std::string user_agent;
-  navigation_handle()->GetRequestHeaders().GetHeader(
-      net::HttpRequestHeaders::kUserAgent, &user_agent);
-
-  std::string origin_policy_header;
-  navigation_handle()->GetResponseHeaders()->GetNormalizedHeader(
-      net::HttpRequestHeaders::kSecOriginPolicy, &origin_policy_header);
-  const char* reason_str = nullptr;
-  switch (reason) {
-    case OriginPolicyErrorReason::kCannotLoadPolicy:
-      reason_str = "CANNOT_LOAD";
-      break;
-    case OriginPolicyErrorReason::kPolicyShouldNotRedirect:
-      reason_str = "REDIRECT";
-      break;
-    case OriginPolicyErrorReason::kOther:
-      reason_str = "OTHER";
-      break;
-  }
-
-  base::DictionaryValue report_body;
-  report_body.SetKey("origin_policy_url", base::Value(policy_url.spec()));
-  report_body.SetKey("policy", base::Value(origin_policy_header));
-  report_body.SetKey("policy_error_reason", base::Value(reason_str));
-
-  SiteInstance* site_instance = navigation_handle()->GetStartingSiteInstance();
-  BrowserContext::GetStoragePartition(site_instance->GetBrowserContext(),
-                                      site_instance)
-      ->GetNetworkContext()
-      ->QueueReport("origin-policy", header_values.report_to,
-                    navigation_handle()->GetURL(), user_agent,
-                    std::move(report_body));
-}
-#else
-void OriginPolicyThrottle::Report(OriginPolicyErrorReason reason,
-                                  const GURL& policy_url) {}
-#endif  // BUILDFLAG(ENABLE_REPORTING)
-
 void OriginPolicyThrottle::OnOriginPolicyManagerRetrieveDone(
     const network::OriginPolicy& origin_policy) {
   switch (origin_policy.state) {
     case network::OriginPolicyState::kCannotLoadPolicy:
-      // TODO(andypaicu): OriginPolicyErrorReason is obsolete and we should use
-      // network::OriginPolicyState instead.
-      CancelNavigation(OriginPolicyErrorReason::kCannotLoadPolicy,
-                       origin_policy.policy_url);
-      return;
-
     case network::OriginPolicyState::kInvalidRedirect:
-      // TODO(andypaicu): OriginPolicyErrorReason is obsolete and we should use
-      // network::OriginPolicyState instead.
-      CancelNavigation(OriginPolicyErrorReason::kPolicyShouldNotRedirect,
-                       origin_policy.policy_url);
+      CancelNavigation(origin_policy.state, origin_policy.policy_url);
       return;
 
     case network::OriginPolicyState::kNoPolicyApplies:
diff --git a/content/browser/frame_host/origin_policy_throttle.h b/content/browser/frame_host/origin_policy_throttle.h
index 8b2877a5..b8a1f68 100644
--- a/content/browser/frame_host/origin_policy_throttle.h
+++ b/content/browser/frame_host/origin_policy_throttle.h
@@ -5,13 +5,10 @@
 #ifndef CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
 #define CONTENT_BROWSER_FRAME_HOST_ORIGIN_POLICY_THROTTLE_H_
 
-#include <map>
 #include <memory>
-#include <string>
 
-#include "base/gtest_prod_util.h"
 #include "base/macros.h"
-#include "base/memory/scoped_refptr.h"
+#include "content/common/content_export.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/navigation_throttle.h"
 #include "services/network/public/cpp/origin_policy.h"
@@ -24,7 +21,6 @@
 
 namespace content {
 class NavigationHandle;
-enum class OriginPolicyErrorReason;
 
 // Constant derived from the spec, https://github.com/WICG/origin-policy
 static constexpr const char* kDefaultOriginPolicyVersion = "0";
@@ -41,11 +37,6 @@
 //   throttle or not.
 class CONTENT_EXPORT OriginPolicyThrottle : public NavigationThrottle {
  public:
-  struct PolicyVersionAndReportTo {
-    std::string policy_version;
-    std::string report_to;
-  };
-
   // Determine whether to request a policy (or advertise origin policy
   // support). Returns whether the policy header should be sent.
   static bool ShouldRequestOriginPolicy(const GURL& url);
@@ -68,23 +59,13 @@
   ThrottleCheckResult WillProcessResponse() override;
   const char* GetNameForLogging() override;
 
-  using KnownVersionMap = std::map<url::Origin, std::string>;
-  static KnownVersionMap& GetKnownVersionsForTesting();
-
  private:
   explicit OriginPolicyThrottle(NavigationHandle* handle);
 
-  // TODO(andypaicu): Remove when we have moved reporting logic to the network
-  // service.
-  PolicyVersionAndReportTo GetRequestedPolicyAndReportGroupFromHeader() const;
-  static PolicyVersionAndReportTo
-  GetRequestedPolicyAndReportGroupFromHeaderString(const std::string& header);
-
   const url::Origin GetRequestOrigin() const;
 
-  void CancelNavigation(OriginPolicyErrorReason reason, const GURL& policy_url);
-
-  void Report(OriginPolicyErrorReason reason, const GURL& policy_url);
+  void CancelNavigation(network::OriginPolicyState state,
+                        const GURL& policy_url);
 
   void OnOriginPolicyManagerRetrieveDone(
       const network::OriginPolicy& origin_policy);
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index b30f84c0..696ef2b 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -177,7 +177,7 @@
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "mojo/public/cpp/bindings/strong_binding.h"
 #include "mojo/public/cpp/system/data_pipe.h"
-#include "net/url_request/url_request_context.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 #include "services/device/public/cpp/device_features.h"
 #include "services/device/public/mojom/sensor_provider.mojom.h"
 #include "services/device/public/mojom/wake_lock.mojom.h"
@@ -2102,6 +2102,57 @@
   SetLastCommittedOrigin(origin);
 }
 
+GURL RenderFrameHostImpl::ComputeSiteForCookiesForNavigation(
+    const GURL& destination) const {
+  // For top-level navigation, |site_for_cookies| will always be the destination
+  // URL.
+  if (frame_tree_node_->IsMainFrame())
+    return destination;
+
+  GURL base_url;
+#if defined(OS_ANDROID)
+  // On Android, a base URL can be set for the frame. If this the case, it is
+  // the URL to use for cookies.
+  NavigationEntry* last_committed_entry =
+      frame_tree_node_->navigator()->GetController()->GetLastCommittedEntry();
+  if (last_committed_entry)
+    base_url = last_committed_entry->GetBaseURLForDataURL();
+#endif
+  // This is pre-navigation, but since at this point the frame being navigated
+  // is known to not be the main frame, it's correct post-navigation as well.
+  const GURL& top_document_url =
+      !base_url.is_empty() ? base_url : frame_tree_->root()->current_url();
+
+  if (GetContentClient()
+          ->browser()
+          ->ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+              top_document_url.scheme_piece())) {
+    return top_document_url;
+  }
+
+  // Check if everything above the frame being navigated is consistent. It's OK
+  // to skip checking the frame itself since it will be validated against
+  // |site_for_cookies| anyway.
+  const FrameTreeNode* current = frame_tree_node_->parent();
+  bool ancestors_are_same_site = true;
+  while (current && ancestors_are_same_site) {
+    // Skip over srcdoc documents, as they are always same-origin with their
+    // closest non-srcdoc parent.
+    while (current->current_url().IsAboutSrcdoc())
+      current = current->parent();
+
+    if (!net::registry_controlled_domains::SameDomainOrHost(
+            top_document_url, current->current_url(),
+            net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+      ancestors_are_same_site = false;
+    }
+    current = current->parent();
+  }
+
+  return (ancestors_are_same_site || !base_url.is_empty()) ? top_document_url
+                                                           : GURL::EmptyGURL();
+}
+
 void RenderFrameHostImpl::SetOriginOfNewFrame(
     const url::Origin& new_frame_creator) {
   // This method should only be called for *new* frames, that haven't committed
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index fd995c4..2234375 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -428,6 +428,10 @@
   // cases, use GetLastCommittedURL instead.
   const GURL& last_successful_url() { return last_successful_url_; }
 
+  // Computes site_for_cookies to be used when navigating this frame to
+  // |destination|.
+  GURL ComputeSiteForCookiesForNavigation(const GURL& destination) const;
+
   // Allows overriding the last committed origin in tests.
   void SetLastCommittedOriginForTesting(const url::Origin& origin);
 
diff --git a/content/browser/frame_host/render_frame_host_impl_browsertest.cc b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
index 7e2774d..1336def 100644
--- a/content/browser/frame_host/render_frame_host_impl_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_impl_browsertest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
+#include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -49,6 +50,7 @@
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "services/network/public/cpp/features.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom-test-utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
@@ -87,6 +89,41 @@
 
   DISALLOW_COPY_AND_ASSIGN(PrerenderTestContentBrowserClient);
 };
+
+const char kTrustMeUrl[] = "trustme://host/path/";
+
+// Configure trustme: as a scheme that should cause cookies to be treated as
+// first-party when top-level, and also installs a URLLoaderFactory that
+// makes all requests to it via kTrustMeUrl return a particular iframe.
+class FirstPartySchemeContentBrowserClient : public TestContentBrowserClient {
+ public:
+  explicit FirstPartySchemeContentBrowserClient(const GURL& iframe_url)
+      : iframe_url_(iframe_url) {}
+
+  ~FirstPartySchemeContentBrowserClient() override = default;
+
+  bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+      base::StringPiece scheme) override {
+    return scheme == "trustme";
+  }
+
+  void RegisterNonNetworkNavigationURLLoaderFactories(
+      int frame_tree_node_id,
+      NonNetworkURLLoaderFactoryMap* factories) override {
+    auto test_url_loader_factory =
+        std::make_unique<network::TestURLLoaderFactory>();
+    test_url_loader_factory->AddResponse(
+        kTrustMeUrl,
+        base::StrCat({"<iframe src=\"", iframe_url_.spec(), "\"></iframe>"}));
+    factories->emplace("trustme", std::move(test_url_loader_factory));
+  }
+
+ private:
+  GURL iframe_url_;
+
+  DISALLOW_COPY_AND_ASSIGN(FirstPartySchemeContentBrowserClient);
+};
+
 }  // anonymous namespace
 
 // TODO(mlamouri): part of these tests were removed because they were dependent
@@ -2470,4 +2507,218 @@
       ->UpdateActiveSchedulerTrackedFeatures(0b0u);
 }
 
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+                       ComputeSiteForCookiesForNavigation) {
+  GURL url = embedded_test_server()->GetURL(
+      "a.com", "/cross_site_iframe_factory.html?a(a(b(d)),c())");
+
+  FirstPartySchemeContentBrowserClient new_client(url);
+  ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+  GURL b_url = embedded_test_server()->GetURL("b.com", "/");
+  GURL c_url = embedded_test_server()->GetURL("c.com", "/");
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+
+  {
+    WebContentsImpl* wc =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    RenderFrameHostImpl* main_frame =
+        static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
+
+    EXPECT_EQ("a.com", main_frame->GetLastCommittedURL().host());
+    ASSERT_EQ(2u, main_frame->child_count());
+    FrameTreeNode* child_a = main_frame->child_at(0);
+    FrameTreeNode* child_c = main_frame->child_at(1);
+    EXPECT_EQ("a.com", child_a->current_url().host());
+    EXPECT_EQ("c.com", child_c->current_url().host());
+
+    ASSERT_EQ(1u, child_a->child_count());
+    FrameTreeNode* child_b = child_a->child_at(0);
+    EXPECT_EQ("b.com", child_b->current_url().host());
+    ASSERT_EQ(1u, child_b->child_count());
+    FrameTreeNode* child_d = child_b->child_at(0);
+    EXPECT_EQ("d.com", child_d->current_url().host());
+
+    EXPECT_EQ("a.com",
+              main_frame->ComputeSiteForCookiesForNavigation(url).host());
+    EXPECT_EQ("b.com",
+              main_frame->ComputeSiteForCookiesForNavigation(b_url).host());
+    EXPECT_EQ("c.com",
+              main_frame->ComputeSiteForCookiesForNavigation(c_url).host());
+
+    // a.com -> a.com frame being navigated.
+    EXPECT_EQ("a.com", child_a->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(url)
+                           .host());
+    EXPECT_EQ("a.com", child_a->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(b_url)
+                           .host());
+    EXPECT_EQ("a.com", child_a->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(c_url)
+                           .host());
+
+    // a.com -> a.com -> b.com frame being navigated.
+
+    // The first case here is especially interesting, since we go to
+    // a/a/a from a/a/b. We currently treat this as all first-party, but there
+    // is a case to be made for doing it differently, due to involvement of b.
+    EXPECT_EQ("a.com", child_b->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(url)
+                           .host());
+    EXPECT_EQ("a.com", child_b->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(b_url)
+                           .host());
+    EXPECT_EQ("a.com", child_b->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(c_url)
+                           .host());
+
+    // a.com -> c.com frame being navigated.
+    EXPECT_EQ("a.com", child_c->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(url)
+                           .host());
+    EXPECT_EQ("a.com", child_c->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(b_url)
+                           .host());
+    EXPECT_EQ("a.com", child_c->current_frame_host()
+                           ->ComputeSiteForCookiesForNavigation(c_url)
+                           .host());
+
+    // a.com -> a.com -> b.com -> d.com frame being navigated.
+    EXPECT_EQ("", child_d->current_frame_host()
+                      ->ComputeSiteForCookiesForNavigation(url)
+                      .host());
+    EXPECT_EQ("", child_d->current_frame_host()
+                      ->ComputeSiteForCookiesForNavigation(b_url)
+                      .host());
+    EXPECT_EQ("", child_d->current_frame_host()
+                      ->ComputeSiteForCookiesForNavigation(c_url)
+                      .host());
+  }
+
+  // The rest of the test relies on
+  // RegisterNonNetworkNavigationURLLoaderFactories, which needs NetworkService
+  // on.
+  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
+    SetBrowserClientForTesting(old_client);
+    return;
+  }
+
+  // Now try with a trusted scheme that gives first-partiness.
+  GURL trusty_url(kTrustMeUrl);
+  EXPECT_TRUE(NavigateToURL(shell(), trusty_url));
+  {
+    WebContentsImpl* wc =
+        static_cast<WebContentsImpl*>(shell()->web_contents());
+    RenderFrameHostImpl* main_frame =
+        static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
+    EXPECT_EQ(trusty_url.GetOrigin(),
+              main_frame->GetLastCommittedURL().GetOrigin());
+
+    ASSERT_EQ(1u, main_frame->child_count());
+    FrameTreeNode* child_a = main_frame->child_at(0);
+    EXPECT_EQ("a.com", child_a->current_url().host());
+
+    ASSERT_EQ(2u, child_a->child_count());
+    FrameTreeNode* child_aa = child_a->child_at(0);
+    EXPECT_EQ("a.com", child_aa->current_url().host());
+
+    ASSERT_EQ(1u, child_aa->child_count());
+    FrameTreeNode* child_aab = child_aa->child_at(0);
+    EXPECT_EQ("b.com", child_aab->current_url().host());
+
+    ASSERT_EQ(1u, child_aab->child_count());
+    FrameTreeNode* child_aabd = child_aab->child_at(0);
+    EXPECT_EQ("d.com", child_aabd->current_url().host());
+
+    // Main frame navigations are not affected by the special schema.
+    EXPECT_EQ(url.GetOrigin(),
+              main_frame->ComputeSiteForCookiesForNavigation(url).GetOrigin());
+    EXPECT_EQ(
+        b_url.GetOrigin(),
+        main_frame->ComputeSiteForCookiesForNavigation(b_url).GetOrigin());
+    EXPECT_EQ(
+        c_url.GetOrigin(),
+        main_frame->ComputeSiteForCookiesForNavigation(c_url).GetOrigin());
+
+    // Child navigation gets the magic scheme.
+    EXPECT_EQ(trusty_url.GetOrigin(),
+              child_aa->current_frame_host()
+                  ->ComputeSiteForCookiesForNavigation(url)
+                  .GetOrigin());
+    EXPECT_EQ(trusty_url.GetOrigin(),
+              child_aa->current_frame_host()
+                  ->ComputeSiteForCookiesForNavigation(b_url)
+                  .GetOrigin());
+    EXPECT_EQ(trusty_url.GetOrigin(),
+              child_aa->current_frame_host()
+                  ->ComputeSiteForCookiesForNavigation(c_url)
+                  .GetOrigin());
+
+    EXPECT_EQ(trusty_url.GetOrigin(),
+              child_aabd->current_frame_host()
+                  ->ComputeSiteForCookiesForNavigation(url)
+                  .GetOrigin());
+    EXPECT_EQ(trusty_url.GetOrigin(),
+              child_aabd->current_frame_host()
+                  ->ComputeSiteForCookiesForNavigation(b_url)
+                  .GetOrigin());
+    EXPECT_EQ(trusty_url.GetOrigin(),
+              child_aabd->current_frame_host()
+                  ->ComputeSiteForCookiesForNavigation(c_url)
+                  .GetOrigin());
+  }
+
+  SetBrowserClientForTesting(old_client);
+}
+
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
+                       ComputeSiteForCookiesForNavigationSrcDoc) {
+  // srcdoc frames basically don't figure into site_for_cookies computation.
+  GURL url = embedded_test_server()->GetURL(
+      "a.com", "/frame_tree/page_with_srcdoc_iframe_tree.html");
+
+  EXPECT_TRUE(NavigateToURL(shell(), url));
+
+  WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+  RenderFrameHostImpl* main_frame =
+      static_cast<RenderFrameHostImpl*>(wc->GetMainFrame());
+  EXPECT_EQ("a.com", main_frame->GetLastCommittedURL().host());
+
+  ASSERT_EQ(1u, main_frame->child_count());
+  FrameTreeNode* child_sd = main_frame->child_at(0);
+  EXPECT_TRUE(child_sd->current_url().IsAboutSrcdoc());
+
+  ASSERT_EQ(1u, child_sd->child_count());
+  FrameTreeNode* child_sd_a = child_sd->child_at(0);
+  EXPECT_EQ("a.com", child_sd_a->current_url().host());
+
+  ASSERT_EQ(1u, child_sd_a->child_count());
+  FrameTreeNode* child_sd_a_sd = child_sd_a->child_at(0);
+  EXPECT_TRUE(child_sd_a_sd->current_url().IsAboutSrcdoc());
+  ASSERT_EQ(0u, child_sd_a_sd->child_count());
+
+  EXPECT_EQ("a.com", child_sd->current_frame_host()
+                         ->ComputeSiteForCookiesForNavigation(url)
+                         .host());
+  EXPECT_EQ("a.com", child_sd_a->current_frame_host()
+                         ->ComputeSiteForCookiesForNavigation(url)
+                         .host());
+  EXPECT_EQ("a.com", child_sd_a_sd->current_frame_host()
+                         ->ComputeSiteForCookiesForNavigation(url)
+                         .host());
+
+  GURL b_url = embedded_test_server()->GetURL("b.com", "/");
+  EXPECT_EQ("b.com",
+            main_frame->ComputeSiteForCookiesForNavigation(b_url).host());
+  EXPECT_EQ("a.com", child_sd->current_frame_host()
+                         ->ComputeSiteForCookiesForNavigation(b_url)
+                         .host());
+  EXPECT_EQ("a.com", child_sd_a->current_frame_host()
+                         ->ComputeSiteForCookiesForNavigation(b_url)
+                         .host());
+  EXPECT_EQ("a.com", child_sd_a_sd->current_frame_host()
+                         ->ComputeSiteForCookiesForNavigation(b_url)
+                         .host());
+}
+
 }  // namespace content
diff --git a/content/browser/gpu/DEPS b/content/browser/gpu/DEPS
index 55accd2..b235dbb 100644
--- a/content/browser/gpu/DEPS
+++ b/content/browser/gpu/DEPS
@@ -2,7 +2,7 @@
 # embedded in mus won't be able to talk to the native ozone.
 specific_include_rules = {
   "gpu_data_manager_impl_private\.cc": [
-    "+ui/ozone/public/ozone_switches.h",
+    "+ui/ozone/public",
   ],
   "gpu_process_host\.cc": [
     "+ui/ozone/public",
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index cac0a978..874f5718 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -56,7 +56,7 @@
 #include "ui/gl/gpu_switching_manager.h"
 
 #if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_switches.h"
+#include "ui/ozone/public/ozone_platform.h"
 #endif
 #if defined(OS_MACOSX)
 #include <ApplicationServices/ApplicationServices.h>
@@ -278,6 +278,7 @@
           dx12_vulkan_version_info));
 }
 #endif
+
 }  // anonymous namespace
 
 GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner)
@@ -645,6 +646,11 @@
     gpu_preferences->disable_gpu_watchdog = true;
   }
 #endif
+
+#if defined(USE_OZONE)
+  gpu_preferences->message_loop_type =
+      ui::OzonePlatform::GetInstance()->GetMessageLoopTypeForGpu();
+#endif
 }
 
 void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
diff --git a/content/browser/indexed_db/indexed_db_factory_unittest.cc b/content/browser/indexed_db/indexed_db_factory_unittest.cc
index ab4ea49..e3e06b4 100644
--- a/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -205,7 +205,7 @@
  public:
   IndexedDBFactoryTestWithMockTime()
       : IndexedDBFactoryTest(std::make_unique<TestBrowserThreadBundle>(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME)) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME)) {}
 
  private:
   DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryTestWithMockTime);
diff --git a/content/browser/loader/loader_browsertest.cc b/content/browser/loader/loader_browsertest.cc
index 13819a5..0c73906 100644
--- a/content/browser/loader/loader_browsertest.cc
+++ b/content/browser/loader/loader_browsertest.cc
@@ -22,6 +22,7 @@
 #include "content/browser/download/download_manager_impl.h"
 #include "content/browser/loader/resource_dispatcher_host_impl.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/view_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -156,6 +157,47 @@
   EXPECT_EQ("text/html", shell()->web_contents()->GetContentsMimeType());
 }
 
+// Tests that the renderer does not crash when issuing a stale-revalidation
+// request when the enable_referrers renderer preference is `false`. See
+// https://crbug.com/966140.
+IN_PROC_BROWSER_TEST_F(LoaderBrowserTest,
+                       DisableReferrersStaleWhileRevalidate) {
+  ASSERT_TRUE(embedded_test_server()->Start());
+  WebContentsImpl* web_contents =
+      static_cast<WebContentsImpl*>(shell()->web_contents());
+
+  // Navigate to the page that will eventually fetch a stale-revalidation
+  // request. Ensure that the renderer has not crashed.
+  ASSERT_TRUE(NavigateToURL(
+      shell(), embedded_test_server()->GetURL("/stale-while-revalidate.html")));
+
+  // Create new renderer preferences and force-disable the |enable_referrers|
+  // preference.
+  blink::mojom::RendererPreferences renderer_preferences;
+  renderer_preferences.enable_referrers = false;
+
+  // Send updated renderer preferences to the renderer.
+  RenderViewHost* rvh = web_contents->GetRenderViewHost();
+  rvh->Send(
+      new ViewMsg_SetRendererPrefs(rvh->GetRoutingID(), renderer_preferences));
+
+  // Wait for the stale-while-revalidate tests to pass by observing the page's
+  // title. If the renderer crashes, the test immediately fails.
+  base::string16 expected_title = base::ASCIIToUTF16("Pass");
+  TitleWatcher title_watcher(web_contents, expected_title);
+
+  // The invocation of runTest() below starts a test written in JavaScript, that
+  // after some time, creates a stale-revalidation request. The above IPC
+  // message should be handled by the renderer (thus updating its preferences),
+  // before this stale-revalidation request is sent. Technically nothing
+  // guarantees this will happen, so it is theoretically possible the test is
+  // racy, however in practice the renderer will always handle the IPC message
+  // before the stale-revalidation request. This is because the renderer is
+  // never completely blocked from the time the test starts.
+  EXPECT_TRUE(ExecuteScript(shell(), "runTest()"));
+  ASSERT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+}
+
 IN_PROC_BROWSER_TEST_F(LoaderBrowserTest, RespectNoSniffDirective) {
   // Covered by URLLoaderTest.RespectNoSniff.
   if (base::FeatureList::IsEnabled(network::features::kNetworkService))
diff --git a/content/browser/scheduler/browser_task_executor_unittest.cc b/content/browser/scheduler/browser_task_executor_unittest.cc
index 76d783e..d0c8965 100644
--- a/content/browser/scheduler/browser_task_executor_unittest.cc
+++ b/content/browser/scheduler/browser_task_executor_unittest.cc
@@ -40,7 +40,8 @@
 class BrowserTaskExecutorTest : public testing::Test {
  private:
   TestBrowserThreadBundle thread_bundle_{
-      base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME};
+      base::test::ScopedTaskEnvironment::MainThreadType::UI,
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 };
 
 using StrictMockTask =
@@ -168,7 +169,8 @@
     ScopedTaskEnvironmentWithCustomScheduler()
         : base::test::ScopedTaskEnvironment(
               SubclassCreatesDefaultTaskRunner{},
-              base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME) {
+              base::test::ScopedTaskEnvironment::MainThreadType::UI,
+              base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
       std::unique_ptr<BrowserUIThreadScheduler> browser_ui_thread_scheduler =
           BrowserUIThreadScheduler::CreateForTesting(sequence_manager(),
                                                      GetTimeDomain());
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc
index 036d2619..aee247d 100644
--- a/content/browser/service_worker/service_worker_provider_host.cc
+++ b/content/browser/service_worker/service_worker_provider_host.cc
@@ -264,7 +264,6 @@
       client_uuid_(base::GenerateGUID()),
       create_time_(base::TimeTicks::Now()),
       render_process_id_(ChildProcessHost::kInvalidUniqueID),
-      render_thread_id_(kDocumentMainThreadId),
       frame_id_(MSG_ROUTING_NONE),
       is_parent_frame_secure_(is_parent_frame_secure),
       frame_tree_node_id_(frame_tree_node_id),
@@ -280,10 +279,7 @@
 
   if (type_ == blink::mojom::ServiceWorkerProviderType::kForServiceWorker) {
     // Actual |render_process_id_| will be set after choosing a process for the
-    // controller, and |render_thread_id_| will be set when the service worker
-    // context gets started.
-    render_thread_id_ = kInvalidEmbeddedWorkerThreadId;
-
+    // controller.
     DCHECK(!client_ptr_info);
   } else {
     DCHECK(client_ptr_info.is_valid());
@@ -722,7 +718,6 @@
     service_manager::mojom::InterfaceProviderRequest
         interface_provider_request) {
   DCHECK(context_);
-  DCHECK_EQ(kInvalidEmbeddedWorkerThreadId, render_thread_id_);
   DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, render_process_id_);
   DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
   DCHECK_EQ(blink::mojom::ServiceWorkerProviderType::kForServiceWorker,
@@ -1289,7 +1284,6 @@
     const std::string& interface_name,
     mojo::ScopedMessagePipeHandle interface_pipe) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  DCHECK_NE(kDocumentMainThreadId, render_thread_id_);
   DCHECK(IsProviderForServiceWorker());
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h
index c050626f..c1707c8af 100644
--- a/content/browser/service_worker/service_worker_provider_host.h
+++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -588,11 +588,6 @@
   const base::TimeTicks create_time_;
   int render_process_id_;
 
-  // For service worker execution contexts, the id of the service worker thread
-  // or |kInvalidEmbeddedWorkerThreadId| before the service worker starts up.
-  // Otherwise, |kDocumentMainThreadId|.
-  int render_thread_id_;
-
   // The window's RenderFrame id, if this is a service worker window client.
   // Otherwise, |MSG_ROUTING_NONE|.
   int frame_id_;
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index a878faa..8c399416 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -6604,14 +6604,8 @@
   EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags);
 }
 
-// Flaky on Linux. See https://crbug.com/980564
-#if defined(OS_LINUX)
-#define MAYBE_PointerEventsNoneOOPIF DISABLED_PointerEventsNoneOOPIF
-#else
-#define MAYBE_PointerEventsNoneOOPIF PointerEventsNoneOOPIF
-#endif
 IN_PROC_BROWSER_TEST_P(SitePerProcessHitTestDataGenerationBrowserTest,
-                       MAYBE_PointerEventsNoneOOPIF) {
+                       PointerEventsNoneOOPIF) {
   auto hit_test_data = SetupAndGetHitTestData(
       "/frame_tree/page_with_positioned_frame_pointer-events_none.html", 0);
   float device_scale_factor = current_device_scale_factor();
@@ -6644,12 +6638,6 @@
       expected_transform.ApproximatelyEqual(hit_test_data[2].transform()));
   EXPECT_EQ(flags, hit_test_data[2].flags);
 
-  // Check that an update on the css property can trigger an update in submitted
-  // hit test data.
-  EXPECT_TRUE(ExecuteScript(web_contents(),
-                            "document.getElementsByTagName('iframe')[0].style."
-                            "pointerEvents = 'auto';\n"));
-
   FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
                             ->GetFrameTree()
                             ->root();
@@ -6658,30 +6646,22 @@
   RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
       root->current_frame_host()->GetRenderWidgetHost()->GetView());
 
-  {
-    MainThreadFrameObserver observer(
-        root->current_frame_host()->GetRenderWidgetHost());
-    observer.Wait();
-  }
-  {
-    MainThreadFrameObserver observer(
-        root->child_at(0)->current_frame_host()->GetRenderWidgetHost());
-    observer.Wait();
-  }
-  {
-    MainThreadFrameObserver observer(
-        root->child_at(1)->current_frame_host()->GetRenderWidgetHost());
-    observer.Wait();
-  }
+  HitTestRegionObserver hit_test_data_change_observer(
+      rwhv_root->GetRootFrameSinkId());
+  hit_test_data_change_observer.WaitForHitTestData();
 
-  WaitForHitTestDataOrChildSurfaceReady(
-      root->child_at(0)->current_frame_host());
-  WaitForHitTestDataOrChildSurfaceReady(
-      root->child_at(1)->current_frame_host());
+  // Check that an update on the css property can trigger an update in submitted
+  // hit test data.
+  EXPECT_TRUE(ExecuteScript(web_contents(),
+                            "document.getElementsByTagName('iframe')[0].style."
+                            "pointerEvents = 'auto';\n"));
+  MainThreadFrameObserver observer(
+      root->current_frame_host()->GetRenderWidgetHost());
+  observer.Wait();
 
-  HitTestRegionObserver observer(rwhv_root->GetRootFrameSinkId());
-  observer.WaitForHitTestData();
-  hit_test_data = observer.GetHitTestData();
+  hit_test_data_change_observer.WaitForHitTestDataChange();
+  hit_test_data = hit_test_data_change_observer.GetHitTestData();
+
   ASSERT_EQ(4u, hit_test_data.size());
   EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString());
   EXPECT_TRUE(
@@ -6696,6 +6676,9 @@
   EXPECT_EQ(expected_region2.ToString(), hit_test_data[3].rect.ToString());
   EXPECT_TRUE(
       expected_transform2.ApproximatelyEqual(hit_test_data[3].transform()));
+  // Hit test region with pointer-events: none is marked as kHitTestIgnore. The
+  // JavaScript above sets the element's pointer-events to 'auto' therefore
+  // kHitTestIgnore should be removed from the flag.
   if (features::IsVizHitTestingSurfaceLayerEnabled()) {
     EXPECT_EQ(kFastHitTestFlags, hit_test_data[3].flags);
   } else {
diff --git a/content/browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc b/content/browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc
index 5cae66b..f8679483 100644
--- a/content/browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc
+++ b/content/browser/web_package/signed_exchange_prefetch_metric_recorder_unittest.cc
@@ -16,7 +16,7 @@
  public:
   SignedExchangePrefetchMetricRecorderTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     metric_recorder_ =
diff --git a/content/browser/worker_host/worker_script_loader_factory.cc b/content/browser/worker_host/worker_script_loader_factory.cc
index c84d028..8e2383b91 100644
--- a/content/browser/worker_host/worker_script_loader_factory.cc
+++ b/content/browser/worker_host/worker_script_loader_factory.cc
@@ -29,15 +29,13 @@
       appcache_host_(std::move(appcache_host)),
       resource_context_getter_(resource_context_getter),
       loader_factory_(std::move(loader_factory)) {
-#if DCHECK_IS_ON()
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  if (service_worker_provider_host_) {
-    DCHECK(service_worker_provider_host_->provider_type() ==
-               blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker ||
-           service_worker_provider_host_->provider_type() ==
-               blink::mojom::ServiceWorkerProviderType::kForSharedWorker);
-  }
-#endif  // DCHECK_IS_ON()
+  DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService));
+  DCHECK(!service_worker_provider_host_ ||
+         service_worker_provider_host_->provider_type() ==
+             blink::mojom::ServiceWorkerProviderType::kForDedicatedWorker ||
+         service_worker_provider_host_->provider_type() ==
+             blink::mojom::ServiceWorkerProviderType::kForSharedWorker);
 }
 
 WorkerScriptLoaderFactory::~WorkerScriptLoaderFactory() {
@@ -53,27 +51,6 @@
     network::mojom::URLLoaderClientPtr client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  // When NetworkService is not enabled, this function is called from the
-  // renderer process, so use ReportBadMessage() instead of DCHECK().
-  if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) {
-    // Handle only the main script. Import scripts (ResourceType::kScript)
-    // should go to the network loader or controller.
-    if (resource_request.resource_type !=
-            static_cast<int>(ResourceType::kWorker) &&
-        resource_request.resource_type !=
-            static_cast<int>(ResourceType::kSharedWorker)) {
-      mojo::ReportBadMessage(
-          "WorkerScriptLoaderFactory should only get requests for worker "
-          "scripts");
-      return;
-    }
-    if (script_loader_) {
-      mojo::ReportBadMessage(
-          "WorkerScriptLoaderFactory should be used only one time");
-      return;
-    }
-  }
   DCHECK(resource_request.resource_type ==
              static_cast<int>(ResourceType::kWorker) ||
          resource_request.resource_type ==
diff --git a/content/browser/worker_network_isolation_key_browsertest.cc b/content/browser/worker_network_isolation_key_browsertest.cc
index 2179fe1..9cadb36 100644
--- a/content/browser/worker_network_isolation_key_browsertest.cc
+++ b/content/browser/worker_network_isolation_key_browsertest.cc
@@ -63,26 +63,42 @@
   }
 
   // Register a service/shared worker |main_script_file| in the scope of
-  // |embedded_test_server|'s origin, that does
+  // |subframe_rfh|'s origin.
+  void RegisterWorker(RenderFrameHost* subframe_rfh,
+                      WorkerType worker_type,
+                      const std::string& main_script_file) {
+    RegisterWorkerWithUrlParameters(subframe_rfh, worker_type, main_script_file,
+                                    {});
+  }
+
+  // Register a service/shared worker |main_script_file| in the scope of
+  // |subframe_rfh|'s origin, that does
   // importScripts(|import_script_url|) and fetch(|fetch_url|).
   void RegisterWorkerThatDoesImportScriptsAndFetch(
-      const net::EmbeddedTestServer* embedded_test_server,
+      RenderFrameHost* subframe_rfh,
       WorkerType worker_type,
       const std::string& main_script_file,
       const GURL& import_script_url,
       const GURL& fetch_url) {
+    RegisterWorkerWithUrlParameters(
+        subframe_rfh, worker_type, main_script_file,
+        {{"import_script_url", import_script_url.spec()},
+         {"fetch_url", fetch_url.spec()}});
+  }
+
+  RenderFrameHost* CreateSubframe(const GURL& subframe_url) {
+    DCHECK_EQ(shell()->web_contents()->GetURL().path(),
+              "/workers/frame_factory.html");
+
     content::TestNavigationObserver navigation_observer(
         shell()->web_contents(), /*number_of_navigations*/ 1,
         content::MessageLoopRunner::QuitMode::DEFERRED);
-    std::string subframe_url =
-        embedded_test_server->GetURL("/workers/service_worker_setup.html")
-            .spec();
 
     std::string subframe_name = GetUniqueSubframeName();
-    EvalJsResult result =
-        EvalJs(shell()->web_contents()->GetMainFrame(),
-               JsReplace("createFrame($1, $2)", subframe_url, subframe_name));
-    ASSERT_TRUE(result.error.empty());
+    EvalJsResult result = EvalJs(
+        shell()->web_contents()->GetMainFrame(),
+        JsReplace("createFrame($1, $2)", subframe_url.spec(), subframe_name));
+    DCHECK(result.error.empty());
     navigation_observer.Wait();
 
     RenderFrameHost* subframe_rfh = FrameMatchingPredicate(
@@ -90,15 +106,29 @@
         base::BindRepeating(&FrameMatchesName, subframe_name));
     DCHECK(subframe_rfh);
 
-    std::string main_script_file_with_param = base::StrCat(
-        {main_script_file, "?import_script_url=", import_script_url.spec(),
-         "&fetch_url=", fetch_url.spec()});
+    return subframe_rfh;
+  }
+
+ private:
+  void RegisterWorkerWithUrlParameters(
+      RenderFrameHost* subframe_rfh,
+      WorkerType worker_type,
+      const std::string& main_script_file,
+      const std::map<std::string, std::string>& params) {
+    std::string main_script_file_with_param(main_script_file);
+    for (auto it = params.begin(); it != params.end(); ++it) {
+      main_script_file_with_param += base::StrCat(
+          {(it == params.begin()) ? "?" : "&", it->first, "=", it->second});
+    }
 
     switch (worker_type) {
       case WorkerType::kServiceWorker:
+        DCHECK(subframe_rfh->GetLastCommittedURL().path() ==
+               "/workers/service_worker_setup.html");
         EXPECT_EQ("ok",
                   EvalJs(subframe_rfh,
-                         JsReplace("setup($1)", main_script_file_with_param)));
+                         JsReplace("setup($1,$2)", main_script_file_with_param,
+                                   "{\"updateViaCache\": \"all\"}")));
         break;
       case WorkerType::kSharedWorker:
         EXPECT_EQ(nullptr, EvalJs(subframe_rfh,
@@ -108,7 +138,6 @@
     }
   }
 
- private:
   std::string GetUniqueSubframeName() {
     subframe_id_ += 1;
     return "subframe_name_" + base::NumberToString(subframe_id_);
@@ -192,12 +221,16 @@
   NavigateToURLBlockUntilNavigationsComplete(
       shell(), embedded_test_server()->GetURL("/workers/frame_factory.html"),
       1);
+  RenderFrameHost* subframe_rfh_1 = CreateSubframe(
+      cross_origin_server_1.GetURL("/workers/service_worker_setup.html"));
+  RegisterWorkerThatDoesImportScriptsAndFetch(subframe_rfh_1, worker_type,
+                                              "worker_with_import_and_fetch.js",
+                                              import_script_url, fetch_url);
 
+  RenderFrameHost* subframe_rfh_2 = CreateSubframe(
+      cross_origin_server_2.GetURL("/workers/service_worker_setup.html"));
   RegisterWorkerThatDoesImportScriptsAndFetch(
-      &cross_origin_server_1, worker_type, "worker_with_import_and_fetch.js",
-      import_script_url, fetch_url);
-  RegisterWorkerThatDoesImportScriptsAndFetch(
-      &cross_origin_server_2, worker_type, "worker_with_import_and_fetch_2.js",
+      subframe_rfh_2, worker_type, "worker_with_import_and_fetch_2.js",
       import_script_url, fetch_url);
 
   cache_status_waiter.Run();
@@ -210,4 +243,81 @@
                        ::testing::Values(WorkerType::kServiceWorker,
                                          WorkerType::kSharedWorker)));
 
+// Test that network isolation key is filled in correctly for service worker's
+// main script request. The test navigates to "a.com" and creates an iframe
+// having origin "c.com" that registers |worker1|. The test then navigates to
+// "b.com" and creates an iframe also having origin "c.com". We now want to test
+// a second register request for |worker1| but just calling register() would be
+// a no-op since |worker1| is already the current worker. So we register a new
+// |worker2| and then |worker1| again.
+//
+// Note that the second navigation to "c.com" also triggers an update check for
+// |worker1|. We expect both the second register request for |worker1| and this
+// update request to exist in the cache.
+//
+// Note that it's sufficient not to test the cache miss when subframe origins
+// are different as in that case the two script urls must be different and it
+// also won't trigger an update.
+IN_PROC_BROWSER_TEST_F(WorkerNetworkIsolationKeyBrowserTest,
+                       ServiceWorkerMainScriptRequest) {
+  // Discard the old process to clear the in-memory cache.
+  CrossProcessNavigation();
+
+  net::EmbeddedTestServer subframe_server;
+  subframe_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
+  ASSERT_TRUE(subframe_server.Start());
+
+  net::EmbeddedTestServer new_tab_server;
+  new_tab_server.ServeFilesFromSourceDirectory(GetTestDataFilePath());
+  ASSERT_TRUE(new_tab_server.Start());
+
+  size_t num_completed = 0;
+  std::string main_script_file = "empty.js";
+  GURL main_script_request_url =
+      subframe_server.GetURL("/workers/" + main_script_file);
+
+  base::RunLoop cache_status_waiter;
+  URLLoaderInterceptor interceptor(
+      base::BindLambdaForTesting(
+          [&](URLLoaderInterceptor::RequestParams* params) { return false; }),
+      base::BindLambdaForTesting(
+          [&](const GURL& request_url,
+              const network::URLLoaderCompletionStatus& status) {
+            if (request_url == main_script_request_url) {
+              num_completed += 1;
+              if (num_completed == 1) {
+                EXPECT_FALSE(status.exists_in_cache);
+              } else if (num_completed == 2) {
+                EXPECT_TRUE(status.exists_in_cache);
+              } else if (num_completed == 3) {
+                EXPECT_TRUE(status.exists_in_cache);
+                cache_status_waiter.Quit();
+              } else {
+                NOTREACHED();
+              }
+            }
+          }),
+      {});
+
+  // Navigate to "a.com" and create the iframe "c.com", which registers
+  // |worker1|.
+  NavigateToURLBlockUntilNavigationsComplete(
+      shell(), embedded_test_server()->GetURL("/workers/frame_factory.html"),
+      1);
+  RenderFrameHost* subframe_rfh_1 = CreateSubframe(
+      subframe_server.GetURL("/workers/service_worker_setup.html"));
+  RegisterWorker(subframe_rfh_1, WorkerType::kServiceWorker, "empty.js");
+
+  // Navigate to "b.com" and create the another iframe on "c.com", which
+  // registers |worker2| and then |worker1| again.
+  NavigateToURLBlockUntilNavigationsComplete(
+      shell(), new_tab_server.GetURL("/workers/frame_factory.html"), 1);
+  RenderFrameHost* subframe_rfh_2 = CreateSubframe(
+      subframe_server.GetURL("/workers/service_worker_setup.html"));
+  RegisterWorker(subframe_rfh_2, WorkerType::kServiceWorker, "empty2.js");
+  RegisterWorker(subframe_rfh_2, WorkerType::kServiceWorker, "empty.js");
+
+  cache_status_waiter.Run();
+}
+
 }  // namespace content
diff --git a/content/common/service_worker/service_worker_types.h b/content/common/service_worker/service_worker_types.h
index 5be3ae660..67711a0 100644
--- a/content/common/service_worker/service_worker_types.h
+++ b/content/common/service_worker/service_worker_types.h
@@ -12,10 +12,6 @@
 
 namespace content {
 
-// Indicates the document main thread ID in the child process. This is used for
-// messaging between the browser process and the child process.
-static const int kDocumentMainThreadId = 0;
-
 // Constants for error messages.
 extern const char kServiceWorkerRegisterErrorPrefix[];
 extern const char kServiceWorkerUpdateErrorPrefix[];
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index 127f97e..3e3b103 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -94,10 +94,6 @@
 #include "services/service_manager/sandbox/mac/sandbox_mac.h"
 #endif
 
-#if defined(USE_OZONE)
-#include "ui/ozone/public/ozone_platform.h"
-#endif
-
 #if BUILDFLAG(USE_VAAPI)
 #include "media/gpu/vaapi/vaapi_wrapper.h"
 #endif
@@ -276,8 +272,9 @@
 #elif defined(USE_OZONE)
     // The MessagePump type required depends on the Ozone platform selected at
     // runtime.
-    main_thread_task_executor.reset(new base::SingleThreadTaskExecutor(
-        ui::OzonePlatform::EnsureInstance()->GetMessageLoopTypeForGpu()));
+    main_thread_task_executor =
+        std::make_unique<base::SingleThreadTaskExecutor>(
+            gpu_preferences.message_loop_type);
 #elif defined(OS_LINUX)
 #error "Unsupported Linux platform."
 #elif defined(OS_MACOSX)
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 932549a..2d5be81d 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -226,7 +226,6 @@
     "notification_source.h",
     "notification_types.h",
     "origin_policy_commands.h",
-    "origin_policy_error_reason.h",
     "overlay_window.h",
     "overscroll_configuration.h",
     "page_navigator.cc",
diff --git a/content/public/browser/background_sync_context.h b/content/public/browser/background_sync_context.h
index 67ab7a4..d2237b8 100644
--- a/content/public/browser/background_sync_context.h
+++ b/content/public/browser/background_sync_context.h
@@ -60,6 +60,7 @@
   // to fire any Background Sync events. Calls |callback| with this value.
   virtual void GetSoonestWakeupDelta(
       blink::mojom::BackgroundSyncType sync_type,
+      base::Time last_browser_wakeup_for_periodic_sync,
       base::OnceCallback<void(base::TimeDelta)> callback) = 0;
 
  protected:
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 25de3b5d..b7f97b9 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -133,6 +133,11 @@
   return nullptr;
 }
 
+bool ContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+    base::StringPiece scheme) {
+  return false;
+}
+
 network::mojom::URLLoaderFactoryPtrInfo
 ContentBrowserClient::CreateURLLoaderFactoryForNetworkRequests(
     RenderProcessHost* process,
@@ -942,7 +947,7 @@
 }
 
 base::Optional<std::string> ContentBrowserClient::GetOriginPolicyErrorPage(
-    OriginPolicyErrorReason error_reason,
+    network::OriginPolicyState error_reason,
     content::NavigationHandle* handle) {
   return base::nullopt;
 }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index de639e5..8da3e82 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -188,7 +188,6 @@
 class VpnServiceProxy;
 class WebContents;
 class WebContentsViewDelegate;
-enum class OriginPolicyErrorReason;
 struct MainFunctionParams;
 struct OpenURLParams;
 struct Referrer;
@@ -325,6 +324,16 @@
   // exceptions should be granted based on initiator's scheme.
   virtual const char* GetInitiatorSchemeBypassingDocumentBlocking();
 
+  // Returns true if everything embedded inside a document with given scheme
+  // should be treated as first-party content. |scheme| will be in canonical
+  // (lowercased) form.
+  //
+  // See also WebSecurityPolicy::RegisterURLSchemeAsFirstPartyWhenTopLevel() in
+  // the renderer, and the field third_party_cookies_allowed_schemes in
+  // network::mojom::CookieManagerParams, which should be synchronized.
+  virtual bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
+      base::StringPiece scheme);
+
   // Called to create a URLLoaderFactory for network requests in the following
   // cases:
   // - The default factory to be used by a frame.  In this case
@@ -1540,7 +1549,7 @@
   // Returns the HTML content of the error page for Origin Policy related
   // errors.
   virtual base::Optional<std::string> GetOriginPolicyErrorPage(
-      OriginPolicyErrorReason error_reason,
+      network::OriginPolicyState error_reason,
       content::NavigationHandle* navigation_handle);
 
   // Returns true if it is OK to ignore errors for certificates specified by the
diff --git a/content/public/browser/dom_storage_context.h b/content/public/browser/dom_storage_context.h
index 1bc9bf3..1a5b9704 100644
--- a/content/public/browser/dom_storage_context.h
+++ b/content/public/browser/dom_storage_context.h
@@ -53,12 +53,6 @@
 
   virtual void PerformSessionStorageCleanup(base::OnceClosure callback) = 0;
 
-  // If this is called, sessionStorage data will be stored on disk, and can be
-  // restored after a browser restart (with RecreateSessionStorage). This
-  // function must be called right after DOMStorageContextWrapper is created,
-  // and before it's used.
-  virtual void SetSaveSessionStorageOnDisk() = 0;
-
   // Creates a SessionStorageNamespace with the given |namespace_id|. Used
   // after tabs are restored by session restore. When created, the
   // SessionStorageNamespace with the correct |namespace_id| will be
diff --git a/content/public/browser/origin_policy_error_reason.h b/content/public/browser/origin_policy_error_reason.h
deleted file mode 100644
index 50787a12..0000000
--- a/content/public/browser/origin_policy_error_reason.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// Copyright (c) 2018 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_ORIGIN_POLICY_ERROR_REASON_H_
-#define CONTENT_PUBLIC_BROWSER_ORIGIN_POLICY_ERROR_REASON_H_
-
-namespace content {
-
-// Enumerate the reasons why an origin policy was rejected.
-enum class OriginPolicyErrorReason : int {
-  kCannotLoadPolicy,         // The policy document could not be downloaded.
-  kPolicyShouldNotRedirect,  // The policy doc request was met with a redirect.
-  kOther,
-};
-
-}  // namespace content
-
-#endif  // CONTENT_PUBLIC_BROWSER_ORIGIN_POLICY_ERROR_REASON_H_
diff --git a/content/public/test/hit_test_region_observer.cc b/content/public/test/hit_test_region_observer.cc
index 47e391b..8f81ca1 100644
--- a/content/public/test/hit_test_region_observer.cc
+++ b/content/public/test/hit_test_region_observer.cc
@@ -76,8 +76,11 @@
 }
 
 void HitTestRegionObserver::WaitForHitTestData() {
+  DCHECK(cached_hit_test_data_.empty());
+
   for (auto& it : GetHostFrameSinkManager()->display_hit_test_query()) {
     if (it.second->ContainsActiveFrameSinkId(frame_sink_id_)) {
+      cached_hit_test_data_ = it.second->GetHitTestData();
       return;
     }
   }
@@ -87,9 +90,30 @@
   run_loop_.reset();
 }
 
+void HitTestRegionObserver::WaitForHitTestDataChange() {
+  DCHECK(!cached_hit_test_data_.empty());
+
+  for (auto& it : GetHostFrameSinkManager()->display_hit_test_query()) {
+    DCHECK(it.second->ContainsActiveFrameSinkId(frame_sink_id_));
+    if (it.second->GetHitTestData() != cached_hit_test_data_) {
+      cached_hit_test_data_ = it.second->GetHitTestData();
+      return;
+    }
+  }
+
+  hit_test_data_change_run_loop_ = std::make_unique<base::RunLoop>();
+  hit_test_data_change_run_loop_->Run();
+  hit_test_data_change_run_loop_.reset();
+}
+
 void HitTestRegionObserver::OnAggregatedHitTestRegionListUpdated(
     const viz::FrameSinkId& frame_sink_id,
     const std::vector<viz::AggregatedHitTestRegion>& hit_test_data) {
+  if (hit_test_data_change_run_loop_ &&
+      cached_hit_test_data_ != hit_test_data) {
+    cached_hit_test_data_ = hit_test_data;
+    hit_test_data_change_run_loop_->Quit();
+  }
 
   if (!run_loop_)
     return;
@@ -109,7 +133,7 @@
       GetHostFrameSinkManager()->display_hit_test_query();
   const auto iter = hit_test_query_map.find(frame_sink_id_);
   DCHECK(iter != hit_test_query_map.end());
-  return iter->second.get()->hit_test_data_;
+  return iter->second.get()->GetHitTestData();
 }
 
 HitTestTransformChangeObserver::HitTestTransformChangeObserver(
diff --git a/content/public/test/hit_test_region_observer.h b/content/public/test/hit_test_region_observer.h
index 6c2a8227..c73b409 100644
--- a/content/public/test/hit_test_region_observer.h
+++ b/content/public/test/hit_test_region_observer.h
@@ -30,7 +30,8 @@
 // HitTestDataWaiter (is-a HitTestRegionObserver) once Viz HitTesting is on by
 // default, and there are no longer dependancies upon content.
 //
-// Test API which observes the arrival of hit test data within a Viz host.
+// Test API which observes the arrival / change of hit test data within a Viz
+// host.
 //
 // HitTestRegionObserver is bound to a viz::FrameSinkId for which it observers
 // changes in hit test data.
@@ -39,14 +40,15 @@
   explicit HitTestRegionObserver(const viz::FrameSinkId& frame_sink_id);
   ~HitTestRegionObserver() override;
 
-  // Waits until the hit testing data for |frame_sink_id_| has arrvied. However
-  // if there is existing hit test data for |frame_sink_id_| this will not wait
-  // for new data to be submitted.
-  //
-  // TODO(jonross): Update this so that it can also be used to wait for updated
-  // data to arrive.
+  // The following functions need to be called in order to wait for the change
+  // in hit test data. The first one should be called before any potential
+  // change to hit test data (to cache the current state) and the second one
+  // should be called after the change. Note that if any change has occurred
+  // after the call to WaitForHitTestData, WaitForHitTestDataChange will return
+  // immediately and the desired data may not be returned. Looping until the
+  // received data match the expected data should be useful in such case.
   void WaitForHitTestData();
-
+  void WaitForHitTestDataChange();
   const std::vector<viz::AggregatedHitTestRegion>& GetHitTestData();
 
  private:
@@ -57,6 +59,8 @@
 
   viz::FrameSinkId const frame_sink_id_;
   std::unique_ptr<base::RunLoop> run_loop_;
+  std::unique_ptr<base::RunLoop> hit_test_data_change_run_loop_;
+  std::vector<viz::AggregatedHitTestRegion> cached_hit_test_data_;
 
   DISALLOW_COPY_AND_ASSIGN(HitTestRegionObserver);
 };
diff --git a/content/public/test/test_browser_thread_bundle_unittest.cc b/content/public/test/test_browser_thread_bundle_unittest.cc
index 28ebbab..e5760e9a 100644
--- a/content/public/test/test_browser_thread_bundle_unittest.cc
+++ b/content/public/test/test_browser_thread_bundle_unittest.cc
@@ -166,7 +166,8 @@
 
 TEST(TestBrowserThreadBundleTest, TraitsConstructorOverrideMainThreadType) {
   TestBrowserThreadBundle test_browser_thread_bundle(
-      base::test::ScopedTaskEnvironment::MainThreadType::UI_MOCK_TIME);
+      base::test::ScopedTaskEnvironment::MainThreadType::UI,
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
 
   // Should set up a UI main thread.
   EXPECT_TRUE(base::MessageLoopCurrentForUI::IsSet());
diff --git a/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc b/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
index 8075706..b59c33569 100644
--- a/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
+++ b/content/renderer/media/audio/audio_renderer_sink_cache_unittest.cc
@@ -34,7 +34,7 @@
  public:
   AudioRendererSinkCacheTest()
       : task_env_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         cache_(std::make_unique<AudioRendererSinkCacheImpl>(
             task_env_.GetMainThreadTaskRunner(),
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 134af7b..d0ca8159 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -1850,14 +1850,16 @@
 // RenderView implementation ---------------------------------------------------
 
 bool RenderViewImpl::Send(IPC::Message* message) {
-  // This method is an override of IPC::Sender, but RenderWidget also has an
-  // override of IPC::Sender, so this method also overrides RenderWidget. Thus
-  // we must call to the base class, not via an upcast or virtual dispatch would
-  // go back here.
-  CHECK(message->routing_id() != MSG_ROUTING_NONE);
+  // No messages sent through RenderView come without a routing id, yay. Let's
+  // keep that up.
+  CHECK_NE(message->routing_id(), MSG_ROUTING_NONE);
 
-  // TODO(ajwong): Don't delegate to render widget. Filter here.
-  return GetWidget()->Send(message);
+  // Don't send any messages after the browser has told us to close.
+  if (GetWidget()->is_closing()) {
+    delete message;
+    return false;
+  }
+  return RenderThread::Get()->Send(message);
 }
 
 RenderWidget* RenderViewImpl::GetWidget() {
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 7ff43ed9..f3f9d052 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -664,7 +664,14 @@
     delete message;
     return false;
   }
-  if (is_frozen_ && !SwappedOutMessages::CanSendWhileSwappedOut(message)) {
+  // TODO(danakj): We believe that we should be able to not block IPC sending.
+  // When there's a provisional main frame using this widget, we should not be
+  // sending messages with the RenderWidget yet. And when the widget is frozen
+  // because there is no local main frame, there should be no code using
+  // RenderWidget and sending messages through it.
+  // We should CHECK() that the RenderWidget is not frozen and that the frame
+  // attached to it is not provisional, instead of dropping messages.
+  if (is_frozen_) {
     delete message;
     return false;
   }
@@ -2476,6 +2483,15 @@
   }
 }
 
+void RenderWidget::ConvertViewportToWindow(blink::WebFloatRect* rect) {
+  if (compositor_deps_->IsUseZoomForDSFEnabled()) {
+    rect->x /= GetOriginalScreenInfo().device_scale_factor;
+    rect->y /= GetOriginalScreenInfo().device_scale_factor;
+    rect->width /= GetOriginalScreenInfo().device_scale_factor;
+    rect->height /= GetOriginalScreenInfo().device_scale_factor;
+  }
+}
+
 void RenderWidget::ConvertWindowToViewport(blink::WebFloatRect* rect) {
   if (compositor_deps_->IsUseZoomForDSFEnabled()) {
     rect->x *= GetOriginalScreenInfo().device_scale_factor;
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index f230403..9f39103 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -418,6 +418,7 @@
   void SetOverscrollBehavior(const cc::OverscrollBehavior&) override;
   void ShowVirtualKeyboardOnElementFocus() override;
   void ConvertViewportToWindow(blink::WebRect* rect) override;
+  void ConvertViewportToWindow(blink::WebFloatRect* rect) override;
   void ConvertWindowToViewport(blink::WebFloatRect* rect) override;
   bool RequestPointerLock() override;
   void RequestPointerUnlock() override;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
index 9c1272d6..a89a61d 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -61,6 +61,7 @@
 #include "gpu/config/gpu_info.h"
 #include "gpu/ipc/client/gpu_channel_host.h"
 #include "media/audio/audio_output_device.h"
+#include "media/base/media_switches.h"
 #include "media/blink/webcontentdecryptionmodule_impl.h"
 #include "media/filters/stream_parser_factory.h"
 #include "media/video/gpu_video_accelerator_factories.h"
@@ -546,6 +547,11 @@
   return RenderThreadImpl::current()->SharedMainThreadContextProvider().get();
 }
 
+bool RendererBlinkPlatformImpl::RTCSmoothnessAlgorithmEnabled() {
+  return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+      switches::kDisableRTCSmoothnessAlgorithm);
+}
+
 //------------------------------------------------------------------------------
 
 std::unique_ptr<WebRTCPeerConnectionHandler>
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
index 88ea9bc..f1bc21b 100644
--- a/content/renderer/renderer_blink_platform_impl.h
+++ b/content/renderer/renderer_blink_platform_impl.h
@@ -128,6 +128,7 @@
       blink::WebLocalFrame* web_frame,
       const media::AudioSourceParameters& params) override;
   viz::ContextProvider* SharedMainThreadContextProvider() override;
+  bool RTCSmoothnessAlgorithmEnabled() override;
   std::unique_ptr<blink::WebRTCPeerConnectionHandler>
   CreateRTCPeerConnectionHandler(
       blink::WebRTCPeerConnectionHandlerClient* client,
diff --git a/content/shell/renderer/web_test/blink_test_runner.cc b/content/shell/renderer/web_test/blink_test_runner.cc
index 8e706dda..dabd9e4 100644
--- a/content/shell/renderer/web_test/blink_test_runner.cc
+++ b/content/shell/renderer/web_test/blink_test_runner.cc
@@ -168,8 +168,7 @@
 BlinkTestRunner::BlinkTestRunner(RenderView* render_view)
     : RenderViewObserver(render_view),
       RenderViewObserverTracker<BlinkTestRunner>(render_view),
-      test_config_(mojom::ShellTestConfiguration::New()),
-      is_main_window_(false) {}
+      test_config_(mojom::ShellTestConfiguration::New()) {}
 
 BlinkTestRunner::~BlinkTestRunner() {}
 
@@ -572,8 +571,6 @@
     return;
 
   std::move(dump_callback_).Run(std::move(dump_result_));
-  dump_callback_.Reset();
-  dump_result_.reset();
 }
 
 void BlinkTestRunner::CloseRemainingWindows() {
diff --git a/content/shell/renderer/web_test/blink_test_runner.h b/content/shell/renderer/web_test/blink_test_runner.h
index 72c5253..ad5ee73 100644
--- a/content/shell/renderer/web_test/blink_test_runner.h
+++ b/content/shell/renderer/web_test/blink_test_runner.h
@@ -187,7 +187,7 @@
       base::OnceCallback<void(const std::vector<std::string>&)>>
       get_bluetooth_events_callbacks_;
 
-  bool is_main_window_;
+  bool is_main_window_ = false;
 
   bool waiting_for_reset_ = false;
 
diff --git a/content/shell/renderer/web_test/web_test_render_frame_observer.h b/content/shell/renderer/web_test/web_test_render_frame_observer.h
index 9489f2b4..64d7c2c 100644
--- a/content/shell/renderer/web_test/web_test_render_frame_observer.h
+++ b/content/shell/renderer/web_test/web_test_render_frame_observer.h
@@ -27,6 +27,7 @@
   void DidFailProvisionalLoad(const blink::WebURLError& error) override;
   void OnDestruct() override;
 
+  // mojom::WebTestControl implementation.
   void CaptureDump(CaptureDumpCallback callback) override;
   void CompositeWithRaster(CompositeWithRasterCallback callback) override;
   void DumpFrameLayout(DumpFrameLayoutCallback callback) override;
diff --git a/content/shell/test_runner/spell_check_client.cc b/content/shell/test_runner/spell_check_client.cc
index 5b8611b..802f470 100644
--- a/content/shell/test_runner/spell_check_client.cc
+++ b/content/shell/test_runner/spell_check_client.cc
@@ -142,7 +142,7 @@
   v8::Isolate* isolate = blink::MainThreadIsolate();
   v8::HandleScope handle_scope(isolate);
 
-  blink::WebFrame* frame = test_runner_->mainFrame();
+  blink::WebFrame* frame = test_runner_->MainFrame();
   if (!frame || frame->IsWebRemoteFrame())
     return;
   blink::WebLocalFrame* local_frame = frame->ToWebLocalFrame();
diff --git a/content/shell/test_runner/test_runner.cc b/content/shell/test_runner/test_runner.cc
index 43343fc..6fdcdf8 100644
--- a/content/shell/test_runner/test_runner.cc
+++ b/content/shell/test_runner/test_runner.cc
@@ -24,7 +24,6 @@
 #include "content/shell/common/web_test/web_test_switches.h"
 #include "content/shell/test_runner/layout_dump.h"
 #include "content/shell/test_runner/mock_content_settings_client.h"
-#include "content/shell/test_runner/mock_screen_orientation_client.h"
 #include "content/shell/test_runner/mock_web_document_subresource_filter.h"
 #include "content/shell/test_runner/pixel_dump.h"
 #include "content/shell/test_runner/spell_check_client.h"
@@ -1425,27 +1424,23 @@
 void TestRunnerBindings::NotImplemented(const gin::Arguments& args) {}
 
 TestRunner::WorkQueue::WorkQueue(TestRunner* controller)
-    : frozen_(false), controller_(controller) {}
+    : controller_(controller) {}
 
 TestRunner::WorkQueue::~WorkQueue() {
   Reset();
 }
 
 void TestRunner::WorkQueue::ProcessWorkSoon() {
-  if (!controller_->loading_frames_.empty())
-    return;
-
-  if (!queue_.empty()) {
-    // We delay processing queued work to avoid recursion problems.
-    controller_->delegate_->PostTask(base::BindOnce(
-        &TestRunner::WorkQueue::ProcessWork, weak_factory_.GetWeakPtr()));
-  } else if (!controller_->web_test_runtime_flags_.wait_until_done()) {
-    controller_->delegate_->TestFinished();
-  }
+  // We delay processing queued work to avoid recursion problems, and to avoid
+  // running tasks in the middle of a navigation call stack, where blink and
+  // content may have inconsistent states halfway through being updated.
+  controller_->delegate_->PostTask(base::BindOnce(
+      &TestRunner::WorkQueue::ProcessWork, weak_factory_.GetWeakPtr()));
 }
 
 void TestRunner::WorkQueue::Reset() {
   frozen_ = false;
+  finished_loading_ = false;
   while (!queue_.empty()) {
     delete queue_.front();
     queue_.pop_front();
@@ -1461,44 +1456,47 @@
 }
 
 void TestRunner::WorkQueue::ProcessWork() {
-  // Quit doing work once a load is in progress.
-  if (controller_->main_view_) {
-    while (!queue_.empty()) {
-      bool startedLoad =
-          queue_.front()->Run(controller_->delegate_, controller_->main_view_);
-      delete queue_.front();
-      queue_.pop_front();
-      if (startedLoad)
-        return;
+  if (!controller_->main_view_)
+    return;
+
+  while (!queue_.empty()) {
+    finished_loading_ = false;  // Watch for loading finishing inside Run().
+    bool started_load =
+        queue_.front()->Run(controller_->delegate_, controller_->main_view_);
+    delete queue_.front();
+    queue_.pop_front();
+
+    if (started_load) {
+      // If a load started, and didn't complete inside of Run(), then mark
+      // the load as running.
+      if (!finished_loading_)
+        controller_->running_load_ = true;
+
+      // Quit doing work once a load is in progress.
+      //
+      // TODO(danakj): We could avoid the post-task of ProcessWork() by not
+      // early-outting here if |finished_loading_|. Since load finished we could
+      // keep running work. And in RemoveLoadingFrame() instead of calling
+      // ProcessWorkSoon() unconditionally, only call it if we're not already
+      // inside ProcessWork().
+      return;
     }
   }
 
-  if (!controller_->web_test_runtime_flags_.wait_until_done() &&
-      controller_->loading_frames_.empty()) {
-    controller_->delegate_->TestFinished();
-  }
+  // If there was no navigation stated, there may be no more tasks in the
+  // system. We can safely finish the test here as we're not in the middle
+  // of a navigation call stack, and ProcessWork() was a posted task.
+  controller_->FinishTestIfReady();
 }
 
 TestRunner::TestRunner(TestInterfaces* interfaces)
-    : test_is_running_(false),
-      close_remaining_windows_(false),
-      work_queue_(this),
-      web_history_item_count_(0),
+    : work_queue_(this),
       test_interfaces_(interfaces),
-      delegate_(nullptr),
-      main_view_(nullptr),
-      mock_content_settings_client_(
-          new MockContentSettingsClient(&web_test_runtime_flags_)),
-      mock_screen_orientation_client_(new MockScreenOrientationClient),
-      spellcheck_(new SpellCheckClient(this)),
-      chooser_count_(0),
-      previously_focused_view_(nullptr),
-      is_web_platform_tests_mode_(false),
-      animation_requires_raster_(false),
-      effective_connection_type_(
-          blink::WebEffectiveConnectionType::kTypeUnknown) {}
+      mock_content_settings_client_(std::make_unique<MockContentSettingsClient>(
+          &web_test_runtime_flags_)),
+      spellcheck_(std::make_unique<SpellCheckClient>(this)) {}
 
-TestRunner::~TestRunner() {}
+TestRunner::~TestRunner() = default;
 
 void TestRunner::Install(
     blink::WebLocalFrame* frame,
@@ -1506,7 +1504,7 @@
   // In WPT, only reftests generate pixel results.
   TestRunnerBindings::Install(weak_factory_.GetWeakPtr(), view_test_runner,
                               frame, is_web_platform_tests_mode());
-  mock_screen_orientation_client_->OverrideAssociatedInterfaceProviderForFrame(
+  mock_screen_orientation_client_.OverrideAssociatedInterfaceProviderForFrame(
       frame);
 }
 
@@ -1526,7 +1524,7 @@
   is_web_platform_tests_mode_ = false;
   loading_frames_.clear();
   web_test_runtime_flags_.Reset();
-  mock_screen_orientation_client_->ResetData();
+  mock_screen_orientation_client_.ResetData();
   mock_content_settings_client_->ResetClientHintsPersistencyData();
   drag_image_.reset();
 
@@ -1554,6 +1552,10 @@
   test_repaint_ = false;
   sweep_horizontally_ = false;
   animation_requires_raster_ = false;
+  // Starts as true for the initial load which does not come from the
+  // WorkQueue.
+  running_load_ = true;
+  did_notify_done_ = false;
 
   http_headers_to_clear_.clear();
 
@@ -1822,13 +1824,67 @@
   if (!loading_frames_.empty())
     return;
 
+  running_load_ = false;
   web_test_runtime_flags_.set_have_loading_frame(false);
   OnWebTestRuntimeFlagsChanged();
 
-  LocationChangeDone();
+  web_history_item_count_ = delegate_->NavigationEntryCount();
+
+  // No more new work after the first complete load.
+  work_queue_.set_frozen(true);
+  // Inform the work queue that any load it started is done, in case it is still
+  // inside ProcessWork().
+  work_queue_.set_finished_loading();
+
+  // The test chooses between running queued tasks or waiting for NotifyDone()
+  // but not both.
+  if (!web_test_runtime_flags_.wait_until_done())
+    work_queue_.ProcessWorkSoon();
 }
 
-blink::WebFrame* TestRunner::mainFrame() const {
+void TestRunner::FinishTestIfReady() {
+  if (!test_is_running_)
+    return;
+  // The test only ends due to no queued tasks when not waiting for
+  // NotifyDone() from the test. The test chooses between these two modes.
+  if (web_test_runtime_flags_.wait_until_done())
+    return;
+  // If the test is running a loading task, we wait for that.
+  if (running_load_)
+    return;
+
+  // The test may cause loading to occur in ways other than through the
+  // WorkQueue, and we wait for them before finishing the test.
+  if (!loading_frames_.empty())
+    return;
+
+  // If there are tasks in the queue still, we must wait for them before
+  // finishing the test.
+  if (!work_queue_.is_empty())
+    return;
+
+  // When there are no more frames loading, and the test hasn't asked to wait
+  // for NotifyDone(), then we normally conclude the test. However if this
+  // TestRunner is attached to a swapped out frame tree - that is the main
+  // frame is in another frame tree - then finishing here would be premature
+  // for the main frame where the test is running. If |did_notify_done_| is true
+  // then we *were* waiting for NotifyDone() and it has already happened, so we
+  // want to proceed as if the NotifyDone() is happening now.
+  //
+  // Ideally, the main frame would wait for loading frames in its frame tree
+  // as well as any secondary renderers, but it does not know about secondary
+  // renderers. So in this case the test should finish when frames finish
+  // loading in the primary renderer, and we don't finish the test from a
+  // secondary renderer unless it is asked for explicitly via NotifyDone.
+  if (!main_view_->MainFrame()->IsWebLocalFrame() && !did_notify_done_)
+    return;
+
+  // No tasks left to run, all frames are done loading from previous tasks, and
+  // we're not waiting for NotifyDone(), so the test is done.
+  delegate_->TestFinished();
+}
+
+blink::WebFrame* TestRunner::MainFrame() const {
   return main_view_->MainFrame();
 }
 
@@ -2086,7 +2142,7 @@
 }
 
 MockScreenOrientationClient* TestRunner::getMockScreenOrientationClient() {
-  return mock_screen_orientation_client_.get();
+  return &mock_screen_orientation_client_;
 }
 
 void TestRunner::SetMockScreenOrientation(const std::string& orientation_str) {
@@ -2107,14 +2163,14 @@
     blink::WebFrame* main_frame = window->webview()->MainFrame();
     // TODO(lukasza): Need to make this work for remote frames.
     if (main_frame->IsWebLocalFrame()) {
-      mock_screen_orientation_client_->UpdateDeviceOrientation(
+      mock_screen_orientation_client_.UpdateDeviceOrientation(
           main_frame->ToWebLocalFrame(), orientation);
     }
   }
 }
 
 void TestRunner::DisableMockScreenOrientation() {
-  mock_screen_orientation_client_->SetDisabled(true);
+  mock_screen_orientation_client_.SetDisabled(true);
 }
 
 void TestRunner::SetPopupBlockingEnabled(bool block_popups) {
@@ -2516,16 +2572,6 @@
   web_test_runtime_flags_.tracked_dictionary().ResetChangeTracking();
 }
 
-void TestRunner::LocationChangeDone() {
-  web_history_item_count_ = delegate_->NavigationEntryCount();
-
-  // No more new work after the first complete load.
-  work_queue_.set_frozen(true);
-
-  if (!web_test_runtime_flags_.wait_until_done())
-    work_queue_.ProcessWorkSoon();
-}
-
 void TestRunner::CheckResponseMimeType() {
   // Text output: the test page can request different types of output which we
   // handle here.
@@ -2558,6 +2604,7 @@
       work_queue_.is_empty())
     delegate_->TestFinished();
   web_test_runtime_flags_.set_wait_until_done(false);
+  did_notify_done_ = true;
   OnWebTestRuntimeFlagsChanged();
 }
 
diff --git a/content/shell/test_runner/test_runner.h b/content/shell/test_runner/test_runner.h
index fb76256e..cbb532f 100644
--- a/content/shell/test_runner/test_runner.h
+++ b/content/shell/test_runner/test_runner.h
@@ -17,6 +17,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/strings/string16.h"
+#include "content/shell/test_runner/mock_screen_orientation_client.h"
 #include "content/shell/test_runner/test_runner_export.h"
 #include "content/shell/test_runner/web_test_runner.h"
 #include "content/shell/test_runner/web_test_runtime_flags.h"
@@ -77,6 +78,14 @@
   void SetTestIsRunning(bool);
   bool TestIsRunning() const { return test_is_running_; }
 
+  // Finishes the test if it is ready. This should be called before running
+  // tasks that will change state, so that the test can capture the current
+  // state. Specifically, should run before the BeginMainFrame step which does
+  // layout and animation etc.
+  // This does *not* run as part of loading finishing because that happens in
+  // the middle of blink call stacks that have inconsistent state.
+  void FinishTestIfReady();
+
   bool UseMockTheme() const { return use_mock_theme_; }
 
   // WebTestRunner implementation.
@@ -148,7 +157,7 @@
   // requests in WorkQueue.
   void RemoveLoadingFrame(blink::WebFrame* frame);
 
-  blink::WebFrame* mainFrame() const;
+  blink::WebFrame* MainFrame() const;
   void policyDelegateDone();
   bool policyDelegateEnabled() const;
   bool policyDelegateIsPermissive() const;
@@ -195,13 +204,16 @@
     void AddWork(WorkItem*);
 
     void set_frozen(bool frozen) { frozen_ = frozen; }
-    bool is_empty() { return queue_.empty(); }
+    bool is_empty() const { return queue_.empty(); }
+
+    void set_finished_loading() { finished_loading_ = true; }
 
    private:
     void ProcessWork();
 
     base::circular_deque<WorkItem*> queue_;
-    bool frozen_;
+    bool frozen_ = false;
+    bool finished_loading_ = false;
     TestRunner* controller_;
 
     base::WeakPtrFactory<WorkQueue> weak_factory_{this};
@@ -505,17 +517,12 @@
 
   void CheckResponseMimeType();
 
-  // In the Mac code, this is called to trigger the end of a test after the
-  // page has finished loading. From here, we can generate the dump for the
-  // test.
-  void LocationChangeDone();
-
-  bool test_is_running_;
+  bool test_is_running_ = false;
 
   // When reset is called, go through and close all but the main test shell
   // window. By default, set to true but toggled to false using
   // setCloseRemainingWindowsWhenComplete().
-  bool close_remaining_windows_;
+  bool close_remaining_windows_ = false;
 
   WorkQueue work_queue_;
 
@@ -526,7 +533,7 @@
   std::string tooltip_text_;
 
   // Bound variable counting the number of top URLs visited.
-  int web_history_item_count_;
+  int web_history_item_count_ = 0;
 
   // Flags controlling what content gets dumped as a layout text result.
   WebTestRuntimeFlags web_test_runtime_flags_;
@@ -552,22 +559,31 @@
   std::vector<unsigned char> audio_data_;
 
   TestInterfaces* test_interfaces_;
-  WebTestDelegate* delegate_;
-  blink::WebView* main_view_;
+  WebTestDelegate* delegate_ = nullptr;
+  blink::WebView* main_view_ = nullptr;
 
   // This is non empty when a load is in progress.
   std::vector<blink::WebFrame*> loading_frames_;
+  // When a loading task is started, this bool is set until all loading_frames_
+  // are completed and removed. This bool becomes true earlier than
+  // loading_frames_ becomes non-empty. Starts as true for the initial load
+  // which does not come from the WorkQueue.
+  bool running_load_ = true;
+  // When NotifyDone() occurs, if loading is still working, it is delayed, and
+  // this bool tracks that NotifyDone() was called. This differentiates from a
+  // test that was not waiting for NotifyDone() at all.
+  bool did_notify_done_ = false;
 
   // WebContentSettingsClient mock object.
   std::unique_ptr<MockContentSettingsClient> mock_content_settings_client_;
 
-  bool use_mock_theme_;
+  bool use_mock_theme_ = false;
 
-  std::unique_ptr<MockScreenOrientationClient> mock_screen_orientation_client_;
+  MockScreenOrientationClient mock_screen_orientation_client_;
   std::unique_ptr<SpellCheckClient> spellcheck_;
 
   // Number of currently active color choosers.
-  int chooser_count_;
+  int chooser_count_ = 0;
 
   // Captured drag image.
   SkBitmap drag_image_;
@@ -575,18 +591,19 @@
   // View that was focused by a previous call to TestRunner::SetFocus method.
   // Note - this can be a dangling pointer to an already destroyed WebView (this
   // is ok, because this is taken care of in WebTestDelegate::SetFocus).
-  blink::WebView* previously_focused_view_;
+  blink::WebView* previously_focused_view_ = nullptr;
 
   // True when running a test in web_tests/external/wpt/.
-  bool is_web_platform_tests_mode_;
+  bool is_web_platform_tests_mode_ = false;
 
   // True if rasterization should be performed during tests that examine
   // fling-style animations. This includes middle-click auto-scroll behaviors.
   // This does not include most "ordinary" animations, such as CSS animations.
-  bool animation_requires_raster_;
+  bool animation_requires_raster_ = false;
 
   // An effective connection type settable by web tests.
-  blink::WebEffectiveConnectionType effective_connection_type_;
+  blink::WebEffectiveConnectionType effective_connection_type_ =
+      blink::WebEffectiveConnectionType::kTypeUnknown;
 
   // Forces v8 compilation cache to be disabled (used for inspector tests).
   bool disable_v8_cache_ = false;
diff --git a/content/shell/test_runner/web_widget_test_proxy.cc b/content/shell/test_runner/web_widget_test_proxy.cc
index 469924c..4536afb 100644
--- a/content/shell/test_runner/web_widget_test_proxy.cc
+++ b/content/shell/test_runner/web_widget_test_proxy.cc
@@ -22,6 +22,14 @@
 
 WebWidgetTestProxy::~WebWidgetTestProxy() = default;
 
+void WebWidgetTestProxy::BeginMainFrame(base::TimeTicks frame_time) {
+  // This must happen before we run BeginMainFrame() in the base class, which
+  // will change states. TestFinished() wants to grab the current state.
+  GetTestRunner()->FinishTestIfReady();
+
+  RenderWidget::BeginMainFrame(frame_time);
+}
+
 void WebWidgetTestProxy::RequestDecode(
     const cc::PaintImage& image,
     base::OnceCallback<void(bool)> callback) {
diff --git a/content/shell/test_runner/web_widget_test_proxy.h b/content/shell/test_runner/web_widget_test_proxy.h
index 0f0f166..04b356f 100644
--- a/content/shell/test_runner/web_widget_test_proxy.h
+++ b/content/shell/test_runner/web_widget_test_proxy.h
@@ -58,6 +58,7 @@
       : RenderWidget(std::forward<Args>(args)...) {}
 
   // RenderWidget overrides.
+  void BeginMainFrame(base::TimeTicks frame_time) override;
   void RequestDecode(const cc::PaintImage& image,
                      base::OnceCallback<void(bool)> callback) override;
   void RequestPresentation(PresentationTimeCallback callback) override;
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 6a269404..73b8cae0 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -856,6 +856,7 @@
     "../browser/background_sync/background_sync_base_browsertest.cc",
     "../browser/background_sync/background_sync_base_browsertest.h",
     "../browser/background_sync/one_shot_background_sync_browsertest.cc",
+    "../browser/background_sync/periodic_background_sync_browsertest.cc",
     "../browser/battery_monitor_browsertest.cc",
     "../browser/blob_storage/blob_storage_browsertest.cc",
     "../browser/blob_storage/blob_url_browsertest.cc",
@@ -1551,15 +1552,14 @@
     "../browser/devtools/devtools_video_consumer_unittest.cc",
     "../browser/devtools/protocol/tracing_handler_unittest.cc",
     "../browser/devtools/protocol_unittest.cc",
-    "../browser/dom_storage/dom_storage_area_unittest.cc",
-    "../browser/dom_storage/dom_storage_context_impl_unittest.cc",
     "../browser/dom_storage/dom_storage_context_wrapper_unittest.cc",
     "../browser/dom_storage/dom_storage_database_unittest.cc",
     "../browser/dom_storage/local_storage_context_mojo_unittest.cc",
     "../browser/dom_storage/session_storage_area_impl_unittest.cc",
     "../browser/dom_storage/session_storage_context_mojo_unittest.cc",
     "../browser/dom_storage/session_storage_data_map_unittest.cc",
-    "../browser/dom_storage/session_storage_database_unittest.cc",
+    "../browser/dom_storage/session_storage_database.cc",
+    "../browser/dom_storage/session_storage_database.h",
     "../browser/dom_storage/session_storage_metadata_unittest.cc",
     "../browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc",
     "../browser/dom_storage/storage_area_impl_unittest.cc",
diff --git a/content/test/data/background_sync/background_sync_test_helpers.js b/content/test/data/background_sync/background_sync_test_helpers.js
index fd9ff2c1..918e25c2 100644
--- a/content/test/data/background_sync/background_sync_test_helpers.js
+++ b/content/test/data/background_sync/background_sync_test_helpers.js
@@ -22,41 +22,128 @@
 
 function registerServiceWorker() {
   navigator.serviceWorker.register('service_worker.js', {scope: './'})
-    .then(function() {
+    .then(() => {
       return navigator.serviceWorker.ready;
     })
-    .then(function(swRegistration) {
+    .then((swRegistration) => {
       sendResultToTest('ok - service worker registered');
     })
     .catch(sendErrorToTest);
 }
 
-function register(tag) {
+function registerOneShotSync(tag) {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
+    .then((swRegistration) => {
       return swRegistration.sync.register(tag);
     })
-    .then(function() {
+    .then(() => {
       sendResultToTest('ok - ' + tag + ' registered');
     })
     .catch(sendErrorToTest);
 }
 
-function registerFromServiceWorker(tag) {
+function registerOneShotSyncFromLocalFrame(frame_url) {
+  let frameWindow;
+  return createFrame(frame_url)
+    .then((frame) => {
+      frameWindow = frame.contentWindow;
+      return frameWindow.navigator.serviceWorker.register('service_worker.js');
+    })
+    .then(() => {
+      return frameWindow.navigator.serviceWorker.ready;
+    })
+    .then((frame_registration) => {
+      return frame_registration.sync.register('foo');
+    })
+    .then(() => {
+      sendResultToTest('ok - iframe registered sync');
+    })
+    .catch(sendErrorToTest);
+}
+
+function registerOneShotSyncFromCrossOriginFrame(cross_frame_url) {
+  return createFrame(cross_frame_url)
+    .then((frame) => {
+      return receiveMessage();
+    })
+    .then((message) => {
+      console.log(message);
+      if (message !== 'registration failed') {
+        sendResultToTest('failed - ' + message);
+        return;
+      }
+      sendResultToTest('ok - frame failed to register sync');
+    });
+}
+
+function registerOneShotSyncFromServiceWorker(tag) {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
-      swRegistration.active.postMessage({action: 'register', tag: tag});
+    .then((swRegistration) => {
+      swRegistration.active.postMessage(
+          {action: 'registerOneShotSync', tag: tag});
       sendResultToTest('ok - ' + tag + ' register sent to SW');
     })
     .catch(sendErrorToTest);
 }
 
-function hasTag(tag) {
+function registerPeriodicSync(tag, minInterval) {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
+    .then((swRegistration) => {
+      if (minInterval !== undefined) {
+        return swRegistration.periodicSync.register(
+            tag, {minInterval: minInterval});
+      } else {
+        return swRegistration.periodicSync.register(tag);
+      }
+    })
+    .then(() => {
+      sendResultToTest('ok - ' + tag + ' registered');
+    })
+    .catch(sendErrorToTest);
+}
+
+function registerPeriodicSyncFromLocalFrame(frame_url, minInterval) {
+  let frameWindow;
+  return createFrame(frame_url)
+    .then((frame) => {
+      frameWindow = frame.contentWindow;
+      return frameWindow.navigator.serviceWorker.register('service_worker.js');
+    })
+    .then(() => {
+      return frameWindow.navigator.serviceWorker.ready;
+    })
+    .then((frame_registration) => {
+      return frame_registration.periodicSync.register(
+          'foo', {minInterval: minInterval});
+    })
+    .then(() => {
+      sendResultToTest('ok - iframe registered periodic sync');
+    })
+    .catch(sendErrorToTest);
+}
+
+function registerPeriodicSyncFromServiceWorker(tag, minInterval) {
+  navigator.serviceWorker.ready
+    .then((swRegistration) => {
+      if (minInterval !== undefined) {
+        swRegistration.active.postMessage(
+          {action: 'registerPeriodicSync', tag: tag, minInterval: minInterval});
+      } else {
+        swRegistration.active.postMessage(
+          {action: 'registerPeriodicSync', tag: tag});
+      }
+
+      sendResultToTest('ok - ' + tag + ' register sent to SW');
+    })
+    .catch(sendErrorToTest);
+}
+
+function hasOneShotSyncTag(tag) {
+  navigator.serviceWorker.ready
+    .then((swRegistration) => {
       return swRegistration.sync.getTags();
     })
-    .then(function(tags) {
+    .then((tags) => {
       if (tags.indexOf(tag) >= 0) {
         sendResultToTest('ok - ' + tag + ' found');
       } else {
@@ -67,39 +154,85 @@
     .catch(sendErrorToTest);
 }
 
-function hasTagFromServiceWorker(tag) {
+function hasPeriodicSyncTag(tag) {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
+    .then((swRegistration) => {
+      return swRegistration.periodicSync.getTags();
+    })
+    .then((tags) => {
+      if (tags.indexOf(tag) >= 0) {
+        sendResultToTest('ok - ' + tag + ' found');
+      } else {
+        sendResultToTest('error - ' + tag + ' not found');
+        return;
+      }
+    })
+    .catch(sendErrorToTest);
+}
+
+function hasOneShotSyncTagFromServiceWorker(tag) {
+  navigator.serviceWorker.ready
+    .then((swRegistration) => {
       swRegistration.active.postMessage(
-          {action: 'hasTag', tag: tag});
+          {action: 'hasOneShotSyncTag', tag: tag});
       sendResultToTest('ok - hasTag sent to SW');
     })
     .catch(sendErrorToTest);
 }
 
-function getTags() {
+function hasPeriodicSyncTagFromServiceWorker(tag) {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
+    .then((swRegistration) => {
+      swRegistration.active.postMessage(
+          {action: 'hasPeriodicSyncTag', tag: tag});
+      sendResultToTest('ok - hasTag sent to SW');
+    })
+    .catch(sendErrorToTest);
+}
+
+function getOneShotSyncTags() {
+  navigator.serviceWorker.ready
+    .then((swRegistration) => {
       return swRegistration.sync.getTags();
     })
-    .then(function(tags) {
+    .then((tags) => {
       sendResultToTest('ok - ' + tags.toString());
     })
     .catch(sendErrorToTest);
 }
 
-function getTagsFromServiceWorker() {
+function getOneShotSyncTagsFromServiceWorker() {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
-      swRegistration.active.postMessage({action: 'getTags'});
+    .then((swRegistration) => {
+      swRegistration.active.postMessage({action: 'getOneShotSyncTags'});
       sendResultToTest('ok - getTags sent to SW');
     })
     .catch(sendErrorToTest);
 }
 
+function unregister(tag) {
+  navigator.serviceWorker.ready
+    .then(swRegistration => {
+        return swRegistration.periodicSync.unregister(tag);
+    })
+    .then(() => {
+      sendResultToTest('ok - ' + tag + ' unregistered');
+    })
+    .catch(sendErrorToTest);
+}
+
+function unregisterFromServiceWorker(tag) {
+  navigator.serviceWorker.ready
+    .then(swRegistration => {
+      swRegistration.active.postMessage({action: 'unregister', tag: tag});
+      sendResultToTest('ok - ' + tag + ' unregister sent to SW');
+    })
+    .catch(sendErrorToTest);
+}
+
 function completeDelayedSyncEvent() {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
+    .then((swRegistration) => {
       swRegistration.active.postMessage({
           action: 'completeDelayedSyncEvent'
         });
@@ -110,7 +243,7 @@
 
 function rejectDelayedSyncEvent() {
   navigator.serviceWorker.ready
-    .then(function(swRegistration) {
+    .then((swRegistration) => {
       swRegistration.active.postMessage({action: 'rejectDelayedSyncEvent'});
       sendResultToTest('ok - delay rejecting');
     })
@@ -118,58 +251,25 @@
 }
 
 function createFrame(url) {
-  return new Promise(function(resolve) {
+  return new Promise((resolve) => {
     const frame = document.createElement('iframe');
     frame.src = url;
-    frame.onload = function() { resolve(frame); };
+    frame.onload = () => { resolve(frame); };
     document.body.appendChild(frame);
   });
 }
 
-function registerFromLocalFrame(frame_url) {
-  let frameWindow;
-  return createFrame(frame_url)
-    .then(function(frame) {
-      frameWindow = frame.contentWindow;
-      return frameWindow.navigator.serviceWorker.register('service_worker.js');
-    })
-    .then(function() {
-      return frameWindow.navigator.serviceWorker.ready;
-    })
-    .then(function(frame_registration) {
-      return frame_registration.sync.register('foo');
-    })
-    .then(function() {
-      sendResultToTest('ok - iframe registered sync');
-    })
-    .catch(sendErrorToTest);
-}
-
 function receiveMessage() {
-  return new Promise(function(resolve) {
-    window.addEventListener('message', function(message) {
+  return new Promise((resolve) => {
+    window.addEventListener('message', (message) => {
       resolve(message.data);
     });
   });
 }
 
-function registerFromCrossOriginFrame(cross_frame_url) {
-  return createFrame(cross_frame_url)
-    .then(function(frame) {
-      return receiveMessage();
-    })
-    .then(function(message) {
-      console.log(message);
-      if (message !== 'registration failed') {
-        sendResultToTest('failed - ' + message);
-        return;
-      }
-      sendResultToTest('ok - frame failed to register sync');
-    });
-}
-
-navigator.serviceWorker.addEventListener('message', function(event) {
+navigator.serviceWorker.addEventListener('message', (event) => {
   const message = event.data;
-  if (message.type == 'sync' || message.type === 'register')
+  if (message.type == 'sync' || message.type === 'register' ||
+        message.type === 'unregister')
     resultQueue.push(message.data);
 }, false);
diff --git a/content/test/data/background_sync/service_worker.js b/content/test/data/background_sync/service_worker.js
index 02c8db6..5be8d813 100644
--- a/content/test/data/background_sync/service_worker.js
+++ b/content/test/data/background_sync/service_worker.js
@@ -15,61 +15,101 @@
 let resolveCallback = null;
 let rejectCallback = null;
 
-this.onmessage = function(event) {
-  if (event.data['action'] === 'completeDelayedSyncEvent') {
-    if (resolveCallback === null) {
-      sendMessageToClients('sync', 'error - resolveCallback is null');
+this.onmessage = (event) => {
+  switch(event.data.action) {
+    case 'completeDelayedSyncEvent': {
+      if (resolveCallback === null) {
+        sendMessageToClients('sync', 'error - resolveCallback is null');
+        return;
+      }
+
+      resolveCallback();
+      sendMessageToClients('sync', 'ok - delay completed');
       return;
     }
+    case 'rejectDelayedSyncEvent': {
+      if (rejectCallback === null) {
+        sendMessageToClients('sync', 'error - rejectCallback is null');
+        return;
+      }
 
-    resolveCallback();
-    sendMessageToClients('sync', 'ok - delay completed');
-    return;
-  }
-
-  if (event.data['action'] === 'rejectDelayedSyncEvent') {
-    if (rejectCallback === null) {
-      sendMessageToClients('sync', 'error - rejectCallback is null');
+      rejectCallback();
+      sendMessageToClients('sync', 'ok - delay rejected');
+    }
+    case 'registerOneShotSync': {
+      const tag = event.data.tag;
+      registration.sync.register(tag)
+        .then(() => {
+          sendMessageToClients('register', 'ok - ' + tag + ' registered in SW');
+        })
+        .catch(sendSyncErrorToClients);
       return;
     }
-
-    rejectCallback();
-    sendMessageToClients('sync', 'ok - delay rejected');
-  }
-
-  if (event.data['action'] === 'register') {
-    const tag = event.data['tag'];
-    registration.sync.register(tag)
-      .then(function () {
-        sendMessageToClients('register', 'ok - ' + tag + ' registered in SW');
-      })
-      .catch(sendSyncErrorToClients);
-  }
-
-  if (event.data['action'] === 'hasTag') {
-    const tag = event.data['tag'];
-    registration.sync.getTags()
-      .then(function(tags) {
-        if (tags.indexOf(tag) >= 0) {
-          sendMessageToClients('register', 'ok - ' + tag + ' found');
-        } else {
-          sendMessageToClients('register', 'error - ' + tag + ' not found');
-          return;
-        }
-      })
-      .catch(sendSyncErrorToClients);
-  }
-
-  if (event.data['action'] === 'getTags') {
-    registration.sync.getTags()
-      .then(function(tags) {
-        sendMessageToClients('register', 'ok - ' + tags.toString());
-      })
-      .catch(sendSyncErrorToClients);
+    case 'registerPeriodicSync': {
+      const tag = event.data.tag;
+      const minInterval = event.data.minInterval;
+      registration.periodicSync.register(tag, { minInterval: minInterval })
+        .then(() =>
+          sendMessageToClients('register', 'ok - ' + tag + ' registered in SW'))
+        .catch(sendSyncErrorToClients);
+      return;
+    }
+    case 'unregister': {
+      const tag = event.data.tag;
+      registration.periodicSync.unregister(tag)
+        .then(() =>
+          sendMessageToClients(
+            'unregister', 'ok - ' + tag + ' unregistered in SW'))
+        .catch(sendSyncErrorToClients);
+      return;
+    }
+    case 'hasOneShotSyncTag': {
+      const tag = event.data.tag;
+      registration.sync.getTags()
+        .then((tags) => {
+          if (tags.indexOf(tag) >= 0) {
+            sendMessageToClients('register', 'ok - ' + tag + ' found');
+          } else {
+            sendMessageToClients('register', 'error - ' + tag + ' not found');
+            return;
+          }
+        })
+        .catch(sendSyncErrorToClients);
+        return;
+      }
+    case 'hasPeriodicSyncTag': {
+      const tag = event.data.tag;
+      registration.periodicSync.getTags()
+        .then((tags) => {
+          if (tags.indexOf(tag) >= 0) {
+            sendMessageToClients('register', 'ok - ' + tag + ' found in SW');
+          } else {
+            sendMessageToClients('register', 'error - ' + tag + ' not found');
+            return;
+          }
+        })
+        .catch(sendSyncErrorToClients);
+      return;
+    }
+    case 'getOneShotSyncTags': {
+      registration.sync.getTags()
+        .then((tags) => {
+          sendMessageToClients('register', 'ok - ' + tags.toString());
+        })
+        .catch(sendSyncErrorToClients);
+      return;
+    }
+    case 'getPeriodicSyncTags': {
+      registration.periodicSync.getTags()
+        .then((tags) => {
+          sendMessageToClients('register', 'ok - ' + tags.toString());
+        })
+        .catch(sendSyncErrorToClients);
+      return;
+    }
   }
 }
-
-this.onsync = function(event) {
+this.onsync = (event) => {
   const eventProperties = [
     // Extract name from toString result: "[object <Class>]"
     Object.prototype.toString.call(event).match(/\s([a-zA-Z]+)/)[1],
@@ -93,7 +133,7 @@
   const tag = event.tag;
 
   if (tag === 'delay') {
-    const syncPromise = new Promise(function(resolve, reject) {
+    const syncPromise = new Promise((resolve, reject) => {
       resolveCallback = resolve;
       rejectCallback = reject;
     });
@@ -105,11 +145,11 @@
 };
 
 function sendMessageToClients(type, data) {
-  clients.matchAll({ includeUncontrolled: true }).then(function(clients) {
-    clients.forEach(function(client) {
+  clients.matchAll({ includeUncontrolled: true }).then((clients) => {
+    clients.forEach((client) => {
       client.postMessage({type, data});
     });
-  }, function(error) {
+  }, (error) => {
     console.log(error);
   });
 }
diff --git a/content/test/data/frame_tree/page_with_srcdoc_iframe_tree.html b/content/test/data/frame_tree/page_with_srcdoc_iframe_tree.html
new file mode 100644
index 0000000..8211ed58
--- /dev/null
+++ b/content/test/data/frame_tree/page_with_srcdoc_iframe_tree.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<html>
+<head></head>
+<body>
+  <p>This page has deeply nested iframes mixing srcdoc and src
+  <p><iframe srcdoc="<iframe src=page_with_srcdoc_frame.html></iframe>" id="test_iframe"></iframe>
+</body>
+</html>
diff --git a/content/test/data/stale-script.js b/content/test/data/stale-script.js
new file mode 100644
index 0000000..a0604705
--- /dev/null
+++ b/content/test/data/stale-script.js
@@ -0,0 +1,5 @@
+// Copyright 2018 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.
+
+// nothing to see here.
diff --git a/content/test/data/stale-script.js.mock-http-headers b/content/test/data/stale-script.js.mock-http-headers
new file mode 100644
index 0000000..677dded
--- /dev/null
+++ b/content/test/data/stale-script.js.mock-http-headers
@@ -0,0 +1,3 @@
+HTTP/1.1 200 OK
+Content-Type: text/javascript
+Cache-Control: private, max-age=0, stale-while-revalidate=60
diff --git a/content/test/data/stale-while-revalidate.html b/content/test/data/stale-while-revalidate.html
new file mode 100644
index 0000000..33975f9
--- /dev/null
+++ b/content/test/data/stale-while-revalidate.html
@@ -0,0 +1,24 @@
+<script>
+function wait25ms() {
+  return new Promise(resolve => {
+    setTimeout(() => {
+      resolve();
+    }, 25);
+  });
+}
+
+// runTest() will be called by the browser test.
+async function runTest() {
+  const url = 'stale-script.js';
+  const response = await fetch(url);
+  const response2 = await fetch(url);
+  while(true) {
+    const revalidation_check = await fetch('stale-script.js');
+    if (performance.getEntriesByName(new URL(url, document.location)).length == 2) {
+      document.title = "Pass";
+      break;
+    }
+    await wait25ms();
+  }
+}
+</script>
diff --git a/content/test/data/workers/empty2.js b/content/test/data/workers/empty2.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/content/test/data/workers/empty2.js
diff --git a/content/test/data/workers/empty2.js.mock-http-headers b/content/test/data/workers/empty2.js.mock-http-headers
new file mode 100644
index 0000000..c6025e4
--- /dev/null
+++ b/content/test/data/workers/empty2.js.mock-http-headers
@@ -0,0 +1,4 @@
+HTTP/1.1 200 OK
+Content-Type: application/javascript
+Cache-Control: max-age=100000
+Access-Control-Allow-Origin: *
\ No newline at end of file
diff --git a/content/test/data/workers/service_worker_setup.html b/content/test/data/workers/service_worker_setup.html
index bb334941..dc986a8 100644
--- a/content/test/data/workers/service_worker_setup.html
+++ b/content/test/data/workers/service_worker_setup.html
@@ -2,9 +2,10 @@
 <meta charset="utf-8">
 <title>register a service worker</title>
 <script>
-async function setup(script_file_arg) {
+async function setup(script_file_arg, register_opts) {
   let script_file = script_file_arg || 'service_worker.js';
-  await navigator.serviceWorker.register(script_file);
+  let options = register_opts || '{}';
+  await navigator.serviceWorker.register(script_file, JSON.parse(options));
   await navigator.serviceWorker.ready;
   return 'ok';
 }
diff --git a/content/test/data/workers/worker_with_import_and_fetch.js b/content/test/data/workers/worker_with_import_and_fetch.js
index e1c3bbb..286b29de 100644
--- a/content/test/data/workers/worker_with_import_and_fetch.js
+++ b/content/test/data/workers/worker_with_import_and_fetch.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// The service worker for the network isolation key test.
+// The service/shared worker for the network isolation key test.
 const url_params = new URLSearchParams(location.search);
 let import_script_url = url_params.get("import_script_url");
 let fetch_url = url_params.get("fetch_url");
diff --git a/content/test/data/workers/worker_with_import_and_fetch_2.js b/content/test/data/workers/worker_with_import_and_fetch_2.js
index e1c3bbb..286b29de 100644
--- a/content/test/data/workers/worker_with_import_and_fetch_2.js
+++ b/content/test/data/workers/worker_with_import_and_fetch_2.js
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// The service worker for the network isolation key test.
+// The service/shared worker for the network isolation key test.
 const url_params = new URLSearchParams(location.search);
 let import_script_url = url_params.get("import_script_url");
 let fetch_url = url_params.get("fetch_url");
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 2b04d30..d5a1933 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -546,6 +546,7 @@
 crbug.com/845438 [ android ] conformance/glsl/bugs/sketchfab-lighting-shader-crash.html [ RetryOnFailure ]
 
 # Android ANGLE GLES
+crbug.com/981579 [ android opengles ] conformance/textures/misc/tex-video-using-tex-unit-non-zero.html [ RetryOnFailure ]
 crbug.com/981579 [ android android-chromium opengles ] conformance/textures/video/tex-2d-rgb-rgb-unsigned_byte.html [ Failure ]
 crbug.com/906724 [ android opengles ] conformance/textures/video/tex-2d-luminance_alpha-luminance_alpha-unsigned_byte.html [ Failure ]
 crbug.com/906724 [ android opengles ] conformance/textures/video/tex-2d-luminance-luminance-unsigned_byte.html [ Failure ]
diff --git a/content/test/test_background_sync_manager.cc b/content/test/test_background_sync_manager.cc
index b1e33c11..c360281c 100644
--- a/content/test/test_background_sync_manager.cc
+++ b/content/test/test_background_sync_manager.cc
@@ -127,10 +127,10 @@
 
 base::TimeDelta TestBackgroundSyncManager::GetSoonestWakeupDelta(
     blink::mojom::BackgroundSyncType sync_type,
-    bool apply_browser_wakeup_limit) {
+    base::Time last_browser_wakeup_for_periodic_sync) {
   base::TimeDelta soonest_wakeup_delta =
-      BackgroundSyncManager::GetSoonestWakeupDelta(sync_type,
-                                                   apply_browser_wakeup_limit);
+      BackgroundSyncManager::GetSoonestWakeupDelta(
+          sync_type, last_browser_wakeup_for_periodic_sync);
   if (sync_type == blink::mojom::BackgroundSyncType::ONE_SHOT)
     soonest_one_shot_sync_wakeup_delta_ = soonest_wakeup_delta;
   else
diff --git a/content/test/test_background_sync_manager.h b/content/test/test_background_sync_manager.h
index d57b7b6b..519b4cb 100644
--- a/content/test/test_background_sync_manager.h
+++ b/content/test/test_background_sync_manager.h
@@ -132,7 +132,7 @@
   // Override to allow the test to cache the result.
   base::TimeDelta GetSoonestWakeupDelta(
       blink::mojom::BackgroundSyncType sync_type,
-      bool apply_browser_wakeup_limit) override;
+      base::Time last_browser_wakeup_for_periodic_sync) override;
 
  protected:
   // Override to allow delays to be injected by tests.
diff --git a/device/fido/ble/fido_ble_device_unittest.cc b/device/fido/ble/fido_ble_device_unittest.cc
index 0e41f42..3381a2a5 100644
--- a/device/fido/ble/fido_ble_device_unittest.cc
+++ b/device/fido/ble/fido_ble_device_unittest.cc
@@ -102,7 +102,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
  private:
   scoped_refptr<MockBluetoothAdapter> adapter_ =
diff --git a/device/fido/ble/fido_ble_discovery_unittest.cc b/device/fido/ble/fido_ble_discovery_unittest.cc
index 0b535b8..8539506 100644
--- a/device/fido/ble/fido_ble_discovery_unittest.cc
+++ b/device/fido/ble/fido_ble_discovery_unittest.cc
@@ -123,7 +123,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
  private:
   FidoBleDiscovery discovery_;
diff --git a/device/fido/fido_request_handler_unittest.cc b/device/fido/fido_request_handler_unittest.cc
index ff7260c..e5196d5 100644
--- a/device/fido/fido_request_handler_unittest.cc
+++ b/device/fido/fido_request_handler_unittest.cc
@@ -327,7 +327,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   test::FakeFidoDiscoveryFactory fake_discovery_factory_;
   scoped_refptr<::testing::NiceMock<MockBluetoothAdapter>> mock_adapter_;
   test::FakeFidoDiscovery* discovery_;
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc
index 67176574..3744659b 100644
--- a/device/fido/get_assertion_handler_unittest.cc
+++ b/device/fido/get_assertion_handler_unittest.cc
@@ -177,7 +177,7 @@
   }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   std::unique_ptr<test::FakeFidoDiscoveryFactory> fake_discovery_factory_ =
       std::make_unique<test::FakeFidoDiscoveryFactory>();
   test::FakeFidoDiscovery* discovery_;
@@ -787,7 +787,7 @@
 // talk to the authenticator.
 TEST(GetAssertionRequestHandlerTest, IncorrectTransportType) {
   base::test::ScopedTaskEnvironment scoped_task_environment{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   device::test::VirtualFidoDeviceFactory virtual_device_factory;
   virtual_device_factory.SetSupportedProtocol(device::ProtocolVersion::kCtap2);
   ASSERT_TRUE(virtual_device_factory.mutable_state()->InjectRegistration(
diff --git a/device/fido/hid/fido_hid_device_unittest.cc b/device/fido/hid/fido_hid_device_unittest.cc
index 19ba1f4..300a8a5 100644
--- a/device/fido/hid/fido_hid_device_unittest.cc
+++ b/device/fido/hid/fido_hid_device_unittest.cc
@@ -191,7 +191,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   device::mojom::HidManagerPtr hid_manager_;
   std::unique_ptr<FakeFidoHidManager> fake_hid_manager_;
 };
diff --git a/device/fido/make_credential_handler_unittest.cc b/device/fido/make_credential_handler_unittest.cc
index e3b821d..a6f0336 100644
--- a/device/fido/make_credential_handler_unittest.cc
+++ b/device/fido/make_credential_handler_unittest.cc
@@ -142,7 +142,7 @@
   }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   std::unique_ptr<test::FakeFidoDiscoveryFactory> fake_discovery_factory_ =
       std::make_unique<test::FakeFidoDiscoveryFactory>();
   test::FakeFidoDiscovery* discovery_;
diff --git a/device/gamepad/abstract_haptic_gamepad_unittest.cc b/device/gamepad/abstract_haptic_gamepad_unittest.cc
index 129c814a..87e32645 100644
--- a/device/gamepad/abstract_haptic_gamepad_unittest.cc
+++ b/device/gamepad/abstract_haptic_gamepad_unittest.cc
@@ -100,7 +100,7 @@
   mojom::GamepadHapticsResult second_callback_result_;
   std::unique_ptr<FakeHapticGamepad> gamepad_;
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
   DISALLOW_COPY_AND_ASSIGN(AbstractHapticGamepadTest);
 };
diff --git a/device/gamepad/hid_haptic_gamepad_base_unittest.cc b/device/gamepad/hid_haptic_gamepad_base_unittest.cc
index 899852c..d3a0ca5 100644
--- a/device/gamepad/hid_haptic_gamepad_base_unittest.cc
+++ b/device/gamepad/hid_haptic_gamepad_base_unittest.cc
@@ -127,7 +127,7 @@
   mojom::GamepadHapticsResult second_callback_result_;
   std::unique_ptr<FakeHidHapticGamepad> gamepad_;
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
   DISALLOW_COPY_AND_ASSIGN(HidHapticGamepadBaseTest);
 };
diff --git a/docs/OWNERS b/docs/OWNERS
index 72e8ffc..94ca8de 100644
--- a/docs/OWNERS
+++ b/docs/OWNERS
@@ -1 +1,2 @@
 *
+# COMPONENT: Build
diff --git a/docs/accessibility/OWNERS b/docs/accessibility/OWNERS
new file mode 100644
index 0000000..df8b5d5
--- /dev/null
+++ b/docs/accessibility/OWNERS
@@ -0,0 +1,2 @@
+# COMPONENT: Internals>Accessibility
+# TEAM: chromium-accessibility@chromium.org
diff --git a/docs/autofill/OWNERS b/docs/autofill/OWNERS
new file mode 100644
index 0000000..29ec06f7
--- /dev/null
+++ b/docs/autofill/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: UI>Browser>Autofill
diff --git a/docs/design/OWNERS b/docs/design/OWNERS
new file mode 100644
index 0000000..3605f481
--- /dev/null
+++ b/docs/design/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Internals>Core
diff --git a/docs/images/OWNERS b/docs/images/OWNERS
new file mode 100644
index 0000000..d1a8dbfc
--- /dev/null
+++ b/docs/images/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Blink>Image
diff --git a/docs/infra/OWNERS b/docs/infra/OWNERS
new file mode 100644
index 0000000..3d2e6d86
--- /dev/null
+++ b/docs/infra/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Infra>Client>Chrome
diff --git a/docs/login/OWNERS b/docs/login/OWNERS
new file mode 100644
index 0000000..7bc732e
--- /dev/null
+++ b/docs/login/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Services>SignIn
diff --git a/docs/media/OWNERS b/docs/media/OWNERS
new file mode 100644
index 0000000..796bd0dc
--- /dev/null
+++ b/docs/media/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Blink>Media
diff --git a/docs/memory-infra/OWNERS b/docs/memory-infra/OWNERS
new file mode 100644
index 0000000..d64ae80
--- /dev/null
+++ b/docs/memory-infra/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Internals>Instrumentation>Memory
diff --git a/docs/memory/OWNERS b/docs/memory/OWNERS
new file mode 100644
index 0000000..d64ae80
--- /dev/null
+++ b/docs/memory/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Internals>Instrumentation>Memory
diff --git a/docs/sync/OWNERS b/docs/sync/OWNERS
new file mode 100644
index 0000000..87ed152
--- /dev/null
+++ b/docs/sync/OWNERS
@@ -0,0 +1,2 @@
+# COMPONENT: Services>Sync
+# TEAM: chromium-reviews@chromium.org
diff --git a/docs/testing/OWNERS b/docs/testing/OWNERS
new file mode 100644
index 0000000..d3d78c2
--- /dev/null
+++ b/docs/testing/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Test
diff --git a/docs/ui/OWNERS b/docs/ui/OWNERS
new file mode 100644
index 0000000..e716953
--- /dev/null
+++ b/docs/ui/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: UI
diff --git a/docs/ui/views/OWNERS b/docs/ui/views/OWNERS
new file mode 100644
index 0000000..ad039d7
--- /dev/null
+++ b/docs/ui/views/OWNERS
@@ -0,0 +1 @@
+# COMPONENT: Internals>Views
diff --git a/google_apis/gaia/gaia_oauth_client_unittest.cc b/google_apis/gaia/gaia_oauth_client_unittest.cc
index 3583d24..9a543bd 100644
--- a/google_apis/gaia/gaia_oauth_client_unittest.cc
+++ b/google_apis/gaia/gaia_oauth_client_unittest.cc
@@ -169,7 +169,7 @@
  protected:
   GaiaOAuthClientTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   void SetUp() override {
     client_info_.client_id = "test_client_id";
diff --git a/google_apis/gcm/engine/gcm_request_test_base.h b/google_apis/gcm/engine/gcm_request_test_base.h
index 0c68b30..a076e4d 100644
--- a/google_apis/gcm/engine/gcm_request_test_base.h
+++ b/google_apis/gcm/engine/gcm_request_test_base.h
@@ -62,7 +62,7 @@
   void FastForwardToTriggerNextRetry();
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
   network::TestURLLoaderFactory test_url_loader_factory_;
   scoped_refptr<network::SharedURLLoaderFactory> shared_factory_;
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 75e700b3d..e9a0103 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -61,6 +61,7 @@
 #include "gpu/vulkan/buildflags.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkDeferredDisplayListRecorder.h"
+#include "third_party/skia/include/core/SkPromiseImageTexture.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/core/SkSurfaceProps.h"
 #include "third_party/skia/include/core/SkTypeface.h"
@@ -69,6 +70,7 @@
 #include "third_party/skia/include/gpu/GrContext.h"
 #include "third_party/skia/include/gpu/GrTypes.h"
 #include "ui/gfx/buffer_format_util.h"
+#include "ui/gfx/skia_util.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_surface.h"
@@ -428,6 +430,30 @@
                                 GLsizei width,
                                 GLsizei height,
                                 const volatile GLbyte* mailboxes);
+  void DoCopySubTextureINTERNALGLPassthrough(GLint xoffset,
+                                             GLint yoffset,
+                                             GLint x,
+                                             GLint y,
+                                             GLsizei width,
+                                             GLsizei height,
+                                             const Mailbox& source_mailbox,
+                                             const Mailbox& dest_mailbox);
+  void DoCopySubTextureINTERNALGL(GLint xoffset,
+                                  GLint yoffset,
+                                  GLint x,
+                                  GLint y,
+                                  GLsizei width,
+                                  GLsizei height,
+                                  const Mailbox& source_mailbox,
+                                  const Mailbox& dest_mailbox);
+  void DoCopySubTextureINTERNALSkia(GLint xoffset,
+                                    GLint yoffset,
+                                    GLint x,
+                                    GLint y,
+                                    GLsizei width,
+                                    GLsizei height,
+                                    const Mailbox& source_mailbox,
+                                    const Mailbox& dest_mailbox);
   void DoLoseContextCHROMIUM(GLenum current, GLenum other) { NOTIMPLEMENTED(); }
   void DoBeginRasterCHROMIUM(GLuint sk_color,
                              GLuint msaa_sample_count,
@@ -1671,55 +1697,88 @@
     return;
   }
 
-  if (use_passthrough_) {
-    std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-        source_shared_image =
-            shared_image_representation_factory_.ProduceGLTexturePassthrough(
-                source_mailbox);
-    std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-        dest_shared_image =
-            shared_image_representation_factory_.ProduceGLTexturePassthrough(
-                dest_mailbox);
-    if (!source_shared_image || !dest_shared_image) {
-      LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
-                         "unknown mailbox");
-      return;
-    }
+  if (!shared_context_state_->GrContextIsGL()) {
+    // Use Skia to copy texture if raster's gr_context() is not using GL.
+    DoCopySubTextureINTERNALSkia(xoffset, yoffset, x, y, width, height,
+                                 source_mailbox, dest_mailbox);
+  } else if (use_passthrough_) {
+    DoCopySubTextureINTERNALGLPassthrough(xoffset, yoffset, x, y, width, height,
+                                          source_mailbox, dest_mailbox);
+  } else {
+    DoCopySubTextureINTERNALGL(xoffset, yoffset, x, y, width, height,
+                               source_mailbox, dest_mailbox);
+  }
+}
 
-    SharedImageRepresentationGLTexturePassthrough::ScopedAccess source_access(
-        source_shared_image.get(), GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
-    if (!source_access.success()) {
-      LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
-                         "unable to access source for read");
-      return;
-    }
+void RasterDecoderImpl::DoCopySubTextureINTERNALGLPassthrough(
+    GLint xoffset,
+    GLint yoffset,
+    GLint x,
+    GLint y,
+    GLsizei width,
+    GLsizei height,
+    const Mailbox& source_mailbox,
+    const Mailbox& dest_mailbox) {
+  DCHECK(source_mailbox != dest_mailbox);
+  DCHECK(use_passthrough_);
 
-    SharedImageRepresentationGLTexturePassthrough::ScopedAccess dest_access(
-        dest_shared_image.get(),
-        GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
-    if (!dest_access.success()) {
-      LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
-                         "unable to access destination for write");
-      return;
-    }
-
-    gles2::TexturePassthrough* source_texture =
-        source_shared_image->GetTexturePassthrough().get();
-    gles2::TexturePassthrough* dest_texture =
-        dest_shared_image->GetTexturePassthrough().get();
-    DCHECK(!source_texture->is_bind_pending());
-    DCHECK_NE(source_texture->service_id(), dest_texture->service_id());
-
-    api()->glCopySubTextureCHROMIUMFn(
-        source_texture->service_id(), /*source_level=*/0,
-        dest_texture->target(), dest_texture->service_id(),
-        /*dest_level=*/0, xoffset, yoffset, x, y, width, height,
-        /*unpack_flip_y=*/false, /*unpack_premultiply_alpha=*/false,
-        /*unpack_unmultiply_alpha=*/false);
-    LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTexture");
+  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+      source_shared_image =
+          shared_image_representation_factory_.ProduceGLTexturePassthrough(
+              source_mailbox);
+  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+      dest_shared_image =
+          shared_image_representation_factory_.ProduceGLTexturePassthrough(
+              dest_mailbox);
+  if (!source_shared_image || !dest_shared_image) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture", "unknown mailbox");
     return;
   }
 
+  SharedImageRepresentationGLTexturePassthrough::ScopedAccess source_access(
+      source_shared_image.get(), GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM);
+  if (!source_access.success()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
+                       "unable to access source for read");
+    return;
+  }
+
+  SharedImageRepresentationGLTexturePassthrough::ScopedAccess dest_access(
+      dest_shared_image.get(), GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM);
+  if (!dest_access.success()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
+                       "unable to access destination for write");
+    return;
+  }
+
+  gles2::TexturePassthrough* source_texture =
+      source_shared_image->GetTexturePassthrough().get();
+  gles2::TexturePassthrough* dest_texture =
+      dest_shared_image->GetTexturePassthrough().get();
+  DCHECK(!source_texture->is_bind_pending());
+  DCHECK_NE(source_texture->service_id(), dest_texture->service_id());
+
+  api()->glCopySubTextureCHROMIUMFn(
+      source_texture->service_id(), /*source_level=*/0, dest_texture->target(),
+      dest_texture->service_id(),
+      /*dest_level=*/0, xoffset, yoffset, x, y, width, height,
+      /*unpack_flip_y=*/false, /*unpack_premultiply_alpha=*/false,
+      /*unpack_unmultiply_alpha=*/false);
+  LOCAL_COPY_REAL_GL_ERRORS_TO_WRAPPER("glCopySubTexture");
+}
+
+void RasterDecoderImpl::DoCopySubTextureINTERNALGL(
+    GLint xoffset,
+    GLint yoffset,
+    GLint x,
+    GLint y,
+    GLsizei width,
+    GLsizei height,
+    const Mailbox& source_mailbox,
+    const Mailbox& dest_mailbox) {
+  DCHECK(source_mailbox != dest_mailbox);
+  DCHECK(shared_context_state_->GrContextIsGL());
+
   std::unique_ptr<SharedImageRepresentationGLTexture> source_shared_image =
       shared_image_representation_factory_.ProduceGLTexture(source_mailbox);
   std::unique_ptr<SharedImageRepresentationGLTexture> dest_shared_image =
@@ -1936,6 +1995,102 @@
   }
 }
 
+void RasterDecoderImpl::DoCopySubTextureINTERNALSkia(
+    GLint xoffset,
+    GLint yoffset,
+    GLint x,
+    GLint y,
+    GLsizei width,
+    GLsizei height,
+    const Mailbox& source_mailbox,
+    const Mailbox& dest_mailbox) {
+  DCHECK(source_mailbox != dest_mailbox);
+
+  // Use Skia to copy texture if raster's gr_context() is not using GL.
+  auto source_shared_image = shared_image_representation_factory_.ProduceSkia(
+      source_mailbox, shared_context_state_);
+  auto dest_shared_image = shared_image_representation_factory_.ProduceSkia(
+      dest_mailbox, shared_context_state_);
+  if (!source_shared_image || !dest_shared_image) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture", "unknown mailbox");
+    return;
+  }
+
+  gfx::Size source_size = source_shared_image->size();
+  gfx::Rect source_rect(x, y, width, height);
+  if (!gfx::Rect(source_size).Contains(source_rect)) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
+                       "source texture bad dimensions.");
+    return;
+  }
+
+  gfx::Size dest_size = dest_shared_image->size();
+  gfx::Rect dest_rect(xoffset, yoffset, width, height);
+  if (!gfx::Rect(dest_size).Contains(dest_rect)) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
+                       "destination texture bad dimensions.");
+    return;
+  }
+
+  std::vector<GrBackendSemaphore> begin_semaphores;
+  std::vector<GrBackendSemaphore> end_semaphores;
+
+  SharedImageRepresentationSkia::ScopedWriteAccess dest_scoped_access(
+      dest_shared_image.get(), &begin_semaphores, &end_semaphores);
+  if (!dest_scoped_access.success()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
+                       "Dest shared image is not writable");
+    return;
+  }
+
+  // With OneCopyRasterBufferProvider, source_shared_image->BeginReadAccess()
+  // will copy pixels from SHM GMB to the texture in |source_shared_image|,
+  // and then use drawImageRect() to draw that texure to the target
+  // |dest_shared_image|. We can save one copy by drawing the SHM GMB to the
+  // target |dest_shared_image| directly.
+  // TODO(penghuang): get rid of the one extra copy. https://crbug.com/984045
+  SharedImageRepresentationSkia::ScopedReadAccess source_scoped_access(
+      source_shared_image.get(), &begin_semaphores, &end_semaphores);
+
+  if (!begin_semaphores.empty()) {
+    bool result = dest_scoped_access.surface()->wait(begin_semaphores.size(),
+                                                     begin_semaphores.data());
+    DCHECK(result);
+  }
+
+  if (!source_scoped_access.success()) {
+    LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, "glCopySubTexture",
+                       "Source shared image is not accessable");
+  } else {
+    auto color_type = viz::ResourceFormatToClosestSkColorType(
+        true /* gpu_compositing */, source_shared_image->format());
+    auto source_image = SkImage::MakeFromTexture(
+        shared_context_state_->gr_context(),
+        source_scoped_access.promise_image_texture()->backendTexture(),
+        kTopLeft_GrSurfaceOrigin, color_type, kUnpremul_SkAlphaType,
+        nullptr /* colorSpace */);
+
+    auto* canvas = dest_scoped_access.surface()->getCanvas();
+    SkPaint paint;
+    paint.setBlendMode(SkBlendMode::kSrc);
+    canvas->drawImageRect(source_image, gfx::RectToSkRect(source_rect),
+                          gfx::RectToSkRect(dest_rect), &paint);
+  }
+
+  // Always flush the surface even if source_scoped_access.success() is false,
+  // so the begin_semaphores can be released, and end_semaphores can be
+  // signalled.
+  GrFlushInfo flush_info = {
+      .fFlags = kNone_GrFlushFlags,
+      .fNumSemaphores = end_semaphores.size(),
+      .fSignalSemaphores = end_semaphores.data(),
+  };
+  gpu::AddVulkanCleanupTaskForSkiaFlush(
+      shared_context_state_->vk_context_provider(), &flush_info);
+  dest_scoped_access.surface()->flush(
+      SkSurface::BackendSurfaceAccess::kNoAccess, flush_info);
+}
+
 namespace {
 
 // Helper to read client data from transfer cache.
diff --git a/gpu/command_buffer/service/shared_image_representation.cc b/gpu/command_buffer/service/shared_image_representation.cc
index 9cedf2e..cc60dd1a 100644
--- a/gpu/command_buffer/service/shared_image_representation.cc
+++ b/gpu/command_buffer/service/shared_image_representation.cc
@@ -4,6 +4,8 @@
 
 #include "gpu/command_buffer/service/shared_image_representation.h"
 
+#include "third_party/skia/include/core/SkPromiseImageTexture.h"
+
 namespace gpu {
 
 SharedImageRepresentation::SharedImageRepresentation(
@@ -27,4 +29,44 @@
   return true;
 }
 
+SharedImageRepresentationSkia::ScopedWriteAccess::ScopedWriteAccess(
+    SharedImageRepresentationSkia* representation,
+    int final_msaa_count,
+    const SkSurfaceProps& surface_props,
+    std::vector<GrBackendSemaphore>* begin_semaphores,
+    std::vector<GrBackendSemaphore>* end_semaphores)
+    : representation_(representation),
+      surface_(representation_->BeginWriteAccess(final_msaa_count,
+                                                 surface_props,
+                                                 begin_semaphores,
+                                                 end_semaphores)) {}
+
+SharedImageRepresentationSkia::ScopedWriteAccess::ScopedWriteAccess(
+    SharedImageRepresentationSkia* representation,
+    std::vector<GrBackendSemaphore>* begin_semaphores,
+    std::vector<GrBackendSemaphore>* end_semaphores)
+    : ScopedWriteAccess(representation,
+                        0 /* final_msaa_count */,
+                        SkSurfaceProps(0 /* flags */, kUnknown_SkPixelGeometry),
+                        begin_semaphores,
+                        end_semaphores) {}
+
+SharedImageRepresentationSkia::ScopedWriteAccess::~ScopedWriteAccess() {
+  if (success())
+    representation_->EndWriteAccess(std::move(surface_));
+}
+
+SharedImageRepresentationSkia::ScopedReadAccess::ScopedReadAccess(
+    SharedImageRepresentationSkia* representation,
+    std::vector<GrBackendSemaphore>* begin_semaphores,
+    std::vector<GrBackendSemaphore>* end_semaphores)
+    : representation_(representation),
+      promise_image_texture_(
+          representation_->BeginReadAccess(begin_semaphores, end_semaphores)) {}
+
+SharedImageRepresentationSkia::ScopedReadAccess::~ScopedReadAccess() {
+  if (success())
+    representation_->EndReadAccess();
+}
+
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_representation.h b/gpu/command_buffer/service/shared_image_representation.h
index ab94c5aa..703c643 100644
--- a/gpu/command_buffer/service/shared_image_representation.h
+++ b/gpu/command_buffer/service/shared_image_representation.h
@@ -159,6 +159,43 @@
 
 class SharedImageRepresentationSkia : public SharedImageRepresentation {
  public:
+  class ScopedWriteAccess {
+   public:
+    ScopedWriteAccess(SharedImageRepresentationSkia* representation,
+                      int final_msaa_count,
+                      const SkSurfaceProps& surface_props,
+                      std::vector<GrBackendSemaphore>* begin_semaphores,
+                      std::vector<GrBackendSemaphore>* end_semaphores);
+    ScopedWriteAccess(SharedImageRepresentationSkia* representation,
+                      std::vector<GrBackendSemaphore>* begin_semaphores,
+                      std::vector<GrBackendSemaphore>* end_semaphores);
+    ~ScopedWriteAccess();
+
+    bool success() const { return !!surface_; }
+    SkSurface* surface() const { return surface_.get(); }
+
+   private:
+    SharedImageRepresentationSkia* const representation_;
+    sk_sp<SkSurface> surface_;
+  };
+
+  class ScopedReadAccess {
+   public:
+    ScopedReadAccess(SharedImageRepresentationSkia* representation,
+                     std::vector<GrBackendSemaphore>* begin_semaphores,
+                     std::vector<GrBackendSemaphore>* end_semaphores);
+    ~ScopedReadAccess();
+
+    bool success() const { return !!promise_image_texture_; }
+    SkPromiseImageTexture* promise_image_texture() const {
+      return promise_image_texture_.get();
+    }
+
+   private:
+    SharedImageRepresentationSkia* const representation_;
+    sk_sp<SkPromiseImageTexture> promise_image_texture_;
+  };
+
   SharedImageRepresentationSkia(SharedImageManager* manager,
                                 SharedImageBacking* backing,
                                 MemoryTypeTracker* tracker)
diff --git a/gpu/config/gpu_preferences.h b/gpu/config/gpu_preferences.h
index a336269..cb12718 100644
--- a/gpu/config/gpu_preferences.h
+++ b/gpu/config/gpu_preferences.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/message_loop/message_loop.h"
 #include "build/build_config.h"
 #include "gpu/gpu_export.h"
 #include "media/media_buildflags.h"
@@ -214,6 +215,9 @@
   // Enable the WebGPU command buffer.
   bool enable_webgpu = false;
 
+  // Determines message loop type for the GPU thread.
+  base::MessageLoop::Type message_loop_type = base::MessageLoop::TYPE_DEFAULT;
+
   // Please update gpu_preferences_unittest.cc when making additions or
   // changes to this struct.
 };
diff --git a/gpu/config/gpu_preferences_unittest.cc b/gpu/config/gpu_preferences_unittest.cc
index 97037088..5f93a19 100644
--- a/gpu/config/gpu_preferences_unittest.cc
+++ b/gpu/config/gpu_preferences_unittest.cc
@@ -72,6 +72,7 @@
   EXPECT_EQ(left.enable_gpu_benchmarking_extension,
             right.enable_gpu_benchmarking_extension);
   EXPECT_EQ(left.enable_webgpu, right.enable_webgpu);
+  EXPECT_EQ(left.message_loop_type, right.message_loop_type);
 }
 
 }  // namespace
@@ -105,11 +106,11 @@
   prefs_mojom.name = value;                        \
   EXPECT_EQ(input_prefs.name, prefs_mojom.name);
 
-#define GPU_PREFERENCES_FIELD_ENUM(name, value)      \
-  input_prefs.name = value;                          \
-  EXPECT_NE(default_prefs.name, input_prefs.name);   \
-  prefs_mojom.name = mojom::value;                   \
-  EXPECT_EQ(static_cast<uint32_t>(input_prefs.name), \
+#define GPU_PREFERENCES_FIELD_ENUM(name, value, mojom_value) \
+  input_prefs.name = value;                                  \
+  EXPECT_NE(default_prefs.name, input_prefs.name);           \
+  prefs_mojom.name = mojom_value;                            \
+  EXPECT_EQ(static_cast<uint32_t>(input_prefs.name),         \
             static_cast<uint32_t>(prefs_mojom.name));
 
     GPU_PREFERENCES_FIELD(disable_accelerated_video_decode, true)
@@ -150,9 +151,12 @@
     GPU_PREFERENCES_FIELD(enable_oop_rasterization, true)
     GPU_PREFERENCES_FIELD(disable_oop_rasterization, true)
     GPU_PREFERENCES_FIELD(watchdog_starts_backgrounded, true)
-    GPU_PREFERENCES_FIELD_ENUM(use_vulkan, VulkanImplementationName::kNative)
+    GPU_PREFERENCES_FIELD_ENUM(use_vulkan, VulkanImplementationName::kNative,
+                               mojom::VulkanImplementationName::kNative)
     GPU_PREFERENCES_FIELD(enable_gpu_benchmarking_extension, true)
     GPU_PREFERENCES_FIELD(enable_webgpu, true)
+    GPU_PREFERENCES_FIELD_ENUM(message_loop_type, base::MessageLoop::TYPE_UI,
+                               base::MessageLoop::TYPE_UI)
 
     input_prefs.texture_target_exception_list.emplace_back(
         gfx::BufferUsage::SCANOUT, gfx::BufferFormat::RGBA_8888);
diff --git a/gpu/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom
index 96d8043..dd9d94e3 100644
--- a/gpu/ipc/common/gpu_preferences.mojom
+++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -5,6 +5,7 @@
 // gpu/config/gpu_preferences.h
 module gpu.mojom;
 
+import "mojo/public/mojom/base/message_loop_type.mojom";
 import "ui/gfx/mojo/buffer_types.mojom";
 
 // Corresponds to gpu::VulkanImplementationName.
@@ -67,4 +68,5 @@
   bool enable_metal;
   bool enable_gpu_benchmarking_extension;
   bool enable_webgpu;
+  mojo_base.mojom.MessageLoopType message_loop_type;
 };
diff --git a/gpu/ipc/common/gpu_preferences_struct_traits.h b/gpu/ipc/common/gpu_preferences_struct_traits.h
index 87a9115..005862b 100644
--- a/gpu/ipc/common/gpu_preferences_struct_traits.h
+++ b/gpu/ipc/common/gpu_preferences_struct_traits.h
@@ -7,8 +7,10 @@
 
 #include <vector>
 
+#include "base/message_loop/message_loop.h"
 #include "gpu/config/gpu_preferences.h"
 #include "gpu/ipc/common/gpu_preferences.mojom.h"
+#include "mojo/public/cpp/base/message_loop_type_mojom_traits.h"
 #include "ui/gfx/mojo/buffer_types_struct_traits.h"
 
 namespace mojo {
@@ -119,6 +121,8 @@
     out->enable_gpu_benchmarking_extension =
         prefs.enable_gpu_benchmarking_extension();
     out->enable_webgpu = prefs.enable_webgpu();
+    if (!prefs.ReadMessageLoopType(&out->message_loop_type))
+      return false;
     return true;
   }
 
@@ -268,6 +272,10 @@
   static bool enable_webgpu(const gpu::GpuPreferences& prefs) {
     return prefs.enable_webgpu;
   }
+  static base::MessageLoop::Type message_loop_type(
+      const gpu::GpuPreferences& prefs) {
+    return prefs.message_loop_type;
+  }
 };
 
 }  // namespace mojo
diff --git a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
index dbdbdf7..e78d98d 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -24,8 +24,6 @@
 #include "ios/chrome/browser/app_startup_parameters.h"
 #include "ios/chrome/browser/chrome_switches.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/u2f/u2f_tab_helper.h"
 #import "ios/chrome/browser/ui/main/test/stub_browser_interface_provider.h"
@@ -66,38 +64,6 @@
   DISALLOW_COPY_AND_ASSIGN(FakeU2FTabHelper);
 };
 
-// Tab mock for using in UserActivity tests.
-@interface UserActivityHandlerTabMock : NSObject
-
-- (instancetype)initWithWebState:(web::WebState*)webState
-    NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-@end
-
-@implementation UserActivityHandlerTabMock {
-  web::WebState* _webState;
-}
-
-- (instancetype)initWithWebState:(web::WebState*)webState {
-  if ((self = [super init])) {
-    DCHECK(webState);
-    _webState = webState;
-  }
-  return self;
-}
-
-- (FakeU2FTabHelper*)U2FTabHelper {
-  return static_cast<FakeU2FTabHelper*>(U2FTabHelper::FromWebState(_webState));
-}
-
-- (NSString*)tabId {
-  return TabIdTabHelper::FromWebState(_webState)->tab_id();
-}
-
-@end
-
 #pragma mark - TabModel Mock
 
 // TabModel mock for using in UserActivity tests.
@@ -117,21 +83,16 @@
   return self;
 }
 
-- (UserActivityHandlerTabMock*)addMockTab {
+- (web::WebState*)addWebState {
   auto testWebState = std::make_unique<web::TestWebState>();
   TabIdTabHelper::CreateForWebState(testWebState.get());
   FakeU2FTabHelper::CreateForWebState(testWebState.get());
-
-  UserActivityHandlerTabMock* tab =
-      [[UserActivityHandlerTabMock alloc] initWithWebState:testWebState.get()];
-  LegacyTabHelper::CreateForWebStateForTesting(testWebState.get(),
-                                               static_cast<Tab*>(tab));
-
+  web::WebState* returnWebState = testWebState.get();
   _webStateList->InsertWebState(0, std::move(testWebState),
                                 WebStateList::INSERT_NO_FLAGS,
                                 WebStateOpener());
 
-  return tab;
+  return returnWebState;
 }
 
 - (WebStateList*)webStateList {
@@ -174,6 +135,15 @@
     handle_startup_parameters_has_been_called_ = NO;
   }
 
+  FakeU2FTabHelper* GetU2FTabHelperForWebState(web::WebState* web_state) {
+    return static_cast<FakeU2FTabHelper*>(
+        U2FTabHelper::FromWebState(web_state));
+  }
+
+  NSString* GetTabIdForWebState(web::WebState* web_state) {
+    return TabIdTabHelper::FromWebState(web_state)->tab_id();
+  }
+
   conditionBlock getCompletionHandler() {
     if (!completion_block_) {
       block_executed_ = NO;
@@ -566,12 +536,12 @@
   // Setup.
   UserActivityHandlerTabModelMock* mockTabModel =
       [[UserActivityHandlerTabModelMock alloc] init];
-  UserActivityHandlerTabMock* tabMock = [mockTabModel addMockTab];
+  web::WebState* web_state = [mockTabModel addWebState];
   id tabModel = static_cast<id>(mockTabModel);
 
-  std::string urlRepresentation =
-      base::StringPrintf("chromium://u2f-callback?isU2F=1&tabID=%s",
-                         base::SysNSStringToUTF8(tabMock.tabId).c_str());
+  std::string urlRepresentation = base::StringPrintf(
+      "chromium://u2f-callback?isU2F=1&tabID=%s",
+      base::SysNSStringToUTF8(GetTabIdForWebState(web_state)).c_str());
 
   GURL gurl(urlRepresentation);
   AppStartupParameters* startupParams =
@@ -599,7 +569,7 @@
 
   // Tests.
   EXPECT_OCMOCK_VERIFY(startupInformationMock);
-  EXPECT_EQ(gurl, [tabMock U2FTabHelper] -> url());
+  EXPECT_EQ(gurl, GetU2FTabHelperForWebState(web_state)->url());
   EXPECT_TRUE(tabOpener.urlLoadParams.web_params.url.is_empty());
   EXPECT_TRUE(tabOpener.urlLoadParams.web_params.virtual_url.is_empty());
 }
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 9c11e5e7..778dbe606 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-  "+components/about_handler",
   "+components/autofill/core/browser",
   "+components/autofill/core/common",
   "+components/autofill/ios/browser",
diff --git a/ios/chrome/browser/browser_state/BUILD.gn b/ios/chrome/browser/browser_state/BUILD.gn
index fbb8335..a3102a3 100644
--- a/ios/chrome/browser/browser_state/BUILD.gn
+++ b/ios/chrome/browser/browser_state/BUILD.gn
@@ -65,7 +65,6 @@
     ":browser_state",
     "//base",
     "//base:i18n",
-    "//components/about_handler",
     "//components/bookmarks/browser",
     "//components/browser_sync",
     "//components/content_settings/core/browser",
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
index 5d5b586..71c3edf 100644
--- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
@@ -24,7 +24,6 @@
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "components/about_handler/about_protocol_handler.h"
 #include "components/content_settings/core/browser/content_settings_provider.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
@@ -429,10 +428,6 @@
       url::kDataScheme, std::make_unique<net::DataProtocolHandler>());
   DCHECK(set_protocol);
 
-  job_factory->SetProtocolHandler(
-      url::kAboutScheme,
-      std::make_unique<about_handler::AboutProtocolHandler>());
-
   return job_factory;
 }
 
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index 3d2aec1..1bd9ae1 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -365,10 +365,6 @@
      flag_descriptions::kWebPageTextAccessibilityName,
      flag_descriptions::kWebPageTextAccessibilityDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(web::kWebPageTextAccessibility)},
-    {"new-password-form-parsing",
-     flag_descriptions::kNewPasswordFormParsingName,
-     flag_descriptions::kNewPasswordFormParsingDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(password_manager::features::kNewPasswordFormParsing)},
     {"app-launcher-refresh", flag_descriptions::kAppLauncherRefreshName,
      flag_descriptions::kAppLauncherRefreshDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kAppLauncherRefresh)},
@@ -449,17 +445,6 @@
     {"copied-content-behavior", flag_descriptions::kCopiedContentBehaviorName,
      flag_descriptions::kCopiedContentBehaviorName, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kCopiedContentBehavior)},
-    {"new-password-form-parsing-for-saving",
-     flag_descriptions::kNewPasswordFormParsingForSavingName,
-     flag_descriptions::kNewPasswordFormParsingForSavingDescription,
-     flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(
-         password_manager::features::kNewPasswordFormParsingForSaving)},
-    {"only-new-password-form-parsing",
-     flag_descriptions::kOnlyNewPasswordFormParsingName,
-     flag_descriptions::kOnlyNewPasswordFormParsingDescription,
-     flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(password_manager::features::kOnlyNewParser)},
     {"snapshot-draw-view", flag_descriptions::kSnapshotDrawViewName,
      flag_descriptions::kSnapshotDrawViewDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kSnapshotDrawView)},
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 06a7afc5..7e3a5db 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -284,19 +284,6 @@
     "Switches the omnibox suggestions and omnibox itself to display the new "
     "design with favicons, new suggestion layout, rich entity support.";
 
-const char kNewPasswordFormParsingName[] = "New password form parsing";
-const char kNewPasswordFormParsingDescription[] =
-    "Replaces existing form parsing in password manager with a new version, "
-    "currently under development. WARNING: when enabled Password Manager might "
-    "stop working";
-
-const char kNewPasswordFormParsingForSavingName[] =
-    "New password form parsing for saving passwords";
-const char kNewPasswordFormParsingForSavingDescription[] =
-    "Replaces existing form parsing for saving in password manager with a new "
-    "version, currently under development. WARNING: when enabled, Password "
-    "Manager might stop working";
-
 const char kNonModalDialogsName[] = "Use non-modal JavaScript dialogs";
 const char kNonModalDialogsDescription[] =
     "Presents JavaScript dialogs non-modally so that the user can change tabs "
@@ -342,11 +329,6 @@
     "Shows Google head non personalized search suggestions provided by a "
     "compact on device model";
 
-const char kOnlyNewPasswordFormParsingName[] =
-    "Use only new password form parsing";
-const char kOnlyNewPasswordFormParsingDescription[] =
-    "The old password form parsing is disabled";
-
 const char kOptionalArticleThumbnailName[] =
     "Enable optional thumbnails for NTP articles";
 const char kOptionalArticleThumbnailDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index de1849b..c567f580 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -238,15 +238,6 @@
 extern const char kNewOmniboxPopupLayoutName[];
 extern const char kNewOmniboxPopupLayoutDescription[];
 
-// Title and description for the flag to enable new password form parsing.
-extern const char kNewPasswordFormParsingName[];
-extern const char kNewPasswordFormParsingDescription[];
-
-// Title and description for the flag to enable new password form parsing for
-// saving.
-extern const char kNewPasswordFormParsingForSavingName[];
-extern const char kNewPasswordFormParsingForSavingDescription[];
-
 // Title and description for the flag to enable non-modal JavaScript dialogs.
 extern const char kNonModalDialogsName[];
 extern const char kNonModalDialogsDescription[];
@@ -286,11 +277,6 @@
 extern const char kOmniboxOnDeviceHeadSuggestionsName[];
 extern const char kOmniboxOnDeviceHeadSuggestionsDescription[];
 
-// Title and description for the flag to enable using only new password form
-// parsing.
-extern const char kOnlyNewPasswordFormParsingName[];
-extern const char kOnlyNewPasswordFormParsingDescription[];
-
 // Title and description for the flag to enable optional thumbnail for NTP
 // articles according to European copyright directive(EUCD).
 extern const char kOptionalArticleThumbnailName[];
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm
index 41d7846..7a102b3 100644
--- a/ios/chrome/browser/passwords/password_controller_unittest.mm
+++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -105,7 +105,8 @@
 
 class MockLogManager : public autofill::LogManager {
  public:
-  MOCK_CONST_METHOD1(LogSavePasswordProgress, void(const std::string& text));
+  MOCK_CONST_METHOD1(LogTextMessage, void(const std::string& text));
+  MOCK_CONST_METHOD1(LogEntry, void(base::Value&&));
   MOCK_CONST_METHOD0(IsLoggingActive, bool(void));
 
   // Methods not important for testing.
@@ -1144,12 +1145,12 @@
   // code better to allow proper unit-testing.
   MockLogManager log_manager;
   EXPECT_CALL(log_manager, IsLoggingActive()).WillRepeatedly(Return(true));
+  EXPECT_CALL(
+      log_manager,
+      LogTextMessage("Message:  PasswordManager::OnPasswordFormsRendered \n"));
   EXPECT_CALL(log_manager,
-              LogSavePasswordProgress(
-                  "Message: \"PasswordManager::OnPasswordFormsRendered\"\n"));
-  EXPECT_CALL(log_manager,
-              LogSavePasswordProgress(testing::Ne(
-                  "Message: \"PasswordManager::OnPasswordFormsRendered\"\n")))
+              LogTextMessage(testing::Ne(
+                  "Message:  PasswordManager::OnPasswordFormsRendered \n")))
       .Times(testing::AnyNumber());
   EXPECT_CALL(*weak_client, GetLogManager())
       .WillRepeatedly(Return(&log_manager));
@@ -1227,10 +1228,9 @@
     // code better to allow proper unit-testing.
     EXPECT_CALL(log_manager, IsLoggingActive()).WillRepeatedly(Return(true));
     const char kExpectedMessage[] =
-        "Message: \"PasswordManager::ProvisionallySaveForm\"\n";
-    EXPECT_CALL(log_manager, LogSavePasswordProgress(kExpectedMessage));
-    EXPECT_CALL(log_manager,
-                LogSavePasswordProgress(testing::Ne(kExpectedMessage)))
+        "Message:  PasswordManager::ProvisionallySaveForm \n";
+    EXPECT_CALL(log_manager, LogTextMessage(kExpectedMessage));
+    EXPECT_CALL(log_manager, LogTextMessage(testing::Ne(kExpectedMessage)))
         .Times(testing::AnyNumber());
 
     ExecuteJavaScript(
@@ -1253,7 +1253,7 @@
       .WillRepeatedly(Return(&log_manager));
   EXPECT_CALL(log_manager, IsLoggingActive()).WillRepeatedly(Return(true));
   const char kExpectedMessage[] =
-      "Message: \"PasswordManager::OnSameDocumentNavigation\"\n";
+      "Message:  PasswordManager::OnSameDocumentNavigation \n";
 
   // The standard pattern is to use a __block variable WaitUntilCondition but
   // __block variable can't be captured in C++ lambda, so as workaround it's
@@ -1262,14 +1262,13 @@
   bool expected_message_logged = false;
   bool* p_expected_message_logged = &expected_message_logged;
 
-  EXPECT_CALL(log_manager, LogSavePasswordProgress(kExpectedMessage))
+  EXPECT_CALL(log_manager, LogTextMessage(kExpectedMessage))
       .WillOnce(testing::Invoke(
           [&expected_message_logged](const std::string& message) {
             expected_message_logged = true;
           }));
 
-  EXPECT_CALL(log_manager,
-              LogSavePasswordProgress(testing::Ne(kExpectedMessage)))
+  EXPECT_CALL(log_manager, LogTextMessage(testing::Ne(kExpectedMessage)))
       .Times(testing::AnyNumber());
 
   LoadHtml(@"<iframe id='frame1' name='frame1'></iframe>");
@@ -1507,22 +1506,22 @@
     base::test::ScopedFeatureList scoped_feature_list;
     scoped_feature_list.InitAndEnableFeature(features::kPasswordGeneration);
     ChromeWebTest::SetUp();
-    
+
     password_manager::NewPasswordFormManager::
     set_wait_for_server_predictions_for_filling(false);
-    
+
     auto client =
     std::make_unique<NiceMock<MockPasswordManagerClient>>(store_.get());
     weak_client_ = client.get();
-    
+
     EXPECT_CALL(*weak_client_, GetPasswordSyncState())
     .WillRepeatedly(
                     Return(password_manager::SyncState::SYNCING_NORMAL_ENCRYPTION));
     EXPECT_CALL(*weak_client_, IsIncognito()).WillRepeatedly(Return(true));
-    
+
     passwordController_ =
     [[PasswordController alloc] initWithWebState:web_state()
                                           client:std::move(client)];
-    
+
     EXPECT_FALSE([passwordController_ passwordGenerationHelper]);
 }
diff --git a/ios/chrome/browser/prerender/preload_controller.mm b/ios/chrome/browser/prerender/preload_controller.mm
index 60a8ecc..7febc8d9 100644
--- a/ios/chrome/browser/prerender/preload_controller.mm
+++ b/ios/chrome/browser/prerender/preload_controller.mm
@@ -23,8 +23,6 @@
 #include "ios/chrome/browser/pref_names.h"
 #include "ios/chrome/browser/prerender/preload_controller_delegate.h"
 #import "ios/chrome/browser/signin/account_consistency_service_factory.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_helper_util.h"
 #import "ios/web/public/deprecated/crw_native_content.h"
 #import "ios/web/public/deprecated/crw_native_content_holder.h"
diff --git a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
index e0161fbb6..42bd110 100644
--- a/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
+++ b/ios/chrome/browser/sessions/ios_chrome_tab_restore_service_client.mm
@@ -13,7 +13,6 @@
 #include "ios/chrome/browser/chrome_url_constants.h"
 #include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios.h"
 #include "ios/chrome/browser/sessions/tab_restore_service_delegate_impl_ios_factory.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/tabs/tab_model_list.h"
 #include "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
diff --git a/ios/chrome/browser/signin/BUILD.gn b/ios/chrome/browser/signin/BUILD.gn
index 1819e4f..849559f 100644
--- a/ios/chrome/browser/signin/BUILD.gn
+++ b/ios/chrome/browser/signin/BUILD.gn
@@ -110,8 +110,6 @@
     "authentication_service_delegate_fake.mm",
     "authentication_service_fake.h",
     "authentication_service_fake.mm",
-    "identity_test_environment_chrome_browser_state_adaptor.cc",
-    "identity_test_environment_chrome_browser_state_adaptor.h",
   ]
   deps = [
     ":signin",
diff --git a/ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.cc b/ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.cc
deleted file mode 100644
index d001a346..0000000
--- a/ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright 2018 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 "ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "components/signin/public/base/account_consistency_method.h"
-#include "components/signin/public/base/test_signin_client.h"
-#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/chrome/browser/signin/device_accounts_provider_impl.h"
-#include "ios/chrome/browser/signin/identity_manager_factory.h"
-#include "ios/chrome/browser/signin/signin_client_factory.h"
-
-namespace {
-
-std::unique_ptr<KeyedService> BuildTestSigninClient(web::BrowserState* state) {
-  return std::make_unique<TestSigninClient>(
-      ios::ChromeBrowserState::FromBrowserState(state)->GetPrefs());
-}
-
-}  // namespace
-
-// static
-std::unique_ptr<TestChromeBrowserState>
-IdentityTestEnvironmentChromeBrowserStateAdaptor::
-    CreateChromeBrowserStateForIdentityTestEnvironment() {
-  return CreateChromeBrowserStateForIdentityTestEnvironment(
-      TestChromeBrowserState::TestingFactories());
-}
-
-// static
-std::unique_ptr<TestChromeBrowserState>
-IdentityTestEnvironmentChromeBrowserStateAdaptor::
-    CreateChromeBrowserStateForIdentityTestEnvironment(
-        const TestChromeBrowserState::TestingFactories& input_factories) {
-  TestChromeBrowserState::Builder builder;
-
-  for (auto& input_factory : input_factories) {
-    builder.AddTestingFactory(input_factory.first, input_factory.second);
-  }
-
-  return CreateChromeBrowserStateForIdentityTestEnvironment(builder);
-}
-
-// static
-std::unique_ptr<TestChromeBrowserState>
-IdentityTestEnvironmentChromeBrowserStateAdaptor::
-    CreateChromeBrowserStateForIdentityTestEnvironment(
-        TestChromeBrowserState::Builder& builder) {
-  for (auto& identity_factory : GetIdentityTestEnvironmentFactories()) {
-    builder.AddTestingFactory(identity_factory.first, identity_factory.second);
-  }
-
-  return builder.Build();
-}
-
-// static
-void IdentityTestEnvironmentChromeBrowserStateAdaptor::
-    SetIdentityTestEnvironmentFactoriesOnBrowserContext(
-        TestChromeBrowserState* chrome_browser_state) {
-  for (const auto& factory_pair : GetIdentityTestEnvironmentFactories()) {
-    factory_pair.first->SetTestingFactory(chrome_browser_state,
-                                          factory_pair.second);
-  }
-}
-
-// static
-void IdentityTestEnvironmentChromeBrowserStateAdaptor::
-    AppendIdentityTestEnvironmentFactories(
-        TestChromeBrowserState::TestingFactories* factories_to_append_to) {
-  TestChromeBrowserState::TestingFactories identity_factories =
-      GetIdentityTestEnvironmentFactories();
-  factories_to_append_to->insert(factories_to_append_to->end(),
-                                 identity_factories.begin(),
-                                 identity_factories.end());
-}
-
-// static
-std::unique_ptr<KeyedService>
-IdentityTestEnvironmentChromeBrowserStateAdaptor::BuildIdentityManagerForTests(
-    web::BrowserState* browser_state) {
-  ios::ChromeBrowserState* chrome_browser_state =
-      ios::ChromeBrowserState::FromBrowserState(browser_state);
-
-  return identity::IdentityTestEnvironment::BuildIdentityManagerForTests(
-      SigninClientFactory::GetForBrowserState(chrome_browser_state),
-      chrome_browser_state->GetPrefs(), base::FilePath(),
-      signin::AccountConsistencyMethod::kMirror);
-}
-
-// static
-TestChromeBrowserState::TestingFactories
-IdentityTestEnvironmentChromeBrowserStateAdaptor::
-    GetIdentityTestEnvironmentFactories() {
-  return {{SigninClientFactory::GetInstance(),
-           base::BindRepeating(&BuildTestSigninClient)},
-          {IdentityManagerFactory::GetInstance(),
-           base::BindRepeating(&BuildIdentityManagerForTests)}};
-}
-
-IdentityTestEnvironmentChromeBrowserStateAdaptor::
-    IdentityTestEnvironmentChromeBrowserStateAdaptor(
-        ios::ChromeBrowserState* chrome_browser_state)
-    : identity_test_env_(
-          IdentityManagerFactory::GetForBrowserState(chrome_browser_state)) {}
diff --git a/ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.h b/ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.h
deleted file mode 100644
index 32a2861..0000000
--- a/ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2018 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 IOS_CHROME_BROWSER_SIGNIN_IDENTITY_TEST_ENVIRONMENT_CHROME_BROWSER_STATE_ADAPTOR_H_
-#define IOS_CHROME_BROWSER_SIGNIN_IDENTITY_TEST_ENVIRONMENT_CHROME_BROWSER_STATE_ADAPTOR_H_
-
-#include <memory>
-
-#include "components/signin/public/identity_manager/identity_test_environment.h"
-#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-
-// Adaptor that supports identity::IdentityTestEnvironment's usage in testing
-// contexts where the relevant fake objects must be injected via the
-// BrowserStateKeyedServiceFactory infrastructure as the production code
-// accesses IdentityManager via that infrastructure. Before using this
-// class, please consider whether you can change the production code in question
-// to take in the relevant dependencies directly rather than obtaining them from
-// the ChromeBrowserState; this is both cleaner in general and allows for direct
-// usage of identity::IdentityTestEnvironment in the test.
-class IdentityTestEnvironmentChromeBrowserStateAdaptor {
- public:
-  // Creates and returns a TestChromeBrowserState that has been configured with
-  // the set of testing factories that IdentityTestEnvironment requires.
-  static std::unique_ptr<TestChromeBrowserState>
-  CreateChromeBrowserStateForIdentityTestEnvironment();
-
-  // Like the above, but additionally configures the returned ChromeBrowserState
-  // with |input_factories|. By default, internally constructs a
-  // TestURLLoaderFactory to use for cookie-related network requests. If this
-  // isn't desired (e.g., because the test is already using a
-  // TestURLLoaderFactory), set
-  // |create_fake_url_loader_factory_for_cookie_requests| to false.
-  static std::unique_ptr<TestChromeBrowserState>
-  CreateChromeBrowserStateForIdentityTestEnvironment(
-      const TestChromeBrowserState::TestingFactories& input_factories);
-
-  // Creates and returns a TestChromeBrowserState that has been configured
-  // with the given |builder|. Optionally, use a
-  // ProfileOAuth2TokenServiceIOSDelegate to build the
-  // FakeProfileOAuth2TokenService.
-  // See the above variant for comments on common parameters.
-  static std::unique_ptr<TestChromeBrowserState>
-  CreateChromeBrowserStateForIdentityTestEnvironment(
-      TestChromeBrowserState::Builder& builder);
-
-  // Sets the testing factories that identity::IdentityTestEnvironment
-  // requires explicitly on a Profile that is passed to it.
-  // See the above variant for comments on common parameters.
-  static void SetIdentityTestEnvironmentFactoriesOnBrowserContext(
-      TestChromeBrowserState* browser_state);
-
-  // Appends the set of testing factories that identity::IdentityTestEnvironment
-  // requires to |factories_to_append_to|, which should be the set of testing
-  // factories supplied to TestChromeBrowserState (via one of the various
-  // mechanisms for doing so). Prefer the above API if possible, as it is less
-  // fragile. This API is primarily for use in tests that do not create the
-  // TestChromeBrowserState internally but rather simply supply the set of
-  // TestingFactories to some external facility (e.g., a superclass).
-  // See CreateProfileForIdentityTestEnvironment() for comments on common
-  // parameters.
-  static void AppendIdentityTestEnvironmentFactories(
-      TestChromeBrowserState::TestingFactories* factories_to_append_to);
-
-  // Constructs an adaptor that associates an IdentityTestEnvironment instance
-  // with |browser_state| via the relevant backing objects. Note that
-  // |browser_state| must have been configured with the IdentityTestEnvironment
-  // testing factories, either because it was created via
-  // CreateChromeBrowserStateForIdentityTestEnvironment() or because
-  // AppendIdentityTestEnvironmentFactories() was invoked on the set of
-  // factories supplied to it.
-  // |browser_state| must outlive this object.
-  explicit IdentityTestEnvironmentChromeBrowserStateAdaptor(
-      ios::ChromeBrowserState* browser_state);
-  ~IdentityTestEnvironmentChromeBrowserStateAdaptor() {}
-
-  // Returns the IdentityTestEnvironment associated with this object (and
-  // implicitly with the ChromeBrowserState passed to this object's
-  // constructor).
-  identity::IdentityTestEnvironment* identity_test_env() {
-    return &identity_test_env_;
-  }
-
- private:
-  // Testing factory that creates an IdentityManager with a
-  // FakeProfileOAuth2TokenService.
-  static std::unique_ptr<KeyedService> BuildIdentityManagerForTests(
-      web::BrowserState* browser_state);
-  static TestChromeBrowserState::TestingFactories
-  GetIdentityTestEnvironmentFactories();
-
-  identity::IdentityTestEnvironment identity_test_env_;
-
-  DISALLOW_COPY_AND_ASSIGN(IdentityTestEnvironmentChromeBrowserStateAdaptor);
-};
-
-#endif  // IOS_CHROME_BROWSER_SIGNIN_IDENTITY_TEST_ENVIRONMENT_CHROME_BROWSER_STATE_ADAPTOR_H_
diff --git a/ios/chrome/browser/snapshots/BUILD.gn b/ios/chrome/browser/snapshots/BUILD.gn
index b608ed1..42045a9 100644
--- a/ios/chrome/browser/snapshots/BUILD.gn
+++ b/ios/chrome/browser/snapshots/BUILD.gn
@@ -80,10 +80,13 @@
     "//ios/chrome/browser/browser_state:test_support",
     "//ios/chrome/browser/ui/image_util",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/browser/web:tab_id_tab_helper",
     "//ios/web",
     "//ios/web/public/test",
     "//ios/web/public/test/fakes:fakes",
+    "//testing/gmock",
     "//testing/gtest",
+    "//third_party/ocmock",
     "//ui/base:test_support",
     "//ui/gfx",
   ]
diff --git a/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm b/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm
index 85b0234e..7be79ac2 100644
--- a/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm
+++ b/ios/chrome/browser/snapshots/snapshot_tab_helper_unittest.mm
@@ -12,11 +12,14 @@
 #import "ios/chrome/browser/snapshots/snapshot_cache_factory.h"
 #import "ios/chrome/browser/ui/image_util/image_util.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/browser/web/tab_id_tab_helper.h"
 #import "ios/web/public/test/fakes/test_web_state.h"
 #include "ios/web/public/test/test_web_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/gtest_mac.h"
 #include "testing/platform_test.h"
+#import "third_party/ocmock/OCMock/OCMock.h"
+#import "third_party/ocmock/gtest_support.h"
 #include "ui/base/test/ios/ui_image_test_utils.h"
 #include "ui/gfx/image/image.h"
 
@@ -337,3 +340,25 @@
 
   ASSERT_FALSE(GetCachedSnapshot());
 }
+
+TEST_F(SnapshotTabHelperTest, ClosingWebStateDoesNotRemoveSnapshot) {
+  id partialMock = OCMPartialMock(
+      SnapshotCacheFactory::GetForBrowserState(browser_state_.get()));
+  std::unique_ptr<web::WebState> web_state =
+      std::make_unique<web::TestWebState>();
+  TabIdTabHelper::CreateForWebState(web_state.get());
+
+  NSString* tab_id = TabIdTabHelper::FromWebState(web_state.get())->tab_id();
+  SnapshotTabHelper::CreateForWebState(web_state.get(), tab_id);
+  [[partialMock reject] removeImageWithSessionID:tab_id];
+
+  // Use @try/@catch as -reject raises an exception.
+  @try {
+    web_state.reset();
+    EXPECT_OCMOCK_VERIFY(partialMock);
+  } @catch (NSException* exception) {
+    // The exception is raised when -removeImageWithSessionID: is invoked. As
+    // this should not happen, mark the test as failed.
+    GTEST_FAIL();
+  }
+}
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn
index cae44fa..ab23318 100644
--- a/ios/chrome/browser/tabs/BUILD.gn
+++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -4,8 +4,6 @@
 
 source_set("tabs") {
   sources = [
-    "legacy_tab_helper.h",
-    "tab.h",
     "tab_helper_util.h",
     "tab_model.h",
     "tab_model_list.h",
@@ -32,9 +30,6 @@
 
 source_set("tabs_internal") {
   sources = [
-    "legacy_tab_helper.mm",
-    "tab.h",
-    "tab.mm",
     "tab_helper_util.mm",
     "tab_model.mm",
     "tab_model_closing_web_state_observer.h",
@@ -124,7 +119,6 @@
     "tab_model_list_unittest.mm",
     "tab_model_unittest.mm",
     "tab_title_util_unittest.mm",
-    "tab_unittest.mm",
   ]
   deps = [
     ":tabs",
diff --git a/ios/chrome/browser/tabs/legacy_tab_helper.h b/ios/chrome/browser/tabs/legacy_tab_helper.h
deleted file mode 100644
index fafe6c7f..0000000
--- a/ios/chrome/browser/tabs/legacy_tab_helper.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2017 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 IOS_CHROME_BROWSER_TABS_LEGACY_TAB_HELPER_H_
-#define IOS_CHROME_BROWSER_TABS_LEGACY_TAB_HELPER_H_
-
-#include "base/macros.h"
-#import "ios/web/public/web_state/web_state_user_data.h"
-
-@class Tab;
-
-// LegacyTabHelper associates a Tab instance to a WebState object.
-class LegacyTabHelper : public web::WebStateUserData<LegacyTabHelper> {
- public:
-  // Creates the LegacyTabHelper. This immediately creates the Tab object.
-  static void CreateForWebState(web::WebState* web_state);
-
-  // Creates the LegacyTabHelper with a pre-constructed Tab object for
-  // testing. The Tab is owned by LegacyTabHelper and must not be nil.
-  static void CreateForWebStateForTesting(web::WebState* web_state, Tab* tab);
-
-  // Returns the Tab associated with |web_state| or nil.
-  static Tab* GetTabForWebState(web::WebState* web_state);
-
- private:
-  friend class web::WebStateUserData<LegacyTabHelper>;
-
-  LegacyTabHelper(web::WebState* web_state, Tab* tab);
-  ~LegacyTabHelper() override;
-
-  // Creates the LegacyTabHelper with an associated Tab object. Creates the
-  // Tab if |tab| is nil.
-  static void CreateForWebStateInternal(web::WebState* web_state, Tab* tab);
-
-  // The Tab instance associated with the WebState.
-  Tab* tab_;
-
-  WEB_STATE_USER_DATA_KEY_DECL();
-
-  DISALLOW_COPY_AND_ASSIGN(LegacyTabHelper);
-};
-
-#endif  // IOS_CHROME_BROWSER_TABS_LEGACY_TAB_HELPER_H_
diff --git a/ios/chrome/browser/tabs/legacy_tab_helper.mm b/ios/chrome/browser/tabs/legacy_tab_helper.mm
deleted file mode 100644
index cf2dca1c..0000000
--- a/ios/chrome/browser/tabs/legacy_tab_helper.mm
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2017 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 "ios/chrome/browser/tabs/legacy_tab_helper.h"
-
-#import "ios/chrome/browser/tabs/tab.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-// static
-void LegacyTabHelper::CreateForWebState(web::WebState* web_state) {
-  CreateForWebStateInternal(web_state, nil);
-}
-
-// static
-void LegacyTabHelper::CreateForWebStateForTesting(web::WebState* web_state,
-                                                  Tab* tab) {
-  DCHECK(tab);
-  DCHECK(!FromWebState(web_state));
-  CreateForWebStateInternal(web_state, tab);
-}
-
-// static
-Tab* LegacyTabHelper::GetTabForWebState(web::WebState* web_state) {
-  DCHECK(web_state);
-  LegacyTabHelper* tab_helper = LegacyTabHelper::FromWebState(web_state);
-  return tab_helper ? tab_helper->tab_ : nil;
-}
-
-LegacyTabHelper::LegacyTabHelper(web::WebState* web_state, Tab* tab)
-    : tab_(tab) {}
-
-LegacyTabHelper::~LegacyTabHelper() = default;
-
-// static
-void LegacyTabHelper::CreateForWebStateInternal(web::WebState* web_state,
-                                                Tab* tab) {
-  DCHECK(web_state);
-  if (!FromWebState(web_state)) {
-    web_state->SetUserData(
-        UserDataKey(),
-        std::unique_ptr<base::SupportsUserData::Data>(new LegacyTabHelper(
-            web_state, tab ? tab : [[Tab alloc] initWithWebState:web_state])));
-  }
-}
-
-WEB_STATE_USER_DATA_KEY_IMPL(LegacyTabHelper)
diff --git a/ios/chrome/browser/tabs/tab.h b/ios/chrome/browser/tabs/tab.h
deleted file mode 100644
index ed1038c..0000000
--- a/ios/chrome/browser/tabs/tab.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2012 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 IOS_CHROME_BROWSER_TABS_TAB_H_
-#define IOS_CHROME_BROWSER_TABS_TAB_H_
-
-#import <UIKit/UIKit.h>
-
-#include "ios/web/public/user_agent.h"
-#include "ui/base/page_transition_types.h"
-
-namespace web {
-class WebState;
-}
-
-// The header name and value for the data reduction proxy to request an image to
-// be reloaded without optimizations.
-extern NSString* const kProxyPassthroughHeaderName;
-extern NSString* const kProxyPassthroughHeaderValue;
-
-// Information related to a single tab. The WebState is similar to desktop
-// Chrome's WebContents in that it encapsulates rendering. Acts as the
-// delegate for the WebState in order to process info about pages having
-// loaded.
-@interface Tab : NSObject
-
-// The Webstate associated with this Tab.
-@property(nonatomic, readonly) web::WebState* webState;
-
-// Creates a new Tab with the given WebState.
-- (instancetype)initWithWebState:(web::WebState*)webState;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_TABS_TAB_H_
diff --git a/ios/chrome/browser/tabs/tab.mm b/ios/chrome/browser/tabs/tab.mm
deleted file mode 100644
index 9a21f36..0000000
--- a/ios/chrome/browser/tabs/tab.mm
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright 2012 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 "ios/chrome/browser/tabs/tab.h"
-
-#import "ios/web/public/web_state/web_state_observer_bridge.h"
-#import "ios/web/web_state/ui/crw_web_controller.h"
-#import "ios/web/web_state/web_state_impl.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-
-@interface Tab ()<CRWWebStateObserver> {
-  // WebStateImpl for this tab.
-  web::WebStateImpl* _webStateImpl;
-
-  // Allows Tab to conform CRWWebStateDelegate protocol.
-  std::unique_ptr<web::WebStateObserverBridge> _webStateObserver;
-
-}
-
-@end
-
-@implementation Tab
-
-#pragma mark - Initializers
-
-- (instancetype)initWithWebState:(web::WebState*)webState {
-  DCHECK(webState);
-  self = [super init];
-  if (self) {
-    // TODO(crbug.com/620465): Tab should only use public API of WebState.
-    // Remove this cast once this is the case.
-    _webStateImpl = static_cast<web::WebStateImpl*>(webState);
-    _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
-    _webStateImpl->AddObserver(_webStateObserver.get());
-  }
-  return self;
-}
-
-#pragma mark - NSObject protocol
-
-- (void)dealloc {
-  // The WebState owns the Tab, so -webStateDestroyed: should be called before
-  // -dealloc and _webStateImpl set to nullptr.
-  DCHECK(!_webStateImpl);
-}
-
-- (NSString*)description {
-  return
-      [NSString stringWithFormat:@"%p ... - %s", self,
-                                 self.webState->GetVisibleURL().spec().c_str()];
-}
-
-#pragma mark - Properties
-
-- (web::WebState*)webState {
-  return _webStateImpl;
-}
-
-#pragma mark - CRWWebStateObserver protocol
-
-- (void)webStateDestroyed:(web::WebState*)webState {
-  DCHECK_EQ(_webStateImpl, webState);
-
-  _webStateImpl->RemoveObserver(_webStateObserver.get());
-  _webStateObserver.reset();
-  _webStateImpl = nullptr;
-}
-
-@end
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm
index 50dabe97..a762513a 100644
--- a/ios/chrome/browser/tabs/tab_helper_util.mm
+++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -45,8 +45,6 @@
 #import "ios/chrome/browser/ssl/ios_security_state_tab_helper.h"
 #import "ios/chrome/browser/store_kit/store_kit_tab_helper.h"
 #import "ios/chrome/browser/sync/ios_chrome_synced_tab_delegate.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/translate/chrome_ios_translate_client.h"
 #import "ios/chrome/browser/u2f/u2f_tab_helper.h"
 #import "ios/chrome/browser/ui/infobars/infobar_feature.h"
@@ -66,12 +64,8 @@
 #import "ios/web/public/web_state/web_state.h"
 
 void AttachTabHelpers(web::WebState* web_state, bool for_prerender) {
-  // TabIdHelper sets up the tab ID which is required for the creation of the
-  // Tab by LegacyTabHelper.
+  // TabIdHelper sets up the tab ID.
   TabIdTabHelper::CreateForWebState(web_state);
-  LegacyTabHelper::CreateForWebState(web_state);
-  Tab* tab = LegacyTabHelper::GetTabForWebState(web_state);
-  DCHECK(tab);
 
   ios::ChromeBrowserState* browser_state =
       ios::ChromeBrowserState::FromBrowserState(web_state->GetBrowserState());
@@ -162,5 +156,5 @@
   }
 
   // Allow the embedder to attach tab helpers.
-  ios::GetChromeBrowserProvider()->AttachTabHelpers(web_state, tab);
+  ios::GetChromeBrowserProvider()->AttachTabHelpers(web_state);
 }
diff --git a/ios/chrome/browser/tabs/tab_model.h b/ios/chrome/browser/tabs/tab_model.h
index de9f7b6..9689f46d 100644
--- a/ios/chrome/browser/tabs/tab_model.h
+++ b/ios/chrome/browser/tabs/tab_model.h
@@ -18,7 +18,6 @@
 class GURL;
 @class SessionServiceIOS;
 @class SessionWindowIOS;
-@class Tab;
 class TabModelSyncedWindowDelegate;
 class TabUsageRecorder;
 class WebStateList;
@@ -48,9 +47,6 @@
 // synchronized.
 @interface TabModel : NSObject <SessionWindowRestoring>
 
-// Currently active tab.
-@property(nonatomic, weak) Tab* currentTab;
-
 // The delegate for sync.
 @property(nonatomic, readonly)
     TabModelSyncedWindowDelegate* syncedWindowDelegate;
@@ -89,10 +85,6 @@
 
 - (instancetype)init NS_UNAVAILABLE;
 
-// Accesses the tab at the given index.
-- (Tab*)tabAtIndex:(NSUInteger)index;
-- (NSUInteger)indexOfTab:(Tab*)tab;
-
 // Add/modify tabs.
 
 // Opens a tab at the specified URL. For certain transition types, will consult
@@ -122,18 +114,9 @@
 - (web::WebState*)insertOpenByDOMWebStateWithOpener:
     (web::WebState*)parentWebState;
 
-// Moves |tab| to the given |index|. |index| must be valid for this tab model
-// (must be less than the current number of tabs). |tab| must already be in this
-// tab model. If |tab| is already at |index|, this method does nothing and will
-// not notify observers.
-- (void)moveTab:(Tab*)tab toIndex:(NSUInteger)index;
-
 // Closes the tab at the given |index|. |index| must be valid.
 - (void)closeTabAtIndex:(NSUInteger)index;
 
-// Closes the given tab.
-- (void)closeTab:(Tab*)tab;
-
 // Closes ALL the tabs.
 - (void)closeAllTabs;
 
diff --git a/ios/chrome/browser/tabs/tab_model.mm b/ios/chrome/browser/tabs/tab_model.mm
index 030ba1a..861fff198 100644
--- a/ios/chrome/browser/tabs/tab_model.mm
+++ b/ios/chrome/browser/tabs/tab_model.mm
@@ -39,8 +39,6 @@
 #import "ios/chrome/browser/sessions/session_window_ios.h"
 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
 #import "ios/chrome/browser/snapshots/snapshot_cache_factory.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model_closing_web_state_observer.h"
 #import "ios/chrome/browser/tabs/tab_model_list.h"
 #import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h"
@@ -269,17 +267,6 @@
 
 #pragma mark - Public methods
 
-- (Tab*)currentTab {
-  web::WebState* webState = _webStateList->GetActiveWebState();
-  return webState ? LegacyTabHelper::GetTabForWebState(webState) : nil;
-}
-
-- (void)setCurrentTab:(Tab*)newTab {
-  int indexOfTab = _webStateList->GetIndexOfWebState(newTab.webState);
-  DCHECK_NE(indexOfTab, WebStateList::kInvalidIndex);
-  _webStateList->ActivateWebStateAt(indexOfTab);
-}
-
 - (TabModelSyncedWindowDelegate*)syncedWindowDelegate {
   return _syncedWindowDelegate.get();
 }
@@ -387,21 +374,6 @@
   return self;
 }
 
-- (Tab*)tabAtIndex:(NSUInteger)index {
-  DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
-  return LegacyTabHelper::GetTabForWebState(
-      _webStateList->GetWebStateAt(static_cast<int>(index)));
-}
-
-- (NSUInteger)indexOfTab:(Tab*)tab {
-  int index = _webStateList->GetIndexOfWebState(tab.webState);
-  if (index == WebStateList::kInvalidIndex)
-    return NSNotFound;
-
-  DCHECK_GE(index, 0);
-  return static_cast<NSUInteger>(index);
-}
-
 - (web::WebState*)insertWebStateWithURL:(const GURL&)URL
                                referrer:(const web::Referrer&)referrer
                              transition:(ui::PageTransition)transition
@@ -474,22 +446,12 @@
   return _webStateList->GetWebStateAt(insertionIndex);
 }
 
-- (void)moveTab:(Tab*)tab toIndex:(NSUInteger)toIndex {
-  DCHECK_LE(toIndex, static_cast<NSUInteger>(INT_MAX));
-  int fromIndex = _webStateList->GetIndexOfWebState(tab.webState);
-  _webStateList->MoveWebStateAt(fromIndex, static_cast<int>(toIndex));
-}
-
 - (void)closeTabAtIndex:(NSUInteger)index {
   DCHECK_LE(index, static_cast<NSUInteger>(INT_MAX));
   _webStateList->CloseWebStateAt(static_cast<int>(index),
                                  WebStateList::CLOSE_USER_ACTION);
 }
 
-- (void)closeTab:(Tab*)tab {
-  [self closeTabAtIndex:[self indexOfTab:tab]];
-}
-
 - (void)closeAllTabs {
   _webStateList->CloseAllWebStates(WebStateList::CLOSE_USER_ACTION);
 }
@@ -506,8 +468,8 @@
 
 - (void)setPrimary:(BOOL)primary {
   if (_tabUsageRecorder) {
-    _tabUsageRecorder->RecordPrimaryTabModelChange(primary,
-                                                   self.currentTab.webState);
+    _tabUsageRecorder->RecordPrimaryTabModelChange(
+        primary, self.webStateList->GetActiveWebState());
   }
 }
 
@@ -549,7 +511,7 @@
 - (void)saveSessionImmediately:(BOOL)immediately {
   // Do nothing if there are tabs in the model but no selected tab. This is
   // a transitional state.
-  if ((!self.currentTab && _webStateList->count()) || !_browserState)
+  if (!_webStateList->GetActiveWebState() || !_browserState)
     return;
   NSString* statePath =
       base::SysUTF8ToNSString(_browserState->GetStatePath().AsUTF8Unsafe());
@@ -644,18 +606,19 @@
   // If there was only one tab and it was the new tab page, clobber it.
   BOOL closedNTPTab = NO;
   if (oldCount == 1) {
-    Tab* tab = [self tabAtIndex:0];
+    web::WebState* webState = _webStateList->GetWebStateAt(0);
     BOOL hasPendingLoad =
-        tab.webState->GetNavigationManager()->GetPendingItem() != nullptr;
+        webState->GetNavigationManager()->GetPendingItem() != nullptr;
     if (!hasPendingLoad &&
-        tab.webState->GetLastCommittedURL() == kChromeUINewTabURL) {
-      [self closeTab:tab];
+        webState->GetLastCommittedURL() == kChromeUINewTabURL) {
+      _webStateList->CloseWebStateAt(0, WebStateList::CLOSE_USER_ACTION);
+
       closedNTPTab = YES;
       oldCount = 0;
     }
   }
   if (_tabUsageRecorder) {
-    _tabUsageRecorder->InitialRestoredTabs(self.currentTab.webState,
+    _tabUsageRecorder->InitialRestoredTabs(_webStateList->GetActiveWebState(),
                                            restoredWebStates);
   }
 
@@ -672,9 +635,10 @@
 
 // Called when UIApplicationWillResignActiveNotification is received.
 - (void)willResignActive:(NSNotification*)notify {
-  if (self.webUsageEnabled && self.currentTab) {
+  if (self.webUsageEnabled && _webStateList->GetActiveWebState()) {
     NSString* tabId =
-        TabIdTabHelper::FromWebState(self.currentTab.webState)->tab_id();
+        TabIdTabHelper::FromWebState(_webStateList->GetActiveWebState())
+            ->tab_id();
     [SnapshotCacheFactory::GetForBrowserState(_browserState)
         willBeSavedGreyWhenBackgrounding:tabId];
   }
@@ -698,9 +662,10 @@
   [self saveSessionImmediately:YES];
 
   // Write out a grey version of the current website to disk.
-  if (self.webUsageEnabled && self.currentTab) {
+  if (self.webUsageEnabled && _webStateList->GetActiveWebState()) {
     NSString* tabId =
-        TabIdTabHelper::FromWebState(self.currentTab.webState)->tab_id();
+        TabIdTabHelper::FromWebState(_webStateList->GetActiveWebState())
+            ->tab_id();
 
     [SnapshotCacheFactory::GetForBrowserState(_browserState)
         saveGreyInBackgroundForSessionID:tabId];
diff --git a/ios/chrome/browser/tabs/tab_model_selected_tab_observer.mm b/ios/chrome/browser/tabs/tab_model_selected_tab_observer.mm
index d5cf48a..410a6fa3 100644
--- a/ios/chrome/browser/tabs/tab_model_selected_tab_observer.mm
+++ b/ios/chrome/browser/tabs/tab_model_selected_tab_observer.mm
@@ -5,9 +5,8 @@
 #import "ios/chrome/browser/tabs/tab_model_selected_tab_observer.h"
 
 #include "base/logging.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
+#import "ios/web/public/web_state/web_state.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -32,11 +31,6 @@
                 oldWebState:(web::WebState*)oldWebState
                     atIndex:(int)atIndex
                      reason:(int)reason {
-  if (oldWebState) {
-    // Save state, such as scroll position, ... of the old selected Tab.
-    Tab* oldTab = LegacyTabHelper::GetTabForWebState(oldWebState);
-    DCHECK(oldTab);
-  }
 
   if (newWebState && !newWebState->IsLoading()) {
     // Persist the session state.
diff --git a/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm b/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm
index b7028d1..240e690 100644
--- a/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm
+++ b/ios/chrome/browser/tabs/tab_model_synced_window_delegate_getter.mm
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/tabs/tab_model_list.h"
 #import "ios/chrome/browser/tabs/tab_model_synced_window_delegate.h"
+#import "ios/chrome/browser/web_state_list/web_state_list.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -34,7 +35,7 @@
     NSArray<TabModel*>* tabModels =
         TabModelList::GetTabModelsForChromeBrowserState(browser_state);
     for (TabModel* tabModel in tabModels) {
-      if (tabModel.currentTab) {
+      if (tabModel.webStateList->GetActiveWebState()) {
         sync_sessions::SyncedWindowDelegate* synced_window_delegate =
             tabModel.syncedWindowDelegate;
         synced_window_delegates[synced_window_delegate->GetSessionId()] =
diff --git a/ios/chrome/browser/tabs/tab_model_unittest.mm b/ios/chrome/browser/tabs/tab_model_unittest.mm
index 6e08b6ef..35debdb 100644
--- a/ios/chrome/browser/tabs/tab_model_unittest.mm
+++ b/ios/chrome/browser/tabs/tab_model_unittest.mm
@@ -19,8 +19,6 @@
 #import "ios/chrome/browser/sessions/session_ios.h"
 #import "ios/chrome/browser/sessions/session_window_ios.h"
 #import "ios/chrome/browser/sessions/test_session_service.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_helper_util.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/web/chrome_web_client.h"
@@ -390,7 +388,8 @@
   [tab_model_ restoreSessionWindow:window forInitialRestore:NO];
 
   ASSERT_EQ(3U, [tab_model_ count]);
-  EXPECT_NSEQ([tab_model_ tabAtIndex:1], [tab_model_ currentTab]);
+  EXPECT_EQ(tab_model_.webStateList->GetWebStateAt(1),
+            tab_model_.webStateList->GetActiveWebState());
   EXPECT_NE(web_state, tab_model_.webStateList->GetWebStateAt(0));
   EXPECT_NE(web_state, tab_model_.webStateList->GetWebStateAt(1));
   EXPECT_NE(web_state, tab_model_.webStateList->GetWebStateAt(2));
@@ -428,7 +427,8 @@
   [tab_model_ restoreSessionWindow:window forInitialRestore:NO];
 
   ASSERT_EQ(5U, [tab_model_ count]);
-  EXPECT_NSEQ([tab_model_ tabAtIndex:3], [tab_model_ currentTab]);
+  EXPECT_EQ(tab_model_.webStateList->GetWebStateAt(3),
+            tab_model_.webStateList->GetActiveWebState());
   EXPECT_EQ(web_state0, tab_model_.webStateList->GetWebStateAt(0));
   EXPECT_EQ(web_state1, tab_model_.webStateList->GetWebStateAt(1));
   EXPECT_NE(web_state0, tab_model_.webStateList->GetWebStateAt(2));
@@ -461,7 +461,8 @@
   [tab_model_ restoreSessionWindow:window forInitialRestore:NO];
 
   ASSERT_EQ(4U, [tab_model_ count]);
-  EXPECT_NSEQ([tab_model_ tabAtIndex:2], [tab_model_ currentTab]);
+  EXPECT_EQ(tab_model_.webStateList->GetWebStateAt(2),
+            tab_model_.webStateList->GetActiveWebState());
   EXPECT_EQ(web_state, tab_model_.webStateList->GetWebStateAt(0));
   EXPECT_NE(web_state, tab_model_.webStateList->GetWebStateAt(1));
   EXPECT_NE(web_state, tab_model_.webStateList->GetWebStateAt(2));
@@ -518,8 +519,9 @@
   EXPECT_EQ([tab_model_ count], 1U);
   EXPECT_EQ(new_web_state, tab_model_.webStateList->GetWebStateAt(0));
   tab_model_.webStateList->ActivateWebStateAt(0);
-  Tab* current_tab = [tab_model_ currentTab];
-  EXPECT_TRUE(current_tab);
+  web::WebState* current_web_state =
+      tab_model_.webStateList->GetActiveWebState();
+  EXPECT_TRUE(current_web_state);
 }
 
 TEST_P(TabModelTest, AddWithOrderController) {
@@ -608,107 +610,6 @@
             tab_model_.webStateList->GetIndexOfWebState(web_state3) + 1);
 }
 
-TEST_P(TabModelTest, MoveTabs) {
-  web::WebState* web_state0 =
-      [tab_model_ insertWebStateWithURL:GURL(kURL1)
-                               referrer:web::Referrer()
-                             transition:ui::PAGE_TRANSITION_TYPED
-                                 opener:nil
-                            openedByDOM:NO
-                                atIndex:[tab_model_ count]
-                           inBackground:NO];
-  web::WebState* web_state1 =
-      [tab_model_ insertWebStateWithURL:GURL(kURL1)
-                               referrer:web::Referrer()
-                             transition:ui::PAGE_TRANSITION_TYPED
-                                 opener:nil
-                            openedByDOM:NO
-                                atIndex:[tab_model_ count]
-                           inBackground:NO];
-  web::WebState* web_state2 =
-      [tab_model_ insertWebStateWithURL:GURL(kURL1)
-                               referrer:web::Referrer()
-                             transition:ui::PAGE_TRANSITION_TYPED
-                                 opener:nil
-                            openedByDOM:NO
-                                atIndex:[tab_model_ count]
-                           inBackground:NO];
-
-  // Basic sanity checks before moving on.
-  ASSERT_EQ(3U, [tab_model_ count]);
-  EXPECT_EQ(web_state0, tab_model_.webStateList->GetWebStateAt(0));
-  EXPECT_EQ(web_state1, tab_model_.webStateList->GetWebStateAt(1));
-  EXPECT_EQ(web_state2, tab_model_.webStateList->GetWebStateAt(2));
-
-  // Check that observer methods are called.
-  FakeWebStateListObservingDelegate* web_state_list_observer =
-      [[FakeWebStateListObservingDelegate alloc] init];
-  [web_state_list_observer observeWebStateList:tab_model_.webStateList];
-
-  // Move a tab from index 1 to index 0 (move tab left by one).
-  [web_state_list_observer setDidMoveWebStateWasCalled:NO];
-  [tab_model_ moveTab:[tab_model_ tabAtIndex:1] toIndex:0];
-  ASSERT_EQ(3U, [tab_model_ count]);
-  EXPECT_EQ(web_state1, tab_model_.webStateList->GetWebStateAt(0));
-  EXPECT_EQ(web_state0, tab_model_.webStateList->GetWebStateAt(1));
-  EXPECT_EQ(web_state2, tab_model_.webStateList->GetWebStateAt(2));
-  EXPECT_TRUE([web_state_list_observer didMoveWebStateWasCalled]);
-
-  // Move a tab from index 1 to index 2 (move tab right by one).
-  [web_state_list_observer setDidMoveWebStateWasCalled:NO];
-  [tab_model_ moveTab:[tab_model_ tabAtIndex:1] toIndex:2];
-  ASSERT_EQ(3U, [tab_model_ count]);
-  EXPECT_EQ(web_state1, tab_model_.webStateList->GetWebStateAt(0));
-  EXPECT_EQ(web_state2, tab_model_.webStateList->GetWebStateAt(1));
-  EXPECT_EQ(web_state0, tab_model_.webStateList->GetWebStateAt(2));
-  EXPECT_TRUE([web_state_list_observer didMoveWebStateWasCalled]);
-
-  // Move a tab from index 0 to index 2 (move tab right by more than one).
-  [web_state_list_observer setDidMoveWebStateWasCalled:NO];
-  [tab_model_ moveTab:[tab_model_ tabAtIndex:0] toIndex:2];
-  ASSERT_EQ(3U, [tab_model_ count]);
-
-  EXPECT_EQ(web_state2, tab_model_.webStateList->GetWebStateAt(0));
-  EXPECT_EQ(web_state0, tab_model_.webStateList->GetWebStateAt(1));
-  EXPECT_EQ(web_state1, tab_model_.webStateList->GetWebStateAt(2));
-  EXPECT_TRUE([web_state_list_observer didMoveWebStateWasCalled]);
-
-  // Move a tab from index 2 to index 0 (move tab left by more than one).
-  [web_state_list_observer setDidMoveWebStateWasCalled:NO];
-  [tab_model_ moveTab:[tab_model_ tabAtIndex:2] toIndex:0];
-  ASSERT_EQ(3U, [tab_model_ count]);
-  EXPECT_EQ(web_state1, tab_model_.webStateList->GetWebStateAt(0));
-  EXPECT_EQ(web_state2, tab_model_.webStateList->GetWebStateAt(1));
-  EXPECT_EQ(web_state0, tab_model_.webStateList->GetWebStateAt(2));
-  EXPECT_TRUE([web_state_list_observer didMoveWebStateWasCalled]);
-
-  // Move a tab from index 2 to index 2 (move tab to the same index).
-  [web_state_list_observer setDidMoveWebStateWasCalled:NO];
-  [tab_model_ moveTab:[tab_model_ tabAtIndex:2] toIndex:2];
-  ASSERT_EQ(3U, [tab_model_ count]);
-  EXPECT_EQ(web_state1, tab_model_.webStateList->GetWebStateAt(0));
-  EXPECT_EQ(web_state2, tab_model_.webStateList->GetWebStateAt(1));
-  EXPECT_EQ(web_state0, tab_model_.webStateList->GetWebStateAt(2));
-  EXPECT_FALSE([web_state_list_observer didMoveWebStateWasCalled]);
-
-  // TabModel asserts that there are no observer when it is deallocated,
-  // so remove the observer before the end of the method.
-  [web_state_list_observer stopObservingWebStateList:tab_model_.webStateList];
-}
-
-TEST_P(TabModelTest, TabCreatedOnInsertion) {
-  std::unique_ptr<web::WebState> web_state = web::WebState::Create(
-      web::WebState::CreateParams(chrome_browser_state_.get()));
-
-  EXPECT_NSEQ(nil, LegacyTabHelper::GetTabForWebState(web_state.get()));
-
-  web::WebState* web_state_ptr = web_state.get();
-  [tab_model_ webStateList]->InsertWebState(0, std::move(web_state),
-                                            WebStateList::INSERT_FORCE_INDEX,
-                                            WebStateOpener());
-  EXPECT_NSNE(nil, LegacyTabHelper::GetTabForWebState(web_state_ptr));
-}
-
 TEST_P(TabModelTest, DISABLED_PersistSelectionChange) {
   NSString* stashPath =
       base::SysUTF8ToNSString(chrome_browser_state_->GetStatePath().value());
@@ -741,8 +642,7 @@
                        inBackground:NO];
 
   ASSERT_EQ(3U, [tab_model_ count]);
-  [tab_model_ setCurrentTab:[tab_model_ tabAtIndex:1]];
-
+  tab_model_.webStateList->ActivateWebStateAt(1);
   // Force state to flush to disk on the main thread so it can be immediately
   // tested below.
   [test_session_service setPerformIO:YES];
@@ -761,7 +661,8 @@
 
   ASSERT_EQ(3u, [tab_model_ count]);
 
-  EXPECT_EQ([tab_model_ tabAtIndex:1], [tab_model_ currentTab]);
+  EXPECT_EQ(tab_model_.webStateList->GetWebStateAt(1),
+            tab_model_.webStateList->GetActiveWebState());
 
   // Clean up.
   EXPECT_TRUE([[NSFileManager defaultManager] removeItemAtPath:stashPath
diff --git a/ios/chrome/browser/tabs/tab_unittest.mm b/ios/chrome/browser/tabs/tab_unittest.mm
deleted file mode 100644
index 6708fe5..0000000
--- a/ios/chrome/browser/tabs/tab_unittest.mm
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright 2012 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 <UIKit/UIKit.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/files/file_path.h"
-#include "base/ios/block_types.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/scoped_feature_list.h"
-#include "components/bookmarks/test/bookmark_test_helpers.h"
-#include "components/history/core/browser/history_service.h"
-#include "components/keyed_service/core/service_access_type.h"
-#include "ios/chrome/browser/application_context.h"
-#include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
-#include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h"
-#import "ios/chrome/browser/chrome_url_util.h"
-#include "ios/chrome/browser/history/history_service_factory.h"
-#include "ios/chrome/browser/history/history_tab_helper.h"
-#import "ios/chrome/browser/snapshots/snapshot_cache.h"
-#import "ios/chrome/browser/snapshots/snapshot_cache_factory.h"
-#import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
-#import "ios/chrome/browser/tabs/tab_helper_util.h"
-#import "ios/chrome/browser/tabs/tab_model.h"
-#import "ios/chrome/browser/ui/open_in/open_in_controller.h"
-#import "ios/chrome/browser/ui/open_in/open_in_controller_testing.h"
-#import "ios/chrome/browser/web/tab_id_tab_helper.h"
-#include "ios/chrome/test/block_cleanup_test.h"
-#include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h"
-#include "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
-#include "ios/public/provider/chrome/browser/test_chrome_browser_provider.h"
-#import "ios/testing/ocmock_complex_type_helper.h"
-#include "ios/web/common/features.h"
-#import "ios/web/navigation/navigation_context_impl.h"
-#import "ios/web/navigation/navigation_manager_impl.h"
-#include "ios/web/public/navigation_item.h"
-#import "ios/web/public/navigation_manager.h"
-#include "ios/web/public/referrer.h"
-#import "ios/web/public/test/fakes/fake_navigation_context.h"
-#include "ios/web/public/test/test_web_thread_bundle.h"
-#import "ios/web/test/fakes/crw_fake_back_forward_list.h"
-#import "ios/web/web_state/ui/crw_web_controller.h"
-#import "ios/web/web_state/web_state_impl.h"
-#import "net/base/mac/url_conversions.h"
-#include "net/http/http_response_headers.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/gtest_mac.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-#import "third_party/ocmock/gtest_support.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-// When C++ exceptions are disabled, the C++ library defines |try| and
-// |catch| so as to allow exception-expecting C++ code to build properly when
-// language support for exceptions is not present.  These macros interfere
-// with the use of |@try| and |@catch| in Objective-C files such as this one.
-// Undefine these macros here, after everything has been #included, since
-// there will be no C++ uses and only Objective-C uses from this point on.
-#undef try
-#undef catch
-
-namespace {
-const char kNewTabUrl[] = "chrome://newtab/";
-const char kGoogleUserUrl[] = "http://google.com";
-const char kGoogleRedirectUrl[] = "http://www.google.fr/";
-static NSString* const kGoogleTitle = @"Google";
-const char kOtherUserUrl[] = "http://other.com";
-const char kOtherRedirectUrl[] = "http://other.fr/";
-NSString* const kOtherTitle = @"Other";
-}  // namespace
-
-@interface ArrayTabModel : TabModel {
- @private
-  NSMutableArray* _tabsForTesting;
-}
-@end
-
-@implementation ArrayTabModel
-- (instancetype)init {
-  if ((self = [super init]))
-    _tabsForTesting = [[NSMutableArray alloc] initWithCapacity:1];
-  return self;
-}
-
-- (void)addTabForTesting:(Tab*)tab {
-  [_tabsForTesting addObject:tab];
-}
-
-- (NSUInteger)indexOfTab:(Tab*)tab {
-  return [_tabsForTesting indexOfObject:tab];
-}
-
-- (NSUInteger)count {
-  return [_tabsForTesting count];
-}
-
-- (void)closeTabAtIndex:(NSUInteger)index {
-  [_tabsForTesting removeObjectAtIndex:index];
-}
-@end
-
-namespace {
-
-// TabTest is parameterized on this enum to test both LegacyNavigationManager
-// and WKBasedNavigationManager.
-enum class NavigationManagerChoice {
-  LEGACY,
-  WK_BASED,
-};
-
-// TODO(crbug.com/620465): can a TestWebState be used instead of a WebStateImpl
-// for those tests? This will require changing Tab to use a WebState instead of
-// a WebStateImpl first though.
-class TabTest : public BlockCleanupTest,
-                public ::testing::WithParamInterface<NavigationManagerChoice> {
- public:
-  TabTest()
-      : scoped_browser_state_manager_(
-            std::make_unique<TestChromeBrowserStateManager>(base::FilePath())),
-        web_state_impl_(nullptr) {}
-
-  void SetUp() override {
-    BlockCleanupTest::SetUp();
-
-    if (GetParam() == NavigationManagerChoice::LEGACY) {
-      scoped_feature_list_.InitAndDisableFeature(
-          web::features::kSlimNavigationManager);
-    } else {
-      scoped_feature_list_.InitAndEnableFeature(
-          web::features::kSlimNavigationManager);
-    }
-
-    [[ChromeAppConstants sharedInstance]
-        setCallbackSchemeForTesting:@"chromium"];
-
-    // Set up the testing profiles.
-    TestChromeBrowserState::Builder test_cbs_builder;
-    test_cbs_builder.AddTestingFactory(
-        SnapshotCacheFactory::GetInstance(),
-        SnapshotCacheFactory::GetDefaultFactory());
-    chrome_browser_state_ = test_cbs_builder.Build();
-    chrome_browser_state_->CreateBookmarkModel(false);
-    bookmarks::test::WaitForBookmarkModelToLoad(
-        ios::BookmarkModelFactory::GetForBrowserState(
-            chrome_browser_state_.get()));
-    ASSERT_TRUE(chrome_browser_state_->CreateHistoryService(true));
-
-    ios::ChromeBrowserState* browser_state = chrome_browser_state_.get();
-    if (UseOffTheRecordBrowserState())
-      browser_state = browser_state->GetOffTheRecordChromeBrowserState();
-
-    mock_web_controller_ =
-        [OCMockObject niceMockForClass:[CRWWebController class]];
-
-    if (GetParam() == NavigationManagerChoice::WK_BASED) {
-      mock_web_view_ = [OCMockObject mockForClass:[WKWebView class]];
-      fake_wk_list_ = [[CRWFakeBackForwardList alloc] init];
-      OCMStub([mock_web_view_ backForwardList]).andReturn(fake_wk_list_);
-      OCMStub([mock_web_controller_ webViewNavigationProxy])
-          .andReturn(mock_web_view_);
-    }
-    OCMStub([mock_web_controller_ isViewAlive]).andReturn(YES);
-
-    web::WebState::CreateParams create_params(browser_state);
-    web_state_impl_ = std::make_unique<web::WebStateImpl>(create_params);
-    web_state_impl_->SetWebController(mock_web_controller_);
-    web_state_impl_->GetNavigationManagerImpl().InitializeSession();
-    web::WebStateImpl* web_state_impl = web_state_impl_.get();
-    [[[static_cast<OCMockObject*>(mock_web_controller_) stub]
-        andReturnValue:OCMOCK_VALUE(web_state_impl)] webStateImpl];
-    web_controller_view_ = [[UIView alloc] init];
-    [[[static_cast<OCMockObject*>(mock_web_controller_) stub]
-        andReturn:web_controller_view_] view];
-    TabIdTabHelper::CreateForWebState(web_state_impl_.get());
-    HistoryTabHelper::CreateForWebState(web_state_impl_.get());
-    LegacyTabHelper::CreateForWebState(web_state_impl_.get());
-    tab_ = LegacyTabHelper::GetTabForWebState(web_state_impl_.get());
-    web::NavigationManager::WebLoadParams load_params(
-        GURL("chrome://version/"));
-    web_state_impl_->GetNavigationManager()->LoadURLWithParams(load_params);
-
-    // There should be no entries in the history at this point.
-    history::QueryResults results;
-    QueryAllHistory(&results);
-    EXPECT_EQ(0UL, results.size());
-  }
-
-  void TearDown() override {
-    // Ensure that the Tab is destroyed before the autorelease pool is cleared.
-    web_state_impl_.reset();
-    BlockCleanupTest::TearDown();
-  }
-
-  void BrowseTo(const GURL& user_url,
-                const GURL& redirect_url,
-                NSString* title) {
-    DCHECK_EQ(tab_.webState, web_state_impl_.get());
-
-    std::unique_ptr<web::NavigationContextImpl> context1 =
-        web::NavigationContextImpl::CreateNavigationContext(
-            web_state_impl_.get(), user_url,
-            /*has_user_gesture=*/true,
-            ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK,
-            /*is_renderer_initiated=*/true);
-    web_state_impl_->OnNavigationStarted(context1.get());
-
-    web::Referrer empty_referrer;
-    web_state_impl_->GetNavigationManagerImpl().AddPendingItem(
-        redirect_url, empty_referrer, ui::PAGE_TRANSITION_CLIENT_REDIRECT,
-        web::NavigationInitiationType::RENDERER_INITIATED,
-        web::NavigationManager::UserAgentOverrideOption::INHERIT);
-
-    std::unique_ptr<web::NavigationContextImpl> context2 =
-        web::NavigationContextImpl::CreateNavigationContext(
-            web_state_impl_.get(), redirect_url,
-            /*has_user_gesture=*/true,
-            ui::PageTransition::PAGE_TRANSITION_AUTO_BOOKMARK,
-            /*is_renderer_initiated=*/true);
-    web_state_impl_->OnNavigationStarted(context2.get());
-
-    if (GetParam() == NavigationManagerChoice::WK_BASED) {
-      [fake_wk_list_
-          setCurrentURL:base::SysUTF8ToNSString(redirect_url.spec())];
-      OCMStub([mock_web_view_ URL]).andReturn(fake_wk_list_.currentItem.URL);
-    }
-    web_state_impl_->GetNavigationManagerImpl().CommitPendingItem();
-
-    context2->SetHasCommitted(true);
-    web_state_impl_->UpdateHttpResponseHeaders(redirect_url);
-    web_state_impl_->OnNavigationFinished(context2.get());
-    web_state_impl_->SetIsLoading(true);
-
-    base::string16 new_title = base::SysNSStringToUTF16(title);
-    web_state_impl_->GetNavigationManager()->GetLastCommittedItem()->SetTitle(
-        new_title);
-
-    web_state_impl_->OnTitleChanged();
-    web_state_impl_->SetIsLoading(false);
-    web_state_impl_->OnPageLoaded(redirect_url, true);
-  }
-
-  void BrowseToNewTab() {
-    DCHECK_EQ(tab_.webState, web_state_impl_.get());
-    const GURL url(kNewTabUrl);
-    // TODO(crbug.com/661992): This will not work with a mock CRWWebController.
-    // The only test that uses it is currently disabled.
-    web::NavigationManager::WebLoadParams params(url);
-    params.transition_type = ui::PAGE_TRANSITION_TYPED;
-    web_state_impl_->GetNavigationManager()->LoadURLWithParams(params);
-    web_state_impl_->SetIsLoading(true);
-    web_state_impl_->SetIsLoading(false);
-    web_state_impl_->OnPageLoaded(url, true);
-    web_state_impl_->OnTitleChanged();
-  }
-
-  void QueryAllHistory(history::QueryResults* results) {
-    base::RunLoop run_loop;
-    base::CancelableTaskTracker tracker;
-    ios::HistoryServiceFactory::GetForBrowserState(
-        chrome_browser_state_.get(), ServiceAccessType::EXPLICIT_ACCESS)
-        ->QueryHistory(base::string16(), history::QueryOptions(),
-                       base::BindLambdaForTesting([&](history::QueryResults r) {
-                         *results = std::move(r);
-                         run_loop.Quit();
-                       }),
-                       &tracker);
-    run_loop.Run();
-  }
-
-  void CheckHistoryResult(const history::URLResult& historyResult,
-                          const GURL& expectedUrl,
-                          NSString* expectedTitle) {
-    EXPECT_EQ(expectedUrl, historyResult.url());
-    EXPECT_EQ(base::SysNSStringToUTF16(expectedTitle), historyResult.title());
-  }
-
-  void CheckCurrentItem(const GURL& expectedUrl, NSString* expectedTitle) {
-    OCMStub([mock_web_view_ URL]).andReturn(net::NSURLWithGURL(expectedUrl));
-    web::NavigationItem* item =
-        web_state_impl_->GetNavigationManager()->GetVisibleItem();
-    EXPECT_EQ(expectedUrl, item->GetURL());
-    EXPECT_EQ(base::SysNSStringToUTF16(expectedTitle), item->GetTitle());
-  }
-
-  void CheckCurrentItem(const history::URLResult& historyResult) {
-    OCMStub([mock_web_view_ URL])
-        .andReturn(net::NSURLWithGURL(historyResult.url()));
-    web::NavigationItem* item =
-        web_state_impl_->GetNavigationManager()->GetVisibleItem();
-    CheckHistoryResult(historyResult, item->GetURL(),
-                       base::SysUTF16ToNSString(item->GetTitle()));
-  }
-
-#ifndef NDEBUG
-  // Method useful when debugging.
-  void LogHistoryQueryResult(const history::QueryResults* results) {
-    for (const auto& result : *results) {
-      NSLog(@"title = %@; url = %@", base::SysUTF16ToNSString(result.title()),
-            base::SysUTF8ToNSString(result.url().spec()));
-    }
-  }
-#endif
-
-  virtual bool UseOffTheRecordBrowserState() const { return false; }
-
- protected:
-  web::TestWebThreadBundle thread_bundle_;
-  IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_;
-  std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
-  std::unique_ptr<web::WebStateImpl> web_state_impl_;
-  __weak CRWWebController* mock_web_controller_;
-  WKWebView* mock_web_view_;
-  CRWFakeBackForwardList* fake_wk_list_;
-  UIView* web_controller_view_;
-  ArrayTabModel* tabModel_;
-  __weak Tab* tab_;
-  base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_P(TabTest, AddToHistoryWithRedirect) {
-  BrowseTo(GURL(kGoogleUserUrl), GURL(kGoogleRedirectUrl), kGoogleTitle);
-  history::QueryResults results;
-  QueryAllHistory(&results);
-  EXPECT_EQ(1U, results.size());
-  CheckHistoryResult(results[0], GURL(kGoogleRedirectUrl), kGoogleTitle);
-  CheckCurrentItem(results[0]);
-}
-
-// TODO(crbug.com/378098): Disabled because forward/back is now implemented in
-// CRWWebController, so this test cannot function with a mock CRWWebController.
-// Rewrite and re-enable this test when it becomes a CRWWebController or
-// NavigationManager test.
-TEST_P(TabTest, DISABLED_BackAndForward) {
-  BrowseTo(GURL(kGoogleUserUrl), GURL(kGoogleRedirectUrl), kGoogleTitle);
-  BrowseTo(GURL(kOtherUserUrl), GURL(kOtherRedirectUrl), kOtherTitle);
-
-  history::QueryResults results;
-  QueryAllHistory(&results);
-  EXPECT_EQ(2U, results.size());
-  CheckHistoryResult(results[0], GURL(kOtherRedirectUrl), kOtherTitle);
-  CheckHistoryResult(results[1], GURL(kGoogleRedirectUrl), kGoogleTitle);
-  CheckCurrentItem(results[0]);
-}
-
-// TODO(crbug.com/378098): Disabled because navigation is no longer
-// possible with a mock
-// CRWWebController. Rewrite and re-enable this test when it becomes a
-// CRWWebController test.
-TEST_P(TabTest, DISABLED_NewTabInMiddleOfNavigation) {
-  BrowseTo(GURL(kGoogleUserUrl), GURL(kGoogleRedirectUrl), kGoogleTitle);
-  BrowseToNewTab();
-  BrowseTo(GURL(kOtherUserUrl), GURL(kOtherRedirectUrl), kOtherTitle);
-
-  // NOTE: NTP is not stored in the history.
-  history::QueryResults results;
-  QueryAllHistory(&results);
-  EXPECT_EQ(2U, results.size());
-  CheckHistoryResult(results[0], GURL(kOtherRedirectUrl), kOtherTitle);
-  CheckHistoryResult(results[1], GURL(kGoogleRedirectUrl), kGoogleTitle);
-}
-
-TEST_P(TabTest, ClosingWebStateDoesNotRemoveSnapshot) {
-  id partialMock = OCMPartialMock(
-      SnapshotCacheFactory::GetForBrowserState(chrome_browser_state_.get()));
-  NSString* tab_id = TabIdTabHelper::FromWebState(tab_.webState)->tab_id();
-  SnapshotTabHelper::CreateForWebState(tab_.webState, tab_id);
-  [[partialMock reject] removeImageWithSessionID:tab_id];
-
-  // Use @try/@catch as -reject raises an exception.
-  @try {
-    web_state_impl_.reset();
-    EXPECT_OCMOCK_VERIFY(partialMock);
-  } @catch (NSException* exception) {
-    // The exception is raised when -removeImageWithSessionID: is invoked. As
-    // this should not happen, mark the test as failed.
-    GTEST_FAIL();
-  }
-}
-
-TEST_P(TabTest, CallingRemoveSnapshotRemovesSnapshot) {
-  id partialMock = OCMPartialMock(
-      SnapshotCacheFactory::GetForBrowserState(chrome_browser_state_.get()));
-  NSString* tab_id = TabIdTabHelper::FromWebState(tab_.webState)->tab_id();
-
-  SnapshotTabHelper::CreateForWebState(tab_.webState, tab_id);
-  OCMExpect([partialMock removeImageWithSessionID:tab_id]);
-
-  SnapshotTabHelper::FromWebState(tab_.webState)->RemoveSnapshot();
-  EXPECT_OCMOCK_VERIFY(partialMock);
-}
-
-INSTANTIATE_TEST_SUITE_P(ProgrammaticTabTest,
-                         TabTest,
-                         ::testing::Values(NavigationManagerChoice::LEGACY,
-                                           NavigationManagerChoice::WK_BASED));
-
-}  // namespace
diff --git a/ios/chrome/browser/ui/activity_services/share_to_data.mm b/ios/chrome/browser/ui/activity_services/share_to_data.mm
index 888c3352..e8ced11b 100644
--- a/ios/chrome/browser/ui/activity_services/share_to_data.mm
+++ b/ios/chrome/browser/ui/activity_services/share_to_data.mm
@@ -6,7 +6,6 @@
 
 #include "base/logging.h"
 #include "base/strings/sys_string_conversions.h"
-#include "ios/chrome/browser/tabs/tab.h"
 #import "net/base/mac/url_conversions.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
diff --git a/ios/chrome/browser/ui/activity_services/share_to_data_builder.mm b/ios/chrome/browser/ui/activity_services/share_to_data_builder.mm
index 4037e63..93569f57 100644
--- a/ios/chrome/browser/ui/activity_services/share_to_data_builder.mm
+++ b/ios/chrome/browser/ui/activity_services/share_to_data_builder.mm
@@ -7,7 +7,6 @@
 #include "base/logging.h"
 #import "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/find_in_page/find_tab_helper.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab_title_util.h"
 #include "ios/chrome/browser/ui/activity_services/chrome_activity_item_thumbnail_generator.h"
 #include "ios/chrome/browser/ui/activity_services/share_to_data.h"
diff --git a/ios/chrome/browser/ui/badges/badge_mediator.mm b/ios/chrome/browser/ui/badges/badge_mediator.mm
index b21a97f..1f26821e 100644
--- a/ios/chrome/browser/ui/badges/badge_mediator.mm
+++ b/ios/chrome/browser/ui/badges/badge_mediator.mm
@@ -76,19 +76,24 @@
                 oldWebState:(web::WebState*)oldWebState
                     atIndex:(int)atIndex
                      reason:(int)reason {
-  DCHECK_EQ(_webStateList, webStateList);
-  web::WebState* webState = webStateList->GetActiveWebState();
-  InfobarBadgeTabHelper* infobarBadgeTabHelper =
-      InfobarBadgeTabHelper::FromWebState(webState);
-  DCHECK(infobarBadgeTabHelper);
-  infobarBadgeTabHelper->SetDelegate(self);
-  // Whenever the WebState changes ask the corresponding
-  // InfobarBadgeTabHelper for all the badges for that WebState.
-  std::vector<id<BadgeItem>> infobar_badges =
-      infobarBadgeTabHelper->GetInfobarBadgeItems();
-  NSArray* infobar_badges_array =
-      [NSArray arrayWithObjects:&infobar_badges[0] count:infobar_badges.size()];
-  [self.consumer setupWithBadges:infobar_badges_array];
+  // Only attempt to retrieve badges if there is a new current web state, since
+  // |newWebState| can be null.
+  if (newWebState) {
+    DCHECK_EQ(_webStateList, webStateList);
+    web::WebState* webState = webStateList->GetActiveWebState();
+    InfobarBadgeTabHelper* infobarBadgeTabHelper =
+        InfobarBadgeTabHelper::FromWebState(webState);
+    DCHECK(infobarBadgeTabHelper);
+    infobarBadgeTabHelper->SetDelegate(self);
+    // Whenever the WebState changes ask the corresponding
+    // InfobarBadgeTabHelper for all the badges for that WebState.
+    std::vector<id<BadgeItem>> infobar_badges =
+        infobarBadgeTabHelper->GetInfobarBadgeItems();
+    NSArray* infobar_badges_array =
+        [NSArray arrayWithObjects:&infobar_badges[0]
+                            count:infobar_badges.size()];
+    [self.consumer setupWithBadges:infobar_badges_array];
+  }
 }
 
 @end
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index 3584db3..cc08c1597 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -329,9 +329,7 @@
   self.definesPresentationContext = YES;
 
   self.scrimView = [[UIControl alloc] init];
-  self.scrimView.backgroundColor =
-      [UIColor colorWithWhite:0
-                        alpha:kTableViewNavigationWhiteAlphaForSearchScrim];
+  self.scrimView.backgroundColor = [UIColor colorNamed:kScrimBackgroundColor];
   self.scrimView.translatesAutoresizingMaskIntoConstraints = NO;
   self.scrimView.accessibilityIdentifier = kBookmarkHomeSearchScrimIdentifier;
   [self.scrimView addTarget:self
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h
index 7e00e3c..7ecdb850e 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h
@@ -8,7 +8,6 @@
 
 @protocol ApplicationCommands;
 @protocol BookmarkInteractionControllerDelegate;
-@class Tab;
 
 namespace bookmarks {
 class BookmarkNode;
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
index 78308da..f5165eac5 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.mm
@@ -17,7 +17,6 @@
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/metrics/new_tab_page_uma.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_title_util.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_edit_view_controller.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_folder_editor_view_controller.h"
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
index 743869d..22680b9d 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -4034,31 +4034,27 @@
 
 - (void)focusTabAtIndex:(NSUInteger)index {
   if (self.tabModel.count > index) {
-    [self.tabModel setCurrentTab:[self.tabModel tabAtIndex:index]];
+    self.tabModel.webStateList->ActivateWebStateAt(static_cast<int>(index));
   }
 }
 
 - (void)focusNextTab {
-  NSInteger currentTabIndex =
-      [self.tabModel indexOfTab:self.tabModel.currentTab];
-  NSInteger modelCount = self.tabModel.count;
-  if (currentTabIndex < modelCount - 1) {
-    Tab* nextTab = [self.tabModel tabAtIndex:currentTabIndex + 1];
-    [self.tabModel setCurrentTab:nextTab];
+  int activeIndex = self.tabModel.webStateList->active_index();
+  if (activeIndex < self.tabModel.webStateList->count()) {
+    self.tabModel.webStateList->ActivateWebStateAt(activeIndex + 1);
   } else {
-    [self.tabModel setCurrentTab:[self.tabModel tabAtIndex:0]];
+    self.tabModel.webStateList->ActivateWebStateAt(0);
   }
 }
 
 - (void)focusPreviousTab {
-  NSInteger currentTabIndex =
-      [self.tabModel indexOfTab:self.tabModel.currentTab];
-  if (currentTabIndex > 0) {
-    Tab* previousTab = [self.tabModel tabAtIndex:currentTabIndex - 1];
-    [self.tabModel setCurrentTab:previousTab];
+  int activeIndex = self.tabModel.webStateList->active_index();
+
+  if (activeIndex > 0) {
+    self.tabModel.webStateList->ActivateWebStateAt(activeIndex - 1);
   } else {
-    Tab* lastTab = [self.tabModel tabAtIndex:self.tabModel.count - 1];
-    [self.tabModel setCurrentTab:lastTab];
+    self.tabModel.webStateList->ActivateWebStateAt(
+        self.tabModel.webStateList->count() - 1);
   }
 }
 
@@ -4343,15 +4339,15 @@
 }
 
 - (void)closeCurrentTab {
-  Tab* currentTab = self.tabModel.currentTab;
-  NSUInteger tabIndex = [self.tabModel indexOfTab:currentTab];
-  if (tabIndex == NSNotFound)
+  int active_index = self.tabModel.webStateList->active_index();
+  if (active_index == WebStateList::kInvalidIndex)
     return;
 
   UIView* snapshotView = [self.contentArea snapshotViewAfterScreenUpdates:NO];
   snapshotView.frame = self.contentArea.frame;
 
-  [self.tabModel closeTabAtIndex:tabIndex];
+  self.tabModel.webStateList->CloseWebStateAt(active_index,
+                                              WebStateList::CLOSE_USER_ACTION);
 
   if (![self canShowTabStrip]) {
     [self.contentArea addSubview:snapshotView];
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm
index 4670905..86ba23b 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_egtest.mm
@@ -12,7 +12,6 @@
 #include "base/feature_list.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/strings/grit/components_strings.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/app/tab_test_util.h"
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
index b4ea30e8..da9ec5c 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller_unittest.mm
@@ -28,7 +28,6 @@
 #include "ios/chrome/browser/search_engines/template_url_service_factory.h"
 #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
 #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_helper_util.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/activity_services/share_protocol.h"
@@ -206,24 +205,16 @@
                                       forProtocol:@protocol(PageInfoCommands)];
     id mockApplicationCommandHandler =
         OCMProtocolMock(@protocol(ApplicationCommands));
-
     // Stub methods for TabModel.
     NSUInteger tabCount = 1;
     [[[tabModel stub] andReturnValue:OCMOCK_VALUE(tabCount)] count];
-    id currentTab = [[BVCTestTabMock alloc]
-        initWithRepresentedObject:[OCMockObject niceMockForClass:[Tab class]]];
-    [[[tabModel stub] andReturn:currentTab] currentTab];
-    [[[tabModel stub] andReturn:currentTab] tabAtIndex:0];
     [[tabModel stub] saveSessionImmediately:NO];
-    [[tabModel stub] setCurrentTab:[OCMArg any]];
     [[tabModel stub] closeAllTabs];
-    tab_ = currentTab;
 
     web::WebState::CreateParams params(chrome_browser_state_.get());
     std::unique_ptr<web::WebState> webState = web::WebState::Create(params);
     webStateImpl_ = static_cast<web::WebStateImpl*>(webState.get());
     AttachTabHelpers(webStateImpl_, NO);
-    [currentTab setWebState:webStateImpl_];
     tabModel_.webStateList->InsertWebState(0, std::move(webState), 0,
                                            WebStateOpener());
     tabModel_.webStateList->ActivateWebStateAt(0);
@@ -280,7 +271,6 @@
   IOSChromeScopedTestingLocalState local_state_;
   std::unique_ptr<TestChromeBrowserState> chrome_browser_state_;
   WebStateImpl* webStateImpl_;
-  Tab* tab_;
   TabModel* tabModel_;
   BrowserViewControllerHelper* bvcHelper_;
   PKAddPassesViewController* passKitViewController_;
@@ -291,19 +281,8 @@
 };
 
 TEST_F(BrowserViewControllerTest, TestWebStateSelected) {
-  [bvc_ webStateSelected:tab_.webState notifyToolbar:YES];
-  EXPECT_EQ([tab_.webState->GetView() superview], [bvc_ contentArea]);
-  EXPECT_TRUE(webStateImpl_->IsVisible());
-}
-
-TEST_F(BrowserViewControllerTest, TestWebStateSelectedIsNewWebState) {
-  id block = [^{
-    return GURL(kChromeUINewTabURL);
-  } copy];
-  id tabMock = (id)tab_;
-  [tabMock onSelector:@selector(url) callBlockExpectation:block];
-  [bvc_ webStateSelected:tab_.webState notifyToolbar:YES];
-  EXPECT_EQ([tab_.webState->GetView() superview], [bvc_ contentArea]);
+  [bvc_ webStateSelected:webStateImpl_ notifyToolbar:YES];
+  EXPECT_EQ([webStateImpl_->GetView() superview], [bvc_ contentArea]);
   EXPECT_TRUE(webStateImpl_->IsVisible());
 }
 
@@ -322,8 +301,6 @@
 // load on a handset, but not stop the load on a tablet.
 TEST_F(BrowserViewControllerTest,
        TestLocationBarBeganEdit_whenPageLoadIsInProgress) {
-  OCMockObject* tabMock = static_cast<OCMockObject*>(tab_);
-
   // Have the TestLocationBarModel indicate that a page load is in progress.
   id partialMock = OCMPartialMock(bvcHelper_);
   OCMExpect([partialMock isToolbarLoading:static_cast<web::WebState*>(
@@ -334,8 +311,6 @@
   [bvc_ locationBarBeganEdit];
   if (!IsIPadIdiom())
     EXPECT_FALSE(webStateImpl_->IsLoading());
-
-  EXPECT_OCMOCK_VERIFY(tabMock);
 }
 
 TEST_F(BrowserViewControllerTest, TestClearPresentedState) {
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
index 068f0ad..b02815f 100644
--- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn
+++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -133,6 +133,7 @@
     "//ios/chrome/browser/ui/overscroll_actions",
     "//ios/chrome/browser/ui/toolbar/buttons",
     "//ios/chrome/browser/ui/toolbar/public",
+    "//ios/chrome/browser/ui/toolbar/resources:tab_toolbar_shadow_color",
     "//ios/chrome/browser/ui/util:util",
     "//ios/chrome/common/favicon",
     "//ios/chrome/common/ui_util",
diff --git a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm
index 4a6428a9..0b89b99 100644
--- a/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm
+++ b/ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h"
 
+#include "base/logging.h"
 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h"
 #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_cell.h"
 #import "ios/chrome/browser/ui/content_suggestions/identifier/content_suggestion_identifier.h"
@@ -79,18 +80,21 @@
 
 // Target for custom action.
 - (BOOL)openInNewTab {
+  DCHECK(self.commandHandler);
   [self.commandHandler openNewTabWithMostVisitedItem:self incognito:NO];
   return YES;
 }
 
 // Target for custom action.
 - (BOOL)openInNewIncognitoTab {
+  DCHECK(self.commandHandler);
   [self.commandHandler openNewTabWithMostVisitedItem:self incognito:YES];
   return YES;
 }
 
 // Target for custom action.
 - (BOOL)removeMostVisited {
+  DCHECK(self.commandHandler);
   [self.commandHandler removeMostVisited:self];
   return YES;
 }
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
index c9e23d1b..ce0c7faf 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
@@ -250,7 +250,7 @@
 
   self.separator = [[UIView alloc] init];
   self.separator.backgroundColor =
-      [UIColor colorWithWhite:0 alpha:kToolbarSeparatorAlpha];
+      [UIColor colorNamed:@"tab_toolbar_shadow_color"];
   self.separator.alpha = 0;
   self.separator.translatesAutoresizingMaskIntoConstraints = NO;
   [searchField addSubview:self.separator];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
index a371d00..906fd1b 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_mediator.mm
@@ -670,6 +670,19 @@
   return _actionButtonItems;
 }
 
+- (void)setCommandHandler:
+    (id<ContentSuggestionsCommands, ContentSuggestionsGestureCommands>)
+        commandHandler {
+  if (_commandHandler == commandHandler)
+    return;
+
+  _commandHandler = commandHandler;
+
+  for (ContentSuggestionsMostVisitedItem* item in self.freshMostVisitedItems) {
+    item.commandHandler = commandHandler;
+  }
+}
+
 #pragma mark - ReadingListModelBridgeObserver
 
 - (void)readingListModelLoaded:(const ReadingListModel*)model {
diff --git a/ios/chrome/browser/ui/first_run/first_run_util.h b/ios/chrome/browser/ui/first_run/first_run_util.h
index 61ef002..1688ee7 100644
--- a/ios/chrome/browser/ui/first_run/first_run_util.h
+++ b/ios/chrome/browser/ui/first_run/first_run_util.h
@@ -8,7 +8,6 @@
 #import <UIKit/UIKit.h>
 
 @class FirstRunConfiguration;
-@class Tab;
 @protocol SyncPresenter;
 
 namespace base {
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.mm b/ios/chrome/browser/ui/history/history_table_view_controller.mm
index 0ee0d56..8a14f9d3 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -206,9 +206,7 @@
 
   self.scrimView = [[UIControl alloc] init];
   self.scrimView.alpha = 0.0f;
-  self.scrimView.backgroundColor =
-      [UIColor colorWithWhite:0
-                        alpha:kTableViewNavigationWhiteAlphaForSearchScrim];
+  self.scrimView.backgroundColor = [UIColor colorNamed:kScrimBackgroundColor];
   self.scrimView.translatesAutoresizingMaskIntoConstraints = NO;
   self.scrimView.accessibilityIdentifier = kHistorySearchScrimIdentifier;
   [self.scrimView addTarget:self
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm b/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm
index 3041c40..38e62d3b 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_model_delegate_ios.mm
@@ -56,7 +56,7 @@
   web::NavigationItem* item = GetNavigationItem();
   if (!item)
     return false;
-  *url = ShouldDisplayURL() ? item->GetVirtualURL() : GURL::EmptyGURL();
+  *url = item->GetVirtualURL();
   return true;
 }
 
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
index acc0ebc..6e19d684 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
@@ -198,9 +198,6 @@
 
     // Setup and activate constraints.
     [NSLayoutConstraint activateConstraints:@[
-      [_locationContainerView.leadingAnchor
-          constraintGreaterThanOrEqualToAnchor:self.leadingAnchor
-                                      constant:kLocationBarLeadingPadding],
       [_trailingButton.centerYAnchor
           constraintEqualToAnchor:self.centerYAnchor],
       [_locationContainerView.centerYAnchor
@@ -230,9 +227,20 @@
         [_leadingButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
         [_leadingButton.leadingAnchor
             constraintEqualToAnchor:self.leadingAnchor],
+        [_leadingButton.trailingAnchor
+            constraintLessThanOrEqualToAnchor:_locationContainerView
+                                                  .leadingAnchor],
         [_leadingButton.centerYAnchor
             constraintEqualToAnchor:self.centerYAnchor],
       ]];
+    } else {
+      // Since there is no leading button, |locationContainerView|'s
+      // leadingAnchor will be pinned to |self|.
+      [NSLayoutConstraint activateConstraints:@[
+        [_locationContainerView.leadingAnchor
+            constraintGreaterThanOrEqualToAnchor:self.leadingAnchor
+                                        constant:kLocationBarLeadingPadding],
+      ]];
     }
   }
 
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
index 9776224..82c9404 100644
--- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
+++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -467,7 +467,7 @@
                 action:@selector(displayModalInfobar)
       forControlEvents:UIControlEventTouchUpInside];
   // Set as hidden as it should only be shown by |displayInfobarButton:|
-  self.locationBarSteadyView.leadingButton.hidden = YES;
+  [self.locationBarSteadyView.leadingButton displayBadge:NO animated:NO];
 }
 
 - (void)displayModalInfobar {
@@ -493,20 +493,27 @@
 #pragma mark - BadgeConsumer
 
 - (void)setupWithBadges:(NSArray*)badges {
-  self.locationBarSteadyView.leadingButton.hidden = (badges.count == 0);
-  self.shouldShowLeadingButton = (badges.count > 0);
+  BOOL hasBadge = badges.count > 0;
+  if (hasBadge) {
+    id<BadgeItem> firstBadge = badges[0];
+    BOOL isAccepted = firstBadge.isAccepted;
+    self.activeBadge = isAccepted;
+    [self.locationBarSteadyView.leadingButton setActive:isAccepted animated:NO];
+  }
+  [self.locationBarSteadyView.leadingButton displayBadge:hasBadge animated:NO];
+  self.shouldShowLeadingButton = hasBadge;
 }
 
 - (void)addBadge:(id<BadgeItem>)badgeItem {
-  self.locationBarSteadyView.leadingButton.hidden = NO;
-  self.shouldShowLeadingButton = YES;
   self.activeBadge = badgeItem.isAccepted;
   [self.locationBarSteadyView.leadingButton setActive:badgeItem.isAccepted
-                                             animated:YES];
+                                             animated:NO];
+  [self.locationBarSteadyView.leadingButton displayBadge:YES animated:YES];
+  self.shouldShowLeadingButton = YES;
 }
 
 - (void)removeBadge:(id<BadgeItem>)badgeItem {
-  self.locationBarSteadyView.leadingButton.hidden = YES;
+  [self.locationBarSteadyView.leadingButton displayBadge:NO animated:NO];
   self.shouldShowLeadingButton = NO;
 }
 
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller_unittest.mm
index 9445e4006..49912ca 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller_unittest.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_collection_view_controller_unittest.mm
@@ -26,7 +26,6 @@
 #include "ios/chrome/browser/signin/authentication_service.h"
 #include "ios/chrome/browser/signin/authentication_service_delegate_fake.h"
 #include "ios/chrome/browser/signin/authentication_service_factory.h"
-#include "ios/chrome/browser/signin/identity_test_environment_chrome_browser_state_adaptor.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
 #include "ios/chrome/browser/sync/sync_setup_service_mock.h"
diff --git a/ios/chrome/browser/ui/settings/language/BUILD.gn b/ios/chrome/browser/ui/settings/language/BUILD.gn
index 5ed9173..b95c1c4 100644
--- a/ios/chrome/browser/ui/settings/language/BUILD.gn
+++ b/ios/chrome/browser/ui/settings/language/BUILD.gn
@@ -53,6 +53,7 @@
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view/cells",
     "//ios/chrome/browser/ui/util",
+    "//ios/chrome/common/colors",
     "//ios/chrome/common/ui_util",
     "//ui/base",
   ]
diff --git a/ios/chrome/browser/ui/settings/language/add_language_table_view_controller.mm b/ios/chrome/browser/ui/settings/language/add_language_table_view_controller.mm
index b9a4c58..3f940e38 100644
--- a/ios/chrome/browser/ui/settings/language/add_language_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/language/add_language_table_view_controller.mm
@@ -14,6 +14,7 @@
 #import "ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h"
 #include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui_util/constraints_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util_mac.h"
@@ -112,9 +113,7 @@
   // Scrim.
   self.scrimView = [[UIControl alloc] init];
   self.scrimView.alpha = 0.0f;
-  self.scrimView.backgroundColor =
-      [UIColor colorWithWhite:0
-                        alpha:kTableViewNavigationWhiteAlphaForSearchScrim];
+  self.scrimView.backgroundColor = [UIColor colorNamed:kScrimBackgroundColor];
   self.scrimView.translatesAutoresizingMaskIntoConstraints = NO;
   self.scrimView.accessibilityIdentifier =
       kAddLanguageSearchScrimAccessibilityIdentifier;
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
index 79aeace..85d8ff91 100644
--- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -48,6 +48,7 @@
 #include "ios/chrome/browser/ui/ui_feature_flags.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui_util/constraints_ui_util.h"
 #include "ios/chrome/grit/ios_strings.h"
 #include "ui/base/l10n/l10n_util_mac.h"
@@ -282,9 +283,7 @@
 
   self.scrimView = [[UIControl alloc] init];
   self.scrimView.alpha = 0.0f;
-  self.scrimView.backgroundColor =
-      [UIColor colorWithWhite:0
-                        alpha:kTableViewNavigationWhiteAlphaForSearchScrim];
+  self.scrimView.backgroundColor = [UIColor colorNamed:kScrimBackgroundColor];
   self.scrimView.translatesAutoresizingMaskIntoConstraints = NO;
   self.scrimView.accessibilityIdentifier = kPasswordsScrimViewId;
   [self.scrimView addTarget:self
diff --git a/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm b/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm
index 2aca491..1a35872 100644
--- a/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm
+++ b/ios/chrome/browser/ui/signin_interaction/signin_interaction_coordinator.mm
@@ -302,6 +302,7 @@
   }
   [self.advancedSigninSettingsCoordinator stop];
   self.advancedSigninSettingsCoordinator = nil;
+  self.presentingViewController = nil;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h b/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h
index 6363c22..c1606d8 100644
--- a/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h
+++ b/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.h
@@ -12,9 +12,6 @@
 extern const float kTableViewNavigationVerticalOffsetForSearchHeader;
 // The Alpha value used by the SearchBar when disabled.
 extern const float kTableViewNavigationAlphaForDisabledSearchBar;
-// The Alpha (on white) used for the scrim covering current data until data
-// is filtered out.
-extern const float kTableViewNavigationWhiteAlphaForSearchScrim;
 // The duration for scrim to fade in or out.
 extern const NSTimeInterval kTableViewNavigationScrimFadeDuration;
 
diff --git a/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.mm b/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.mm
index dcdbc984..7332ae0 100644
--- a/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.mm
+++ b/ios/chrome/browser/ui/table_view/table_view_navigation_controller_constants.mm
@@ -10,7 +10,6 @@
 
 const float kTableViewNavigationVerticalOffsetForSearchHeader = 6.0f;
 const float kTableViewNavigationAlphaForDisabledSearchBar = 0.5f;
-const float kTableViewNavigationWhiteAlphaForSearchScrim = 0.4f;
 const NSTimeInterval kTableViewNavigationScrimFadeDuration = 0.2;
 
 NSString* const kTableViewNavigationDismissButtonId =
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
index 3c7ab1e..53754e3 100644
--- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
+++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -21,7 +21,6 @@
 #import "ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction.h"
 #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h"
 #include "ios/chrome/browser/system_flags.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/tabs/tab_title_util.h"
 #import "ios/chrome/browser/ui/bubble/bubble_util.h"
@@ -1772,7 +1771,7 @@
     SnapshotTabHelper::FromWebState(_tabModel.webStateList->GetActiveWebState())
         ->UpdateSnapshotWithCallback(nil);
   }
-  [_tabModel setCurrentTab:[_tabModel tabAtIndex:index]];
+  _tabModel.webStateList->ActivateWebStateAt(static_cast<int>(index));
   [self updateContentOffsetForWebStateIndex:index isNewWebState:NO];
 }
 
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm
index 11dec9e..8e1484d 100644
--- a/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm
+++ b/ios/chrome/browser/ui/tabs/tab_strip_controller_unittest.mm
@@ -9,7 +9,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #import "ios/chrome/browser/sessions/test_session_service.h"
-#import "ios/chrome/browser/tabs/legacy_tab_helper.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/tabs/tab_strip_controller.h"
 #import "ios/chrome/browser/ui/tabs/tab_strip_view.h"
@@ -32,34 +31,6 @@
 #error "This file requires ARC support."
 #endif
 
-@interface TabStripControllerTestTab : NSObject
-
-- (instancetype)initWithWebState:(web::WebState*)webState
-    NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-@end
-
-@implementation TabStripControllerTestTab {
-  web::WebState* _webState;
-}
-
-
-- (instancetype)initWithWebState:(web::WebState*)webState {
-  if ((self = [super init])) {
-    DCHECK(webState);
-    _webState = webState;
-  }
-  return self;
-}
-
-- (web::WebState*)webState {
-  return _webState;
-}
-
-@end
-
 @interface TabStripControllerTestTabModel : NSObject
 
 @property(nonatomic, assign) ios::ChromeBrowserState* browserState;
@@ -87,22 +58,15 @@
   _browserState = nullptr;
 }
 
-- (TabStripControllerTestTab*)addTabForTestingWithTitle:(NSString*)title {
+- (void)addWebStateForTestingWithTitle:(NSString*)title {
   auto testWebState = std::make_unique<web::TestWebState>();
   testWebState->SetTitle(base::SysNSStringToUTF16(title));
   auto testNavigationManager = std::make_unique<web::TestNavigationManager>();
   testNavigationManager->SetVisibleItem(_visibleNavigationItem.get());
   testWebState->SetNavigationManager(std::move(testNavigationManager));
-  TabStripControllerTestTab* tab =
-      [[TabStripControllerTestTab alloc] initWithWebState:testWebState.get()];
-
-  LegacyTabHelper::CreateForWebStateForTesting(testWebState.get(),
-                                               static_cast<Tab*>(tab));
   _webStateList->InsertWebState(0, std::move(testWebState),
                                 WebStateList::INSERT_NO_FLAGS,
                                 WebStateOpener());
-
-  return tab;
 }
 
 - (BOOL)isEmpty {
@@ -143,8 +107,8 @@
     tab_model_.browserState = chrome_browser_state_.get();
 
     // Populate the TabModel.
-    tab1_ = [tab_model_ addTabForTestingWithTitle:@"Tab Title 1"];
-    tab2_ = [tab_model_ addTabForTestingWithTitle:@"Tab Title 2"];
+    [tab_model_ addWebStateForTestingWithTitle:@"Tab Title 1"];
+    [tab_model_ addWebStateForTestingWithTitle:@"Tab Title 2"];
 
     controller_ = [[TabStripController alloc]
         initWithTabModel:static_cast<TabModel*>(tab_model_)
@@ -169,8 +133,6 @@
   TabStripControllerTestTabModel* tab_model_;
   TabStripController* controller_;
   UIWindow* window_;
-  TabStripControllerTestTab* tab1_;
-  TabStripControllerTestTab* tab2_;
 };
 
 TEST_F(TabStripControllerTest, LoadAndDisplay) {
diff --git a/ios/chrome/browser/ui/tabs/tab_view.h b/ios/chrome/browser/ui/tabs/tab_view.h
index 242fac61..0726335 100644
--- a/ios/chrome/browser/ui/tabs/tab_view.h
+++ b/ios/chrome/browser/ui/tabs/tab_view.h
@@ -7,7 +7,6 @@
 
 #import <UIKit/UIKit.h>
 
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/ui/tabs/tab_view_delegate.h"
 
 @class GTMFadeTruncatingLabel;
diff --git a/ios/chrome/browser/ui/toolbar/BUILD.gn b/ios/chrome/browser/ui/toolbar/BUILD.gn
index 4ebd214..d6214433 100644
--- a/ios/chrome/browser/ui/toolbar/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/BUILD.gn
@@ -82,6 +82,7 @@
     "toolbar_progress_bar.mm",
   ]
   deps = [
+    "resources:tab_toolbar_shadow_color",
     "//base",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/ui/activity_services/requirements",
diff --git a/ios/chrome/browser/ui/toolbar/buttons/BUILD.gn b/ios/chrome/browser/ui/toolbar/buttons/BUILD.gn
index 7a94671..b0ab66e 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/buttons/BUILD.gn
@@ -25,6 +25,9 @@
     "toolbar_type.h",
   ]
   deps = [
+    "resources:tab_toolbar_button_color",
+    "resources:tab_toolbar_button_color_highlighted",
+    "resources:tab_toolbar_button_halo_color",
     "resources:toolbar_back",
     "resources:toolbar_bookmark",
     "resources:toolbar_bookmark_active",
@@ -47,6 +50,7 @@
     "//ios/chrome/browser/ui/toolbar/public:feature_flags",
     "//ios/chrome/browser/ui/util",
     "//ios/chrome/browser/web_state_list",
+    "//ios/chrome/common/colors",
     "//ios/chrome/common/ui_util",
     "//ios/public/provider/chrome/browser",
     "//ios/public/provider/chrome/browser/images",
diff --git a/ios/chrome/browser/ui/toolbar/buttons/resources/BUILD.gn b/ios/chrome/browser/ui/toolbar/buttons/resources/BUILD.gn
index 6e2d4f8b..f4afb010 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/toolbar/buttons/resources/BUILD.gn
@@ -4,6 +4,24 @@
 
 import("//build/config/ios/asset_catalog.gni")
 
+colorset("tab_toolbar_button_color") {
+  sources = [
+    "tab_toolbar_button_color.colorset/Contents.json",
+  ]
+}
+
+colorset("tab_toolbar_button_color_highlighted") {
+  sources = [
+    "tab_toolbar_button_color_highlighted.colorset/Contents.json",
+  ]
+}
+
+colorset("tab_toolbar_button_halo_color") {
+  sources = [
+    "tab_toolbar_button_halo_color.colorset/Contents.json",
+  ]
+}
+
 imageset("toolbar_new_tab_page") {
   sources = [
     "toolbar_new_tab_page.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_color.colorset/Contents.json b/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_color.colorset/Contents.json
new file mode 100644
index 0000000..4b476100
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_color.colorset/Contents.json
@@ -0,0 +1,38 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "colors" : [
+    {
+      "idiom" : "universal",
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0x80",
+          "alpha" : "1.000",
+          "blue" : "0x8A",
+          "green" : "0x86"
+        }
+      }
+    },
+    {
+      "idiom" : "universal",
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0xE8",
+          "alpha" : "1.000",
+          "blue" : "0xED",
+          "green" : "0xEA"
+        }
+      }
+    }
+  ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_color_highlighted.colorset/Contents.json b/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_color_highlighted.colorset/Contents.json
new file mode 100644
index 0000000..7d71006
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_color_highlighted.colorset/Contents.json
@@ -0,0 +1,38 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "colors" : [
+    {
+      "idiom" : "universal",
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0xE5",
+          "alpha" : "1.000",
+          "blue" : "0xE8",
+          "green" : "0xE7"
+        }
+      }
+    },
+    {
+      "idiom" : "universal",
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0x7D",
+          "alpha" : "1.000",
+          "blue" : "0x82",
+          "green" : "0x7F"
+        }
+      }
+    }
+  ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_halo_color.colorset/Contents.json b/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_halo_color.colorset/Contents.json
new file mode 100644
index 0000000..59092f3
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/buttons/resources/tab_toolbar_button_halo_color.colorset/Contents.json
@@ -0,0 +1,38 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "colors" : [
+    {
+      "idiom" : "universal",
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0xE8",
+          "alpha" : "1.000",
+          "blue" : "0xED",
+          "green" : "0xEA"
+        }
+      }
+    },
+    {
+      "idiom" : "universal",
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0x5F",
+          "alpha" : "1.000",
+          "blue" : "0x67",
+          "green" : "0x63"
+        }
+      }
+    }
+  ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button.mm
index 7252f7f7..04ebde1f 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_button.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_button.mm
@@ -128,7 +128,9 @@
   spotlightView.userInteractionEnabled = NO;
   spotlightView.layer.cornerRadius = kSpotlightCornerRadius;
   spotlightView.backgroundColor = self.configuration.buttonsSpotlightColor;
-  [self addSubview:spotlightView];
+  // Make sure that the spotlightView is below the image to avoid changing the
+  // color of the image.
+  [self insertSubview:spotlightView belowSubview:self.imageView];
   AddSameCenterConstraints(self, spotlightView);
   [spotlightView.widthAnchor constraintEqualToConstant:kSpotlightSize].active =
       YES;
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
index 44a42ab..6a0478f 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_configuration.mm
@@ -9,6 +9,7 @@
 #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h"
 #include "ios/chrome/browser/ui/util/ui_util.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
+#import "ios/chrome/common/colors/semantic_color_names.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -29,7 +30,7 @@
 - (UIColor*)NTPBackgroundColor {
   switch (self.style) {
     case NORMAL:
-      return ntp_home::kNTPBackgroundColor();
+      return [UIColor colorNamed:kBackgroundColor];
     case INCOGNITO:
       return [UIColor colorWithWhite:kNTPBackgroundColorBrightnessIncognito
                                alpha:1.0];
@@ -39,7 +40,7 @@
 - (UIColor*)backgroundColor {
   switch (self.style) {
     case NORMAL:
-      return [UIColor colorWithWhite:kBlurBackgroundGrayscaleComponent alpha:1];
+      return [UIColor colorNamed:kBackgroundColor];
     case INCOGNITO:
       return UIColorFromRGB(kIncognitoToolbarBackgroundColor);
     }
@@ -48,7 +49,7 @@
 - (UIColor*)buttonsTintColor {
   switch (self.style) {
     case NORMAL:
-      return [UIColor colorWithWhite:0 alpha:kToolbarButtonTintColorAlpha];
+      return [UIColor colorNamed:@"tab_toolbar_button_color"];
     case INCOGNITO:
       return [UIColor whiteColor];
   }
@@ -57,8 +58,7 @@
 - (UIColor*)buttonsTintColorHighlighted {
   switch (self.style) {
     case NORMAL:
-      return [UIColor colorWithWhite:0
-                               alpha:kToolbarButtonTintColorAlphaHighlighted];
+      return [UIColor colorNamed:@"tab_toolbar_button_color_highlighted"];
       break;
     case INCOGNITO:
       return [UIColor
@@ -71,7 +71,7 @@
 - (UIColor*)buttonsSpotlightColor {
   switch (self.style) {
     case NORMAL:
-      return [UIColor colorWithWhite:0 alpha:kToolbarSpotlightAlpha];
+      return [UIColor colorNamed:@"tab_toolbar_button_halo_color"];
       break;
     case INCOGNITO:
       return [UIColor colorWithWhite:1 alpha:kToolbarSpotlightAlpha];
@@ -82,7 +82,7 @@
 - (UIColor*)dimmedButtonsSpotlightColor {
   switch (self.style) {
     case NORMAL:
-      return [UIColor colorWithWhite:0 alpha:kDimmedToolbarSpotlightAlpha];
+      return [UIColor colorNamed:@"tab_toolbar_button_halo_color"];
       break;
     case INCOGNITO:
       return [UIColor colorWithWhite:1 alpha:kDimmedToolbarSpotlightAlpha];
diff --git a/ios/chrome/browser/ui/toolbar/buttons/toolbar_search_button.mm b/ios/chrome/browser/ui/toolbar/buttons/toolbar_search_button.mm
index dc8c1a95..19ee6b62 100644
--- a/ios/chrome/browser/ui/toolbar/buttons/toolbar_search_button.mm
+++ b/ios/chrome/browser/ui/toolbar/buttons/toolbar_search_button.mm
@@ -28,11 +28,6 @@
   [super setDimmed:dimmed];
 
   self.spotlightView.hidden = dimmed && !self.spotlighted;
-  if (!dimmed) {
-    // Override the color of the non-dimmed button.
-    self.spotlightView.backgroundColor =
-        [self.configuration locationBarBackgroundColorWithVisibility:1];
-  }
 }
 
 - (void)setSpotlighted:(BOOL)spotlighted {
@@ -47,8 +42,7 @@
   spotlightView.translatesAutoresizingMaskIntoConstraints = NO;
   spotlightView.userInteractionEnabled = NO;
   spotlightView.layer.cornerRadius = kSpotlightHeight / 2;
-  spotlightView.backgroundColor =
-      [self.configuration locationBarBackgroundColorWithVisibility:1];
+  spotlightView.backgroundColor = self.configuration.buttonsSpotlightColor;
   // Make sure that the spotlightView is below the image to avoid changing the
   // color of the image.
   [self insertSubview:spotlightView belowSubview:self.imageView];
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm
index b378dd85..290f0e41 100644
--- a/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_view.mm
@@ -279,7 +279,7 @@
 - (void)setUpSeparator {
   self.separator = [[UIView alloc] init];
   self.separator.backgroundColor =
-      [UIColor colorWithWhite:0 alpha:kToolbarSeparatorAlpha];
+      [UIColor colorNamed:@"tab_toolbar_shadow_color"];
   self.separator.translatesAutoresizingMaskIntoConstraints = NO;
   [self addSubview:self.separator];
 }
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm
index db41bfc..5af9b18 100644
--- a/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm
+++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.mm
@@ -68,7 +68,8 @@
 
 - (void)resetAfterSideSwipeSnapshot {
   [super resetAfterSideSwipeSnapshot];
-  self.view.backgroundColor = nil;
+  self.view.backgroundColor =
+      self.buttonFactory.toolbarConfiguration.backgroundColor;
   self.view.locationBarContainer.hidden = NO;
 }
 
diff --git a/ios/chrome/browser/ui/toolbar/public/toolbar_constants.h b/ios/chrome/browser/ui/toolbar/public/toolbar_constants.h
index ee608bd..9c3da3d 100644
--- a/ios/chrome/browser/ui/toolbar/public/toolbar_constants.h
+++ b/ios/chrome/browser/ui/toolbar/public/toolbar_constants.h
@@ -31,7 +31,6 @@
 extern const CGFloat kProgressBarHeight;
 
 // Separator.
-extern const CGFloat kToolbarSeparatorAlpha;
 // Height of the separator. Should be aligned to upper pixel.
 extern const CGFloat kToolbarSeparatorHeight;
 
diff --git a/ios/chrome/browser/ui/toolbar/public/toolbar_constants.mm b/ios/chrome/browser/ui/toolbar/public/toolbar_constants.mm
index ed1fe51..31f76981 100644
--- a/ios/chrome/browser/ui/toolbar/public/toolbar_constants.mm
+++ b/ios/chrome/browser/ui/toolbar/public/toolbar_constants.mm
@@ -19,7 +19,6 @@
 
 const CGFloat kProgressBarHeight = 2.0f;
 
-const CGFloat kToolbarSeparatorAlpha = 0.33f;
 const CGFloat kToolbarSeparatorHeight = 0.1f;
 
 const CGFloat kAdaptiveToolbarButtonHeight = 44.0f;
diff --git a/ios/chrome/browser/ui/toolbar/resources/BUILD.gn b/ios/chrome/browser/ui/toolbar/resources/BUILD.gn
new file mode 100644
index 0000000..f614247f
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/resources/BUILD.gn
@@ -0,0 +1,11 @@
+# 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.
+
+import("//build/config/ios/asset_catalog.gni")
+
+colorset("tab_toolbar_shadow_color") {
+  sources = [
+    "tab_toolbar_shadow_color.colorset/Contents.json",
+  ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/resources/tab_toolbar_shadow_color.colorset/Contents.json b/ios/chrome/browser/ui/toolbar/resources/tab_toolbar_shadow_color.colorset/Contents.json
new file mode 100644
index 0000000..8752f64
--- /dev/null
+++ b/ios/chrome/browser/ui/toolbar/resources/tab_toolbar_shadow_color.colorset/Contents.json
@@ -0,0 +1,38 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "colors" : [
+    {
+      "idiom" : "universal",
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0x00",
+          "alpha" : "0.200",
+          "blue" : "0x00",
+          "green" : "0x00"
+        }
+      }
+    },
+    {
+      "idiom" : "universal",
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0x00",
+          "alpha" : "0.900",
+          "blue" : "0x00",
+          "green" : "0x00"
+        }
+      }
+    }
+  ]
+}
diff --git a/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm b/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm
index 061b9fca..329a972 100644
--- a/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm
+++ b/ios/chrome/browser/ui/toolbar/secondary_toolbar_view.mm
@@ -126,7 +126,7 @@
 
   self.separator = [[UIView alloc] init];
   self.separator.backgroundColor =
-      [UIColor colorWithWhite:0 alpha:kToolbarSeparatorAlpha];
+      [UIColor colorNamed:@"tab_toolbar_shadow_color"];
   self.separator.translatesAutoresizingMaskIntoConstraints = NO;
   [self addSubview:self.separator];
 
diff --git a/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc b/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
index bc5f666e..bf6963e 100644
--- a/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
+++ b/ios/chrome/browser/ui/webui/ntp_tiles_internals_ui.cc
@@ -75,7 +75,6 @@
     case ntp_tiles::TileSource::CUSTOM_LINKS:
     case ntp_tiles::TileSource::WHITELIST:
     case ntp_tiles::TileSource::EXPLORE:
-    case ntp_tiles::TileSource::SEARCH_PAGE:
       return false;
   }
   NOTREACHED();
diff --git a/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.h b/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.h
index b6fd065..59f091ee 100644
--- a/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.h
+++ b/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.h
@@ -20,7 +20,7 @@
   ~PasswordManagerInternalsUIIOS() override;
 
   // LogReceiver implementation.
-  void LogSavePasswordProgress(const std::string& text) override;
+  void LogEntry(const base::Value& entry) override;
 
   // web::WebStateObserver implementation.
   void PageLoaded(
diff --git a/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.mm b/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.mm
index 3d2eebc..26da3af 100644
--- a/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.mm
+++ b/ios/chrome/browser/ui/webui/password_manager_internals_ui_ios.mm
@@ -59,16 +59,10 @@
   web_ui()->GetWebState()->RemoveObserver(this);
 }
 
-void PasswordManagerInternalsUIIOS::LogSavePasswordProgress(
-    const std::string& text) {
-  if (!registered_with_logging_service_ || text.empty())
+void PasswordManagerInternalsUIIOS::LogEntry(const base::Value& entry) {
+  if (!registered_with_logging_service_ || entry.is_none())
     return;
-  std::string no_quotes(text);
-  std::replace(no_quotes.begin(), no_quotes.end(), '"', ' ');
-  base::Value text_string_value(net::EscapeForHTML(no_quotes));
-
-  std::vector<const base::Value*> args{&text_string_value};
-  web_ui()->CallJavascriptFunction("addLog", args);
+  web_ui()->CallJavascriptFunction("addRawLog", {&entry});
 }
 
 void PasswordManagerInternalsUIIOS::PageLoaded(
@@ -92,8 +86,9 @@
   if (service) {
     registered_with_logging_service_ = true;
 
-    std::string past_logs(service->RegisterReceiver(this));
-    LogSavePasswordProgress(past_logs);
+    const auto& past_logs = service->RegisterReceiver(this);
+    for (const auto& entry : past_logs)
+      LogEntry(entry);
   }
 }
 
diff --git a/ios/chrome/browser/url_loading/app_url_loading_service.h b/ios/chrome/browser/url_loading/app_url_loading_service.h
index 8d3b152..7ed27d8 100644
--- a/ios/chrome/browser/url_loading/app_url_loading_service.h
+++ b/ios/chrome/browser/url_loading/app_url_loading_service.h
@@ -14,7 +14,6 @@
 
 struct UrlLoadParams;
 
-@class Tab;
 @class TabModel;
 
 namespace ios {
@@ -38,7 +37,7 @@
 // If the current tab in |targetMode| is a NTP, it can be reused to open URL.
 // |completion| is executed after the tab is opened. After Tab is open the
 // virtual URL is set to the pending navigation item.
-- (Tab*)openSelectedTabInMode:(ApplicationMode)targetMode
+- (void)openSelectedTabInMode:(ApplicationMode)targetMode
             withUrlLoadParams:(const UrlLoadParams&)urlLoadParams
                    completion:(ProceduralBlock)completion;
 
diff --git a/ios/chrome/browser/url_loading/url_loading_service_unittest.mm b/ios/chrome/browser/url_loading/url_loading_service_unittest.mm
index 6ed9f5a..ff59fe5 100644
--- a/ios/chrome/browser/url_loading/url_loading_service_unittest.mm
+++ b/ios/chrome/browser/url_loading/url_loading_service_unittest.mm
@@ -12,7 +12,6 @@
 #include "base/strings/sys_string_conversions.h"
 #import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/main/test_browser.h"
-#import "ios/chrome/browser/tabs/tab.h"
 #import "ios/chrome/browser/tabs/tab_helper_util.h"
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/url_loading/app_url_loading_service.h"
diff --git a/ios/chrome/browser/web/tab_order_egtest.mm b/ios/chrome/browser/web/tab_order_egtest.mm
index 767821e..0c9f3eb 100644
--- a/ios/chrome/browser/web/tab_order_egtest.mm
+++ b/ios/chrome/browser/web/tab_order_egtest.mm
@@ -18,8 +18,6 @@
 #error "This file requires ARC support."
 #endif
 
-@class Tab;
-
 using chrome_test_util::GetCurrentWebState;
 using chrome_test_util::OpenLinkInNewTabButton;
 using web::WebViewInWebState;
diff --git a/ios/chrome/common/colors/resources/BUILD.gn b/ios/chrome/common/colors/resources/BUILD.gn
index bb15786f..bf1f242 100644
--- a/ios/chrome/common/colors/resources/BUILD.gn
+++ b/ios/chrome/common/colors/resources/BUILD.gn
@@ -6,13 +6,21 @@
 
 group("resources") {
   deps = [
+    ":background_color",
     ":destructive_tint_color",
     ":disabled_tint_color",
+    ":scrim_background_color",
     ":solid_button_text_color",
     ":tint_color",
   ]
 }
 
+colorset("background_color") {
+  sources = [
+    "background_color.colorset/Contents.json",
+  ]
+}
+
 colorset("destructive_tint_color") {
   sources = [
     "destructive_tint_color.colorset/Contents.json",
@@ -25,6 +33,12 @@
   ]
 }
 
+colorset("scrim_background_color") {
+  sources = [
+    "scrim_background_color.colorset/Contents.json",
+  ]
+}
+
 colorset("solid_button_text_color") {
   sources = [
     "solid_button_text_color.colorset/Contents.json",
diff --git a/ios/chrome/common/colors/resources/background_color.colorset/Contents.json b/ios/chrome/common/colors/resources/background_color.colorset/Contents.json
new file mode 100644
index 0000000..4610f73e6
--- /dev/null
+++ b/ios/chrome/common/colors/resources/background_color.colorset/Contents.json
@@ -0,0 +1,38 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "colors" : [
+    {
+      "idiom" : "universal",
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "1.000",
+          "alpha" : "1.000",
+          "blue" : "1.000",
+          "green" : "1.000"
+        }
+      }
+    },
+    {
+      "idiom" : "universal",
+      "appearances" : [
+        {
+          "appearance" : "luminosity",
+          "value" : "dark"
+        }
+      ],
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0.208",
+          "alpha" : "1.000",
+          "blue" : "0.227",
+          "green" : "0.216"
+        }
+      }
+    }
+  ]
+}
\ No newline at end of file
diff --git a/ios/chrome/common/colors/resources/scrim_background_color.colorset/Contents.json b/ios/chrome/common/colors/resources/scrim_background_color.colorset/Contents.json
new file mode 100644
index 0000000..3f60141
--- /dev/null
+++ b/ios/chrome/common/colors/resources/scrim_background_color.colorset/Contents.json
@@ -0,0 +1,20 @@
+{
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  },
+  "colors" : [
+    {
+      "idiom" : "universal",
+      "color" : {
+        "color-space" : "display-p3",
+        "components" : {
+          "red" : "0x00",
+          "alpha" : "0.400",
+          "blue" : "0x00",
+          "green" : "0x00"
+        }
+      }
+    }
+  ]
+}
diff --git a/ios/chrome/common/colors/semantic_color_names.h b/ios/chrome/common/colors/semantic_color_names.h
index bb36ec4..52dccf6 100644
--- a/ios/chrome/common/colors/semantic_color_names.h
+++ b/ios/chrome/common/colors/semantic_color_names.h
@@ -7,8 +7,10 @@
 
 #import <UIKit/UIKit.h>
 
+extern NSString* const kBackgroundColor;
 extern NSString* const kDestructiveTintColor;
 extern NSString* const kDisabledTintColor;
+extern NSString* const kScrimBackgroundColor;
 extern NSString* const kSolidButtonTextColor;
 extern NSString* const kTintColor;
 
diff --git a/ios/chrome/common/colors/semantic_color_names.mm b/ios/chrome/common/colors/semantic_color_names.mm
index 57d6a5a..61320cc 100644
--- a/ios/chrome/common/colors/semantic_color_names.mm
+++ b/ios/chrome/common/colors/semantic_color_names.mm
@@ -8,7 +8,9 @@
 #error "This file requires ARC support."
 #endif
 
+NSString* const kBackgroundColor = @"background_color";
 NSString* const kDestructiveTintColor = @"destructive_tint_color";
 NSString* const kDisabledTintColor = @"disabled_tint_color";
+NSString* const kScrimBackgroundColor = @"scrim_background_color";
 NSString* const kSolidButtonTextColor = @"solid_button_text_color";
 NSString* const kTintColor = @"tint_color";
diff --git a/ios/chrome/test/app/tab_test_util.mm b/ios/chrome/test/app/tab_test_util.mm
index ab39ede1..fa1558c 100644
--- a/ios/chrome/test/app/tab_test_util.mm
+++ b/ios/chrome/test/app/tab_test_util.mm
@@ -111,8 +111,12 @@
 }
 
 void CloseCurrentTab() {
-  TabModel* tab_model = GetCurrentTabModel();
-  [tab_model closeTab:tab_model.currentTab];
+  WebStateList* web_state_list = GetCurrentWebStateList();
+  if (!web_state_list ||
+      web_state_list->active_index() == WebStateList::kInvalidIndex)
+    return;
+  web_state_list->CloseWebStateAt(web_state_list->active_index(),
+                                  WebStateList::CLOSE_USER_ACTION);
 }
 
 void CloseTabAtIndex(NSUInteger index) {
@@ -137,8 +141,9 @@
 
 void SelectTabAtIndexInCurrentMode(NSUInteger index) {
   @autoreleasepool {  // Make sure that all internals are deallocated.
-    TabModel* tab_model = GetCurrentTabModel();
-    [tab_model setCurrentTab:[tab_model tabAtIndex:index]];
+
+    WebStateList* web_state_list = GetCurrentWebStateList();
+    web_state_list->ActivateWebStateAt(static_cast<int>(index));
   }
 }
 
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.h b/ios/public/provider/chrome/browser/chrome_browser_provider.h
index 75b1f32..dbef8f3 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.h
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.h
@@ -38,7 +38,6 @@
 
 @protocol LogoVendor;
 @protocol TextFieldStyling;
-@class Tab;
 @class TabModel;
 @class UITextField;
 @class UIView;
@@ -117,10 +116,8 @@
   // |main_tab_model| is created.
   virtual void InitializeCastService(TabModel* main_tab_model) const;
 
-  // Attaches any embedder-specific tab helpers to the given |web_state|.  The
-  // owning |tab| is included for helpers that need access to information that
-  // is not yet available through web::WebState.
-  virtual void AttachTabHelpers(web::WebState* web_state, Tab* tab) const;
+  // Attaches any embedder-specific tab helpers to the given |web_state|.
+  virtual void AttachTabHelpers(web::WebState* web_state) const;
 
   // Returns an instance of the voice search provider, if one exists.
   virtual VoiceSearchProvider* GetVoiceSearchProvider() const;
diff --git a/ios/public/provider/chrome/browser/chrome_browser_provider.mm b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
index b03270f..1cf0fd5 100644
--- a/ios/public/provider/chrome/browser/chrome_browser_provider.mm
+++ b/ios/public/provider/chrome/browser/chrome_browser_provider.mm
@@ -76,8 +76,7 @@
 void ChromeBrowserProvider::InitializeCastService(
     TabModel* main_tab_model) const {}
 
-void ChromeBrowserProvider::AttachTabHelpers(web::WebState* web_state,
-                                             Tab* tab) const {}
+void ChromeBrowserProvider::AttachTabHelpers(web::WebState* web_state) const {}
 
 VoiceSearchProvider* ChromeBrowserProvider::GetVoiceSearchProvider() const {
   return nullptr;
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity.mm b/ios/public/provider/chrome/browser/signin/chrome_identity.mm
index 90284ad..f4d6bfa3 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity.mm
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity.mm
@@ -32,4 +32,12 @@
   return nil;
 }
 
+- (NSString*)description {
+  return [NSString stringWithFormat:@"<%@: %p, GaiaID: \"%@\", name: \"%@\", "
+                                    @"email: \"%@\", hosted domain: \"%@\">",
+                                    self.class.description, self, self.gaiaID,
+                                    self.userFullName, self.userEmail,
+                                    self.hostedDomain];
+}
+
 @end
diff --git a/ios/web/navigation/wk_based_navigation_manager_impl.mm b/ios/web/navigation/wk_based_navigation_manager_impl.mm
index 1d7eb3e..e413044 100644
--- a/ios/web/navigation/wk_based_navigation_manager_impl.mm
+++ b/ios/web/navigation/wk_based_navigation_manager_impl.mm
@@ -9,6 +9,7 @@
 
 #include "base/bind.h"
 #include "base/callback.h"
+#include "base/ios/ios_util.h"
 #include "base/logging.h"
 #include "base/mac/bundle_locations.h"
 #include "base/memory/ptr_util.h"
@@ -288,10 +289,13 @@
   // If |currentItem| is not nil, it is the last committed item in the
   // WKWebView.
   if (proxy.backForwardList && !proxy.backForwardList.currentItem) {
-    // WKWebView's URL should be about:blank for empty window open item.
-    // TODO(crbug.com/885249): Use GURL::IsAboutBlank() instead.
-    DCHECK(base::StartsWith(net::GURLWithNSURL(proxy.URL).spec(),
-                            url::kAboutBlankURL, base::CompareCase::SENSITIVE));
+    if (!base::ios::IsRunningOnIOS13OrLater()) {
+      // Prior to iOS 13 WKWebView's URL should be about:blank for empty window
+      // open item. TODO(crbug.com/885249): Use GURL::IsAboutBlank() instead.
+      DCHECK(base::StartsWith(net::GURLWithNSURL(proxy.URL).spec(),
+                              url::kAboutBlankURL,
+                              base::CompareCase::SENSITIVE));
+    }
     // There should be no back-forward history for empty window open item.
     DCHECK_EQ(0UL, proxy.backForwardList.backList.count);
     DCHECK_EQ(0UL, proxy.backForwardList.forwardList.count);
diff --git a/ios/web/shell/test/page_state_egtest.mm b/ios/web/shell/test/page_state_egtest.mm
index 001725a..86b3981c 100644
--- a/ios/web/shell/test/page_state_egtest.mm
+++ b/ios/web/shell/test/page_state_egtest.mm
@@ -84,6 +84,12 @@
 // Tests that page scroll position of a page is restored upon returning to the
 // page via the back/forward buttons.
 - (void)testScrollPositionRestoring {
+  // grey_scrollInDirection scrolls incorrect distance on iOS 13.
+  // TODO(crbug.com/983144): Enable this test on iOS 13.
+  if (@available(iOS 13, *)) {
+    return;
+  }
+
   // Scroll the first page and verify the offset.
   ScrollLongPageToTop(_server.GetURL(kLongPage1));
   [[EarlGrey selectElementWithMatcher:web::WebViewScrollView()]
diff --git a/media/audio/audio_output_device_unittest.cc b/media/audio/audio_output_device_unittest.cc
index a5f8700..90a51bd 100644
--- a/media/audio/audio_output_device_unittest.cc
+++ b/media/audio/audio_output_device_unittest.cc
@@ -110,7 +110,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment task_env_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   AudioParameters default_audio_parameters_;
   StrictMock<MockRenderCallback> callback_;
   MockAudioOutputIPC* audio_output_ipc_;  // owned by audio_device_
diff --git a/media/audio/audio_thread_hang_monitor_unittest.cc b/media/audio/audio_thread_hang_monitor_unittest.cc
index 364edb7..ac5b3de6 100644
--- a/media/audio/audio_thread_hang_monitor_unittest.cc
+++ b/media/audio/audio_thread_hang_monitor_unittest.cc
@@ -38,7 +38,7 @@
 class AudioThreadHangMonitorTest : public Test {
  public:
   AudioThreadHangMonitorTest()
-      : task_env_(base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+      : task_env_(base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         histograms_(),
         audio_thread_("Audio thread"),
         hang_monitor_({nullptr, base::OnTaskRunnerDeleter(nullptr)}) {
diff --git a/media/gpu/linux/platform_video_frame_pool_unittest.cc b/media/gpu/linux/platform_video_frame_pool_unittest.cc
index e9a46d7..aa223ff 100644
--- a/media/gpu/linux/platform_video_frame_pool_unittest.cc
+++ b/media/gpu/linux/platform_video_frame_pool_unittest.cc
@@ -55,7 +55,7 @@
 
   PlatformVideoFramePoolTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {
     pool_.reset(new PlatformVideoFramePool(
         base::BindRepeating(&CreateDmabufVideoFrame), &test_clock_));
     pool_->set_parent_task_runner(base::ThreadTaskRunnerHandle::Get());
diff --git a/media/mojo/services/cdm_service_unittest.cc b/media/mojo/services/cdm_service_unittest.cc
index 158b08fc..510e3ca 100644
--- a/media/mojo/services/cdm_service_unittest.cc
+++ b/media/mojo/services/cdm_service_unittest.cc
@@ -207,7 +207,7 @@
 }
 
 // Same as DestroyCdmFactory test, but do not disable delayed service release.
-// TODO(xhwang): Use ScopedTaskEnvironment::MainThreadType::MOCK_TIME and
+// TODO(xhwang): Use  ScopedTaskEnvironment::TimeSource::MOCK_TIME and
 // ScopedTaskEnvironment::FastForwardBy() so we don't have to really wait for
 // the delay in the test. But currently FastForwardBy() doesn't support delayed
 // task yet.
diff --git a/mojo/public/cpp/base/message_loop_type.typemap b/mojo/public/cpp/base/message_loop_type.typemap
new file mode 100644
index 0000000..44d9fa57
--- /dev/null
+++ b/mojo/public/cpp/base/message_loop_type.typemap
@@ -0,0 +1,15 @@
+# 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.
+
+mojom = "//mojo/public/mojom/base/message_loop_type.mojom"
+public_headers = [ "//base/message_loop/message_loop.h" ]
+traits_headers = [ "//mojo/public/cpp/base/message_loop_type_mojom_traits.h" ]
+sources = [
+  "//mojo/public/cpp/base/message_loop_type_mojom_traits.cc",
+  "//mojo/public/cpp/base/message_loop_type_mojom_traits.h",
+]
+public_deps = [
+  "//base",
+]
+type_mappings = [ "mojo_base.mojom.MessageLoopType=base::MessageLoop::Type" ]
diff --git a/mojo/public/cpp/base/message_loop_type_mojom_traits.cc b/mojo/public/cpp/base/message_loop_type_mojom_traits.cc
new file mode 100644
index 0000000..2daaa609
--- /dev/null
+++ b/mojo/public/cpp/base/message_loop_type_mojom_traits.cc
@@ -0,0 +1,76 @@
+// 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 "mojo/public/cpp/base/message_loop_type_mojom_traits.h"
+#include "build/build_config.h"
+
+namespace mojo {
+
+// static
+mojo_base::mojom::MessageLoopType
+EnumTraits<mojo_base::mojom::MessageLoopType, base::MessageLoop::Type>::ToMojom(
+    base::MessageLoop::Type input) {
+  switch (input) {
+    case base::MessageLoop::TYPE_DEFAULT:
+      return mojo_base::mojom::MessageLoopType::kDefault;
+    case base::MessageLoop::TYPE_UI:
+      return mojo_base::mojom::MessageLoopType::kUi;
+    case base::MessageLoop::TYPE_CUSTOM:
+      return mojo_base::mojom::MessageLoopType::kCustom;
+    case base::MessageLoop::TYPE_IO:
+      return mojo_base::mojom::MessageLoopType::kIo;
+#if defined(OS_ANDROID)
+    case base::MessageLoop::TYPE_JAVA:
+      return mojo_base::mojom::MessageLoopType::kJava;
+#endif
+#if defined(OS_MACOSX)
+    case base::MessageLoop::Type::NS_RUNLOOP:
+      return mojo_base::mojom::MessageLoopType::kNsRunloop;
+#endif
+#if defined(OS_WIN)
+    case base::MessageLoop::Type::UI_WITH_WM_QUIT_SUPPORT:
+      return mojo_base::mojom::MessageLoopType::kUiWithWmQuitSupport;
+#endif
+  }
+  NOTREACHED();
+  return mojo_base::mojom::MessageLoopType::kDefault;
+}
+
+// static
+bool EnumTraits<mojo_base::mojom::MessageLoopType, base::MessageLoop::Type>::
+    FromMojom(mojo_base::mojom::MessageLoopType input,
+              base::MessageLoop::Type* output) {
+  switch (input) {
+    case mojo_base::mojom::MessageLoopType::kDefault:
+      *output = base::MessageLoop::TYPE_DEFAULT;
+      return true;
+    case mojo_base::mojom::MessageLoopType::kUi:
+      *output = base::MessageLoop::TYPE_UI;
+      return true;
+    case mojo_base::mojom::MessageLoopType::kCustom:
+      *output = base::MessageLoop::TYPE_CUSTOM;
+      return true;
+    case mojo_base::mojom::MessageLoopType::kIo:
+      *output = base::MessageLoop::TYPE_IO;
+      return true;
+#if defined(OS_ANDROID)
+    case mojo_base::mojom::MessageLoopType::kJava:
+      *output = base::MessageLoop::TYPE_JAVA;
+      return true;
+#endif
+#if defined(OS_MACOSX)
+    case mojo_base::mojom::MessageLoopType::kNsRunloop:
+      *output = base::MessageLoop::Type::NS_RUNLOOP;
+      return true;
+#endif
+#if defined(OS_WIN)
+    case mojo_base::mojom::MessageLoopType::kUiWithWmQuitSupport:
+      *output = base::MessageLoop::Type::UI_WITH_WM_QUIT_SUPPORT;
+      return true;
+#endif
+  }
+  return false;
+}
+
+}  // namespace mojo
diff --git a/mojo/public/cpp/base/message_loop_type_mojom_traits.h b/mojo/public/cpp/base/message_loop_type_mojom_traits.h
new file mode 100644
index 0000000..44860d0
--- /dev/null
+++ b/mojo/public/cpp/base/message_loop_type_mojom_traits.h
@@ -0,0 +1,26 @@
+// 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 MOJO_PUBLIC_CPP_BASE_MESSAGE_LOOP_TYPE_MOJOM_TRAITS_H_
+#define MOJO_PUBLIC_CPP_BASE_MESSAGE_LOOP_TYPE_MOJOM_TRAITS_H_
+
+#include "base/component_export.h"
+#include "base/message_loop/message_loop.h"
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "mojo/public/mojom/base/message_loop_type.mojom.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(MOJO_BASE_MOJOM)
+    EnumTraits<mojo_base::mojom::MessageLoopType, base::MessageLoop::Type> {
+  static mojo_base::mojom::MessageLoopType ToMojom(
+      base::MessageLoop::Type input);
+  static bool FromMojom(mojo_base::mojom::MessageLoopType input,
+                        base::MessageLoop::Type* output);
+};
+
+}  // namespace mojo
+
+#endif  // MOJO_PUBLIC_CPP_BASE_MESSAGE_LOOP_TYPE_MOJOM_TRAITS_H_
diff --git a/mojo/public/cpp/base/typemaps.gni b/mojo/public/cpp/base/typemaps.gni
index 49a7cd1..8d80625 100644
--- a/mojo/public/cpp/base/typemaps.gni
+++ b/mojo/public/cpp/base/typemaps.gni
@@ -14,6 +14,7 @@
   "//mojo/public/cpp/base/read_only_buffer.typemap",
   "//mojo/public/cpp/base/memory_allocator_dump_cross_process_uid.typemap",
   "//mojo/public/cpp/base/memory_pressure_level.typemap",
+  "//mojo/public/cpp/base/message_loop_type.typemap",
   "//mojo/public/cpp/base/process_id.typemap",
   "//mojo/public/cpp/base/ref_counted_memory.typemap",
   "//mojo/public/cpp/base/shared_memory.typemap",
diff --git a/mojo/public/mojom/base/BUILD.gn b/mojo/public/mojom/base/BUILD.gn
index e98c6dfb..c1a5d9e 100644
--- a/mojo/public/mojom/base/BUILD.gn
+++ b/mojo/public/mojom/base/BUILD.gn
@@ -16,6 +16,7 @@
     "generic_pending_receiver.mojom",
     "memory_allocator_dump_cross_process_uid.mojom",
     "memory_pressure_level.mojom",
+    "message_loop_type.mojom",
     "process_id.mojom",
     "read_only_buffer.mojom",
     "ref_counted_memory.mojom",
diff --git a/mojo/public/mojom/base/message_loop_type.mojom b/mojo/public/mojom/base/message_loop_type.mojom
new file mode 100644
index 0000000..d0d8775
--- /dev/null
+++ b/mojo/public/mojom/base/message_loop_type.mojom
@@ -0,0 +1,21 @@
+// 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.
+
+module mojo_base.mojom;
+
+// Mirror of base::MessageLoop::Type.
+enum MessageLoopType {
+  kDefault,
+  kUi,
+  kCustom,
+  kIo,
+  [EnableIf=is_android]
+  kJava,
+  [EnableIf=is_mac]
+  kNsRunloop,
+  [EnableIf=is_ios]
+  kNsRunloop,
+  [EnableIf=is_win]
+  kUiWithWmQuitSupport,
+};
diff --git a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
index 96ff98d..aba258c 100644
--- a/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
+++ b/net/android/java/src/org/chromium/net/AndroidNetworkLibrary.java
@@ -299,8 +299,15 @@
      */
     @CalledByNative
     public static int getWifiSignalLevel(int countBuckets) {
-        final Intent intent = ContextUtils.getApplicationContext().registerReceiver(
-                null, new IntentFilter(WifiManager.RSSI_CHANGED_ACTION));
+        Intent intent = null;
+        try {
+            intent = ContextUtils.getApplicationContext().registerReceiver(
+                    null, new IntentFilter(WifiManager.RSSI_CHANGED_ACTION));
+        } catch (IllegalArgumentException e) {
+            // Some devices unexpectedly throw IllegalArgumentException when registering
+            // the broadcast receiver. See https://crbug.com/984179.
+            return -1;
+        }
         if (intent == null) {
             return -1;
         }
diff --git a/net/base/address_list.cc b/net/base/address_list.cc
index 0d2a905..94eea32 100644
--- a/net/base/address_list.cc
+++ b/net/base/address_list.cc
@@ -15,22 +15,6 @@
 
 namespace net {
 
-namespace {
-
-base::Value NetLogAddressListParams(const AddressList* address_list) {
-  base::Value dict(base::Value::Type::DICTIONARY);
-  base::Value list(base::Value::Type::LIST);
-
-  for (const auto& ip_endpoint : *address_list)
-    list.GetList().emplace_back(ip_endpoint.ToString());
-
-  dict.SetKey("address_list", std::move(list));
-  dict.SetStringKey("canonical_name", address_list->canonical_name());
-  return dict;
-}
-
-}  // namespace
-
 AddressList::AddressList() = default;
 
 AddressList::AddressList(const AddressList&) = default;
@@ -91,7 +75,15 @@
 }
 
 base::Value AddressList::NetLogParams() const {
-  return NetLogAddressListParams(this);
+  base::Value dict(base::Value::Type::DICTIONARY);
+  base::Value list(base::Value::Type::LIST);
+
+  for (const auto& ip_endpoint : *this)
+    list.GetList().emplace_back(ip_endpoint.ToString());
+
+  dict.SetKey("address_list", std::move(list));
+  dict.SetStringKey("canonical_name", canonical_name());
+  return dict;
 }
 
 }  // namespace net
diff --git a/net/base/network_change_notifier_posix_unittest.cc b/net/base/network_change_notifier_posix_unittest.cc
index f433dfa..682fb2e 100644
--- a/net/base/network_change_notifier_posix_unittest.cc
+++ b/net/base/network_change_notifier_posix_unittest.cc
@@ -18,7 +18,7 @@
  public:
   NetworkChangeNotifierPosixTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         notifier_(new NetworkChangeNotifierPosix(
             NetworkChangeNotifier::CONNECTION_UNKNOWN,
             NetworkChangeNotifier::SUBTYPE_UNKNOWN)) {
diff --git a/net/disk_cache/net_log_parameters.cc b/net/disk_cache/net_log_parameters.cc
index 6dfccb74..96e99bb0 100644
--- a/net/disk_cache/net_log_parameters.cc
+++ b/net/disk_cache/net_log_parameters.cc
@@ -15,14 +15,6 @@
 
 namespace {
 
-base::Value NetLogParametersEntryCreationParams(const disk_cache::Entry* entry,
-                                                bool created) {
-  base::Value dict(base::Value::Type::DICTIONARY);
-  dict.SetStringKey("key", entry->GetKey());
-  dict.SetBoolKey("created", created);
-  return dict;
-}
-
 base::Value NetLogReadWriteDataParams(int index,
                                       int offset,
                                       int buf_len,
@@ -62,17 +54,6 @@
   return dict;
 }
 
-base::Value NetLogGetAvailableRangeResultParams(int64_t start, int result) {
-  base::Value dict(base::Value::Type::DICTIONARY);
-  if (result > 0) {
-    dict.SetIntKey("length", result);
-    dict.SetKey("start", net::NetLogNumberValue(start));
-  } else {
-    dict.SetIntKey("net_error", result);
-  }
-  return dict;
-}
-
 }  // namespace
 
 namespace disk_cache {
@@ -80,7 +61,10 @@
 base::Value CreateNetLogParametersEntryCreationParams(const Entry* entry,
                                                       bool created) {
   DCHECK(entry);
-  return NetLogParametersEntryCreationParams(entry, created);
+  base::Value dict(base::Value::Type::DICTIONARY);
+  dict.SetStringKey("key", entry->GetKey());
+  dict.SetBoolKey("created", created);
+  return dict;
 }
 
 void NetLogReadWriteData(const net::NetLogWithSource& net_log,
@@ -125,7 +109,14 @@
 
 base::Value CreateNetLogGetAvailableRangeResultParams(int64_t start,
                                                       int result) {
-  return NetLogGetAvailableRangeResultParams(start, result);
+  base::Value dict(base::Value::Type::DICTIONARY);
+  if (result > 0) {
+    dict.SetIntKey("length", result);
+    dict.SetKey("start", net::NetLogNumberValue(start));
+  } else {
+    dict.SetIntKey("net_error", result);
+  }
+  return dict;
 }
 
 }  // namespace disk_cache
diff --git a/net/socket/connect_job_unittest.cc b/net/socket/connect_job_unittest.cc
index 2c97a0e..5448982 100644
--- a/net/socket/connect_job_unittest.cc
+++ b/net/socket/connect_job_unittest.cc
@@ -90,7 +90,7 @@
  public:
   ConnectJobTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         common_connect_job_params_(
             nullptr /* client_socket_factory */,
             nullptr /* host_resolver */,
diff --git a/net/socket/socket_net_log_params.cc b/net/socket/socket_net_log_params.cc
index 23b460e8..eb8d372 100644
--- a/net/socket/socket_net_log_params.cc
+++ b/net/socket/socket_net_log_params.cc
@@ -16,8 +16,6 @@
 
 namespace net {
 
-namespace {
-
 base::Value NetLogSocketErrorParams(int net_error, int os_error) {
   base::DictionaryValue dict;
   dict.SetInteger("net_error", net_error);
@@ -25,30 +23,6 @@
   return std::move(dict);
 }
 
-base::Value NetLogHostPortPairParams(const HostPortPair* host_and_port) {
-  base::DictionaryValue dict;
-  dict.SetString("host_and_port", host_and_port->ToString());
-  return std::move(dict);
-}
-
-base::Value NetLogIPEndPointParams(const IPEndPoint* address) {
-  base::DictionaryValue dict;
-  dict.SetString("address", address->ToString());
-  return std::move(dict);
-}
-
-base::Value NetLogSourceAddressParams(const struct sockaddr* net_address,
-                                      socklen_t address_len) {
-  base::DictionaryValue dict;
-  IPEndPoint ipe;
-  bool result = ipe.FromSockAddr(net_address, address_len);
-  DCHECK(result);
-  dict.SetString("source_address", ipe.ToString());
-  return std::move(dict);
-}
-
-}  // namespace
-
 void NetLogSocketError(const NetLogWithSource& net_log,
                        NetLogEventType type,
                        int net_error,
@@ -58,16 +32,25 @@
 }
 
 base::Value CreateNetLogHostPortPairParams(const HostPortPair* host_and_port) {
-  return NetLogHostPortPairParams(host_and_port);
+  base::DictionaryValue dict;
+  dict.SetString("host_and_port", host_and_port->ToString());
+  return std::move(dict);
 }
 
 base::Value CreateNetLogIPEndPointParams(const IPEndPoint* address) {
-  return NetLogIPEndPointParams(address);
+  base::DictionaryValue dict;
+  dict.SetString("address", address->ToString());
+  return std::move(dict);
 }
 
 base::Value CreateNetLogSourceAddressParams(const struct sockaddr* net_address,
                                             socklen_t address_len) {
-  return NetLogSourceAddressParams(net_address, address_len);
+  base::DictionaryValue dict;
+  IPEndPoint ipe;
+  bool result = ipe.FromSockAddr(net_address, address_len);
+  DCHECK(result);
+  dict.SetString("source_address", ipe.ToString());
+  return std::move(dict);
 }
 
 }  // namespace net
diff --git a/printing/backend/cups_ipp_util.cc b/printing/backend/cups_ipp_util.cc
index 272ca9c..019b8cc6 100644
--- a/printing/backend/cups_ipp_util.cc
+++ b/printing/backend/cups_ipp_util.cc
@@ -30,7 +30,6 @@
 constexpr char kIppMedia[] = CUPS_MEDIA;
 constexpr char kIppDuplex[] = CUPS_SIDES;
 constexpr char kIppResolution[] = "printer-resolution";            // RFC 2911
-constexpr char kIppDocumentName[] = "document-name";               // RFC 8011
 constexpr char kIppRequestingUserName[] = "requesting-user-name";  // RFC 8011
 constexpr char kIppPin[] = "job-password";                       // PWG 5100.11
 constexpr char kIppPinEncryption[] = "job-password-encryption";  // PWG 5100.11
diff --git a/printing/backend/cups_ipp_util.h b/printing/backend/cups_ipp_util.h
index 41c7a9f..567a662 100644
--- a/printing/backend/cups_ipp_util.h
+++ b/printing/backend/cups_ipp_util.h
@@ -21,7 +21,6 @@
 extern const char kIppColor[];
 extern const char kIppMedia[];
 extern const char kIppDuplex[];
-extern const char kIppDocumentName[];
 extern const char kIppRequestingUserName[];
 extern const char kIppPin[];
 extern const char kIppPinEncryption[];
diff --git a/printing/backend/cups_printer.cc b/printing/backend/cups_printer.cc
index f158f31..44b686a2 100644
--- a/printing/backend/cups_printer.cc
+++ b/printing/backend/cups_printer.cc
@@ -147,38 +147,38 @@
 
 ipp_status_t CupsPrinter::CreateJob(int* job_id,
                                     const std::string& title,
-                                    base::StringPiece username,
+                                    const std::string& username,
                                     const std::vector<cups_option_t>& options) {
   DCHECK(dest_info_) << "Verify availability before starting a print job";
 
   cups_option_t* data = const_cast<cups_option_t*>(
       options.data());  // createDestJob will not modify the data
   if (!username.empty())
-    cupsSetUser(username.data());
+    cupsSetUser(username.c_str());
 
-  ipp_status_t create_status =
-      cupsCreateDestJob(cups_http_, destination_.get(), dest_info_.get(),
-                        job_id, title.c_str(), options.size(), data);
+  ipp_status_t create_status = cupsCreateDestJob(
+      cups_http_, destination_.get(), dest_info_.get(), job_id,
+      title.empty() ? nullptr : title.c_str(), options.size(), data);
   cupsSetUser(nullptr);  // reset to default username ("anonymous")
   return create_status;
 }
 
 bool CupsPrinter::StartDocument(int job_id,
-                                const std::string& document_name,
+                                const std::string& docname,
                                 bool last_document,
-                                base::StringPiece username,
+                                const std::string& username,
                                 const std::vector<cups_option_t>& options) {
   DCHECK(dest_info_);
   DCHECK(job_id);
   if (!username.empty())
-    cupsSetUser(username.data());
+    cupsSetUser(username.c_str());
 
   cups_option_t* data = const_cast<cups_option_t*>(
       options.data());  // createStartDestDocument will not modify the data
-  http_status_t start_doc_status =
-      cupsStartDestDocument(cups_http_, destination_.get(), dest_info_.get(),
-                            job_id, document_name.c_str(), CUPS_FORMAT_PDF,
-                            options.size(), data, last_document ? 1 : 0);
+  http_status_t start_doc_status = cupsStartDestDocument(
+      cups_http_, destination_.get(), dest_info_.get(), job_id,
+      docname.empty() ? nullptr : docname.c_str(), CUPS_FORMAT_PDF,
+      options.size(), data, last_document ? 1 : 0);
 
   cupsSetUser(nullptr);  // reset to default username ("anonymous")
   return start_doc_status == HTTP_CONTINUE;
@@ -199,11 +199,11 @@
   return status == IPP_STATUS_OK;
 }
 
-ipp_status_t CupsPrinter::CloseJob(int job_id, base::StringPiece username) {
+ipp_status_t CupsPrinter::CloseJob(int job_id, const std::string& username) {
   DCHECK(dest_info_);
   DCHECK(job_id);
   if (!username.empty())
-    cupsSetUser(username.data());
+    cupsSetUser(username.c_str());
 
   ipp_status_t result = cupsCloseDestJob(cups_http_, destination_.get(),
                                          dest_info_.get(), job_id);
diff --git a/printing/backend/cups_printer.h b/printing/backend/cups_printer.h
index 52a1595..d66ba52 100644
--- a/printing/backend/cups_printer.h
+++ b/printing/backend/cups_printer.h
@@ -87,23 +87,23 @@
   bool ToPrinterInfo(PrinterBasicInfo* basic_info) const;
 
   // Start a print job.  Writes the id of the started job to |job_id|.  |job_id|
-  // is 0 if there is an error.  If |username| is empty no username is sent.
-  // Check availability before using this operation. Usage on an unavailable
-  // printer is undefined.
+  // is 0 if there is an error.  |title| is not sent if empty.  |username| is
+  // not sent if empty.  Check availability before using this operation.  Usage
+  // on an unavailable printer is undefined.
   ipp_status_t CreateJob(int* job_id,
                          const std::string& title,
-                         base::StringPiece username,
+                         const std::string& username,
                          const std::vector<cups_option_t>& options);
 
   // Add a document to a print job.  |job_id| must be non-zero and refer to a
-  // job started with CreateJob.  |document_name| will be displayed in print
-  // status.  |last_doc| should be true if this is the last document for this
-  // print job.  If |username| is empty no username is sent.  |options| should
-  // be IPP key value pairs for the Send-Document operation.
+  // job started with CreateJob.  |docname| will be displayed in print status
+  // if not empty.  |last_doc| should be true if this is the last document for
+  // this print job.  |username| is not sent if empty.  |options| should be IPP
+  // key value pairs for the Send-Document operation.
   bool StartDocument(int job_id,
-                     const std::string& document_name,
+                     const std::string& docname,
                      bool last_doc,
-                     base::StringPiece username,
+                     const std::string& username,
                      const std::vector<cups_option_t>& options);
 
   // Add data to the current document started by StartDocument.  Calling this
@@ -115,9 +115,9 @@
   bool FinishDocument();
 
   // Close the job.  If the job is not closed, the documents will not be
-  // printed.  |job_id| should match the id from CreateJob.  If |username| is
-  // empty no username is sent.
-  ipp_status_t CloseJob(int job_id, base::StringPiece username);
+  // printed.  |job_id| should match the id from CreateJob.  |username| is not
+  // sent if empty.
+  ipp_status_t CloseJob(int job_id, const std::string& username);
 
   // Cancel the print job |job_id|.  Returns true if the operation succeeded.
   // Returns false if it failed for any reason.
diff --git a/printing/print_job_constants.cc b/printing/print_job_constants.cc
index 5817cb0..82d764463 100644
--- a/printing/print_job_constants.cc
+++ b/printing/print_job_constants.cc
@@ -63,9 +63,6 @@
 // Print job duplex mode. Value is an int from DuplexMode enum.
 const char kSettingDuplexMode[] = "duplex";
 
-// Job title to be sent to printer.
-const char kSettingJobTitle[] = "jobTitle";
-
 // Option to fit source page contents to printer paper size: true if
 // selected else false.
 const char kSettingFitToPageEnabled[] = "fitToPageEnabled";
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h
index 017b6b8..299a97f4 100644
--- a/printing/print_job_constants.h
+++ b/printing/print_job_constants.h
@@ -34,7 +34,6 @@
 PRINTING_EXPORT extern const char kSettingHeaderFooterDate[];
 PRINTING_EXPORT extern const char kSettingHeaderFooterTitle[];
 PRINTING_EXPORT extern const char kSettingHeaderFooterURL[];
-PRINTING_EXPORT extern const char kSettingJobTitle[];
 PRINTING_EXPORT extern const char kSettingLandscape[];
 PRINTING_EXPORT extern const char kSettingMediaSize[];
 PRINTING_EXPORT extern const char kSettingMediaSizeHeightMicrons[];
diff --git a/printing/print_settings.h b/printing/print_settings.h
index 7ac2275..3d9c3c5f 100644
--- a/printing/print_settings.h
+++ b/printing/print_settings.h
@@ -199,9 +199,6 @@
   void set_username(const std::string& username) { username_ = username; }
   const std::string& username() const { return username_; }
 
-  void set_job_title(const std::string& job_title) { job_title_ = job_title; }
-  const std::string& job_title() const { return job_title_; }
-
   void set_pin_value(const std::string& pin_value) { pin_value_ = pin_value; }
   const std::string& pin_value() const { return pin_value_; }
 #endif
diff --git a/printing/print_settings_conversion.cc b/printing/print_settings_conversion.cc
index 2ba73332..2563ae6 100644
--- a/printing/print_settings_conversion.cc
+++ b/printing/print_settings_conversion.cc
@@ -217,10 +217,6 @@
     const std::string* username = job_settings.FindStringKey(kSettingUsername);
     if (username)
       settings->set_username(*username);
-
-    const std::string* job_title = job_settings.FindStringKey(kSettingJobTitle);
-    if (job_title)
-      settings->set_job_title(*job_title);
   }
 
   const std::string* pin_value = job_settings.FindStringKey(kSettingPinValue);
diff --git a/printing/print_settings_conversion_unittest.cc b/printing/print_settings_conversion_unittest.cc
index 2b28cb9..e8a0a7c 100644
--- a/printing/print_settings_conversion_unittest.cc
+++ b/printing/print_settings_conversion_unittest.cc
@@ -42,7 +42,6 @@
   "previewModifiable": true,
   "sendUserInfo": true,
   "username": "username@domain.net",
-  "jobTitle": "test.pdf",
   "pinValue": "0000"
 })";
 
@@ -59,7 +58,6 @@
 #if defined(OS_CHROMEOS)
   EXPECT_TRUE(settings.send_user_info());
   EXPECT_EQ("username@domain.net", settings.username());
-  EXPECT_EQ("test.pdf", settings.job_title());
   EXPECT_EQ("0000", settings.pin_value());
 #endif
 }
@@ -76,7 +74,6 @@
   ASSERT_TRUE(success);
   EXPECT_FALSE(settings.send_user_info());
   EXPECT_EQ("", settings.username());
-  EXPECT_EQ("", settings.job_title());
 }
 #endif
 
diff --git a/printing/printing_context_chromeos.cc b/printing/printing_context_chromeos.cc
index 594adf9..d4ead5d7 100644
--- a/printing/printing_context_chromeos.cc
+++ b/printing/printing_context_chromeos.cc
@@ -126,7 +126,6 @@
       ConstructOption(kIppCollate,
                       GetCollateString(settings.collate())));  // collate
   if (settings.send_user_info()) {
-    options.push_back(ConstructOption(kIppDocumentName, settings.job_title()));
     options.push_back(
         ConstructOption(kIppRequestingUserName, settings.username()));
   }
@@ -292,12 +291,13 @@
   DCHECK(!in_print_job_);
   in_print_job_ = true;
 
-  std::string converted_name = base::UTF16ToUTF8(document_name);
-  std::string title = base::UTF16ToUTF8(settings_.title());
-  std::vector<ScopedCupsOption> cups_options = SettingsToCupsOptions(settings_);
+  std::string converted_name;
+  if (settings_.send_user_info())
+    converted_name = base::UTF16ToUTF8(document_name);
 
+  std::vector<ScopedCupsOption> cups_options = SettingsToCupsOptions(settings_);
   std::vector<cups_option_t> options;
-  base::StringPiece username;
+  std::string username;
   const base::StringPiece requestingUserName(kIppRequestingUserName);
   for (const ScopedCupsOption& option : cups_options) {
     if (option->name == requestingUserName) {
@@ -311,7 +311,7 @@
   }
 
   ipp_status_t create_status =
-      printer_->CreateJob(&job_id_, title, username, options);
+      printer_->CreateJob(&job_id_, converted_name, username, options);
 
   if (job_id_ == 0) {
     DLOG(WARNING) << "Creating cups job failed"
@@ -362,10 +362,9 @@
     return OnError();
   }
 
-  ipp_status_t job_status =
-      printer_->CloseJob(job_id_, settings_.send_user_info()
-                                      ? base::StringPiece(settings_.username())
-                                      : base::StringPiece());
+  ipp_status_t job_status = printer_->CloseJob(
+      job_id_,
+      settings_.send_user_info() ? settings_.username() : std::string());
   job_id_ = 0;
 
   if (job_status != IPP_STATUS_OK) {
diff --git a/remoting/base/service_urls.cc b/remoting/base/service_urls.cc
index 124cbfe..8c786af 100644
--- a/remoting/base/service_urls.cc
+++ b/remoting/base/service_urls.cc
@@ -12,9 +12,6 @@
 // Configurable service data.
 constexpr char kDirectoryBaseUrl[] = "https://www.googleapis.com/chromoting/v1";
 constexpr char kGcdBaseUrl[] = "https://www.googleapis.com/clouddevices/v1";
-constexpr char kXmppServerAddress[] = "talk.google.com:443";
-constexpr char kXmppServerAddressForMe2MeHost[] = "talk.google.com:5222";
-constexpr bool kXmppServerUseTls = true;
 constexpr char kGcdJid[] = "clouddevices.gserviceaccount.com";
 constexpr char kFtlServerEndpoint[] = "instantmessaging-pa.googleapis.com";
 constexpr char kRemotingServerEndpoint[] = "remotedesktop-pa.googleapis.com";
@@ -23,8 +20,6 @@
 #if !defined(NDEBUG)
 constexpr char kDirectoryBaseUrlSwitch[] = "directory-base-url";
 constexpr char kGcdBaseUrlSwitch[] = "gcd-base-url";
-constexpr char kXmppServerAddressSwitch[] = "xmpp-server-address";
-constexpr char kXmppServerDisableTlsSwitch[] = "disable-xmpp-server-tls";
 constexpr char kDirectoryBotJidSwitch[] = "directory-bot-jid";
 constexpr char kGcdJidSwitch[] = "gcd-jid";
 constexpr char kFtlServerEndpointSwitch[] = "ftl-server-endpoint";
@@ -40,9 +35,6 @@
 ServiceUrls::ServiceUrls()
     : directory_base_url_(kDirectoryBaseUrl),
       gcd_base_url_(kGcdBaseUrl),
-      xmpp_server_address_(kXmppServerAddress),
-      xmpp_server_address_for_me2me_host_(kXmppServerAddressForMe2MeHost),
-      xmpp_server_use_tls_(kXmppServerUseTls),
       directory_bot_jid_(kRemotingBotJid),
       gcd_jid_(kGcdJid),
       ftl_server_endpoint_(kFtlServerEndpoint),
@@ -60,14 +52,6 @@
     if (command_line->HasSwitch(kGcdBaseUrlSwitch)) {
       gcd_base_url_ = command_line->GetSwitchValueASCII(kGcdBaseUrlSwitch);
     }
-    if (command_line->HasSwitch(kXmppServerAddressSwitch)) {
-      xmpp_server_address_ =
-          command_line->GetSwitchValueASCII(kXmppServerAddressSwitch);
-      xmpp_server_address_for_me2me_host_ = xmpp_server_address_;
-    }
-    if (command_line->HasSwitch(kXmppServerDisableTlsSwitch)) {
-      xmpp_server_use_tls_ = false;
-    }
     if (command_line->HasSwitch(kDirectoryBotJidSwitch)) {
       directory_bot_jid_ =
           command_line->GetSwitchValueASCII(kDirectoryBotJidSwitch);
diff --git a/remoting/base/service_urls.h b/remoting/base/service_urls.h
index 2268ef7..2a69048 100644
--- a/remoting/base/service_urls.h
+++ b/remoting/base/service_urls.h
@@ -27,15 +27,6 @@
   }
   const std::string& gcd_base_url() const { return gcd_base_url_; }
 
-  // XMPP Server configuration.
-  const std::string& xmpp_server_address() const {
-    return xmpp_server_address_;
-  }
-  const std::string& xmpp_server_address_for_me2me_host() const {
-    return xmpp_server_address_for_me2me_host_;
-  }
-  bool xmpp_server_use_tls() const { return xmpp_server_use_tls_; }
-
   // Remoting directory bot JID (for registering hosts, logging, heartbeats).
   const std::string& directory_bot_jid() const { return directory_bot_jid_; }
 
@@ -69,9 +60,6 @@
   std::string directory_base_url_;
   std::string directory_hosts_url_;
   std::string gcd_base_url_;
-  std::string xmpp_server_address_;
-  std::string xmpp_server_address_for_me2me_host_;
-  bool xmpp_server_use_tls_;
   std::string directory_bot_jid_;
   std::string gcd_jid_;
   std::string ice_config_url_;
diff --git a/remoting/client/chromoting_session.cc b/remoting/client/chromoting_session.cc
index ace8856..747677f 100644
--- a/remoting/client/chromoting_session.cc
+++ b/remoting/client/chromoting_session.cc
@@ -45,10 +45,6 @@
 
 namespace {
 
-const char* const kXmppServer = "talk.google.com";
-const int kXmppPort = 5222;
-const bool kXmppUseTls = true;
-
 // Default DPI to assume for old clients that use notifyClientResolution.
 const int kDefaultDPI = 96;
 
@@ -489,24 +485,10 @@
       client_context_.get(), this, session_context_->video_renderer.get(),
       session_context_->audio_player_weak_factory->GetWeakPtr()));
 
-  XmppSignalStrategy::XmppServerConfig xmpp_config;
-  xmpp_config.host = kXmppServer;
-  xmpp_config.port = kXmppPort;
-  xmpp_config.use_tls = kXmppUseTls;
-  xmpp_config.username = session_context_->info.username;
-  xmpp_config.auth_token = session_context_->info.auth_token;
-
-  if (!session_context_->info.host_ftl_id.empty()) {
-    signaling_ = std::make_unique<FtlSignalStrategy>(
-        runtime_->CreateOAuthTokenGetter(),
-        std::make_unique<FtlClientUuidDeviceIdProvider>());
-    logger_->SetSignalStrategyType(ChromotingEvent::SignalStrategyType::FTL);
-  } else {
-    signaling_ = std::make_unique<XmppSignalStrategy>(
-        net::ClientSocketFactory::GetDefaultFactory(),
-        runtime_->url_requester(), xmpp_config);
-    logger_->SetSignalStrategyType(ChromotingEvent::SignalStrategyType::XMPP);
-  }
+  signaling_ = std::make_unique<FtlSignalStrategy>(
+      runtime_->CreateOAuthTokenGetter(),
+      std::make_unique<FtlClientUuidDeviceIdProvider>());
+  logger_->SetSignalStrategyType(ChromotingEvent::SignalStrategyType::FTL);
 
   token_getter_ = runtime_->CreateOAuthTokenGetter();
 
diff --git a/remoting/client/chromoting_session.h b/remoting/client/chromoting_session.h
index bfc6bec..4820eab 100644
--- a/remoting/client/chromoting_session.h
+++ b/remoting/client/chromoting_session.h
@@ -23,7 +23,7 @@
 #include "remoting/protocol/clipboard_stub.h"
 #include "remoting/protocol/cursor_shape_stub.h"
 #include "remoting/signaling/ftl_device_id_provider.h"
-#include "remoting/signaling/xmpp_signal_strategy.h"
+#include "remoting/signaling/signal_strategy.h"
 
 namespace remoting {
 
diff --git a/remoting/host/gcd_state_updater_unittest.cc b/remoting/host/gcd_state_updater_unittest.cc
index ed97783..6193e567 100644
--- a/remoting/host/gcd_state_updater_unittest.cc
+++ b/remoting/host/gcd_state_updater_unittest.cc
@@ -35,7 +35,7 @@
  public:
   GcdStateUpdaterTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         test_shared_url_loader_factory_(
             base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
diff --git a/remoting/host/heartbeat_sender_unittest.cc b/remoting/host/heartbeat_sender_unittest.cc
index 827d9be..c04bec99 100644
--- a/remoting/host/heartbeat_sender_unittest.cc
+++ b/remoting/host/heartbeat_sender_unittest.cc
@@ -142,7 +142,7 @@
 
   ServerLogEntry::Mode mode() const override { return ServerLogEntry::ME2ME; }
 
-  // |heartbeat_sender_| must be deleted before |muxing_signal_strategy_|.
+  // |heartbeat_sender_| must be deleted before |signal_strategy_|.
   std::unique_ptr<HeartbeatSender> heartbeat_sender_;
 
   FakeOAuthTokenGetter oauth_token_getter_{OAuthTokenGetter::Status::SUCCESS,
diff --git a/remoting/host/it2me/it2me_host.h b/remoting/host/it2me/it2me_host.h
index c1cde09..713e705 100644
--- a/remoting/host/it2me/it2me_host.h
+++ b/remoting/host/it2me/it2me_host.h
@@ -20,7 +20,7 @@
 #include "remoting/protocol/errors.h"
 #include "remoting/protocol/port_range.h"
 #include "remoting/protocol/validating_authenticator.h"
-#include "remoting/signaling/xmpp_signal_strategy.h"
+#include "remoting/signaling/signal_strategy.h"
 
 namespace base {
 class DictionaryValue;
diff --git a/remoting/host/signaling_connector.cc b/remoting/host/signaling_connector.cc
deleted file mode 100644
index ffe1cee..0000000
--- a/remoting/host/signaling_connector.cc
+++ /dev/null
@@ -1,192 +0,0 @@
-// Copyright (c) 2012 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 "remoting/host/signaling_connector.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/strings/string_util.h"
-#include "google_apis/google_api_keys.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "remoting/base/logging.h"
-#include "remoting/host/dns_blackhole_checker.h"
-#include "remoting/signaling/signaling_address.h"
-
-namespace remoting {
-
-namespace {
-
-constexpr base::TimeDelta kBackoffResetDelay = base::TimeDelta::FromSeconds(30);
-
-// The delay between reconnect attempts will increase exponentially up
-// to the maximum specified here.
-const int kMaxReconnectDelaySeconds = 10 * 60;
-
-const char* SignalStrategyErrorToString(SignalStrategy::Error error){
-  switch(error) {
-    case SignalStrategy::OK:
-      return "OK";
-    case SignalStrategy::AUTHENTICATION_FAILED:
-      return "AUTHENTICATION_FAILED";
-    case SignalStrategy::NETWORK_ERROR:
-      return "NETWORK_ERROR";
-    case SignalStrategy::PROTOCOL_ERROR:
-      return "PROTOCOL_ERROR";
-  }
-  NOTREACHED();
-  return "";
-}
-
-}  // namespace
-
-SignalingConnector::SignalingConnector(
-    XmppSignalStrategy* signal_strategy,
-    std::unique_ptr<DnsBlackholeChecker> dns_blackhole_checker,
-    OAuthTokenGetter* oauth_token_getter,
-    const base::Closure& auth_failed_callback)
-    : signal_strategy_(signal_strategy),
-      auth_failed_callback_(auth_failed_callback),
-      dns_blackhole_checker_(std::move(dns_blackhole_checker)),
-      oauth_token_getter_(oauth_token_getter),
-      reconnect_attempts_(0),
-      weak_factory_(this) {
-  DCHECK(!auth_failed_callback_.is_null());
-  DCHECK(dns_blackhole_checker_.get());
-  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
-  signal_strategy_->AddListener(this);
-  ScheduleTryReconnect();
-}
-
-SignalingConnector::~SignalingConnector() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  signal_strategy_->RemoveListener(this);
-  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
-}
-
-void SignalingConnector::OnSignalStrategyStateChange(
-    SignalStrategy::State state) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  if (state == SignalStrategy::CONNECTED) {
-    HOST_LOG << "Signaling connected. New JID: "
-             << signal_strategy_->GetLocalAddress().jid();
-    backoff_reset_timer_.Start(FROM_HERE, kBackoffResetDelay, this,
-                               &SignalingConnector::ResetBackoff);
-  } else if (state == SignalStrategy::DISCONNECTED) {
-    HOST_LOG << "Signaling disconnected. error="
-             << SignalStrategyErrorToString(signal_strategy_->GetError());
-    backoff_reset_timer_.Stop();
-    reconnect_attempts_++;
-
-    if (signal_strategy_->GetError() == SignalStrategy::AUTHENTICATION_FAILED)
-      oauth_token_getter_->InvalidateCache();
-
-    ScheduleTryReconnect();
-  }
-}
-
-bool SignalingConnector::OnSignalStrategyIncomingStanza(
-    const jingle_xmpp::XmlElement* stanza) {
-  return false;
-}
-
-void SignalingConnector::OnNetworkChanged(
-    net::NetworkChangeNotifier::ConnectionType type) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (type != net::NetworkChangeNotifier::CONNECTION_NONE &&
-      signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) {
-    HOST_LOG << "Network state changed to online.";
-    ResetAndTryReconnect();
-  }
-}
-
-void SignalingConnector::OnAccessToken(OAuthTokenGetter::Status status,
-                                       const std::string& user_email,
-                                       const std::string& access_token) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  if (status == OAuthTokenGetter::AUTH_ERROR) {
-    auth_failed_callback_.Run();
-    return;
-  } else if (status == OAuthTokenGetter::NETWORK_ERROR) {
-    OnNetworkError();
-    return;
-  }
-
-  DCHECK_EQ(status, OAuthTokenGetter::SUCCESS);
-  HOST_LOG << "Received user info.";
-
-  signal_strategy_->SetAuthInfo(user_email, access_token);
-
-  // Now that we've refreshed the token and verified that it's for the correct
-  // user account, try to connect using the new token.
-  DCHECK_EQ(signal_strategy_->GetState(), SignalStrategy::DISCONNECTED);
-  signal_strategy_->Connect();
-}
-
-void SignalingConnector::OnNetworkError() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  reconnect_attempts_++;
-  ScheduleTryReconnect();
-}
-
-void SignalingConnector::ScheduleTryReconnect() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  if (timer_.IsRunning() || net::NetworkChangeNotifier::IsOffline())
-    return;
-  int delay_s = std::min(1 << reconnect_attempts_,
-                         kMaxReconnectDelaySeconds);
-  timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(delay_s),
-               this, &SignalingConnector::TryReconnect);
-}
-
-void SignalingConnector::ResetAndTryReconnect() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  signal_strategy_->Disconnect();
-  ResetBackoff();
-  timer_.Stop();
-  ScheduleTryReconnect();
-}
-
-void SignalingConnector::TryReconnect() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(dns_blackhole_checker_.get());
-
-  // This will check if this machine is allowed to access the chromoting
-  // host talkgadget.
-  dns_blackhole_checker_->CheckForDnsBlackhole(
-      base::Bind(&SignalingConnector::OnDnsBlackholeCheckerDone,
-                 base::Unretained(this)));
-}
-
-void SignalingConnector::OnDnsBlackholeCheckerDone(bool allow) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  // Unable to access the host talkgadget. Don't allow the connection, but
-  // schedule a reconnect in case this is a transient problem rather than
-  // an outright block.
-  if (!allow) {
-    reconnect_attempts_++;
-    HOST_LOG << "Talkgadget check failed. Scheduling reconnect. Attempt "
-              << reconnect_attempts_;
-    ScheduleTryReconnect();
-    return;
-  }
-
-  if (signal_strategy_->GetState() == SignalStrategy::DISCONNECTED) {
-    HOST_LOG << "Attempting to connect signaling.";
-    oauth_token_getter_->CallWithToken(base::BindOnce(
-        &SignalingConnector::OnAccessToken, weak_factory_.GetWeakPtr()));
-  }
-}
-
-void SignalingConnector::ResetBackoff() {
-  backoff_reset_timer_.Stop();
-  reconnect_attempts_ = 0;
-}
-
-}  // namespace remoting
diff --git a/remoting/host/signaling_connector.h b/remoting/host/signaling_connector.h
deleted file mode 100644
index f0d78f3..0000000
--- a/remoting/host/signaling_connector.h
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (c) 2012 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 REMOTING_HOST_SIGNALING_CONNECTOR_H_
-#define REMOTING_HOST_SIGNALING_CONNECTOR_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequence_checker.h"
-#include "base/timer/timer.h"
-#include "net/base/network_change_notifier.h"
-#include "remoting/base/oauth_token_getter.h"
-#include "remoting/signaling/xmpp_signal_strategy.h"
-
-namespace remoting {
-
-class DnsBlackholeChecker;
-
-// SignalingConnector listens for SignalStrategy status notifications
-// and attempts to keep it connected when possible. When signalling is
-// not connected it keeps trying to reconnect it until it is
-// connected. It limits connection attempt rate using exponential
-// backoff. It also monitors network state and reconnects signalling
-// whenever connection type changes or IP address changes.
-class SignalingConnector
-    : public SignalStrategy::Listener,
-      public net::NetworkChangeNotifier::NetworkChangeObserver {
- public:
-  // The |auth_failed_callback| is called when authentication fails.
-  SignalingConnector(XmppSignalStrategy* signal_strategy,
-                     std::unique_ptr<DnsBlackholeChecker> dns_blackhole_checker,
-                     OAuthTokenGetter* oauth_token_getter,
-                     const base::Closure& auth_failed_callback);
-  ~SignalingConnector() override;
-
-  // OAuthTokenGetter callback.
-  void OnAccessToken(OAuthTokenGetter::Status status,
-                     const std::string& user_email,
-                     const std::string& access_token);
-
-  // SignalStrategy::Listener interface.
-  void OnSignalStrategyStateChange(SignalStrategy::State state) override;
-  bool OnSignalStrategyIncomingStanza(const jingle_xmpp::XmlElement* stanza) override;
-
-  // NetworkChangeNotifier::NetworkChangeObserver interface.
-  void OnNetworkChanged(
-      net::NetworkChangeNotifier::ConnectionType type) override;
-
- private:
-  void OnNetworkError();
-  void ScheduleTryReconnect();
-  void ResetAndTryReconnect();
-  void TryReconnect();
-  void OnDnsBlackholeCheckerDone(bool allow);
-  void ResetBackoff();
-
-  XmppSignalStrategy* signal_strategy_;
-  base::Closure auth_failed_callback_;
-  std::unique_ptr<DnsBlackholeChecker> dns_blackhole_checker_;
-
-  OAuthTokenGetter* oauth_token_getter_;
-
-  // Number of times we tried to connect without success.
-  int reconnect_attempts_;
-
-  base::OneShotTimer timer_;
-
-  // Timer to reset |backoff_|. We delay resetting the backoff so that we can
-  // treat an immediate CONNECTED->DISCONNECTED transition as failure.
-  base::OneShotTimer backoff_reset_timer_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  base::WeakPtrFactory<SignalingConnector> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(SignalingConnector);
-};
-
-}  // namespace remoting
-
-#endif  // REMOTING_HOST_SIGNALING_CONNECTOR_H_
diff --git a/remoting/host/xmpp_register_support_host_request_unittest.cc b/remoting/host/xmpp_register_support_host_request_unittest.cc
index ce011bc..7a5c143 100644
--- a/remoting/host/xmpp_register_support_host_request_unittest.cc
+++ b/remoting/host/xmpp_register_support_host_request_unittest.cc
@@ -74,7 +74,7 @@
   }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   MockSignalStrategy signal_strategy_;
   base::ObserverList<SignalStrategy::Listener, true> signal_strategy_listeners_;
   scoped_refptr<RsaKeyPair> key_pair_;
diff --git a/remoting/protocol/BUILD.gn b/remoting/protocol/BUILD.gn
index 5f842839..0bbf0d1 100644
--- a/remoting/protocol/BUILD.gn
+++ b/remoting/protocol/BUILD.gn
@@ -68,8 +68,6 @@
     "host_video_dispatcher.h",
     "host_video_stats_dispatcher.cc",
     "host_video_stats_dispatcher.h",
-    "http_ice_config_request.cc",
-    "http_ice_config_request.h",
     "ice_config.cc",
     "ice_config.h",
     "ice_config_request.h",
@@ -346,7 +344,6 @@
     "content_description_unittest.cc",
     "data_channel_manager_unittest.cc",
     "frame_stats_unittest.cc",
-    "http_ice_config_request_unittest.cc",
     "ice_config_unittest.cc",
     "ice_transport_unittest.cc",
     "input_event_tracker_unittest.cc",
diff --git a/remoting/protocol/http_ice_config_request.cc b/remoting/protocol/http_ice_config_request.cc
deleted file mode 100644
index 34b8714..0000000
--- a/remoting/protocol/http_ice_config_request.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2016 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 "remoting/protocol/http_ice_config_request.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/values.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "remoting/protocol/ice_config.h"
-
-namespace remoting {
-namespace protocol {
-
-net::NetworkTrafficAnnotationTag CreateIceConfigRequestAnnotation() {
-  return net::DefineNetworkTrafficAnnotation("CRD_ice_config_request", R"(
-        semantics {
-          sender: "Chrome Remote Desktop"
-          description:
-            "Request is used by Chrome Remote Desktop to fetch ICE "
-            "configuration which contains list of STUN & TURN servers and TURN "
-            "credentials."
-          trigger:
-            "When a Chrome Remote Desktop session is being connected and "
-            "periodically while a session is active, as necessary. Currently "
-            "the API issues credentials that expire every 24 hours, so this "
-            "request will only be sent again while session is active more than "
-            "24 hours and it needs to renegotiate the ICE connection. The 24 "
-            "hour period is controlled by the server and may change. In some "
-            "cases, e.g. if direct connection is used, it will not trigger "
-            "periodically."
-          data: "None."
-          destination: GOOGLE_OWNED_SERVICE
-        }
-        policy {
-          cookies_allowed: NO
-          setting:
-            "This feature cannot be disabled by settings. You can block Chrome "
-            "Remote Desktop as specified here: "
-            "https://support.google.com/chrome/?p=remote_desktop"
-          chrome_policy {
-            RemoteAccessHostFirewallTraversal {
-              policy_options {mode: MANDATORY}
-              RemoteAccessHostFirewallTraversal: false
-            }
-          }
-        }
-        comments:
-          "Above specified policy is only applicable on the host side and "
-          "doesn't have effect in Android and iOS client apps. The product "
-          "is shipped separately from Chromium, except on Chrome OS."
-        )");
-}
-
-HttpIceConfigRequest::HttpIceConfigRequest(
-    UrlRequestFactory* url_request_factory,
-    const std::string& url,
-    OAuthTokenGetter* oauth_token_getter)
-    : url_(url), weak_factory_(this) {
-  net::NetworkTrafficAnnotationTag traffic_annotation =
-      CreateIceConfigRequestAnnotation();
-  url_request_ = url_request_factory->CreateUrlRequest(
-      UrlRequest::Type::GET, url_, traffic_annotation);
-  oauth_token_getter_ = oauth_token_getter;
-  url_request_->SetPostData("application/json", "");
-}
-
-HttpIceConfigRequest::~HttpIceConfigRequest() = default;
-
-void HttpIceConfigRequest::Send(OnIceConfigCallback callback) {
-  DCHECK(on_ice_config_callback_.is_null());
-  DCHECK(!callback.is_null());
-
-  on_ice_config_callback_ = std::move(callback);
-
-  if (oauth_token_getter_) {
-    oauth_token_getter_->CallWithToken(base::BindOnce(
-        &HttpIceConfigRequest::OnOAuthToken, weak_factory_.GetWeakPtr()));
-  } else {
-    SendRequest();
-  }
-}
-
-void HttpIceConfigRequest::OnOAuthToken(OAuthTokenGetter::Status status,
-                                        const std::string& user_email,
-                                        const std::string& access_token) {
-  if (status != OAuthTokenGetter::SUCCESS) {
-    LOG(ERROR) << "Failed to get OAuth token for IceConfig request.";
-    std::move(on_ice_config_callback_).Run(IceConfig());
-    return;
-  }
-
-  url_request_->AddHeader("Authorization:Bearer " + access_token);
-  SendRequest();
-}
-
-void HttpIceConfigRequest::SendRequest() {
-  url_request_->Start(
-      base::Bind(&HttpIceConfigRequest::OnResponse, base::Unretained(this)));
-}
-
-void HttpIceConfigRequest::OnResponse(const UrlRequest::Result& result) {
-  DCHECK(!on_ice_config_callback_.is_null());
-
-  if (result.status != -1 && result.status != 200) {
-    LOG(ERROR) << "Received status code " << result.status << " from " << url_
-               << ": " << result.response_body;
-    std::move(on_ice_config_callback_).Run(IceConfig());
-    return;
-  }
-
-  if (!result.success) {
-    LOG(ERROR) << "Failed to fetch " << url_;
-    std::move(on_ice_config_callback_).Run(IceConfig());
-    return;
-  }
-
-  IceConfig ice_config = IceConfig::Parse(result.response_body);
-  if (ice_config.is_null()) {
-    LOG(ERROR) << "Received invalid response from " << url_ << ": "
-               << result.response_body;
-  }
-
-  std::move(on_ice_config_callback_).Run(ice_config);
-}
-
-}  // namespace protocol
-}  // namespace remoting
diff --git a/remoting/protocol/http_ice_config_request.h b/remoting/protocol/http_ice_config_request.h
deleted file mode 100644
index f1b084a..0000000
--- a/remoting/protocol/http_ice_config_request.h
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2016 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 REMOTING_PROTOCOL_HTTP_ICE_CONFIG_REQUEST_H_
-#define REMOTING_PROTOCOL_HTTP_ICE_CONFIG_REQUEST_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "remoting/base/oauth_token_getter.h"
-#include "remoting/base/url_request.h"
-#include "remoting/protocol/ice_config_request.h"
-
-namespace remoting {
-namespace protocol {
-
-net::NetworkTrafficAnnotationTag CreateIceConfigRequestAnnotation();
-
-// IceConfigRequest that fetches IceConfig from using HTTP. If the config has
-// been fetched succesfully but some parts couldn't be parsed then the returned
-// config contains all entries that were parsed successfully and
-// |expiration_time| is set to Now, i.e. the config is considered expired.
-class HttpIceConfigRequest : public IceConfigRequest {
- public:
-  HttpIceConfigRequest(UrlRequestFactory* url_request_factory,
-                       const std::string& url,
-                       OAuthTokenGetter* oauth_token_getter);
-  ~HttpIceConfigRequest() override;
-
-  // IceConfigRequest interface.
-  void Send(OnIceConfigCallback callback) override;
-
- private:
-  void OnOAuthToken(OAuthTokenGetter::Status status,
-                    const std::string& user_email,
-                    const std::string& access_token);
-
-  void SendRequest();
-
-  void OnResponse(const UrlRequest::Result& result);
-
-  std::string url_;
-  OAuthTokenGetter* oauth_token_getter_;
-  std::unique_ptr<UrlRequest> url_request_;
-  OnIceConfigCallback on_ice_config_callback_;
-
-  base::WeakPtrFactory<HttpIceConfigRequest> weak_factory_;
-
-  DISALLOW_COPY_AND_ASSIGN(HttpIceConfigRequest);
-};
-
-}  // namespace protocol
-}  // namespace remoting
-
-#endif  // REMOTING_PROTOCOL_HTTP_ICE_CONFIG_REQUEST_H_
diff --git a/remoting/protocol/http_ice_config_request_unittest.cc b/remoting/protocol/http_ice_config_request_unittest.cc
deleted file mode 100644
index 9f6ef8e..0000000
--- a/remoting/protocol/http_ice_config_request_unittest.cc
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2016 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 "remoting/protocol/http_ice_config_request.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/run_loop.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/scoped_task_environment.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "remoting/base/chromium_url_request.h"
-#include "remoting/base/fake_oauth_token_getter.h"
-#include "remoting/protocol/ice_config.h"
-#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
-#include "services/network/test/test_url_loader_factory.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace remoting {
-namespace protocol {
-
-namespace {
-
-const char kTestResponse[] =
-    "{"
-    "  \"lifetimeDuration\": \"43200.000s\","
-    "  \"iceServers\": ["
-    "    {"
-    "      \"urls\": ["
-    "        \"turns:the_server.com\""
-    "      ],"
-    "      \"username\": \"123\","
-    "      \"credential\": \"abc\""
-    "    },"
-    "    {"
-    "      \"urls\": ["
-    "        \"stun:stun_server.com:18344\""
-    "      ]"
-    "    }"
-    "  ]"
-    "}";
-const char kTestOAuthToken[] = "TestOAuthToken";
-
-const char kAuthHeaderBearer[] = "Bearer ";
-
-}  // namespace
-
-static const char kTestUrl[] = "http://host/ice_config";
-
-class HttpIceConfigRequestTest : public testing::Test {
- public:
-  HttpIceConfigRequestTest()
-      : test_shared_url_loader_factory_(
-            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
-                &test_url_loader_factory_)),
-        url_request_factory_(test_shared_url_loader_factory_) {}
-
-  void OnResult(const IceConfig& config) {
-    received_config_ = std::make_unique<IceConfig>(config);
-  }
-
- protected:
-  network::TestURLLoaderFactory test_url_loader_factory_;
-  scoped_refptr<network::SharedURLLoaderFactory>
-      test_shared_url_loader_factory_;
-
-  ChromiumUrlRequestFactory url_request_factory_;
-
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  std::unique_ptr<HttpIceConfigRequest> request_;
-  std::unique_ptr<IceConfig> received_config_;
-};
-
-TEST_F(HttpIceConfigRequestTest, Parse) {
-  test_url_loader_factory_.AddResponse(kTestUrl, kTestResponse);
-
-  request_.reset(
-      new HttpIceConfigRequest(&url_request_factory_, kTestUrl, nullptr));
-  request_->Send(
-      base::Bind(&HttpIceConfigRequestTest::OnResult, base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
-
-  ASSERT_FALSE(received_config_->is_null());
-
-  EXPECT_EQ(1U, received_config_->turn_servers.size());
-  EXPECT_EQ(1U, received_config_->stun_servers.size());
-}
-
-TEST_F(HttpIceConfigRequestTest, InvalidConfig) {
-  test_url_loader_factory_.AddResponse(kTestUrl, "ERROR");
-
-  request_.reset(
-      new HttpIceConfigRequest(&url_request_factory_, kTestUrl, nullptr));
-  request_->Send(
-      base::Bind(&HttpIceConfigRequestTest::OnResult, base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(received_config_->is_null());
-}
-
-TEST_F(HttpIceConfigRequestTest, FailedRequest) {
-  test_url_loader_factory_.AddResponse(kTestUrl, std::string(),
-                                       net::HTTP_INTERNAL_SERVER_ERROR);
-
-  request_.reset(
-      new HttpIceConfigRequest(&url_request_factory_, kTestUrl, nullptr));
-  request_->Send(
-      base::Bind(&HttpIceConfigRequestTest::OnResult, base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(received_config_->is_null());
-}
-
-TEST_F(HttpIceConfigRequestTest, Authentication) {
-  test_url_loader_factory_.AddResponse(kTestUrl, kTestResponse);
-
-  test_url_loader_factory_.SetInterceptor(
-      base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
-        EXPECT_TRUE(
-            request.headers.HasHeader(net::HttpRequestHeaders::kAuthorization));
-        std::string auth_header;
-        request.headers.GetHeader(net::HttpRequestHeaders::kAuthorization,
-                                  &auth_header);
-        EXPECT_EQ(auth_header,
-                  std::string(kAuthHeaderBearer) + kTestOAuthToken);
-      }));
-
-  FakeOAuthTokenGetter token_getter(OAuthTokenGetter::SUCCESS,
-                                    "user@example.com", kTestOAuthToken);
-  request_ = std::make_unique<HttpIceConfigRequest>(&url_request_factory_,
-                                                    kTestUrl, &token_getter);
-  request_->Send(
-      base::Bind(&HttpIceConfigRequestTest::OnResult, base::Unretained(this)));
-  base::RunLoop().RunUntilIdle();
-  ASSERT_TRUE(received_config_);
-
-  EXPECT_EQ(1U, received_config_->turn_servers.size());
-  EXPECT_EQ(1U, received_config_->stun_servers.size());
-}
-
-}  // namespace protocol
-}  // namespace remoting
diff --git a/remoting/signaling/BUILD.gn b/remoting/signaling/BUILD.gn
index 9227f139..44df316 100644
--- a/remoting/signaling/BUILD.gn
+++ b/remoting/signaling/BUILD.gn
@@ -29,8 +29,6 @@
     "message_tracker.cc",
     "message_tracker.h",
     "messaging_client.h",
-    "muxing_signal_strategy.cc",
-    "muxing_signal_strategy.h",
     "push_notification_subscriber.cc",
     "push_notification_subscriber.h",
     "registration_manager.h",
@@ -44,12 +42,6 @@
     "signaling_address.h",
     "xmpp_log_to_server.cc",
     "xmpp_log_to_server.h",
-    "xmpp_login_handler.cc",
-    "xmpp_login_handler.h",
-    "xmpp_signal_strategy.cc",
-    "xmpp_signal_strategy.h",
-    "xmpp_stream_parser.cc",
-    "xmpp_stream_parser.h",
   ]
 
   configs += [
@@ -98,7 +90,6 @@
       "remoting_log_to_server.h",
       "server_log_entry.cc",
       "xmpp_log_to_server.cc",
-      "xmpp_signal_strategy.cc",
     ]
     deps -= [
       "//google_apis",
@@ -139,16 +130,12 @@
     "iq_sender_unittest.cc",
     "jid_util_unittest.cc",
     "message_tracker_unittest.cc",
-    "muxing_signal_strategy_unittest.cc",
     "push_notification_subscriber_unittest.cc",
     "remoting_log_to_server_unittest.cc",
     "server_log_entry_unittest.cc",
     "server_log_entry_unittest.h",
     "signaling_address_unittest.cc",
     "xmpp_log_to_server_unittest.cc",
-    "xmpp_login_handler_unittest.cc",
-    "xmpp_signal_strategy_unittest.cc",
-    "xmpp_stream_parser_unittest.cc",
   ]
 
   deps = [
diff --git a/remoting/signaling/muxing_signal_strategy.cc b/remoting/signaling/muxing_signal_strategy.cc
deleted file mode 100644
index 708711e..0000000
--- a/remoting/signaling/muxing_signal_strategy.cc
+++ /dev/null
@@ -1,371 +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.
-
-#include "remoting/signaling/muxing_signal_strategy.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/rand_util.h"
-#include "base/sequence_checker.h"
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/timer/timer.h"
-#include "remoting/signaling/signaling_address.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-
-namespace remoting {
-
-namespace {
-
-constexpr base::TimeDelta kWaitForAllStrategiesConnectedTimeout =
-    base::TimeDelta::FromSeconds(5);
-
-}  // namespace
-
-class MuxingSignalStrategy::Core final : public SignalStrategy::Listener {
- public:
-  Core(std::unique_ptr<SignalStrategy> ftl_signal_strategy,
-       std::unique_ptr<SignalStrategy> xmpp_signal_strategy);
-  ~Core() override;
-
-  void Invalidate();
-
-  void Connect();
-  State GetState() const;
-  const SignalingAddress& GetLocalAddress() const;
-  void AddListener(SignalStrategy::Listener* listener);
-  void RemoveListener(SignalStrategy::Listener* listener);
-  bool SendStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza);
-
-  SignalStrategy* ftl_signal_strategy() { return ftl_signal_strategy_.get(); }
-
-  SignalStrategy* xmpp_signal_strategy() { return xmpp_signal_strategy_.get(); }
-
- private:
-  enum class MuxingState {
-    ALL_DISCONNECTED,
-    SOME_CONNECTING,
-    ONLY_ONE_CONNECTED_BEFORE_TIMEOUT,
-    ALL_CONNECTED,
-    ONLY_ONE_CONNECTED_AFTER_TIMEOUT,
-  };
-
-  SignalStrategy* GetSignalStrategyForStanza(
-      const jingle_xmpp::XmlElement* stanza);
-
-  // Returns true if the state is updated.
-  bool UpdateState();
-
-  void OnWaitForAllStrategiesConnectedTimeout();
-
-  // SignalStrategy::Listener implementations.
-  void OnSignalStrategyStateChange(SignalStrategy::State state) override;
-  bool OnSignalStrategyIncomingStanza(
-      const jingle_xmpp::XmlElement* stanza) override;
-
-  bool IsAnyStrategyConnected() const;
-  bool IsEveryStrategyConnected() const;
-  bool IsEveryStrategyDisconnected() const;
-
-  base::ObserverList<SignalStrategy::Listener> listeners_;
-
-  std::unique_ptr<SignalStrategy> ftl_signal_strategy_;
-  std::unique_ptr<SignalStrategy> xmpp_signal_strategy_;
-
-  SignalingAddress current_local_address_;
-  MuxingState state_ = MuxingState::ALL_DISCONNECTED;
-
-  base::OneShotTimer wait_for_all_strategies_connected_timeout_timer_;
-
-  SEQUENCE_CHECKER(sequence_checker_);
-
-  base::WeakPtrFactory<Core> weak_factory_;
-  DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-MuxingSignalStrategy::Core::Core(
-    std::unique_ptr<SignalStrategy> ftl_signal_strategy,
-    std::unique_ptr<SignalStrategy> xmpp_signal_strategy)
-    : weak_factory_(this) {
-  ftl_signal_strategy_ = std::move(ftl_signal_strategy);
-  xmpp_signal_strategy_ = std::move(xmpp_signal_strategy);
-  DCHECK(ftl_signal_strategy_);
-  DCHECK(xmpp_signal_strategy_);
-  DCHECK_EQ(State::DISCONNECTED, ftl_signal_strategy_->GetState());
-  DCHECK_EQ(State::DISCONNECTED, xmpp_signal_strategy_->GetState());
-  ftl_signal_strategy_->AddListener(this);
-  xmpp_signal_strategy_->AddListener(this);
-
-  UpdateState();
-}
-
-MuxingSignalStrategy::Core::~Core() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(!ftl_signal_strategy_);
-  DCHECK(!xmpp_signal_strategy_);
-}
-
-void MuxingSignalStrategy::Core::Invalidate() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  wait_for_all_strategies_connected_timeout_timer_.AbandonAndStop();
-  ftl_signal_strategy_->RemoveListener(this);
-  xmpp_signal_strategy_->RemoveListener(this);
-  ftl_signal_strategy_.reset();
-  xmpp_signal_strategy_.reset();
-}
-
-void MuxingSignalStrategy::Core::Connect() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  ftl_signal_strategy_->Connect();
-  xmpp_signal_strategy_->Connect();
-}
-
-SignalStrategy::State MuxingSignalStrategy::Core::GetState() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  switch (state_) {
-    case MuxingState::ALL_DISCONNECTED:
-      return State::DISCONNECTED;
-    case MuxingState::SOME_CONNECTING:
-    case MuxingState::ONLY_ONE_CONNECTED_BEFORE_TIMEOUT:
-      return State::CONNECTING;
-    case MuxingState::ONLY_ONE_CONNECTED_AFTER_TIMEOUT:
-    case MuxingState::ALL_CONNECTED:
-      return State::CONNECTED;
-    default:
-      NOTREACHED();
-      return State::DISCONNECTED;
-  }
-}
-
-const SignalingAddress& MuxingSignalStrategy::Core::GetLocalAddress() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK(!current_local_address_.empty())
-      << "GetLocalAddress() can only be called inside "
-      << "OnSignalStrategyIncomingStanza().";
-  return current_local_address_;
-}
-
-void MuxingSignalStrategy::Core::AddListener(
-    SignalStrategy::Listener* listener) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  listeners_.AddObserver(listener);
-}
-
-void MuxingSignalStrategy::Core::RemoveListener(
-    SignalStrategy::Listener* listener) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  listeners_.RemoveObserver(listener);
-}
-
-bool MuxingSignalStrategy::Core::SendStanza(
-    std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  SignalStrategy* strategy = GetSignalStrategyForStanza(stanza.get());
-  if (!strategy) {
-    return false;
-  }
-  return strategy->SendStanza(std::move(stanza));
-}
-
-SignalStrategy* MuxingSignalStrategy::Core::GetSignalStrategyForStanza(
-    const jingle_xmpp::XmlElement* stanza) {
-  std::string error;
-  SignalingAddress receiver =
-      SignalingAddress::Parse(stanza, SignalingAddress::TO, &error);
-  if (!error.empty()) {
-    LOG(DFATAL) << "Failed to parse receiver address: " << error;
-    return nullptr;
-  }
-  if (receiver.channel() == SignalingAddress::Channel::FTL) {
-    DCHECK(ftl_signal_strategy_->GetLocalAddress().empty() ||
-           ftl_signal_strategy_->GetLocalAddress().channel() ==
-               SignalingAddress::Channel::FTL)
-        << "|ftl_signal_strategy_|'s local address channel is not FTL. "
-        << "You might have flipped the signal strategies. "
-        << "Local address: " << ftl_signal_strategy_->GetLocalAddress().jid();
-    return ftl_signal_strategy_.get();
-  } else {
-    DCHECK(xmpp_signal_strategy_->GetLocalAddress().empty() ||
-           xmpp_signal_strategy_->GetLocalAddress().channel() !=
-               SignalingAddress::Channel::FTL)
-        << "|xmpp_signal_strategy_|'s local address channel is FTL. "
-        << "You might have flipped the signal strategies. "
-        << "Local address: " << xmpp_signal_strategy_->GetLocalAddress().jid();
-  }
-  return xmpp_signal_strategy_.get();
-}
-
-bool MuxingSignalStrategy::Core::UpdateState() {
-  MuxingState new_state = state_;
-  if (IsEveryStrategyConnected()) {
-    wait_for_all_strategies_connected_timeout_timer_.AbandonAndStop();
-    new_state = MuxingState::ALL_CONNECTED;
-  } else if (IsEveryStrategyDisconnected()) {
-    wait_for_all_strategies_connected_timeout_timer_.AbandonAndStop();
-    new_state = MuxingState::ALL_DISCONNECTED;
-  } else if (IsAnyStrategyConnected()) {
-    if (state_ == MuxingState::ALL_CONNECTED  // One connection is dropped
-        || (state_ == MuxingState::ONLY_ONE_CONNECTED_BEFORE_TIMEOUT &&
-            !wait_for_all_strategies_connected_timeout_timer_.IsRunning())) {
-      new_state = MuxingState::ONLY_ONE_CONNECTED_AFTER_TIMEOUT;
-    } else if (state_ != MuxingState::ONLY_ONE_CONNECTED_AFTER_TIMEOUT) {
-      new_state = MuxingState::ONLY_ONE_CONNECTED_BEFORE_TIMEOUT;
-      if (!wait_for_all_strategies_connected_timeout_timer_.IsRunning()) {
-        wait_for_all_strategies_connected_timeout_timer_.Start(
-            FROM_HERE, kWaitForAllStrategiesConnectedTimeout, this,
-            &MuxingSignalStrategy::Core::
-                OnWaitForAllStrategiesConnectedTimeout);
-      }
-    }
-    // Otherwise we are not changing the state unless all strategies are
-    // connected or all strategies are disconnected.
-  } else {
-    new_state = MuxingState::SOME_CONNECTING;
-  }
-  if (state_ == new_state) {
-    return false;
-  }
-  state_ = new_state;
-  return true;
-}
-
-void MuxingSignalStrategy::Core::OnWaitForAllStrategiesConnectedTimeout() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
-  if (!IsEveryStrategyConnected()) {
-    LOG(WARNING) << "Timeout waiting for all strategies to be connected.";
-    OnSignalStrategyStateChange(/* unused */ State::CONNECTED);
-  }
-}
-
-void MuxingSignalStrategy::Core::OnSignalStrategyStateChange(
-    SignalStrategy::State unused) {
-  bool is_state_changed = UpdateState();
-  if (is_state_changed) {
-    for (auto& listener : listeners_) {
-      listener.OnSignalStrategyStateChange(GetState());
-    }
-  }
-}
-
-bool MuxingSignalStrategy::Core::OnSignalStrategyIncomingStanza(
-    const jingle_xmpp::XmlElement* stanza) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  SignalStrategy* strategy = GetSignalStrategyForStanza(stanza);
-  DCHECK(current_local_address_.empty());
-  current_local_address_ = strategy->GetLocalAddress();
-  bool message_handled = false;
-  for (auto& listener : listeners_) {
-    if (listener.OnSignalStrategyIncomingStanza(stanza)) {
-      message_handled = true;
-      break;
-    }
-  }
-  current_local_address_ = SignalingAddress();
-  return message_handled;
-}
-
-bool MuxingSignalStrategy::Core::IsAnyStrategyConnected() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return xmpp_signal_strategy_->GetState() == State::CONNECTED ||
-         ftl_signal_strategy_->GetState() == State::CONNECTED;
-}
-
-bool MuxingSignalStrategy::Core::IsEveryStrategyConnected() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return xmpp_signal_strategy_->GetState() == State::CONNECTED &&
-         ftl_signal_strategy_->GetState() == State::CONNECTED;
-}
-
-bool MuxingSignalStrategy::Core::IsEveryStrategyDisconnected() const {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  return xmpp_signal_strategy_->GetState() == State::DISCONNECTED &&
-         ftl_signal_strategy_->GetState() == State::DISCONNECTED;
-}
-
-MuxingSignalStrategy::MuxingSignalStrategy(
-    std::unique_ptr<SignalStrategy> ftl_signal_strategy,
-    std::unique_ptr<SignalStrategy> xmpp_signal_strategy)
-    : ftl_signal_strategy_(std::move(ftl_signal_strategy)),
-      xmpp_signal_strategy_(std::move(xmpp_signal_strategy)) {}
-
-MuxingSignalStrategy::~MuxingSignalStrategy() {
-  if (!core_) {
-    // The core has never been created. Just do nothing.
-    return;
-  }
-  GetCore()->Invalidate();
-  base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE,
-                                                     std::move(core_));
-}
-
-void MuxingSignalStrategy::Connect() {
-  GetCore()->Connect();
-}
-
-SignalStrategy::State MuxingSignalStrategy::GetState() const {
-  return GetCore()->GetState();
-}
-
-const SignalingAddress& MuxingSignalStrategy::GetLocalAddress() const {
-  return GetCore()->GetLocalAddress();
-}
-
-void MuxingSignalStrategy::AddListener(SignalStrategy::Listener* listener) {
-  GetCore()->AddListener(listener);
-}
-
-void MuxingSignalStrategy::RemoveListener(SignalStrategy::Listener* listener) {
-  GetCore()->RemoveListener(listener);
-}
-
-bool MuxingSignalStrategy::SendStanza(
-    std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-  return GetCore()->SendStanza(std::move(stanza));
-}
-
-std::string MuxingSignalStrategy::GetNextId() {
-  return base::NumberToString(base::RandUint64());
-}
-
-SignalStrategy* MuxingSignalStrategy::ftl_signal_strategy() {
-  return GetCore()->ftl_signal_strategy();
-}
-
-SignalStrategy* MuxingSignalStrategy::xmpp_signal_strategy() {
-  return GetCore()->xmpp_signal_strategy();
-}
-
-void MuxingSignalStrategy::Disconnect() {
-  NOTREACHED();
-}
-
-SignalStrategy::Error MuxingSignalStrategy::GetError() const {
-  NOTREACHED();
-  return Error::NETWORK_ERROR;
-}
-
-MuxingSignalStrategy::Core* MuxingSignalStrategy::GetCore() {
-  return GetCoreImpl();
-}
-
-const MuxingSignalStrategy::Core* MuxingSignalStrategy::GetCore() const {
-  return const_cast<MuxingSignalStrategy*>(this)->GetCoreImpl();
-}
-
-MuxingSignalStrategy::Core* MuxingSignalStrategy::GetCoreImpl() {
-  if (!core_) {
-    core_ = std::make_unique<Core>(std::move(ftl_signal_strategy_),
-                                   std::move(xmpp_signal_strategy_));
-  }
-  return core_.get();
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/muxing_signal_strategy.h b/remoting/signaling/muxing_signal_strategy.h
deleted file mode 100644
index 69593b5..0000000
--- a/remoting/signaling/muxing_signal_strategy.h
+++ /dev/null
@@ -1,91 +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 REMOTING_SIGNALING_MUXING_SIGNAL_STRATEGY_H_
-#define REMOTING_SIGNALING_MUXING_SIGNAL_STRATEGY_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "remoting/signaling/signal_strategy.h"
-
-namespace remoting {
-
-// WARNING: This class is designed to be used exclusively by
-// JingleSessionManager on the host during the XMPP->FTL signaling migration
-// process. It doesn't support anything other than sending and receiving
-// stanzas. Use (Ftl|Xmpp)SignalStrategy directly if possible.
-//
-// MuxingSignalStrategy multiplexes FtlSignalStrategy and XmppSignalStrategy.
-// It can accept stanzas with FTL or XMPP receiver and forward them to the
-// proper SignalStrategy.
-//
-// Caller can create MuxingSignalStrategy on one thread and thereafter use it
-// on another thread.
-class MuxingSignalStrategy final : public SignalStrategy {
- public:
-  MuxingSignalStrategy(std::unique_ptr<SignalStrategy> ftl_signal_strategy,
-                       std::unique_ptr<SignalStrategy> xmpp_signal_strategy);
-  ~MuxingSignalStrategy() override;
-
-  // SignalStrategy implementations.
-
-  // This will connect both |ftl_signal_strategy_| and |xmpp_signal_strategy_|.
-  void Connect() override;
-
-  // The state is a mapping of the MuxingState (defined in
-  // MuxingSignalStrategy::Core):
-  //
-  // ALL_DISCONNECTED -> DISCONNECTED
-  // SOME_CONNECTING, ONLY_ONE_CONNECTED_BEFORE_TIMEOUT -> CONNECTING
-  // ALL_CONNECTED, ONLY_ONE_CONNECTED_AFTER_TIMEOUT -> CONNECTED
-  //
-  // Note that MuxingSignalStrategy will notify listeners whenever the muxing
-  // state is changed, which means listeners may get notified for
-  // CONNECTING->CONNECTING and CONNECTED->CONNECTED transitions. This is to
-  // allow heartbeat sender to send new heartbeat when a strategy is connected
-  // or disconnected after the timeout.
-  State GetState() const override;
-
-  // GetLocalAddress() can only be called inside
-  // OnSignalStrategyIncomingStanza().
-  const SignalingAddress& GetLocalAddress() const override;
-
-  void AddListener(SignalStrategy::Listener* listener) override;
-  void RemoveListener(SignalStrategy::Listener* listener) override;
-
-  bool SendStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza) override;
-  std::string GetNextId() override;
-
-  SignalStrategy* ftl_signal_strategy();
-  SignalStrategy* xmpp_signal_strategy();
-
- private:
-  class Core;
-
-  // These methods are not supported. Caller should directly call them on the
-  // underlying signal strategies instead.
-  void Disconnect() override;
-  Error GetError() const override;
-
-  // Returns pointer to the core, and creates a core if it has not been created.
-  //
-  // The Core constructor will bind the underlying signal strategies to the
-  // current sequence, so we delay construction of the core so that user can
-  // create MuxingSignalStrategy on one sequence and use it on another sequence.
-  Core* GetCore();
-  const Core* GetCore() const;
-  Core* GetCoreImpl();
-
-  // These will be moved to |core_| once the core is created.
-  std::unique_ptr<SignalStrategy> ftl_signal_strategy_;
-  std::unique_ptr<SignalStrategy> xmpp_signal_strategy_;
-
-  std::unique_ptr<Core> core_;
-  DISALLOW_COPY_AND_ASSIGN(MuxingSignalStrategy);
-};
-
-}  // namespace remoting
-
-#endif  // REMOTING_SIGNALING_MUXING_SIGNAL_STRATEGY_H_
diff --git a/remoting/signaling/muxing_signal_strategy_unittest.cc b/remoting/signaling/muxing_signal_strategy_unittest.cc
deleted file mode 100644
index 2df6cab1..0000000
--- a/remoting/signaling/muxing_signal_strategy_unittest.cc
+++ /dev/null
@@ -1,340 +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.
-
-#include "remoting/signaling/muxing_signal_strategy.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/memory/ptr_util.h"
-#include "base/test/mock_callback.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/time/time.h"
-#include "remoting/signaling/fake_signal_strategy.h"
-#include "remoting/signaling/signaling_address.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-#include "third_party/libjingle_xmpp/xmpp/constants.h"
-
-namespace remoting {
-
-namespace {
-
-using testing::_;
-using testing::Return;
-
-constexpr char kLocalFtlId[] = "local_user@domain.com/chromoting_ftl_abc123";
-constexpr char kRemoteFtlId[] = "remote_user@domain.com/chromoting_ftl_def456";
-constexpr char kLocalJabberId[] = "local_user@domain.com/chromotingABC123";
-constexpr char kRemoteJabberId[] = "remote_user@domain.com/chromotingDEF456";
-
-constexpr base::TimeDelta kWaitForAllStrategiesConnectedTimeout =
-    base::TimeDelta::FromSecondsD(5.5);
-
-MATCHER_P(StanzaMatchesString, expected_str, "") {
-  return arg->Str() == expected_str;
-}
-
-std::unique_ptr<jingle_xmpp::XmlElement> CreateXmlStanza(
-    const std::string& from,
-    const std::string& to) {
-  static constexpr char kStanzaTemplate[] =
-      "<iq xmlns=\"jabber:client\" type=\"set\">"
-      "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
-      "<resource>chromoting</resource>"
-      "</bind>"
-      "</iq>";
-  auto stanza = base::WrapUnique<jingle_xmpp::XmlElement>(
-      jingle_xmpp::XmlElement::ForStr(kStanzaTemplate));
-  stanza->SetAttr(jingle_xmpp::QN_FROM, from);
-  stanza->SetAttr(jingle_xmpp::QN_TO, to);
-  return stanza;
-}
-
-}  // namespace
-
-class MuxingSignalStrategyTest : public testing::Test,
-                                 public SignalStrategy::Listener {
- public:
-  MuxingSignalStrategyTest() {
-    auto ftl_signal_strategy =
-        std::make_unique<FakeSignalStrategy>(SignalingAddress(kLocalFtlId));
-    auto xmpp_signal_strategy =
-        std::make_unique<FakeSignalStrategy>(SignalingAddress(kLocalJabberId));
-    ftl_signal_strategy_ = ftl_signal_strategy.get();
-    xmpp_signal_strategy_ = xmpp_signal_strategy.get();
-
-    // Start in disconnected state.
-    ftl_signal_strategy_->Disconnect();
-    xmpp_signal_strategy_->Disconnect();
-
-    ftl_signal_strategy_->SetPeerCallback(mock_ftl_peer_callback_.Get());
-    xmpp_signal_strategy_->SetPeerCallback(mock_xmpp_peer_callback_.Get());
-
-    muxing_signal_strategy_ = std::make_unique<MuxingSignalStrategy>(
-        std::move(ftl_signal_strategy), std::move(xmpp_signal_strategy));
-    muxing_signal_strategy_->AddListener(this);
-  }
-
-  ~MuxingSignalStrategyTest() override {
-    muxing_signal_strategy_->RemoveListener(this);
-    muxing_signal_strategy_.reset();
-    scoped_task_environment_.FastForwardUntilNoTasksRemain();
-  }
-
- protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
-
-  std::unique_ptr<MuxingSignalStrategy> muxing_signal_strategy_;
-
-  FakeSignalStrategy* ftl_signal_strategy_;
-  FakeSignalStrategy* xmpp_signal_strategy_;
-
-  base::MockCallback<FakeSignalStrategy::PeerCallback> mock_ftl_peer_callback_;
-  base::MockCallback<FakeSignalStrategy::PeerCallback> mock_xmpp_peer_callback_;
-
-  std::vector<SignalStrategy::State> state_history_;
-  std::vector<std::unique_ptr<jingle_xmpp::XmlElement>> received_messages_;
-  std::vector<SignalingAddress> received_stanza_local_addresses_;
-
- private:
-  // SignalStrategy::Listener overrides.
-  void OnSignalStrategyStateChange(SignalStrategy::State state) override {
-    state_history_.push_back(state);
-  }
-
-  bool OnSignalStrategyIncomingStanza(
-      const jingle_xmpp::XmlElement* stanza) override {
-    received_messages_.push_back(
-        std::make_unique<jingle_xmpp::XmlElement>(*stanza));
-    received_stanza_local_addresses_.push_back(
-        muxing_signal_strategy_->GetLocalAddress());
-    return true;
-  }
-};
-
-TEST_F(MuxingSignalStrategyTest, StateTransition_NothingIsConnected) {
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-
-  ASSERT_EQ(0u, state_history_.size());
-}
-
-TEST_F(MuxingSignalStrategyTest, StateTransition_OnlyXmppIsConnected) {
-  xmpp_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  xmpp_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-
-  ASSERT_EQ(3u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ONLY_ONE_CONNECTED_AFTER_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-}
-
-TEST_F(MuxingSignalStrategyTest, StateTransition_OnlyFtlIsConnected) {
-  ftl_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  ftl_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-
-  ASSERT_EQ(3u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ONLY_ONE_CONNECTED_AFTER_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-}
-
-TEST_F(MuxingSignalStrategyTest,
-       StateTransition_BothAreConnectingThenConnected) {
-  xmpp_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  ftl_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  xmpp_signal_strategy_->Connect();
-  ftl_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-
-  ASSERT_EQ(3u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ALL_CONNECTED
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-}
-
-TEST_F(MuxingSignalStrategyTest,
-       StateTransition_ConnectingThenConnectedOneAfterAnother) {
-  xmpp_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  xmpp_signal_strategy_->Connect();
-  ftl_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  ftl_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-
-  ASSERT_EQ(3u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ALL_CONNECTED
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-}
-
-TEST_F(
-    MuxingSignalStrategyTest,
-    StateTransition_StartedConnectionBeforeTimeoutAndTheOtherStartedConnectionAfterTimeout) {
-  xmpp_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  xmpp_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-  ftl_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  ftl_signal_strategy_->Connect();
-
-  ASSERT_EQ(4u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ONLY_ONE_CONNECTED_AFTER_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-
-  // ALL_CONNECTED
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[3]);
-}
-
-TEST_F(
-    MuxingSignalStrategyTest,
-    StateTransition_OneConnectedBeforeTimeoutAndTheOtherConnectedAfterTimeout) {
-  xmpp_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  ftl_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  xmpp_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-  ftl_signal_strategy_->Connect();
-
-  ASSERT_EQ(4u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ONLY_ONE_CONNECTED_AFTER_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-
-  // ALL_CONNECTED
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[3]);
-}
-
-TEST_F(MuxingSignalStrategyTest, StateTransition_OneConnectedThenDisconnected) {
-  xmpp_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  xmpp_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-  xmpp_signal_strategy_->Disconnect();
-
-  ASSERT_EQ(4u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ONLY_ONE_CONNECTED_AFTER_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-
-  // ALL_DISCONNECTED
-  ASSERT_EQ(SignalStrategy::DISCONNECTED, state_history_[3]);
-}
-
-TEST_F(MuxingSignalStrategyTest,
-       StateTransition_BothConnectedThenDisconnectedOneByOne) {
-  xmpp_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  ftl_signal_strategy_->SetState(SignalStrategy::CONNECTING);
-  xmpp_signal_strategy_->Connect();
-  ftl_signal_strategy_->Connect();
-  scoped_task_environment_.FastForwardBy(kWaitForAllStrategiesConnectedTimeout);
-  xmpp_signal_strategy_->Disconnect();
-  ftl_signal_strategy_->Disconnect();
-
-  ASSERT_EQ(5u, state_history_.size());
-
-  // SOME_CONNECTING
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // ONLY_ONE_CONNECTED_BEFORE_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTING, state_history_[1]);
-
-  // ALL_CONNECTED
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[2]);
-
-  // ONLY_ONE_CONNECTED_AFTER_TIMEOUT
-  ASSERT_EQ(SignalStrategy::CONNECTED, state_history_[3]);
-
-  // ALL_DISCONNECTED
-  ASSERT_EQ(SignalStrategy::DISCONNECTED, state_history_[4]);
-}
-
-TEST_F(MuxingSignalStrategyTest, SendStanza_MessageRoutedToFtlSignalStrategy) {
-  xmpp_signal_strategy_->Connect();
-  ftl_signal_strategy_->Connect();
-
-  auto stanza = CreateXmlStanza(kLocalFtlId, kRemoteFtlId);
-  std::string stanza_string = stanza->Str();
-  EXPECT_CALL(mock_ftl_peer_callback_, Run(StanzaMatchesString(stanza_string)))
-      .WillOnce(Return());
-  muxing_signal_strategy_->SendStanza(std::move(stanza));
-}
-
-TEST_F(MuxingSignalStrategyTest, SendStanza_MessageRoutedToXmppSignalStrategy) {
-  xmpp_signal_strategy_->Connect();
-  ftl_signal_strategy_->Connect();
-
-  auto stanza = CreateXmlStanza(kLocalJabberId, kRemoteJabberId);
-  std::string stanza_string = stanza->Str();
-  EXPECT_CALL(mock_xmpp_peer_callback_, Run(StanzaMatchesString(stanza_string)))
-      .WillOnce(Return());
-  muxing_signal_strategy_->SendStanza(std::move(stanza));
-}
-
-TEST_F(MuxingSignalStrategyTest,
-       ReceiveStanza_MessagesFromBothStrategiesAreReceived) {
-  xmpp_signal_strategy_->Connect();
-  ftl_signal_strategy_->Connect();
-
-  xmpp_signal_strategy_->OnIncomingMessage(
-      CreateXmlStanza(kRemoteJabberId, kLocalJabberId));
-  ftl_signal_strategy_->OnIncomingMessage(
-      CreateXmlStanza(kRemoteFtlId, kLocalFtlId));
-
-  ASSERT_EQ(2u, received_messages_.size());
-  ASSERT_EQ(kRemoteJabberId, received_messages_[0]->Attr(jingle_xmpp::QN_FROM));
-  ASSERT_EQ(kLocalJabberId, received_messages_[0]->Attr(jingle_xmpp::QN_TO));
-  ASSERT_EQ(kRemoteFtlId, received_messages_[1]->Attr(jingle_xmpp::QN_FROM));
-  ASSERT_EQ(kLocalFtlId, received_messages_[1]->Attr(jingle_xmpp::QN_TO));
-
-  ASSERT_EQ(2u, received_stanza_local_addresses_.size());
-  ASSERT_EQ(kLocalJabberId, received_stanza_local_addresses_[0].jid());
-  ASSERT_EQ(kLocalFtlId, received_stanza_local_addresses_[1].jid());
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/xmpp_login_handler.cc b/remoting/signaling/xmpp_login_handler.cc
deleted file mode 100644
index f331f27..0000000
--- a/remoting/signaling/xmpp_login_handler.cc
+++ /dev/null
@@ -1,242 +0,0 @@
-// Copyright 2015 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 "remoting/signaling/xmpp_login_handler.h"
-
-#include <utility>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/logging.h"
-#include "remoting/signaling/xmpp_stream_parser.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-
-// Undefine SendMessage and ERROR defined in Windows headers.
-#ifdef SendMessage
-#undef SendMessage
-#endif
-
-#ifdef ERROR
-#undef ERROR
-#endif
-
-namespace remoting {
-
-const char kOAuthMechanism[] = "X-OAUTH2";
-
-jingle_xmpp::StaticQName kXmppIqName = {"jabber:client", "iq"};
-
-char kXmppBindNs[] = "urn:ietf:params:xml:ns:xmpp-bind";
-jingle_xmpp::StaticQName kXmppBindName = {kXmppBindNs, "bind"};
-jingle_xmpp::StaticQName kXmppJidName = {kXmppBindNs, "jid"};
-
-jingle_xmpp::StaticQName kJabberFeaturesName = {"http://etherx.jabber.org/streams",
-                                         "features"};
-
-char kXmppTlsNs[] = "urn:ietf:params:xml:ns:xmpp-tls";
-jingle_xmpp::StaticQName kStartTlsName = {kXmppTlsNs, "starttls"};
-jingle_xmpp::StaticQName kTlsProceedName = {kXmppTlsNs, "proceed"};
-
-char kXmppSaslNs[] = "urn:ietf:params:xml:ns:xmpp-sasl";
-jingle_xmpp::StaticQName kSaslMechanismsName = {kXmppSaslNs, "mechanisms"};
-jingle_xmpp::StaticQName kSaslMechanismName = {kXmppSaslNs, "mechanism"};
-jingle_xmpp::StaticQName kSaslSuccessName = {kXmppSaslNs, "success"};
-
-XmppLoginHandler::XmppLoginHandler(const std::string& server,
-                                   const std::string& username,
-                                   const std::string& auth_token,
-                                   TlsMode tls_mode,
-                                   Delegate* delegate)
-    : server_(server),
-      username_(username),
-      auth_token_(auth_token),
-      tls_mode_(tls_mode),
-      delegate_(delegate),
-      state_(State::INIT) {
-}
-
-XmppLoginHandler::~XmppLoginHandler() = default;
-
-void XmppLoginHandler::Start() {
-  switch (tls_mode_) {
-    case TlsMode::NO_TLS:
-      state_ = State::WAIT_STREAM_HEADER_AFTER_TLS;
-      StartAuthHandshake();
-      break;
-    case TlsMode::WITH_HANDSHAKE:
-      state_ = State::WAIT_STREAM_HEADER;
-      StartStream("<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
-      break;
-    case TlsMode::WITHOUT_HANDSHAKE:
-      // If <starttls> handshake is not required then start TLS right away.
-      state_ = State::STARTING_TLS;
-      delegate_->StartTls();
-      break;
-  }
-}
-
-void XmppLoginHandler::OnDataReceived(const std::string& data) {
-  DCHECK(state_ != State::INIT && state_ != State::DONE &&
-         state_ != State::ERROR);
-  stream_parser_->AppendData(data);
-}
-
-void XmppLoginHandler::OnStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-  switch (state_) {
-    case State::WAIT_STREAM_HEADER: {
-      if (stanza->Name() == kJabberFeaturesName &&
-          stanza->FirstNamed(kStartTlsName) != nullptr) {
-        state_ = State::WAIT_STARTTLS_RESPONSE;
-      } else {
-        LOG(ERROR) << "Server doesn't support TLS.";
-        OnError(SignalStrategy::PROTOCOL_ERROR);
-      }
-      break;
-    }
-
-    case State::WAIT_STARTTLS_RESPONSE: {
-      if (stanza->Name() == kTlsProceedName) {
-        state_ = State::STARTING_TLS;
-        delegate_->StartTls();
-      } else {
-        LOG(ERROR) << "Failed to start TLS: " << stanza->Str();
-        OnError(SignalStrategy::PROTOCOL_ERROR);
-      }
-      break;
-    }
-
-    case State::WAIT_STREAM_HEADER_AFTER_TLS: {
-      jingle_xmpp::XmlElement* mechanisms_element =
-          stanza->FirstNamed(kSaslMechanismsName);
-      bool oauth_supported = false;
-      if (mechanisms_element) {
-        for (jingle_xmpp::XmlElement* element =
-                 mechanisms_element->FirstNamed(kSaslMechanismName);
-             element; element = element->NextNamed(kSaslMechanismName)) {
-          if (element->BodyText() == kOAuthMechanism) {
-            oauth_supported = true;
-            break;
-          }
-        }
-      }
-
-      if (!oauth_supported) {
-        LOG(ERROR) << kOAuthMechanism
-                   << " auth mechanism is not supported by the server.";
-        OnError(SignalStrategy::PROTOCOL_ERROR);
-        return;
-      }
-
-      state_ = State::WAIT_AUTH_RESULT;
-      break;
-    }
-
-    case State::WAIT_AUTH_RESULT: {
-      if (stanza->Name() == kSaslSuccessName) {
-        state_ = State::WAIT_STREAM_HEADER_AFTER_AUTH;
-        StartStream(
-            "<iq type=\"set\" id=\"0\">"
-              "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
-                "<resource>chromoting</resource>"
-              "</bind>"
-            "</iq>"
-            "<iq type=\"set\" id=\"1\">"
-              "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
-            "</iq>");
-      } else {
-        OnError(SignalStrategy::AUTHENTICATION_FAILED);
-      }
-      break;
-    }
-
-    case State::WAIT_STREAM_HEADER_AFTER_AUTH:
-      if (stanza->Name() == kJabberFeaturesName &&
-          stanza->FirstNamed(kXmppBindName) != nullptr) {
-        state_ = State::WAIT_BIND_RESULT;
-      } else {
-        LOG(ERROR) << "Server doesn't support bind after authentication.";
-        OnError(SignalStrategy::PROTOCOL_ERROR);
-      }
-      break;
-
-    case State::WAIT_BIND_RESULT: {
-      jingle_xmpp::XmlElement* bind = stanza->FirstNamed(kXmppBindName);
-      jingle_xmpp::XmlElement* jid = bind ? bind->FirstNamed(kXmppJidName) : nullptr;
-      if (stanza->Attr(jingle_xmpp::QName("", "id")) != "0" ||
-          stanza->Attr(jingle_xmpp::QName("", "type")) != "result" || !jid) {
-        LOG(ERROR) << "Received unexpected response to bind: " << stanza->Str();
-        OnError(SignalStrategy::PROTOCOL_ERROR);
-        return;
-      }
-      jid_ = jid->BodyText();
-      state_ = State::WAIT_SESSION_IQ_RESULT;
-      break;
-    }
-
-    case State::WAIT_SESSION_IQ_RESULT:
-      if (stanza->Name() != kXmppIqName ||
-          stanza->Attr(jingle_xmpp::QName("", "id")) != "1" ||
-          stanza->Attr(jingle_xmpp::QName("", "type")) != "result") {
-        LOG(ERROR) << "Failed to start session: " << stanza->Str();
-        OnError(SignalStrategy::PROTOCOL_ERROR);
-        return;
-      }
-      state_ = State::DONE;
-      delegate_->OnHandshakeDone(jid_, std::move(stream_parser_));
-      break;
-
-    default:
-      NOTREACHED();
-      break;
-  }
-}
-
-void XmppLoginHandler::OnTlsStarted() {
-  DCHECK(state_ == State::STARTING_TLS);
-  state_ = State::WAIT_STREAM_HEADER_AFTER_TLS;
-  StartAuthHandshake();
-}
-
-void XmppLoginHandler::StartAuthHandshake() {
-  DCHECK(state_ == State::WAIT_STREAM_HEADER_AFTER_TLS);
-
-  std::string cookie;
-  base::Base64Encode(
-      std::string("\0", 1) + username_ + std::string("\0", 1) + auth_token_,
-      &cookie);
-  StartStream(
-      "<auth xmlns=\"" + std::string(kXmppSaslNs) + "\" "
-             "mechanism=\"" +  "X-OAUTH2" + "\" "
-             "auth:service=\"oauth2\" "
-             "auth:allow-generated-jid=\"true\" "
-             "auth:client-uses-full-bind-result=\"true\" "
-             "auth:allow-non-google-login=\"true\" "
-             "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" +
-        cookie +
-      "</auth>");
-}
-
-void XmppLoginHandler::OnParserError() {
-  OnError(SignalStrategy::PROTOCOL_ERROR);
-}
-
-void XmppLoginHandler::StartStream(const std::string& first_message) {
-  stream_parser_.reset(new XmppStreamParser());
-  stream_parser_->SetCallbacks(
-      base::Bind(&XmppLoginHandler::OnStanza, base::Unretained(this)),
-      base::Bind(&XmppLoginHandler::OnParserError, base::Unretained(this)));
-  delegate_->SendMessage("<stream:stream to=\"" + server_ +
-                         "\" version=\"1.0\" xmlns=\"jabber:client\" "
-                         "xmlns:stream=\"http://etherx.jabber.org/streams\">" +
-                         first_message);
-}
-
-void XmppLoginHandler::OnError(SignalStrategy::Error error) {
-  if (state_ != State::ERROR) {
-    state_ = State::ERROR;
-    delegate_->OnLoginHandlerError(error);
-  }
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/xmpp_login_handler.h b/remoting/signaling/xmpp_login_handler.h
deleted file mode 100644
index 46c8b0d..0000000
--- a/remoting/signaling/xmpp_login_handler.h
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2015 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 REMOTING_SIGNALING_XMPP_LOGIN_HANDLER_H_
-#define REMOTING_SIGNALING_XMPP_LOGIN_HANDLER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "remoting/signaling/signal_strategy.h"
-
-// Undefine SendMessage and ERROR defined in Windows headers.
-#ifdef SendMessage
-#undef SendMessage
-#endif
-
-#ifdef ERROR
-#undef ERROR
-#endif
-
-namespace remoting {
-
-class XmppStreamParser;
-
-// XmppLoginHandler handles authentication handshake for XmppSignalStrategy. It
-// receives incoming data using onDataReceived(), calls Delegate::SendMessage()
-// to send outgoing messages and calls Delegate::OnHandshakeDone() after
-// authentication is finished successfully or Delegate::OnError() on error.
-//
-// See RFC3920 for description of XMPP and authentication handshake.
-class XmppLoginHandler {
- public:
-  class Delegate {
-   public:
-    Delegate() {}
-
-    // All Delegate methods are allowed to destroy XmppLoginHandler.
-    virtual void SendMessage(const std::string& message) = 0;
-    virtual void StartTls() = 0;
-    virtual void OnHandshakeDone(const std::string& jid,
-                                 std::unique_ptr<XmppStreamParser> parser) = 0;
-    virtual void OnLoginHandlerError(SignalStrategy::Error error) = 0;
-
-   protected:
-    virtual ~Delegate() {}
-  };
-
-  enum class TlsMode {
-    NO_TLS,
-    WITH_HANDSHAKE,
-    WITHOUT_HANDSHAKE,
-  };
-
-  XmppLoginHandler(const std::string& server,
-                   const std::string& username,
-                   const std::string& auth_token,
-                   TlsMode tls_mode,
-                   Delegate* delegate);
-  ~XmppLoginHandler();
-
-  void Start();
-  void OnDataReceived(const std::string& data);
-  void OnTlsStarted();
-
- private:
-  // States the handshake goes through. States are iterated from INIT to DONE
-  // sequentially, except for ERROR state which may be accepted at any point.
-  //
-  // Following messages are sent/received in each state:
-  //    INIT
-  //      client -> server: Stream header
-  //      client -> server: <starttls>
-  //    WAIT_STREAM_HEADER
-  //      client <- server: Stream header with list of supported features which
-  //          should include starttls.
-  //    WAIT_STARTTLS_RESPONSE
-  //      client <- server: <proceed>
-  //    STARTING_TLS
-  //      TLS handshake
-  //      client -> server: Stream header
-  //      client -> server: <auth> message with the OAuth2 token.
-  //    WAIT_STREAM_HEADER_AFTER_TLS
-  //      client <- server: Stream header with list of supported authentication
-  //          methods which is expected to include X-OAUTH2
-  //    WAIT_AUTH_RESULT
-  //      client <- server: <success> or <failure>
-  //      client -> server: Stream header
-  //      client -> server: <bind>
-  //      client -> server: <iq><session/></iq> to start the session
-  //    WAIT_STREAM_HEADER_AFTER_AUTH
-  //      client <- server: Stream header with list of features that should
-  //         include <bind>.
-  //    WAIT_BIND_RESULT
-  //      client <- server: <bind> result with JID.
-  //    WAIT_SESSION_IQ_RESULT
-  //      client <- server: result for <iq><session/></iq>
-  //    DONE
-  enum class State {
-    INIT,
-    WAIT_STREAM_HEADER,
-    WAIT_STARTTLS_RESPONSE,
-    STARTING_TLS,
-    WAIT_STREAM_HEADER_AFTER_TLS,
-    WAIT_AUTH_RESULT,
-    WAIT_STREAM_HEADER_AFTER_AUTH,
-    WAIT_BIND_RESULT,
-    WAIT_SESSION_IQ_RESULT,
-    DONE,
-    ERROR,
-  };
-
-  // Callbacks for XmppStreamParser.
-  void OnStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza);
-  void OnParserError();
-
-  // Starts authentication handshake in WAIT_STREAM_HEADER_AFTER_TLS state.
-  void StartAuthHandshake();
-
-  // Helper used to send stream header.
-  void StartStream(const std::string& first_message);
-
-  // Report the |error| to the delegate and changes |state_| to ERROR,
-  void OnError(SignalStrategy::Error error);
-
-  std::string server_;
-  std::string username_;
-  std::string auth_token_;
-  TlsMode tls_mode_;
-  Delegate* delegate_;
-
-  State state_;
-
-  std::string jid_;
-
-  std::unique_ptr<XmppStreamParser> stream_parser_;
-
-  DISALLOW_COPY_AND_ASSIGN(XmppLoginHandler);
-};
-
-}  // namespace remoting
-
-#endif  // REMOTING_SIGNALING_XMPP_LOGIN_HANDLER_H_
diff --git a/remoting/signaling/xmpp_login_handler_unittest.cc b/remoting/signaling/xmpp_login_handler_unittest.cc
deleted file mode 100644
index d47ddaf..0000000
--- a/remoting/signaling/xmpp_login_handler_unittest.cc
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2015 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 "remoting/signaling/xmpp_login_handler.h"
-
-#include <utility>
-
-#include "base/base64.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "remoting/signaling/xmpp_stream_parser.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-
-#ifdef SendMessage
-#undef SendMessage
-#endif
-
-#ifdef ERROR
-#undef ERROR
-#endif
-
-namespace remoting {
-
-char kTestUsername[] = "testUsername@gmail.com";
-char kTestToken[] = "testToken";
-
-class XmppLoginHandlerTest : public testing::Test,
-                             public XmppLoginHandler::Delegate {
- public:
-  XmppLoginHandlerTest()
-      : start_tls_called_(false), error_(SignalStrategy::OK) {}
-
-  void TearDown() override {
-    login_handler_.reset();
-    parser_.reset();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void SendMessage(const std::string& message) override {
-    sent_data_ += message;
-    if (delete_login_handler_from_delegate_)
-      login_handler_.reset();
-  }
-
-  void StartTls() override {
-    start_tls_called_ = true;
-    if (delete_login_handler_from_delegate_)
-      login_handler_.reset();
-  }
-
-  void OnHandshakeDone(const std::string& jid,
-                       std::unique_ptr<XmppStreamParser> parser) override {
-    jid_ = jid;
-    parser_ = std::move(parser);
-    if (delete_login_handler_from_delegate_)
-      login_handler_.reset();
-  }
-
-  void OnLoginHandlerError(SignalStrategy::Error error) override {
-    EXPECT_NE(error, SignalStrategy::OK);
-    error_ = error;
-    if (delete_login_handler_from_delegate_)
-      login_handler_.reset();
-  }
-
- protected:
-  void HandshakeBase();
-
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
-  std::unique_ptr<XmppLoginHandler> login_handler_;
-  std::string sent_data_;
-  bool start_tls_called_;
-  std::string jid_;
-  std::unique_ptr<XmppStreamParser> parser_;
-  SignalStrategy::Error error_;
-  bool delete_login_handler_from_delegate_ = false;
-};
-
-void XmppLoginHandlerTest::HandshakeBase() {
-  login_handler_.reset(
-      new XmppLoginHandler("google.com", kTestUsername, kTestToken,
-                           XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE, this));
-  login_handler_->Start();
-  EXPECT_TRUE(start_tls_called_);
-
-  login_handler_->OnTlsStarted();
-  std::string cookie;
-  base::Base64Encode(
-      std::string("\0", 1) + kTestUsername + std::string("\0", 1) + kTestToken,
-      &cookie);
-  EXPECT_EQ(
-      sent_data_,
-      "<stream:stream to=\"google.com\" version=\"1.0\" "
-          "xmlns=\"jabber:client\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\">"
-      "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-OAUTH2\" "
-          "auth:service=\"oauth2\" auth:allow-generated-jid=\"true\" "
-          "auth:client-uses-full-bind-result=\"true\" "
-          "auth:allow-non-google-login=\"true\" "
-          "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" + cookie +
-      "</auth>");
-  sent_data_.clear();
-
-  login_handler_->OnDataReceived(
-      "<stream:stream from=\"google.com\" id=\"DCDDE5171CB2154A\" "
-          "version=\"1.0\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\" "
-          "xmlns=\"jabber:client\">"
-        "<stream:features>"
-          "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
-            "<mechanism>X-OAUTH2</mechanism>"
-            "<mechanism>X-GOOGLE-TOKEN</mechanism>"
-            "<mechanism>PLAIN</mechanism>"
-          "</mechanisms>"
-        "</stream:features>");
-}
-
-TEST_F(XmppLoginHandlerTest, SuccessfulAuth) {
-  HandshakeBase();
-
-  login_handler_->OnDataReceived(
-      "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>");
-  EXPECT_EQ(
-      sent_data_,
-      "<stream:stream to=\"google.com\" version=\"1.0\" "
-          "xmlns=\"jabber:client\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\">"
-        "<iq type=\"set\" id=\"0\">"
-          "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
-            "<resource>chromoting</resource>"
-          "</bind>"
-        "</iq>"
-        "<iq type=\"set\" id=\"1\">"
-          "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
-        "</iq>");
-  sent_data_.clear();
-
-  // |login_handler_| will call OnHandshakeDone() which will delete
-  // |login_handler_|.
-  delete_login_handler_from_delegate_ = true;
-
-  login_handler_->OnDataReceived(
-      "<stream:stream from=\"google.com\" id=\"104FA10576E2AA80\" "
-          "version=\"1.0\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\" "
-          "xmlns=\"jabber:client\">"
-        "<stream:features>"
-          "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
-          "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
-        "</stream:features>"
-        "<iq id=\"0\" type=\"result\">"
-          "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
-            "<jid>" + std::string(kTestUsername) + "/chromoting52B4920E</jid>"
-          "</bind>"
-        "</iq>"
-        "<iq type=\"result\" id=\"1\"/>");
-
-  EXPECT_EQ(jid_, std::string(kTestUsername) + "/chromoting52B4920E");
-  EXPECT_TRUE(parser_);
-  EXPECT_FALSE(login_handler_);
-}
-
-TEST_F(XmppLoginHandlerTest, StartTlsHandshake) {
-  login_handler_.reset(
-      new XmppLoginHandler("google.com", kTestUsername, kTestToken,
-                           XmppLoginHandler::TlsMode::WITH_HANDSHAKE, this));
-  login_handler_->Start();
-  EXPECT_FALSE(start_tls_called_);
-
-  EXPECT_EQ(sent_data_,
-            "<stream:stream to=\"google.com\" version=\"1.0\" "
-            "xmlns=\"jabber:client\" "
-            "xmlns:stream=\"http://etherx.jabber.org/streams\">"
-            "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
-  sent_data_.clear();
-
-  login_handler_->OnDataReceived(
-      "<stream:stream from=\"google.com\" id=\"78A87C70559EF28A\" "
-          "version=\"1.0\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\" "
-          "xmlns=\"jabber:client\">"
-        "<stream:features>"
-          "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\">"
-            "<required/>"
-          "</starttls>"
-          "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
-            "<mechanism>X-OAUTH2</mechanism>"
-            "<mechanism>X-GOOGLE-TOKEN</mechanism>"
-          "</mechanisms>"
-        "</stream:features>");
-
-  login_handler_->OnDataReceived(
-      "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
-  EXPECT_TRUE(start_tls_called_);
-}
-
-TEST_F(XmppLoginHandlerTest, AuthError) {
-  HandshakeBase();
-
-  login_handler_->OnDataReceived(
-      "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
-      "<not-authorized/></failure>");
-  EXPECT_EQ(error_, SignalStrategy::AUTHENTICATION_FAILED);
-}
-
-TEST_F(XmppLoginHandlerTest, NoTls) {
-  login_handler_.reset(
-      new XmppLoginHandler("google.com", kTestUsername, kTestToken,
-                           XmppLoginHandler::TlsMode::NO_TLS, this));
-  login_handler_->Start();
-
-  EXPECT_FALSE(start_tls_called_);
-  std::string cookie;
-  base::Base64Encode(
-      std::string("\0", 1) + kTestUsername + std::string("\0", 1) + kTestToken,
-      &cookie);
-  EXPECT_EQ(
-      sent_data_,
-      "<stream:stream to=\"google.com\" version=\"1.0\" "
-          "xmlns=\"jabber:client\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\">"
-      "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-OAUTH2\" "
-          "auth:service=\"oauth2\" auth:allow-generated-jid=\"true\" "
-          "auth:client-uses-full-bind-result=\"true\" "
-          "auth:allow-non-google-login=\"true\" "
-          "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" + cookie +
-      "</auth>");
-}
-
-TEST_F(XmppLoginHandlerTest, StreamParseError) {
-  HandshakeBase();
-  delete_login_handler_from_delegate_ = true;
-  login_handler_->OnDataReceived("BAD DATA");
-  EXPECT_EQ(error_, SignalStrategy::PROTOCOL_ERROR);
-}
-
-// Verify that LoginHandler doesn't crash when destroyed from
-// Delegate::SendMessage().
-TEST_F(XmppLoginHandlerTest, DeleteInSendMessage) {
-  login_handler_.reset(
-      new XmppLoginHandler("google.com", kTestUsername, kTestToken,
-                           XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE, this));
-  login_handler_->Start();
-  EXPECT_TRUE(start_tls_called_);
-
-  delete_login_handler_from_delegate_ = true;
-  login_handler_->OnTlsStarted();
-  EXPECT_FALSE(login_handler_);
-}
-
-// Verify that LoginHandler doesn't crash when destroyed from
-// Delegate::StartTls().
-TEST_F(XmppLoginHandlerTest, DeleteInStartTls) {
-  login_handler_.reset(
-      new XmppLoginHandler("google.com", kTestUsername, kTestToken,
-                           XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE, this));
-  delete_login_handler_from_delegate_ = true;
-  login_handler_->Start();
-  EXPECT_TRUE(start_tls_called_);
-  EXPECT_FALSE(login_handler_);
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/xmpp_signal_strategy.cc b/remoting/signaling/xmpp_signal_strategy.cc
deleted file mode 100644
index c81452a..0000000
--- a/remoting/signaling/xmpp_signal_strategy.cc
+++ /dev/null
@@ -1,594 +0,0 @@
-// Copyright 2014 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 "remoting/signaling/xmpp_signal_strategy.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "base/rand_util.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_checker.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "net/cert/cert_verifier.h"
-#include "net/cert/ct_policy_enforcer.h"
-#include "net/cert/multi_log_ct_verifier.h"
-#include "net/http/transport_security_state.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/ssl_client_socket.h"
-#include "net/socket/stream_socket.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-#include "net/url_request/url_request_context_getter.h"
-#include "remoting/base/buffered_socket_writer.h"
-#include "remoting/base/logging.h"
-#include "remoting/signaling/signaling_address.h"
-#include "remoting/signaling/xmpp_login_handler.h"
-#include "remoting/signaling/xmpp_stream_parser.h"
-#include "services/network/proxy_resolving_client_socket.h"
-#include "services/network/proxy_resolving_client_socket_factory.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-
-// Use 50 seconds keep-alive interval, in case routers terminate
-// connections that are idle for more than a minute.
-const int kKeepAliveIntervalSeconds = 50;
-
-const int kReadBufferSize = 4096;
-
-const int kDefaultXmppPort = 5222;
-const int kDefaultHttpsPort = 443;
-
-namespace remoting {
-
-XmppSignalStrategy::XmppServerConfig::XmppServerConfig()
-    : port(kDefaultXmppPort), use_tls(true) {
-}
-
-XmppSignalStrategy::XmppServerConfig::XmppServerConfig(
-    const XmppServerConfig& other) = default;
-
-XmppSignalStrategy::XmppServerConfig::~XmppServerConfig() = default;
-
-class XmppSignalStrategy::Core : public XmppLoginHandler::Delegate {
- public:
-  Core(
-      net::ClientSocketFactory* socket_factory,
-      const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
-      const XmppServerConfig& xmpp_server_config);
-  ~Core() override;
-
-  void Connect();
-  void Disconnect();
-  State GetState() const;
-  Error GetError() const;
-  const SignalingAddress& GetLocalAddress() const;
-  void AddListener(Listener* listener);
-  void RemoveListener(Listener* listener);
-  bool SendStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza);
-
-  void SetAuthInfo(const std::string& username,
-                   const std::string& auth_token);
-
- private:
-  enum class TlsState {
-    // StartTls() hasn't been called. |socket_| is not encrypted.
-    NOT_REQUESTED,
-
-    // StartTls() has been called. Waiting for |writer_| to finish writing
-    // data before starting TLS.
-    WAITING_FOR_FLUSH,
-
-    // TLS has been started, waiting for TLS handshake to finish.
-    CONNECTING,
-
-    // TLS is connected.
-    CONNECTED,
-  };
-
-  void OnSocketConnected(int result);
-  void OnTlsConnected(int result);
-
-  void ReadSocket();
-  void OnReadResult(int result);
-  void HandleReadResult(int result);
-
-  // XmppLoginHandler::Delegate interface.
-  void SendMessage(const std::string& message) override;
-  void StartTls() override;
-  void OnHandshakeDone(const std::string& jid,
-                       std::unique_ptr<XmppStreamParser> parser) override;
-  void OnLoginHandlerError(SignalStrategy::Error error) override;
-
-  // Callback for BufferedSocketWriter.
-  void OnMessageSent();
-
-  // Event handlers for XmppStreamParser.
-  void OnStanza(const std::unique_ptr<jingle_xmpp::XmlElement> stanza);
-  void OnParserError();
-
-  void OnNetworkError(int error);
-
-  void SendKeepAlive();
-
-  net::ClientSocketFactory* socket_factory_;
-  scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
-  XmppServerConfig xmpp_server_config_;
-
-  // Used by the |socket_|.
-  std::unique_ptr<network::ProxyResolvingClientSocketFactory>
-      proxy_resolving_socket_factory_;
-  std::unique_ptr<net::CertVerifier> cert_verifier_;
-  std::unique_ptr<net::TransportSecurityState> transport_security_state_;
-  std::unique_ptr<net::CTVerifier> cert_transparency_verifier_;
-  std::unique_ptr<net::CTPolicyEnforcer> ct_policy_enforcer_;
-
-  std::unique_ptr<net::StreamSocket> socket_;
-  std::unique_ptr<BufferedSocketWriter> writer_;
-  scoped_refptr<net::IOBuffer> read_buffer_;
-  bool read_pending_ = false;
-
-  TlsState tls_state_ = TlsState::NOT_REQUESTED;
-
-  std::unique_ptr<XmppLoginHandler> login_handler_;
-  std::unique_ptr<XmppStreamParser> stream_parser_;
-  SignalingAddress local_address_;
-
-  Error error_ = OK;
-
-  base::ObserverList<Listener, true> listeners_;
-
-  base::RepeatingTimer keep_alive_timer_;
-
-  base::ThreadChecker thread_checker_;
-
-  DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-XmppSignalStrategy::Core::Core(
-    net::ClientSocketFactory* socket_factory,
-    const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
-    const XmppSignalStrategy::XmppServerConfig& xmpp_server_config)
-    : socket_factory_(socket_factory),
-      request_context_getter_(request_context_getter),
-      xmpp_server_config_(xmpp_server_config) {
-#if defined(NDEBUG)
-  // Non-secure connections are allowed only for debugging.
-  CHECK(xmpp_server_config_.use_tls);
-#endif
-  thread_checker_.DetachFromThread();
-}
-
-XmppSignalStrategy::Core::~Core() {
-  Disconnect();
-}
-
-void XmppSignalStrategy::Core::Connect() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  // Disconnect first if we are currently connected.
-  Disconnect();
-
-  error_ = OK;
-
-  for (auto& observer : listeners_)
-    observer.OnSignalStrategyStateChange(CONNECTING);
-
-  if (!proxy_resolving_socket_factory_) {
-    proxy_resolving_socket_factory_ =
-        std::make_unique<network::ProxyResolvingClientSocketFactory>(
-            request_context_getter_->GetURLRequestContext());
-  }
-  socket_ = proxy_resolving_socket_factory_->CreateSocket(
-      GURL("https://" +
-           net::HostPortPair(xmpp_server_config_.host, xmpp_server_config_.port)
-               .ToString()),
-      false /*use_tls*/);
-
-  int result = socket_->Connect(base::Bind(
-      &Core::OnSocketConnected, base::Unretained(this)));
-
-  keep_alive_timer_.Start(
-      FROM_HERE, base::TimeDelta::FromSeconds(kKeepAliveIntervalSeconds),
-      base::Bind(&Core::SendKeepAlive, base::Unretained(this)));
-
-  if (result != net::ERR_IO_PENDING)
-    OnSocketConnected(result);
-}
-
-void XmppSignalStrategy::Core::Disconnect() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (socket_) {
-    login_handler_.reset();
-    stream_parser_.reset();
-    writer_.reset();
-    socket_.reset();
-    tls_state_ = TlsState::NOT_REQUESTED;
-    read_pending_ = false;
-
-    for (auto& observer : listeners_)
-      observer.OnSignalStrategyStateChange(DISCONNECTED);
-  }
-}
-
-SignalStrategy::State XmppSignalStrategy::Core::GetState() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (stream_parser_) {
-    DCHECK(socket_);
-    return CONNECTED;
-  } else if (socket_) {
-    return CONNECTING;
-  } else {
-    return DISCONNECTED;
-  }
-}
-
-SignalStrategy::Error XmppSignalStrategy::Core::GetError() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return error_;
-}
-
-const SignalingAddress& XmppSignalStrategy::Core::GetLocalAddress() const {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  return local_address_;
-}
-
-void XmppSignalStrategy::Core::AddListener(Listener* listener) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  listeners_.AddObserver(listener);
-}
-
-void XmppSignalStrategy::Core::RemoveListener(Listener* listener) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  listeners_.RemoveObserver(listener);
-}
-
-bool XmppSignalStrategy::Core::SendStanza(
-    std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (!stream_parser_) {
-    VLOG(0) << "Dropping signalling message because XMPP is not connected.";
-    return false;
-  }
-
-  HOST_LOG << "Sending outgoing stanza:\n"
-           << stanza->Str()
-           << "\n=========================================================";
-  SendMessage(stanza->Str());
-
-  // Return false if the SendMessage() call above resulted in the SignalStrategy
-  // being disconnected.
-  return stream_parser_ != nullptr;
-}
-
-void XmppSignalStrategy::Core::SetAuthInfo(const std::string& username,
-                                           const std::string& auth_token) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  xmpp_server_config_.username = username;
-  xmpp_server_config_.auth_token = auth_token;
-}
-
-void XmppSignalStrategy::Core::SendMessage(const std::string& message) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(tls_state_ == TlsState::NOT_REQUESTED ||
-         tls_state_ == TlsState::CONNECTED);
-
-  scoped_refptr<net::IOBufferWithSize> buffer =
-      base::MakeRefCounted<net::IOBufferWithSize>(message.size());
-  memcpy(buffer->data(), message.data(), message.size());
-
-  net::NetworkTrafficAnnotationTag traffic_annotation =
-      net::DefineNetworkTrafficAnnotation("xmpp_signal_strategy", R"(
-        semantics {
-          sender: "Xmpp Signal Strategy"
-           description:
-            "This request is used for setting up the ICE connection between "
-            "the client and the host for Chrome Remote Desktop."
-          trigger:
-            "Initiating a Chrome Remote Desktop connection."
-          data: "No user data."
-          destination: OTHER
-          destination_other:
-            "The Chrome Remote Desktop client/host that user is connecting to."
-        }
-        policy {
-          cookies_allowed: NO
-          setting:
-            "This request cannot be stopped in settings, but will not be sent "
-            "if user does not use Chrome Remote Desktop."
-          policy_exception_justification:
-            "Not implemented. 'RemoteAccessHostClientDomainList' and "
-            "'RemoteAccessHostDomainList' policies can limit the domains to "
-            "which a connection can be made, but they cannot be used to block "
-            "the request to all domains. Please refer to help desk for other "
-            "approaches to manage this feature."
-        })");
-  writer_->Write(buffer,
-                 base::BindOnce(&Core::OnMessageSent, base::Unretained(this)),
-                 traffic_annotation);
-}
-
-void XmppSignalStrategy::Core::StartTls() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(login_handler_);
-  DCHECK(tls_state_ == TlsState::NOT_REQUESTED ||
-         tls_state_ == TlsState::WAITING_FOR_FLUSH);
-
-  if (writer_->has_data_pending()) {
-    tls_state_ = TlsState::WAITING_FOR_FLUSH;
-    return;
-  }
-
-  tls_state_ = TlsState::CONNECTING;
-
-  // Reset the writer so we don't try to write to the raw socket anymore.
-  writer_.reset();
-
-  DCHECK(!read_pending_);
-
-  cert_verifier_ =
-      net::CertVerifier::CreateDefault(/*cert_net_fetcher=*/nullptr);
-  transport_security_state_.reset(new net::TransportSecurityState());
-  cert_transparency_verifier_.reset(new net::MultiLogCTVerifier());
-  ct_policy_enforcer_.reset(new net::DefaultCTPolicyEnforcer());
-  net::SSLClientSocketContext context;
-  context.cert_verifier = cert_verifier_.get();
-  context.transport_security_state = transport_security_state_.get();
-  context.cert_transparency_verifier = cert_transparency_verifier_.get();
-  context.ct_policy_enforcer = ct_policy_enforcer_.get();
-
-  socket_ = socket_factory_->CreateSSLClientSocket(
-      std::move(socket_),
-      net::HostPortPair(xmpp_server_config_.host, kDefaultHttpsPort),
-      net::SSLConfig(), context);
-
-  int result = socket_->Connect(
-      base::Bind(&Core::OnTlsConnected, base::Unretained(this)));
-  if (result != net::ERR_IO_PENDING)
-    OnTlsConnected(result);
-}
-
-void XmppSignalStrategy::Core::OnHandshakeDone(
-    const std::string& jid,
-    std::unique_ptr<XmppStreamParser> parser) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  local_address_ = SignalingAddress(jid);
-  stream_parser_ = std::move(parser);
-  stream_parser_->SetCallbacks(
-      base::Bind(&Core::OnStanza, base::Unretained(this)),
-      base::Bind(&Core::OnParserError, base::Unretained(this)));
-
-  // Don't need |login_handler_| anymore.
-  login_handler_.reset();
-
-  for (auto& observer : listeners_)
-    observer.OnSignalStrategyStateChange(CONNECTED);
-}
-
-void XmppSignalStrategy::Core::OnLoginHandlerError(
-    SignalStrategy::Error error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  error_ = error;
-  Disconnect();
-}
-
-void XmppSignalStrategy::Core::OnMessageSent() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (tls_state_ == TlsState::WAITING_FOR_FLUSH &&
-      !writer_->has_data_pending()) {
-    StartTls();
-  }
-}
-
-void XmppSignalStrategy::Core::OnStanza(
-    const std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  HOST_LOG << "Received incoming stanza:\n"
-           << stanza->Str()
-           << "\n=========================================================";
-
-  for (auto& listener : listeners_) {
-    if (listener.OnSignalStrategyIncomingStanza(stanza.get()))
-      return;
-  }
-}
-
-void XmppSignalStrategy::Core::OnParserError() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  error_ = NETWORK_ERROR;
-  Disconnect();
-}
-
-void XmppSignalStrategy::Core::OnSocketConnected(int result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (result != net::OK) {
-    OnNetworkError(result);
-    return;
-  }
-
-  writer_ = BufferedSocketWriter::CreateForSocket(
-      socket_.get(), base::Bind(&Core::OnNetworkError, base::Unretained(this)));
-
-  XmppLoginHandler::TlsMode tls_mode;
-  if (xmpp_server_config_.use_tls) {
-    tls_mode = (xmpp_server_config_.port == kDefaultXmppPort)
-                   ? XmppLoginHandler::TlsMode::WITH_HANDSHAKE
-                   : XmppLoginHandler::TlsMode::WITHOUT_HANDSHAKE;
-  } else {
-    tls_mode = XmppLoginHandler::TlsMode::NO_TLS;
-  }
-
-  // The server name is passed as to attribute in the <stream>. When connecting
-  // to talk.google.com it affects the certificate the server will use for TLS:
-  // talk.google.com uses gmail certificate when specified server is gmail.com
-  // or googlemail.com and google.com cert otherwise. In the same time it
-  // doesn't accept talk.google.com as target server. Here we use google.com
-  // server name when authenticating to talk.google.com. This ensures that the
-  // server will use google.com cert which will be accepted by the TLS
-  // implementation in Chrome (TLS API doesn't allow specifying domain other
-  // than the one that was passed to connect()).
-  std::string server = xmpp_server_config_.host;
-  if (server == "talk.google.com")
-    server = "google.com";
-
-  login_handler_.reset(
-      new XmppLoginHandler(server, xmpp_server_config_.username,
-                           xmpp_server_config_.auth_token, tls_mode, this));
-  login_handler_->Start();
-
-  ReadSocket();
-}
-
-void XmppSignalStrategy::Core::OnTlsConnected(int result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(tls_state_ == TlsState::CONNECTING);
-  tls_state_ = TlsState::CONNECTED;
-
-  if (result != net::OK) {
-    OnNetworkError(result);
-    return;
-  }
-
-  writer_ = BufferedSocketWriter::CreateForSocket(
-      socket_.get(), base::Bind(&Core::OnNetworkError, base::Unretained(this)));
-
-  login_handler_->OnTlsStarted();
-
-  ReadSocket();
-}
-
-void XmppSignalStrategy::Core::ReadSocket() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  while (socket_ && !read_pending_ && (tls_state_ == TlsState::NOT_REQUESTED ||
-                                       tls_state_ == TlsState::CONNECTED)) {
-    read_buffer_ = base::MakeRefCounted<net::IOBuffer>(kReadBufferSize);
-    int result = socket_->Read(
-        read_buffer_.get(), kReadBufferSize,
-        base::Bind(&Core::OnReadResult, base::Unretained(this)));
-    HandleReadResult(result);
-  }
-}
-
-void XmppSignalStrategy::Core::OnReadResult(int result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-  DCHECK(read_pending_);
-  read_pending_ = false;
-  HandleReadResult(result);
-  ReadSocket();
-}
-
-void XmppSignalStrategy::Core::HandleReadResult(int result) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (result == net::ERR_IO_PENDING) {
-    read_pending_ = true;
-    return;
-  }
-
-  if (result < 0) {
-    OnNetworkError(result);
-    return;
-  }
-
-  if (result == 0) {
-    // Connection was closed by the server.
-    error_ = OK;
-    Disconnect();
-    return;
-  }
-
-  if (stream_parser_) {
-    stream_parser_->AppendData(std::string(read_buffer_->data(), result));
-  } else {
-    login_handler_->OnDataReceived(std::string(read_buffer_->data(), result));
-  }
-}
-
-void XmppSignalStrategy::Core::OnNetworkError(int error) {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  LOG(ERROR) << "XMPP socket error " << error;
-  error_ = NETWORK_ERROR;
-  Disconnect();
-}
-
-void XmppSignalStrategy::Core::SendKeepAlive() {
-  DCHECK(thread_checker_.CalledOnValidThread());
-
-  if (GetState() == CONNECTED)
-    SendMessage(" ");
-}
-
-XmppSignalStrategy::XmppSignalStrategy(
-    net::ClientSocketFactory* socket_factory,
-    const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
-    const XmppServerConfig& xmpp_server_config)
-    : core_(new Core(socket_factory,
-                     request_context_getter,
-                     xmpp_server_config)) {
-}
-
-XmppSignalStrategy::~XmppSignalStrategy() {
-  // All listeners should be removed at this point, so it's safe to detach
-  // |core_|.
-  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, core_.release());
-}
-
-void XmppSignalStrategy::Connect() {
-  core_->Connect();
-}
-
-void XmppSignalStrategy::Disconnect() {
-  core_->Disconnect();
-}
-
-SignalStrategy::State XmppSignalStrategy::GetState() const {
-  return core_->GetState();
-}
-
-SignalStrategy::Error XmppSignalStrategy::GetError() const {
-  return core_->GetError();
-}
-
-const SignalingAddress& XmppSignalStrategy::GetLocalAddress() const {
-  return core_->GetLocalAddress();
-}
-
-void XmppSignalStrategy::AddListener(Listener* listener) {
-  core_->AddListener(listener);
-}
-
-void XmppSignalStrategy::RemoveListener(Listener* listener) {
-  core_->RemoveListener(listener);
-}
-bool XmppSignalStrategy::SendStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-  return core_->SendStanza(std::move(stanza));
-}
-
-std::string XmppSignalStrategy::GetNextId() {
-  return base::NumberToString(base::RandUint64());
-}
-
-void XmppSignalStrategy::SetAuthInfo(const std::string& username,
-                                     const std::string& auth_token) {
-  core_->SetAuthInfo(username, auth_token);
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/xmpp_signal_strategy.h b/remoting/signaling/xmpp_signal_strategy.h
deleted file mode 100644
index 97a5ef2..0000000
--- a/remoting/signaling/xmpp_signal_strategy.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 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 REMOTING_SIGNALING_XMPP_SIGNAL_STRATEGY_H_
-#define REMOTING_SIGNALING_XMPP_SIGNAL_STRATEGY_H_
-
-#include "remoting/signaling/signal_strategy.h"
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-
-namespace net {
-class ClientSocketFactory;
-class URLRequestContextGetter;
-}  // namespace net
-
-namespace remoting {
-
-// XmppSignalStrategy implements SignalStrategy using direct XMPP connection.
-// This class can be created on a different thread from the one it is used (when
-// Connect() is called).
-class XmppSignalStrategy : public SignalStrategy {
- public:
-  // XMPP Server configuration for XmppSignalStrategy.
-  struct XmppServerConfig {
-    XmppServerConfig();
-    XmppServerConfig(const XmppServerConfig& other);
-    ~XmppServerConfig();
-
-    std::string host;
-    int port;
-    bool use_tls;
-
-    std::string username;
-    std::string auth_token;
-  };
-
-  XmppSignalStrategy(
-      net::ClientSocketFactory* socket_factory,
-      const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
-      const XmppServerConfig& xmpp_server_config);
-  ~XmppSignalStrategy() override;
-
-  // SignalStrategy interface.
-  void Connect() override;
-  void Disconnect() override;
-  State GetState() const override;
-  Error GetError() const override;
-  const SignalingAddress& GetLocalAddress() const override;
-  void AddListener(Listener* listener) override;
-  void RemoveListener(Listener* listener) override;
-  bool SendStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza) override;
-  std::string GetNextId() override;
-
-  // This method is used to update the auth info (for example when the OAuth
-  // access token is renewed). It is OK to call this even when we are in the
-  // CONNECTED state. It will be used on the next Connect() call.
-  void SetAuthInfo(const std::string& username,
-                   const std::string& auth_token);
-
- private:
-  // This ensures that even if a Listener deletes the current instance during
-  // OnSignalStrategyIncomingStanza(), we can delete |core_| asynchronously.
-  class Core;
-
-  std::unique_ptr<Core> core_;
-
-  DISALLOW_COPY_AND_ASSIGN(XmppSignalStrategy);
-};
-
-}  // namespace remoting
-
-#endif  // REMOTING_SIGNALING_XMPP_SIGNAL_STRATEGY_H_
diff --git a/remoting/signaling/xmpp_signal_strategy_unittest.cc b/remoting/signaling/xmpp_signal_strategy_unittest.cc
deleted file mode 100644
index 96dcbfd1..0000000
--- a/remoting/signaling/xmpp_signal_strategy_unittest.cc
+++ /dev/null
@@ -1,390 +0,0 @@
-// Copyright 2015 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 "remoting/signaling/xmpp_signal_strategy.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "net/socket/socket_test_util.h"
-#include "net/socket/stream_socket.h"
-#include "net/url_request/url_request_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-
-namespace remoting {
-
-namespace {
-
-class XmppSocketDataProvider : public net::SocketDataProvider {
- public:
-  net::MockRead OnRead() override {
-    return net::MockRead(net::ASYNC, net::ERR_IO_PENDING);
-  }
-
-  net::MockWriteResult OnWrite(const std::string& data) override {
-    if (write_error_ != net::OK)
-      return net::MockWriteResult(net::SYNCHRONOUS, write_error_);
-
-    written_data_.append(data);
-
-    if (use_async_write_) {
-      pending_write_size_ = data.size();
-      return net::MockWriteResult(net::ASYNC, net::ERR_IO_PENDING);
-    }
-
-    return net::MockWriteResult(net::SYNCHRONOUS, data.size());
-  }
-
-  void Reset() override {}
-
-  bool AllReadDataConsumed() const override {
-    return true;
-  }
-
-  bool AllWriteDataConsumed() const override {
-    return true;
-  }
-
-  void ReceiveData(const std::string& text) {
-    socket()->OnReadComplete(
-        net::MockRead(net::ASYNC, text.data(), text.size()));
-  }
-
-  void Close() {
-    ReceiveData(std::string());
-  }
-
-  void SimulateAsyncReadError() {
-    socket()->OnReadComplete(
-        net::MockRead(net::ASYNC, net::ERR_CONNECTION_RESET));
-  }
-
-  std::string GetAndClearWrittenData() {
-    std::string data;
-    data.swap(written_data_);
-    return data;
-  }
-
-  void set_use_async_write(bool use_async_write) {
-    use_async_write_ = use_async_write;
-  }
-
-  void set_write_error(net::Error error) {
-    write_error_ = error;
-  }
-
-  void CompletePendingWrite() {
-    socket()->OnWriteComplete(pending_write_size_);
-  }
-
- private:
-  std::string written_data_;
-  bool use_async_write_ = false;
-  int pending_write_size_ = 0;
-  net::Error write_error_ = net::OK;
-};
-
-class MockClientSocketFactory : public net::MockClientSocketFactory {
- public:
-  std::unique_ptr<net::SSLClientSocket> CreateSSLClientSocket(
-      std::unique_ptr<net::StreamSocket> stream_socket,
-      const net::HostPortPair& host_and_port,
-      const net::SSLConfig& ssl_config,
-      const net::SSLClientSocketContext& context) override {
-    ssl_socket_created_ = true;
-    return net::MockClientSocketFactory::CreateSSLClientSocket(
-        std::move(stream_socket), host_and_port, ssl_config, context);
-  }
-
-  bool ssl_socket_created() const { return ssl_socket_created_; }
-
- private:
-  bool ssl_socket_created_ = false;
-};
-
-}  // namespace
-
-const char kTestUsername[] = "test_username@example.com";
-const char kTestAuthToken[] = "test_auth_token";
-const int kDefaultPort = 443;
-
-class XmppSignalStrategyTest : public testing::Test,
-                               public SignalStrategy::Listener {
- public:
-  XmppSignalStrategyTest()
-      : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::IO) {}
-
-  void SetUp() override {
-    auto url_request_context = std::make_unique<net::TestURLRequestContext>(
-        true /* delay_initialization */);
-    url_request_context->set_client_socket_factory(&client_socket_factory_);
-    url_request_context->Init();
-    request_context_getter_ = new net::TestURLRequestContextGetter(
-        scoped_task_environment_.GetMainThreadTaskRunner(),
-        std::move(url_request_context));
-  }
-
-  void CreateSignalStrategy(int port) {
-    XmppSignalStrategy::XmppServerConfig config;
-    config.host = "talk.google.com";
-    config.port = port;
-    config.username = kTestUsername;
-    config.auth_token = kTestAuthToken;
-    signal_strategy_.reset(new XmppSignalStrategy(
-        &client_socket_factory_, request_context_getter_, config));
-    signal_strategy_->AddListener(this);
-  }
-
-  void TearDown() override {
-    signal_strategy_->RemoveListener(this);
-    signal_strategy_.reset();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void OnSignalStrategyStateChange(SignalStrategy::State state) override {
-    state_history_.push_back(state);
-  }
-
-  bool OnSignalStrategyIncomingStanza(const jingle_xmpp::XmlElement* stanza) override {
-    received_messages_.push_back(std::make_unique<jingle_xmpp::XmlElement>(*stanza));
-    return true;
-  }
-
-  void Connect(bool success);
-
- protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-  scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
-  MockClientSocketFactory client_socket_factory_;
-  std::unique_ptr<XmppSocketDataProvider> socket_data_provider_;
-  std::unique_ptr<net::SSLSocketDataProvider> ssl_socket_data_provider_;
-  std::unique_ptr<XmppSignalStrategy> signal_strategy_;
-
-  std::vector<SignalStrategy::State> state_history_;
-  std::vector<std::unique_ptr<jingle_xmpp::XmlElement>> received_messages_;
-};
-
-void XmppSignalStrategyTest::Connect(bool success) {
-  EXPECT_EQ(SignalStrategy::DISCONNECTED, signal_strategy_->GetState());
-  state_history_.clear();
-
-  socket_data_provider_.reset(new XmppSocketDataProvider());
-  socket_data_provider_->set_connect_data(
-      net::MockConnect(net::ASYNC, net::OK));
-  client_socket_factory_.AddSocketDataProvider(socket_data_provider_.get());
-
-  ssl_socket_data_provider_.reset(
-      new net::SSLSocketDataProvider(net::ASYNC, net::OK));
-  client_socket_factory_.AddSSLSocketDataProvider(
-      ssl_socket_data_provider_.get());
-
-  signal_strategy_->Connect();
-
-  EXPECT_EQ(SignalStrategy::CONNECTING, signal_strategy_->GetState());
-  EXPECT_EQ(1U, state_history_.size());
-  EXPECT_EQ(SignalStrategy::CONNECTING, state_history_[0]);
-
-  // No data written before TLS.
-  EXPECT_EQ("", socket_data_provider_->GetAndClearWrittenData());
-
-  base::RunLoop().RunUntilIdle();
-
-  socket_data_provider_->ReceiveData(
-      "<stream:stream from=\"google.com\" id=\"DCDDE5171CB2154A\" "
-        "version=\"1.0\" "
-        "xmlns:stream=\"http://etherx.jabber.org/streams\" "
-        "xmlns=\"jabber:client\">"
-      "<stream:features>"
-        "<mechanisms xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
-          "<mechanism>X-OAUTH2</mechanism>"
-          "<mechanism>X-GOOGLE-TOKEN</mechanism>"
-          "<mechanism>PLAIN</mechanism>"
-        "</mechanisms>"
-      "</stream:features>");
-
-  base::RunLoop().RunUntilIdle();
-
-  std::string cookie;
-  base::Base64Encode(std::string("\0", 1) + kTestUsername +
-                         std::string("\0", 1) + kTestAuthToken,
-                     &cookie);
-  // Expect auth message.
-  EXPECT_EQ(
-      "<stream:stream to=\"google.com\" version=\"1.0\" "
-          "xmlns=\"jabber:client\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\">"
-      "<auth xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" mechanism=\"X-OAUTH2\" "
-          "auth:service=\"oauth2\" auth:allow-generated-jid=\"true\" "
-          "auth:client-uses-full-bind-result=\"true\" "
-          "auth:allow-non-google-login=\"true\" "
-          "xmlns:auth=\"http://www.google.com/talk/protocol/auth\">" + cookie +
-      "</auth>", socket_data_provider_->GetAndClearWrittenData());
-
-  if (!success) {
-    socket_data_provider_->ReceiveData(
-        "<failure xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\">"
-        "<not-authorized/></failure>");
-    EXPECT_EQ(2U, state_history_.size());
-    EXPECT_EQ(SignalStrategy::DISCONNECTED, state_history_[1]);
-    EXPECT_EQ(SignalStrategy::AUTHENTICATION_FAILED,
-              signal_strategy_->GetError());
-    return;
-  }
-
-  socket_data_provider_->ReceiveData(
-      "<success xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\"/>");
-
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(
-      "<stream:stream to=\"google.com\" version=\"1.0\" "
-        "xmlns=\"jabber:client\" "
-        "xmlns:stream=\"http://etherx.jabber.org/streams\">"
-      "<iq type=\"set\" id=\"0\">"
-        "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
-          "<resource>chromoting</resource>"
-        "</bind>"
-      "</iq>"
-      "<iq type=\"set\" id=\"1\">"
-        "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
-      "</iq>",
-      socket_data_provider_->GetAndClearWrittenData());
-  socket_data_provider_->ReceiveData(
-      "<stream:stream from=\"google.com\" id=\"104FA10576E2AA80\" "
-        "version=\"1.0\" "
-        "xmlns:stream=\"http://etherx.jabber.org/streams\" "
-        "xmlns=\"jabber:client\">"
-      "<stream:features>"
-        "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\"/>"
-        "<session xmlns=\"urn:ietf:params:xml:ns:xmpp-session\"/>"
-      "</stream:features>"
-      "<iq id=\"0\" type=\"result\">"
-        "<bind xmlns=\"urn:ietf:params:xml:ns:xmpp-bind\">"
-          "<jid>" + std::string(kTestUsername) + "/chromoting52B4920E</jid>"
-        "</bind>"
-      "</iq>"
-      "<iq type=\"result\" id=\"1\"/>");
-
-  EXPECT_EQ(2U, state_history_.size());
-  EXPECT_EQ(SignalStrategy::CONNECTED, state_history_[1]);
-}
-
-TEST_F(XmppSignalStrategyTest, SendAndReceive) {
-  CreateSignalStrategy(kDefaultPort);
-  Connect(true);
-
-  EXPECT_TRUE(signal_strategy_->SendStanza(
-      std::make_unique<jingle_xmpp::XmlElement>(jingle_xmpp::QName(std::string(), "hello"))));
-  EXPECT_EQ("<hello/>", socket_data_provider_->GetAndClearWrittenData());
-
-  socket_data_provider_->ReceiveData("<hi xmlns=\"hello\"/>");
-  EXPECT_EQ(1U, received_messages_.size());
-  EXPECT_EQ("<hi xmlns=\"hello\"/>", received_messages_[0]->Str());
-}
-
-TEST_F(XmppSignalStrategyTest, AuthError) {
-  CreateSignalStrategy(kDefaultPort);
-  Connect(false);
-}
-
-TEST_F(XmppSignalStrategyTest, ConnectionClosed) {
-  CreateSignalStrategy(kDefaultPort);
-  Connect(true);
-
-  socket_data_provider_->Close();
-
-  EXPECT_EQ(3U, state_history_.size());
-  EXPECT_EQ(SignalStrategy::DISCONNECTED, state_history_[2]);
-  EXPECT_EQ(SignalStrategy::DISCONNECTED, signal_strategy_->GetState());
-  EXPECT_EQ(SignalStrategy::OK, signal_strategy_->GetError());
-
-  // Can't send messages anymore.
-  EXPECT_FALSE(signal_strategy_->SendStanza(
-      std::make_unique<jingle_xmpp::XmlElement>(jingle_xmpp::QName(std::string(), "hello"))));
-
-  // Try connecting again.
-  Connect(true);
-}
-
-TEST_F(XmppSignalStrategyTest, NetworkReadError) {
-  CreateSignalStrategy(kDefaultPort);
-  Connect(true);
-
-  socket_data_provider_->SimulateAsyncReadError();
-
-  EXPECT_EQ(3U, state_history_.size());
-  EXPECT_EQ(SignalStrategy::DISCONNECTED, state_history_[2]);
-  EXPECT_EQ(SignalStrategy::NETWORK_ERROR, signal_strategy_->GetError());
-
-  // Can't send messages anymore.
-  EXPECT_FALSE(signal_strategy_->SendStanza(
-      std::make_unique<jingle_xmpp::XmlElement>(jingle_xmpp::QName(std::string(), "hello"))));
-
-  // Try connecting again.
-  Connect(true);
-}
-
-TEST_F(XmppSignalStrategyTest, NetworkWriteError) {
-  CreateSignalStrategy(kDefaultPort);
-  Connect(true);
-
-  socket_data_provider_->set_write_error(net::ERR_FAILED);
-
-  // Next SendMessage() will call Write() which will fail.
-  EXPECT_FALSE(signal_strategy_->SendStanza(
-      std::make_unique<jingle_xmpp::XmlElement>(jingle_xmpp::QName(std::string(), "hello"))));
-
-  EXPECT_EQ(3U, state_history_.size());
-  EXPECT_EQ(SignalStrategy::DISCONNECTED, state_history_[2]);
-  EXPECT_EQ(SignalStrategy::NETWORK_ERROR, signal_strategy_->GetError());
-
-  // Try connecting again.
-  Connect(true);
-}
-
-TEST_F(XmppSignalStrategyTest, StartTlsWithPendingWrite) {
-  // Use port 5222 so that XmppLoginHandler uses starttls/proceed handshake
-  // before starting TLS.
-  CreateSignalStrategy(5222);
-
-  socket_data_provider_.reset(new XmppSocketDataProvider());
-  socket_data_provider_->set_connect_data(
-      net::MockConnect(net::SYNCHRONOUS, net::OK));
-  client_socket_factory_.AddSocketDataProvider(socket_data_provider_.get());
-
-  ssl_socket_data_provider_.reset(
-      new net::SSLSocketDataProvider(net::ASYNC, net::OK));
-  client_socket_factory_.AddSSLSocketDataProvider(
-      ssl_socket_data_provider_.get());
-
-  // Make sure write is handled asynchronously.
-  socket_data_provider_->set_use_async_write(true);
-
-  signal_strategy_->Connect();
-  base::RunLoop().RunUntilIdle();
-
-  socket_data_provider_->ReceiveData(
-      "<stream:stream from=\"google.com\" id=\"104FA10576E2AA80\" "
-          "version=\"1.0\" "
-          "xmlns:stream=\"http://etherx.jabber.org/streams\" "
-          "xmlns=\"jabber:client\">"
-        "<stream:features>"
-          "<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>"
-        "</stream:features>"
-        "<proceed xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\"/>");
-
-  // Verify that SSL is connected only after write is finished.
-  EXPECT_FALSE(client_socket_factory_.ssl_socket_created());
-  socket_data_provider_->CompletePendingWrite();
-  EXPECT_TRUE(client_socket_factory_.ssl_socket_created());
-}
-
-
-  }  // namespace remoting
diff --git a/remoting/signaling/xmpp_stream_parser.cc b/remoting/signaling/xmpp_stream_parser.cc
deleted file mode 100644
index 10ba038..0000000
--- a/remoting/signaling/xmpp_stream_parser.cc
+++ /dev/null
@@ -1,172 +0,0 @@
-// Copyright 2015 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 "remoting/signaling/xmpp_stream_parser.h"
-
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlbuilder.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlparser.h"
-
-namespace remoting {
-
-class XmppStreamParser::Core : public jingle_xmpp::XmlParseHandler {
- public:
-  typedef base::Callback<void(std::unique_ptr<jingle_xmpp::XmlElement> stanza)>
-      OnStanzaCallback;
-
-  Core();
-  ~Core() override;
-
-  void SetCallbacks(const OnStanzaCallback& on_stanza_callback,
-                    const base::Closure& on_error_callback);
-
-  void AppendData(const std::string& data);
-
- private:
-  // jingle_xmpp::XmlParseHandler interface.
-  void StartElement(jingle_xmpp::XmlParseContext* context,
-                    const char* name,
-                    const char** atts) override;
-  void EndElement(jingle_xmpp::XmlParseContext* context, const char* name) override;
-  void CharacterData(jingle_xmpp::XmlParseContext* context,
-                     const char* text,
-                     int len) override;
-  void Error(jingle_xmpp::XmlParseContext* context, XML_Error error_code) override;
-
-  void ProcessError();
-
-  OnStanzaCallback on_stanza_callback_;
-  base::Closure on_error_callback_;
-
-  jingle_xmpp::XmlParser parser_;
-  int depth_;
-  jingle_xmpp::XmlBuilder builder_;
-
-  bool error_;
-
-  DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-XmppStreamParser::Core::Core()
-    : parser_(this),
-      depth_(0),
-      error_(false) {
-}
-
-XmppStreamParser::Core::~Core() = default;
-
-void XmppStreamParser::Core::SetCallbacks(
-    const OnStanzaCallback& on_stanza_callback,
-    const base::Closure& on_error_callback) {
-  on_stanza_callback_ = on_stanza_callback;
-  on_error_callback_ = on_error_callback;
-}
-
-void XmppStreamParser::Core::AppendData(const std::string& data) {
-  if (error_)
-    return;
-  parser_.Parse(data.data(), data.size(), false);
-}
-
-void XmppStreamParser::Core::StartElement(jingle_xmpp::XmlParseContext* context,
-                                    const char* name,
-                                    const char** atts) {
-  DCHECK(!error_);
-
-  ++depth_;
-  if (depth_ == 1) {
-    std::unique_ptr<jingle_xmpp::XmlElement> header(
-        jingle_xmpp::XmlBuilder::BuildElement(context, name, atts));
-    if (!header) {
-      LOG(ERROR) << "Failed to parse XMPP stream header.";
-      ProcessError();
-    }
-    return;
-  }
-
-  builder_.StartElement(context, name, atts);
-}
-
-void XmppStreamParser::Core::EndElement(jingle_xmpp::XmlParseContext* context,
-                                        const char* name) {
-  DCHECK(!error_);
-
-  --depth_;
-  if (depth_ == 0) {
-    LOG(ERROR) << "XMPP stream ended unexpectedly.";
-    ProcessError();
-    return;
-  }
-
-  builder_.EndElement(context, name);
-
-  if (depth_ == 1) {
-    if (!on_stanza_callback_.is_null())
-      on_stanza_callback_.Run(base::WrapUnique(builder_.CreateElement()));
-  }
-}
-
-void XmppStreamParser::Core::CharacterData(jingle_xmpp::XmlParseContext* context,
-                                           const char* text,
-                                           int len) {
-  DCHECK(!error_);
-
-  // Ignore data between stanzas.
-  if (depth_ <= 1) {
-    // Only whitespace is allowed outside of the stanzas.
-    bool all_spaces = true;
-    for (char c: std::string(text, len)) {
-      if (c != ' ') {
-        all_spaces = false;
-        break;
-      }
-    }
-    if (!all_spaces) {
-      LOG(ERROR) << "Received unexpected string: " << std::string(text,
-                                                                  text + len);
-      ProcessError();
-    }
-  } else if (depth_ > 1) {
-    builder_.CharacterData(context, text, len);
-  }
-}
-
-void XmppStreamParser::Core::Error(jingle_xmpp::XmlParseContext* context,
-                                   XML_Error error_code) {
-  LOG(ERROR) << "XMPP parser error: " << error_code;
-  ProcessError();
-}
-
-void XmppStreamParser::Core::ProcessError() {
-  error_ = true;
-  if (!on_error_callback_.is_null())
-    on_error_callback_.Run();
-}
-
-XmppStreamParser::XmppStreamParser() : core_(new Core()) {
-}
-
-XmppStreamParser::~XmppStreamParser() {
-  // Set null callbacks and delete |core_| asynchronously to make sure it's not
-  // deleted from a callback.
-  core_->SetCallbacks(OnStanzaCallback(), base::Closure());
-  base::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, core_.release());
-}
-
-void XmppStreamParser::SetCallbacks(const OnStanzaCallback& on_stanza_callback,
-                                    const base::Closure& on_error_callback) {
-  core_->SetCallbacks(on_stanza_callback, on_error_callback);
-}
-
-void XmppStreamParser::AppendData(const std::string& data) {
-  core_->AppendData(data);
-}
-
-}  // namespace remoting
diff --git a/remoting/signaling/xmpp_stream_parser.h b/remoting/signaling/xmpp_stream_parser.h
deleted file mode 100644
index 1b45ba8..0000000
--- a/remoting/signaling/xmpp_stream_parser.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2015 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 REMOTING_SIGNALING_XMPP_STREAM_PARSER_H_
-#define REMOTING_SIGNALING_XMPP_STREAM_PARSER_H_
-
-#include <memory>
-#include <string>
-
-#include "base/callback.h"
-#include "base/macros.h"
-
-namespace jingle_xmpp {
-class XmlElement;
-}  // namespace jingle_xmpp
-
-namespace remoting {
-
-// XmppStreamParser is used to parse XMPP stream. Data is fed to the parser
-// using appendData() method and it calls |on_stanza_callback\ and
-// |on_error_callback| specified using SetCallbacks().
-class XmppStreamParser {
- public:
-  typedef base::Callback<void(std::unique_ptr<jingle_xmpp::XmlElement> stanza)>
-      OnStanzaCallback;
-
-  XmppStreamParser();
-  ~XmppStreamParser();
-
-  void SetCallbacks(const OnStanzaCallback& on_stanza_callback,
-                    const base::Closure& on_error_callback);
-
-  void AppendData(const std::string& data);
-
- private:
-  class Core;
-
-  std::unique_ptr<Core> core_;
-
-  DISALLOW_COPY_AND_ASSIGN(XmppStreamParser);
-};
-
-}  // namespace remoting
-
-#endif  // REMOTING_SIGNALING_XMPP_STREAM_PARSER_H_
diff --git a/remoting/signaling/xmpp_stream_parser_unittest.cc b/remoting/signaling/xmpp_stream_parser_unittest.cc
deleted file mode 100644
index 6922476c..0000000
--- a/remoting/signaling/xmpp_stream_parser_unittest.cc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2015 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 "remoting/signaling/xmpp_stream_parser.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/run_loop.h"
-#include "base/test/scoped_task_environment.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle_xmpp/xmllite/xmlelement.h"
-
-namespace remoting {
-
-class XmppStreamParserTest : public testing::Test {
- public:
-  XmppStreamParserTest() : error_(false) {}
-
-  void SetUp() override {
-    parser_.reset(new remoting::XmppStreamParser());
-    parser_->SetCallbacks(
-        base::Bind(&XmppStreamParserTest::OnStanza, base::Unretained(this)),
-        base::Bind(&XmppStreamParserTest::OnError, base::Unretained(this)));
-  }
-
-  void TearDown() override {
-    parser_.reset();
-    base::RunLoop().RunUntilIdle();
-  }
-
-  void OnStanza(std::unique_ptr<jingle_xmpp::XmlElement> stanza) {
-    received_stanzas_.push_back(std::move(stanza));
-  }
-
-  void OnError() {
-    error_ = true;
-  }
-
- protected:
-  base::test::ScopedTaskEnvironment scoped_task_environment_;
-
-  std::unique_ptr<XmppStreamParser> parser_;
-  std::vector<std::unique_ptr<jingle_xmpp::XmlElement>> received_stanzas_;
-  bool error_;
-};
-
-TEST_F(XmppStreamParserTest, ParseXmppStream) {
-  parser_->AppendData("<stream><iq>text</iq>");
-  EXPECT_EQ(received_stanzas_[0]->Str(), "<iq>text</iq>");
-}
-
-TEST_F(XmppStreamParserTest, HandleMultipleIncomingStanzas) {
-  parser_->AppendData("<stream><iq>text</iq><iq>more text</iq>");
-  EXPECT_EQ(received_stanzas_[0]->Str(), "<iq>text</iq>");
-  EXPECT_EQ(received_stanzas_[1]->Str(), "<iq>more text</iq>");
-}
-
-TEST_F(XmppStreamParserTest, IgnoreWhitespaceBetweenStanzas) {
-  parser_->AppendData("<stream> <iq>text</iq>");
-  EXPECT_EQ(received_stanzas_[0]->Str(), "<iq>text</iq>");
-}
-
-TEST_F(XmppStreamParserTest, AssembleMessagesFromChunks) {
-  parser_->AppendData("<stream><i");
-  parser_->AppendData("q>");
-
-  // Split one UTF-8 sequence into two chunks
-  std::string data = "😃";
-  parser_->AppendData(data.substr(0, 2));
-  parser_->AppendData(data.substr(2));
-
-  parser_->AppendData("</iq>");
-
-  EXPECT_EQ(received_stanzas_[0]->Str(), "<iq>😃</iq>");
-}
-
-TEST_F(XmppStreamParserTest, StopParsingOnErrors) {
-  parser_->AppendData("<stream><invalidtag p!='a'></invalidtag><iq>text</iq>");
-  EXPECT_TRUE(error_);
-  EXPECT_TRUE(received_stanzas_.empty());
-}
-
-TEST_F(XmppStreamParserTest, FailOnInvalidStreamHeader) {
-  parser_->AppendData("<stream p!='a'>");
-  EXPECT_TRUE(error_);
-}
-
-TEST_F(XmppStreamParserTest, FailOnLooseText) {
-  parser_->AppendData("stream<");
-  EXPECT_TRUE(error_);
-}
-
-}  // namespace remoting
diff --git a/remoting/test/it2me_cli_host.cc b/remoting/test/it2me_cli_host.cc
index f5dfa34..d43f216 100644
--- a/remoting/test/it2me_cli_host.cc
+++ b/remoting/test/it2me_cli_host.cc
@@ -41,13 +41,10 @@
 // Connect message parameters:
 constexpr char kCRDConnectUserName[] = "userName";
 constexpr char kCRDConnectAuth[] = "authServiceWithToken";
-constexpr char kCRDConnectXMPPServer[] = "xmppServerAddress";
-constexpr char kCRDConnectXMPPTLS[] = "xmppServerUseTls";
 constexpr char kCRDConnectDirectoryBot[] = "directoryBotJid";
 constexpr char kCRDConnectNoDialogs[] = "noDialogs";
 
 // Connect message parameter values:
-constexpr char kCRDConnectXMPPServerValue[] = "talk.google.com:443";
 constexpr char kCRDConnectDirectoryBotValue[] = "remoting@bot.talk.google.com";
 
 // CRD host states we care about:
@@ -219,9 +216,6 @@
 
   connect_params.SetKey(kCRDConnectUserName, base::Value(user_email));
   connect_params.SetKey(kCRDConnectAuth, base::Value("oauth2:" + access_token));
-  connect_params.SetKey(kCRDConnectXMPPServer,
-                        base::Value(kCRDConnectXMPPServerValue));
-  connect_params.SetKey(kCRDConnectXMPPTLS, base::Value(true));
   connect_params.SetKey(kCRDConnectDirectoryBot,
                         base::Value(kCRDConnectDirectoryBotValue));
   connect_params.SetKey(kCRDConnectNoDialogs, base::Value(true));
diff --git a/services/audio/input_controller_unittest.cc b/services/audio/input_controller_unittest.cc
index de779c8..02a7e1c7 100644
--- a/services/audio/input_controller_unittest.cc
+++ b/services/audio/input_controller_unittest.cc
@@ -109,7 +109,7 @@
  public:
   InputControllerTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         audio_manager_(std::make_unique<media::FakeAudioManager>(
             std::make_unique<media::TestAudioThread>(false),
             &log_factory_)),
diff --git a/services/audio/loopback_stream_unittest.cc b/services/audio/loopback_stream_unittest.cc
index 924bb6b..860eab37 100644
--- a/services/audio/loopback_stream_unittest.cc
+++ b/services/audio/loopback_stream_unittest.cc
@@ -252,7 +252,7 @@
 
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   LoopbackCoordinator coordinator_;
   const base::UnguessableToken group_id_;
   std::vector<std::unique_ptr<FakeLoopbackGroupMember>> sources_;
diff --git a/services/audio/test/audio_system_to_service_adapter_test.cc b/services/audio/test/audio_system_to_service_adapter_test.cc
index 06d76711..6990ef0 100644
--- a/services/audio/test/audio_system_to_service_adapter_test.cc
+++ b/services/audio/test/audio_system_to_service_adapter_test.cc
@@ -434,7 +434,7 @@
   MOCK_METHOD0(ClientDisconnected, void(void));
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
   const base::Optional<std::string> valid_reply_{kValidReplyId};
   base::MockCallback<media::AudioSystem::OnDeviceIdCallback> response_received_;
diff --git a/services/audio/test/service_lifetime_connector_test.cc b/services/audio/test/service_lifetime_connector_test.cc
index 1d1807c6..88715d6 100644
--- a/services/audio/test/service_lifetime_connector_test.cc
+++ b/services/audio/test/service_lifetime_connector_test.cc
@@ -54,7 +54,7 @@
 
  protected:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
   StrictMock<base::MockCallback<base::RepeatingClosure>> quit_request_;
   std::unique_ptr<media::MockAudioManager> audio_manager_;
diff --git a/services/device/geolocation/position_cache_impl_perftest.cc b/services/device/geolocation/position_cache_impl_perftest.cc
index f0f74826..9a80117 100644
--- a/services/device/geolocation/position_cache_impl_perftest.cc
+++ b/services/device/geolocation/position_cache_impl_perftest.cc
@@ -21,7 +21,7 @@
  public:
   PositionCacheImplPerfTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         cache_(task_environment_.GetMockTickClock()) {}
 
   void SetUp() override {
diff --git a/services/device/geolocation/position_cache_impl_unittest.cc b/services/device/geolocation/position_cache_impl_unittest.cc
index 251ddab..a7815f6 100644
--- a/services/device/geolocation/position_cache_impl_unittest.cc
+++ b/services/device/geolocation/position_cache_impl_unittest.cc
@@ -21,7 +21,7 @@
  public:
   PositionCacheImplTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         network_change_notifier_(net::NetworkChangeNotifier::CreateMock()),
         cache_(task_environment_.GetMockTickClock()) {}
 
diff --git a/services/device/geolocation/public_ip_address_location_notifier_unittest.cc b/services/device/geolocation/public_ip_address_location_notifier_unittest.cc
index daa152e..0ad5b6c 100644
--- a/services/device/geolocation/public_ip_address_location_notifier_unittest.cc
+++ b/services/device/geolocation/public_ip_address_location_notifier_unittest.cc
@@ -123,7 +123,7 @@
 
   // Use a TaskRunner on which we can fast-forward time.
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
 
   // Test NetworkConnectionTracker instance.
   std::unique_ptr<network::TestNetworkConnectionTracker>
diff --git a/services/device/public/cpp/usb/usb_ids.h b/services/device/public/cpp/usb/usb_ids.h
index a9545fa..318abdd 100644
--- a/services/device/public/cpp/usb/usb_ids.h
+++ b/services/device/public/cpp/usb/usb_ids.h
@@ -17,6 +17,10 @@
   const char* name;
 };
 
+// This structure is used in an array so the cumulative size is significant.
+// Order fields to minimize/eliminate alignment padding.
+// Chose field size based on contained data to further reduce structure size.
+// For example, uint16_t instead of size_t.
 struct UsbVendor {
   const char* name;
   const UsbProduct* products;
diff --git a/services/image_annotation/annotator_unittest.cc b/services/image_annotation/annotator_unittest.cc
index 6833ca3..730d4f41 100644
--- a/services/image_annotation/annotator_unittest.cc
+++ b/services/image_annotation/annotator_unittest.cc
@@ -385,7 +385,7 @@
 // Test that annotation works for one client, and that the cache is populated.
 TEST(AnnotatorTest, OcrSuccessAndCache) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -491,7 +491,7 @@
 // Test that description annotations are successfully returned.
 TEST(AnnotatorTest, DescriptionSuccess) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -598,7 +598,7 @@
 // Test that the specialized OCR result takes precedence.
 TEST(AnnotatorTest, DoubleOcrResult) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -713,7 +713,7 @@
 // Test that HTTP failure is gracefully handled.
 TEST(AnnotatorTest, HttpError) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -768,7 +768,7 @@
 // Test that backend failure is gracefully handled.
 TEST(AnnotatorTest, BackendError) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -851,7 +851,7 @@
 // Test that partial results are returned if the OCR backend fails.
 TEST(AnnotatorTest, OcrBackendError) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -945,7 +945,7 @@
 // Test that partial results are returned if the description backend fails.
 TEST(AnnotatorTest, DescriptionBackendError) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1035,7 +1035,7 @@
 // Test that server failure (i.e. nonsense response) is gracefully handled.
 TEST(AnnotatorTest, ServerError) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1093,7 +1093,7 @@
 // Test that adult content returns an error.
 TEST(AnnotatorTest, AdultError) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1168,7 +1168,7 @@
 // Test that work is reassigned if a processor fails.
 TEST(AnnotatorTest, ProcessorFails) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1248,7 +1248,7 @@
 // then fails local processing, then another client makes the same request.
 TEST(AnnotatorTest, ProcessorFailedPreviously) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1317,7 +1317,7 @@
 // Test that work is reassigned if processor dies.
 TEST(AnnotatorTest, ProcessorDies) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1392,7 +1392,7 @@
 // Test that multiple concurrent requests are handled in the same batch.
 TEST(AnnotatorTest, ConcurrentSameBatch) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1479,7 +1479,7 @@
 // Test that multiple concurrent requests are handled in separate batches.
 TEST(AnnotatorTest, ConcurrentSeparateBatches) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1623,7 +1623,7 @@
 // Test that work is not duplicated if it is already ongoing.
 TEST(AnnotatorTest, DuplicateWork) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1731,7 +1731,7 @@
 // model policy (i.e. are too small or have too-high an aspect ratio).
 TEST(AnnotatorTest, DescPolicy) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -1933,7 +1933,7 @@
 // Test that description language preferences are sent to the server.
 TEST(AnnotatorTest, DescLanguage) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   TestServerURLLoaderFactory test_url_factory(
       "https://ia-pa.googleapis.com/v1/");
   data_decoder::TestDataDecoderService test_dd_service;
@@ -2127,7 +2127,7 @@
 // domains.
 TEST(AnnotatorTest, ApiKey) {
   base::test::ScopedTaskEnvironment test_task_env(
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME);
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME);
   data_decoder::TestDataDecoderService test_dd_service;
 
   // A call to a secure Google-owner server URL should include the specified API
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index 8fbd123..f231bfe 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -86,6 +86,7 @@
     "origin_policy/origin_policy_constants.h",
     "origin_policy/origin_policy_fetcher.cc",
     "origin_policy/origin_policy_fetcher.h",
+    "origin_policy/origin_policy_header_values.h",
     "origin_policy/origin_policy_manager.cc",
     "origin_policy/origin_policy_manager.h",
     "origin_policy/origin_policy_parser.cc",
diff --git a/services/network/mdns_responder_unittest.cc b/services/network/mdns_responder_unittest.cc
index 16f10eb..c7f6070 100644
--- a/services/network/mdns_responder_unittest.cc
+++ b/services/network/mdns_responder_unittest.cc
@@ -407,7 +407,7 @@
   }
 
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   // Overrides the current thread task runner, so we can simulate the passage
   // of time and avoid any actual sleeps.
   NiceMock<net::MockMDnsSocketFactory> socket_factory_;
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 0bc1dff..d5b30a8 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -537,8 +537,7 @@
   resource_scheduler_ =
       std::make_unique<ResourceScheduler>(enable_resource_scheduler_);
 
-  origin_policy_manager_ = std::make_unique<OriginPolicyManager>(
-      CreateUrlLoaderFactoryForNetworkService());
+  origin_policy_manager_ = std::make_unique<OriginPolicyManager>(this);
 
   InitializeCorsParams();
 }
@@ -568,8 +567,7 @@
   resource_scheduler_ =
       std::make_unique<ResourceScheduler>(enable_resource_scheduler_);
 
-  origin_policy_manager_ = std::make_unique<OriginPolicyManager>(
-      CreateUrlLoaderFactoryForNetworkService());
+  origin_policy_manager_ = std::make_unique<OriginPolicyManager>(this);
 
   InitializeCorsParams();
 }
@@ -602,8 +600,7 @@
   for (const auto& key : cors_exempt_header_list)
     cors_exempt_header_list_.insert(key);
 
-  origin_policy_manager_ = std::make_unique<OriginPolicyManager>(
-      CreateUrlLoaderFactoryForNetworkService());
+  origin_policy_manager_ = std::make_unique<OriginPolicyManager>(this);
 }
 
 NetworkContext::~NetworkContext() {
diff --git a/services/network/origin_policy/origin_policy_fetcher.cc b/services/network/origin_policy/origin_policy_fetcher.cc
index e8f3d1a..8876ac75 100644
--- a/services/network/origin_policy/origin_policy_fetcher.cc
+++ b/services/network/origin_policy/origin_policy_fetcher.cc
@@ -17,29 +17,26 @@
 
 OriginPolicyFetcher::OriginPolicyFetcher(
     OriginPolicyManager* owner_policy_manager,
-    const std::string& policy_version,
-    const std::string& report_to,
+    const OriginPolicyHeaderValues& header_info,
     const url::Origin& origin,
     mojom::URLLoaderFactory* factory,
     mojom::OriginPolicyManager::RetrieveOriginPolicyCallback callback)
     : owner_policy_manager_(owner_policy_manager),
-      report_to_(report_to),
-      fetch_url_(GetPolicyURL(policy_version, origin)),
+      fetch_url_(GetPolicyURL(header_info.policy_version, origin)),
       callback_(std::move(callback)),
-      must_redirect_(false) {
+      must_redirect_(false),
+      header_info_(header_info) {
   DCHECK(callback_);
-  DCHECK(!policy_version.empty());
+  DCHECK(!header_info.policy_version.empty());
   FetchPolicy(factory);
 }
 
 OriginPolicyFetcher::OriginPolicyFetcher(
     OriginPolicyManager* owner_policy_manager,
-    const std::string& report_to,
     const url::Origin& origin,
     mojom::URLLoaderFactory* factory,
     mojom::OriginPolicyManager::RetrieveOriginPolicyCallback callback)
     : owner_policy_manager_(owner_policy_manager),
-      report_to_(report_to),
       fetch_url_(GetDefaultPolicyURL(origin)),
       callback_(std::move(callback)),
       must_redirect_(true) {
@@ -75,7 +72,8 @@
     std::unique_ptr<std::string> policy_content) {
   // Fail hard if the policy could not be loaded.
   if (!policy_content || must_redirect_) {
-    Report(OriginPolicyState::kCannotLoadPolicy);
+    owner_policy_manager_->MaybeReport(OriginPolicyState::kCannotLoadPolicy,
+                                       header_info_, fetch_url_);
     WorkDone(nullptr, OriginPolicyState::kCannotLoadPolicy);
   } else {
     WorkDone(std::move(policy_content), OriginPolicyState::kLoaded);
@@ -93,7 +91,8 @@
   }
 
   // Fail hard if the policy response follows an invalid redirect.
-  Report(OriginPolicyState::kInvalidRedirect);
+  owner_policy_manager_->MaybeReport(OriginPolicyState::kInvalidRedirect,
+                                     header_info_, fetch_url_);
 
   WorkDone(nullptr, OriginPolicyState::kInvalidRedirect);
 }
@@ -178,7 +177,4 @@
          GetPolicyURL(new_version, url::Origin::Create(fetch_url_));
 }
 
-// TODO(andypaicu): use report_to implement this function
-void OriginPolicyFetcher::Report(OriginPolicyState error_state) {}
-
 }  // namespace network
diff --git a/services/network/origin_policy/origin_policy_fetcher.h b/services/network/origin_policy/origin_policy_fetcher.h
index 00be556..35fb686c 100644
--- a/services/network/origin_policy/origin_policy_fetcher.h
+++ b/services/network/origin_policy/origin_policy_fetcher.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "net/url_request/redirect_info.h"
+#include "services/network/origin_policy/origin_policy_header_values.h"
 #include "services/network/public/cpp/simple_url_loader.h"
 #include "services/network/public/mojom/origin_policy_manager.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
@@ -26,8 +27,7 @@
   // origin using the specified policy_version.
   OriginPolicyFetcher(
       OriginPolicyManager* owner_policy_manager,
-      const std::string& policy_version,
-      const std::string& report_to,
+      const OriginPolicyHeaderValues& header_info,
       const url::Origin& origin,
       mojom::URLLoaderFactory* factory,
       mojom::OriginPolicyManager::RetrieveOriginPolicyCallback callback);
@@ -37,7 +37,6 @@
   // Spec: https://wicg.github.io/origin-policy/#origin-policy-well-known
   OriginPolicyFetcher(
       OriginPolicyManager* owner_policy_manager,
-      const std::string& report_to,
       const url::Origin& origin,
       mojom::URLLoaderFactory* factory,
       mojom::OriginPolicyManager::RetrieveOriginPolicyCallback callback);
@@ -69,8 +68,6 @@
 
   bool IsValidRedirect(const net::RedirectInfo& redirect_info) const;
 
-  void Report(OriginPolicyState error_state);
-
   // The owner of this object. When it is destroyed, this is destroyed too.
   OriginPolicyManager* const owner_policy_manager_;
 
@@ -78,9 +75,6 @@
   // be kept alive while the load is ongoing.
   std::unique_ptr<network::SimpleURLLoader> url_loader_;
 
-  // Used to determine the reporting group in case of a failure.
-  std::string report_to_;
-
   // Used for testing if a redirect is valid.
   GURL fetch_url_;
 
@@ -91,6 +85,10 @@
   // which must redirect to the latest origin policy.
   bool must_redirect_;
 
+  // The header info parsed from the received `Sec-Origin-Policy` header. Empty
+  // if no header is present.
+  OriginPolicyHeaderValues header_info_;
+
   DISALLOW_COPY_AND_ASSIGN(OriginPolicyFetcher);
 };
 
diff --git a/services/network/origin_policy/origin_policy_fetcher_unittest.cc b/services/network/origin_policy/origin_policy_fetcher_unittest.cc
index 6607b17..8e512d6 100644
--- a/services/network/origin_policy/origin_policy_fetcher_unittest.cc
+++ b/services/network/origin_policy/origin_policy_fetcher_unittest.cc
@@ -16,6 +16,7 @@
 #include "services/network/network_service.h"
 #include "services/network/origin_policy/origin_policy_constants.h"
 #include "services/network/origin_policy/origin_policy_fetcher.h"
+#include "services/network/origin_policy/origin_policy_header_values.h"
 #include "services/network/origin_policy/origin_policy_manager.h"
 #include "services/network/origin_policy/origin_policy_parser.h"
 #include "services/network/public/cpp/origin_policy.h"
@@ -52,8 +53,7 @@
     network_context_->CreateURLLoaderFactory(
         mojo::MakeRequest(&url_loader_factory_), std::move(params));
 
-    manager_ = std::make_unique<OriginPolicyManager>(
-        network_context_->CreateUrlLoaderFactoryForNetworkService());
+    manager_ = std::make_unique<OriginPolicyManager>(network_context_.get());
 
     test_server_.RegisterRequestHandler(base::BindRepeating(
         &OriginPolicyFetcherTest::HandleResponse, base::Unretained(this)));
@@ -199,11 +199,12 @@
     auto fetcher =
         test.initial_version.empty()
             ? std::make_unique<OriginPolicyFetcher>(
-                  manager(), "" /* report_to */, test_server_origin(),
-                  url_loader_factory(),
+                  manager(), test_server_origin(), url_loader_factory(),
                   base::BindOnce(&DummyRetrieveOriginPolicyCallback))
             : std::make_unique<OriginPolicyFetcher>(
-                  manager(), test.initial_version, "" /* report_to */,
+                  manager(),
+                  OriginPolicyHeaderValues(
+                      {.policy_version = test.initial_version}),
                   test_server_origin(), url_loader_factory(),
                   base::BindOnce(&DummyRetrieveOriginPolicyCallback));
 
@@ -321,10 +322,10 @@
 }
 
 TEST_F(OriginPolicyFetcherTest, EmptyVersionConstructor) {
-  EXPECT_DCHECK_DEATH(OriginPolicyFetcher(
-      manager(), "" /* policy_version */, "" /* report_to */,
-      test_server_origin(), url_loader_factory(),
-      base::BindOnce(&DummyRetrieveOriginPolicyCallback)));
+  EXPECT_DCHECK_DEATH(
+      OriginPolicyFetcher(manager(), OriginPolicyHeaderValues(),
+                          test_server_origin(), url_loader_factory(),
+                          base::BindOnce(&DummyRetrieveOriginPolicyCallback)));
 }
 
 }  // namespace network
diff --git a/services/network/origin_policy/origin_policy_header_values.h b/services/network/origin_policy/origin_policy_header_values.h
new file mode 100644
index 0000000..94344afa
--- /dev/null
+++ b/services/network/origin_policy/origin_policy_header_values.h
@@ -0,0 +1,25 @@
+// 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 SERVICES_NETWORK_ORIGIN_POLICY_ORIGIN_POLICY_HEADER_VALUES_H_
+#define SERVICES_NETWORK_ORIGIN_POLICY_ORIGIN_POLICY_HEADER_VALUES_H_
+
+#include <string>
+
+namespace network {
+// Represents a parsed `Sec-Origin-Policy` header.
+// Spec: https://wicg.github.io/origin-policy/#origin-policy-header
+struct OriginPolicyHeaderValues {
+  // The policy version that is parsed from the `policy=` parameter.
+  std::string policy_version;
+  // The report group to send reports to if an error occurs. Uses the
+  // reporting API. Parsed from the `report-to=` parameter.
+  std::string report_to;
+  // The raw header that was used to populate this struct. Added to the report
+  // that is send in case on an origin policy error.
+  std::string raw_header;
+};
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_ORIGIN_POLICY_ORIGIN_POLICY_HEADER_VALUES_H_
diff --git a/services/network/origin_policy/origin_policy_manager.cc b/services/network/origin_policy/origin_policy_manager.cc
index 315d8dd..44004ab 100644
--- a/services/network/origin_policy/origin_policy_manager.cc
+++ b/services/network/origin_policy/origin_policy_manager.cc
@@ -10,6 +10,7 @@
 #include "base/logging.h"
 #include "base/optional.h"
 #include "net/http/http_util.h"
+#include "services/network/network_context.h"
 #include "services/network/origin_policy/origin_policy_fetcher.h"
 
 namespace {
@@ -22,9 +23,10 @@
 
 namespace network {
 
-OriginPolicyManager::OriginPolicyManager(
-    mojom::URLLoaderFactoryPtr url_loader_factory)
-    : url_loader_factory_(std::move(url_loader_factory)) {}
+OriginPolicyManager::OriginPolicyManager(NetworkContext* owner_network_context)
+    : owner_network_context_(owner_network_context),
+      url_loader_factory_(
+          owner_network_context_->CreateUrlLoaderFactoryForNetworkService()) {}
 
 OriginPolicyManager::~OriginPolicyManager() {}
 
@@ -72,6 +74,7 @@
                                         ? OriginPolicyState::kNoPolicyApplies
                                         : OriginPolicyState::kCannotLoadPolicy,
                                     std::move(callback));
+      MaybeReport(OriginPolicyState::kCannotLoadPolicy, header_info, GURL());
       return;
     }
     header_info.policy_version = iter->second;
@@ -82,8 +85,8 @@
   }
 
   origin_policy_fetchers_.emplace(std::make_unique<OriginPolicyFetcher>(
-      this, header_info.policy_version, header_info.report_to, origin,
-      url_loader_factory_.get(), std::move(callback)));
+      this, header_info, origin, url_loader_factory_.get(),
+      std::move(callback)));
 }
 
 void OriginPolicyManager::AddExceptionFor(const url::Origin& origin) {
@@ -104,21 +107,61 @@
     const url::Origin& origin,
     RetrieveOriginPolicyCallback callback) {
   origin_policy_fetchers_.emplace(std::make_unique<OriginPolicyFetcher>(
-      this, std::string() /* report_to */, origin, url_loader_factory_.get(),
-      std::move(callback)));
+      this, origin, url_loader_factory_.get(), std::move(callback)));
 }
 
+#if BUILDFLAG(ENABLE_REPORTING)
+void OriginPolicyManager::MaybeReport(
+    OriginPolicyState state,
+    const OriginPolicyHeaderValues& header_info,
+    const GURL& policy_url) {
+  if (header_info.report_to.empty())
+    return;
+
+  const char* reason_str = nullptr;
+  switch (state) {
+    case OriginPolicyState::kCannotLoadPolicy:
+      reason_str = "CANNOT_LOAD";
+      break;
+    case OriginPolicyState::kInvalidRedirect:
+      reason_str = "REDIRECT";
+      break;
+    case OriginPolicyState::kOther:
+      reason_str = "OTHER";
+      break;
+    default:
+      NOTREACHED();
+      return;
+  }
+
+  base::DictionaryValue report_body;
+  report_body.SetKey("origin_policy_url", base::Value(policy_url.spec()));
+  report_body.SetKey("policy", base::Value(header_info.raw_header));
+  report_body.SetKey("policy_error_reason", base::Value(reason_str));
+
+  owner_network_context_->QueueReport("origin-policy", header_info.report_to,
+                                      policy_url, base::nullopt,
+                                      std::move(report_body));
+}
+#else
+void OriginPolicyManager::MaybeReport(
+    OriginPolicyState state,
+    const OriginPolicyHeaderValues& header_info,
+    const GURL& policy_url) {}
+#endif  // BUILDFLAG(ENABLE_REPORTING)
+
 // static
 const char* OriginPolicyManager::GetExemptedVersionForTesting() {
   return kExemptedOriginPolicyVersion;
 }
 
 // static
-OriginPolicyManager::OriginPolicyHeaderValues
+OriginPolicyHeaderValues
 OriginPolicyManager::GetRequestedPolicyAndReportGroupFromHeaderString(
     const std::string& header_value) {
   if (net::HttpUtil::TrimLWS(header_value) == kOriginPolicyDeletePolicy)
-    return OriginPolicyHeaderValues({kOriginPolicyDeletePolicy, ""});
+    return OriginPolicyHeaderValues(
+        {kOriginPolicyDeletePolicy, "", header_value});
 
   base::Optional<std::string> policy;
   base::Optional<std::string> report_to;
@@ -140,8 +183,9 @@
   valid &= (policy.has_value() && policy->find('.') == std::string::npos);
 
   if (!valid)
-    return OriginPolicyHeaderValues();
-  return OriginPolicyHeaderValues({policy.value(), report_to.value_or("")});
+    return OriginPolicyHeaderValues({"", "", header_value});
+  return OriginPolicyHeaderValues(
+      {policy.value(), report_to.value_or(""), header_value});
 }
 
 // static
diff --git a/services/network/origin_policy/origin_policy_manager.h b/services/network/origin_policy/origin_policy_manager.h
index 95947f78..1a32fb7b 100644
--- a/services/network/origin_policy/origin_policy_manager.h
+++ b/services/network/origin_policy/origin_policy_manager.h
@@ -15,11 +15,13 @@
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/binding_set.h"
 #include "services/network/origin_policy/origin_policy_constants.h"
+#include "services/network/origin_policy/origin_policy_header_values.h"
 #include "services/network/public/mojom/origin_policy_manager.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 
 namespace network {
 
+class NetworkContext;
 class OriginPolicyFetcher;
 
 // The OriginPolicyManager is the entry point for all Origin Policy related
@@ -30,21 +32,13 @@
 class COMPONENT_EXPORT(NETWORK_SERVICE) OriginPolicyManager
     : public mojom::OriginPolicyManager {
  public:
-  // Represents a parsed `Sec-Origin-Policy` header.
-  // Spec: https://wicg.github.io/origin-policy/#origin-policy-header
-  struct OriginPolicyHeaderValues {
-    // The policy version that is parsed from the `policy=` parameter.
-    std::string policy_version;
-    // The report group to send reports to if an error occurs. Uses the
-    // reporting API. Parsed from the `report-to=` parameter.
-    std::string report_to;
-  };
-
-  explicit OriginPolicyManager(mojom::URLLoaderFactoryPtr url_loader_factory);
+  // The |owner_network_context| is the owner of this object and it needs to
+  // always outlive this object.
+  explicit OriginPolicyManager(NetworkContext* owner_network_context);
   ~OriginPolicyManager() override;
 
-  // Bind a request to this object.  Mojo messages
-  // coming through the associated pipe will be served by this object.
+  // Bind a request to this object.  Mojo messages coming through the associated
+  // pipe will be served by this object.
   void AddBinding(mojom::OriginPolicyManagerRequest request);
 
   // mojom::OriginPolicyManager
@@ -64,6 +58,12 @@
   void RetrieveDefaultOriginPolicy(const url::Origin& origin,
                                    RetrieveOriginPolicyCallback callback);
 
+  // Attempts to report a policy retrieval failure. Does nothing if
+  // `header_info` has an empty `report_to` member.
+  void MaybeReport(OriginPolicyState state,
+                   const OriginPolicyHeaderValues& header_info,
+                   const GURL& policy_url);
+
   // ForTesting methods
   mojo::BindingSet<mojom::OriginPolicyManager>& GetBindingsForTesting() {
     return bindings_;
@@ -94,6 +94,10 @@
       OriginPolicyState state,
       RetrieveOriginPolicyCallback callback);
 
+  // Owner of this object. It needs to always outlive this object.
+  // Used for queueing reports and creating a URLLoaderFactory.
+  NetworkContext* const owner_network_context_;
+
   // In memory cache of current policy version per origin.
   // TODO(andypaicu): clear this when the disk cache is cleaned.
   KnownVersionMap latest_version_map_;
diff --git a/services/network/origin_policy/origin_policy_manager_unittest.cc b/services/network/origin_policy/origin_policy_manager_unittest.cc
index 3be49ee2..31435d46 100644
--- a/services/network/origin_policy/origin_policy_manager_unittest.cc
+++ b/services/network/origin_policy/origin_policy_manager_unittest.cc
@@ -6,20 +6,27 @@
 #include <utility>
 
 #include "base/strings/strcat.h"
+#include "base/test/gtest_util.h"
 #include "base/test/scoped_task_environment.h"
 #include "net/http/http_status_code.h"
 #include "net/http/http_util.h"
+#include "net/reporting/reporting_policy.h"
+#include "net/reporting/reporting_service.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
+#include "net/url_request/url_request_context.h"
 #include "services/network/network_context.h"
 #include "services/network/network_service.h"
 #include "services/network/origin_policy/origin_policy_fetcher.h"
 #include "services/network/origin_policy/origin_policy_manager.h"
 #include "services/network/origin_policy/origin_policy_parser.h"
 #include "services/network/public/cpp/origin_policy.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+using ::testing::_;
+
 namespace network {
 
 namespace {
@@ -42,8 +49,7 @@
     network_context_ = std::make_unique<NetworkContext>(
         network_service_.get(), mojo::MakeRequest(&network_context_ptr_),
         std::move(context_params));
-    manager_ = std::make_unique<OriginPolicyManager>(
-        network_context_->CreateUrlLoaderFactoryForNetworkService());
+    manager_ = std::make_unique<OriginPolicyManager>(network_context_.get());
 
     test_server_.RegisterRequestHandler(base::BindRepeating(
         &OriginPolicyManagerTest::HandleResponse, base::Unretained(this)));
@@ -227,7 +233,7 @@
   };
   for (const auto& test : kTests) {
     SCOPED_TRACE(test.header);
-    OriginPolicyManager::OriginPolicyHeaderValues result = OriginPolicyManager::
+    OriginPolicyHeaderValues result = OriginPolicyManager::
         GetRequestedPolicyAndReportGroupFromHeaderStringForTesting(test.header);
     EXPECT_EQ(test.expected_policy_version, result.policy_version);
     EXPECT_EQ(test.expected_report_to, result.report_to);
@@ -298,8 +304,7 @@
   for (const auto& test : kTests) {
     SCOPED_TRACE(test.header);
 
-    OriginPolicyManager manager(
-        network_context()->CreateUrlLoaderFactoryForNetworkService());
+    OriginPolicyManager manager(network_context());
 
     TestOriginPolicyManagerResult tester(this, &manager);
     tester.RetrieveOriginPolicy(test.header);
@@ -323,8 +328,7 @@
   {
     mojom::OriginPolicyManagerPtr origin_policy_ptr;
 
-    OriginPolicyManager manager(
-        network_context()->CreateUrlLoaderFactoryForNetworkService());
+    OriginPolicyManager manager(network_context());
 
     manager.AddBinding(mojo::MakeRequest(&origin_policy_ptr));
 
@@ -436,4 +440,140 @@
   }
 }
 
+#if BUILDFLAG(ENABLE_REPORTING)
+class MockReportingService : public net::ReportingService {
+ public:
+  MOCK_METHOD6(QueueReport,
+               void(const GURL&,
+                    const std::string&,
+                    const std::string&,
+                    const std::string&,
+                    std::unique_ptr<const base::Value>,
+                    int));
+  MOCK_METHOD2(ProcessHeader, void(const GURL&, const std::string&));
+  MOCK_METHOD2(RemoveBrowsingData,
+               void(int, const base::RepeatingCallback<bool(const GURL&)>&));
+  MOCK_METHOD1(RemoveAllBrowsingData, void(int));
+  MOCK_METHOD0(OnShutdown, void());
+  MOCK_CONST_METHOD0(GetPolicy, const net::ReportingPolicy&());
+  MOCK_CONST_METHOD0(StatusAsValue, base::Value());
+  MOCK_CONST_METHOD0(GetContextForTesting, net::ReportingContext*());
+};
+
+MATCHER_P(ReportBodyEquals, expected, "") {
+  if (!arg->is_dict() || !expected->is_dict() || arg->DictSize() != 3 ||
+      expected->DictSize() != 3) {
+    return false;
+  }
+
+  for (const std::string& key_name :
+       {"origin_policy_url", "policy", "policy_error_reason"}) {
+    if (!arg->FindStringKey(key_name) || !expected->FindStringKey(key_name) ||
+        *arg->FindStringKey(key_name) != *expected->FindStringKey(key_name)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+TEST_F(OriginPolicyManagerTest, TestMaybeReport) {
+  struct ReportingTest {
+    OriginPolicyState state;
+    const OriginPolicyHeaderValues& header_info;
+    const GURL& policy_url;
+    const std::string expected_origin_policy_url = "";
+    const std::string expected_policy = "";
+    const std::string expected_policy_error_reason = "";
+  };
+
+  // These tests should cause the report to be queued.
+  ReportingTest kReportingTests[] = {
+      {OriginPolicyState::kCannotLoadPolicy,
+       OriginPolicyHeaderValues({"version1", "report1", "raw1"}),
+       GURL("http://example1.com/"), "http://example1.com/", "raw1",
+       "CANNOT_LOAD"},
+      {OriginPolicyState::kInvalidRedirect,
+       OriginPolicyHeaderValues({"version2", "report2", "raw2"}),
+       GURL("http://example2.com/"), "http://example2.com/", "raw2",
+       "REDIRECT"},
+      {OriginPolicyState::kOther,
+       OriginPolicyHeaderValues({"version3", "report3", "raw3"}),
+       GURL("http://example3.com/"), "http://example3.com/", "raw3", "OTHER"},
+  };
+
+  // These tests should trigger a dcheck.
+  ReportingTest kDheckTests[] = {
+      {OriginPolicyState::kLoaded,
+       OriginPolicyHeaderValues({"version1", "report1", "raw1"}),
+       GURL("http://example1.com/")},
+      {OriginPolicyState::kNoPolicyApplies,
+       OriginPolicyHeaderValues({"version2", "report2", "raw2"}),
+       GURL("http://example2.com/")},
+  };
+
+  // These tests should return without queueing a report.
+  ReportingTest kReturningTests[] = {
+      {OriginPolicyState::kInvalidRedirect,
+       OriginPolicyHeaderValues({"", "", ""}), GURL("http://example1.com/")},
+      {OriginPolicyState::kLoaded,
+       OriginPolicyHeaderValues({"version1", "", "raw1"}),
+       GURL("http://example1.com/")},
+      {OriginPolicyState::kCannotLoadPolicy,
+       OriginPolicyHeaderValues({"version1", "", "raw1"}),
+       GURL("http://example1.com/")},
+      {OriginPolicyState::kOther,
+       OriginPolicyHeaderValues({"version1", "", "raw1"}),
+       GURL("http://example1.com/")},
+      {OriginPolicyState::kInvalidRedirect,
+       OriginPolicyHeaderValues({"version1", "", "raw1"}),
+       GURL("http://example1.com/")},
+      {OriginPolicyState::kNoPolicyApplies,
+       OriginPolicyHeaderValues({"version1", "", "raw1"}),
+       GURL("http://example1.com/")},
+  };
+
+  for (const auto& test : kReportingTests) {
+    MockReportingService mock_service;
+    network_context()->url_request_context()->set_reporting_service(
+        &mock_service);
+
+    base::DictionaryValue expected_report_body;
+    expected_report_body.SetKey("origin_policy_url",
+                                base::Value(test.expected_origin_policy_url));
+    expected_report_body.SetKey("policy", base::Value(test.expected_policy));
+    expected_report_body.SetKey("policy_error_reason",
+                                base::Value(test.expected_policy_error_reason));
+
+    EXPECT_CALL(
+        mock_service,
+        QueueReport(test.policy_url, _ /* user_agent */,
+                    test.header_info.report_to, "origin-policy",
+                    ReportBodyEquals(&expected_report_body), _ /* depth */))
+        .Times(1);
+
+    manager()->MaybeReport(test.state, test.header_info, test.policy_url);
+
+    network_context()->url_request_context()->set_reporting_service(nullptr);
+  }
+
+  for (const auto& test : kDheckTests) {
+    EXPECT_DCHECK_DEATH(
+        manager()->MaybeReport(test.state, test.header_info, test.policy_url));
+  }
+
+  for (const auto& test : kReturningTests) {
+    MockReportingService mock_service;
+    network_context()->url_request_context()->set_reporting_service(
+        &mock_service);
+
+    EXPECT_CALL(mock_service, QueueReport(_, _, _, _, _, _)).Times(0);
+
+    manager()->MaybeReport(test.state, test.header_info, test.policy_url);
+
+    network_context()->url_request_context()->set_reporting_service(nullptr);
+  }
+}
+#endif  // BUILDFLAG(ENABLE_REPORTING)
+
 }  // namespace network
diff --git a/services/network/public/cpp/simple_url_loader_unittest.cc b/services/network/public/cpp/simple_url_loader_unittest.cc
index bbb2dee..0374341 100644
--- a/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -2978,7 +2978,7 @@
  public:
   SimpleURLLoaderMockTimeTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME),
         disallow_blocking_(std::make_unique<base::ScopedDisallowBlocking>()) {
     SimpleURLLoader::SetTimeoutTickClockForTest(
         scoped_task_environment_.GetMockTickClock());
diff --git a/services/network/throttling/throttling_controller_unittest.cc b/services/network/throttling/throttling_controller_unittest.cc
index c0baaa9..367a9ea 100644
--- a/services/network/throttling/throttling_controller_unittest.cc
+++ b/services/network/throttling/throttling_controller_unittest.cc
@@ -148,7 +148,7 @@
 
  private:
   base::test::ScopedTaskEnvironment scoped_task_environment_{
-      base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME};
+      base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME};
   MockNetworkLayer network_layer_;
   TestCallback callback_;
   net::CompletionRepeatingCallback completion_callback_;
diff --git a/services/preferences/tracked/pref_hash_filter.cc b/services/preferences/tracked/pref_hash_filter.cc
index 485c515..1493df8 100644
--- a/services/preferences/tracked/pref_hash_filter.cc
+++ b/services/preferences/tracked/pref_hash_filter.cc
@@ -55,16 +55,14 @@
         tracked_preferences,
     prefs::mojom::ResetOnLoadObserverPtr reset_on_load_observer,
     prefs::mojom::TrackedPreferenceValidationDelegate* delegate,
-    size_t reporting_ids_count,
-    bool report_super_mac_validity)
+    size_t reporting_ids_count)
     : pref_hash_store_(std::move(pref_hash_store)),
       external_validation_hash_store_pair_(
           external_validation_hash_store_pair.first
               ? base::make_optional(
                     std::move(external_validation_hash_store_pair))
               : base::nullopt),
-      reset_on_load_observer_(std::move(reset_on_load_observer)),
-      report_super_mac_validity_(report_super_mac_validity) {
+      reset_on_load_observer_(std::move(reset_on_load_observer)) {
   DCHECK(pref_hash_store_);
   DCHECK_GE(reporting_ids_count, tracked_preferences.size());
   // Verify that, if |external_validation_hash_store_pair_| is present, both its
@@ -234,11 +232,6 @@
     CleanupDeprecatedTrackedPreferences(pref_store_contents.get(),
                                         hash_store_transaction.get());
 
-    if (report_super_mac_validity_) {
-      UMA_HISTOGRAM_BOOLEAN("Settings.HashesDictionaryTrusted",
-                            hash_store_transaction->IsSuperMACValid());
-    }
-
     for (auto it = tracked_paths_.begin(); it != tracked_paths_.end(); ++it) {
       if (it->second->EnforceAndReport(
               pref_store_contents.get(), hash_store_transaction.get(),
diff --git a/services/preferences/tracked/pref_hash_filter.h b/services/preferences/tracked/pref_hash_filter.h
index 2bad7bb..5c0b6b2 100644
--- a/services/preferences/tracked/pref_hash_filter.h
+++ b/services/preferences/tracked/pref_hash_filter.h
@@ -55,9 +55,7 @@
   // If |reset_on_load_observer| is provided, it will be notified if a reset
   // occurs in FilterOnLoad.
   // |reporting_ids_count| is the count of all possible IDs (possibly greater
-  // than |tracked_preferences.size()|). If |report_super_mac_validity| is true,
-  // the state of the super MAC will be reported via UMA during
-  // FinalizeFilterOnLoad.
+  // than |tracked_preferences.size()|).
   // |external_validation_hash_store_pair_| will be used (if non-null) to
   // perform extra validations without triggering resets.
   PrefHashFilter(std::unique_ptr<PrefHashStore> pref_hash_store,
@@ -66,8 +64,7 @@
                      tracked_preferences,
                  prefs::mojom::ResetOnLoadObserverPtr reset_on_load_observer,
                  prefs::mojom::TrackedPreferenceValidationDelegate* delegate,
-                 size_t reporting_ids_count,
-                 bool report_super_mac_validity);
+                 size_t reporting_ids_count);
 
   ~PrefHashFilter() override;
 
@@ -150,9 +147,6 @@
   // FilterSerializeData.
   ChangedPathsMap changed_paths_;
 
-  // Whether to report the validity of the super MAC at load time (via UMA).
-  bool report_super_mac_validity_;
-
   DISALLOW_COPY_AND_ASSIGN(PrefHashFilter);
 };
 
diff --git a/services/preferences/tracked/pref_hash_filter_unittest.cc b/services/preferences/tracked/pref_hash_filter_unittest.cc
index 6d51fd8..969e581f 100644
--- a/services/preferences/tracked/pref_hash_filter_unittest.cc
+++ b/services/preferences/tracked/pref_hash_filter_unittest.cc
@@ -586,7 +586,7 @@
             std::move(temp_mock_external_validation_pref_hash_store),
             std::move(temp_mock_external_validation_hash_store_contents)),
         std::move(configuration), std::move(reset_on_load_observer),
-        &mock_validation_delegate_, base::size(kTestTrackedPrefs), true));
+        &mock_validation_delegate_, base::size(kTestTrackedPrefs)));
   }
 
   // Verifies whether a reset was reported by the PrefHashFiler. Also verifies
@@ -717,42 +717,6 @@
   VerifyRecordedReset(false);
 }
 
-TEST_P(PrefHashFilterTest, ReportSuperMacValidity) {
-  // Do this once just to force the histogram to be defined.
-  DoFilterOnLoad(false);
-
-  base::HistogramBase* histogram = base::StatisticsRecorder::FindHistogram(
-      "Settings.HashesDictionaryTrusted");
-  ASSERT_TRUE(histogram);
-
-  base::HistogramBase::Count initial_untrusted =
-      histogram->SnapshotSamples()->GetCount(0);
-  base::HistogramBase::Count initial_trusted =
-      histogram->SnapshotSamples()->GetCount(1);
-
-  Reset();
-
-  // Run with an invalid super MAC.
-  mock_pref_hash_store_->set_is_super_mac_valid_result(false);
-
-  DoFilterOnLoad(false);
-
-  // Verify that the invalidity was reported.
-  ASSERT_EQ(initial_untrusted + 1, histogram->SnapshotSamples()->GetCount(0));
-  ASSERT_EQ(initial_trusted, histogram->SnapshotSamples()->GetCount(1));
-
-  Reset();
-
-  // Run with a valid super MAC.
-  mock_pref_hash_store_->set_is_super_mac_valid_result(true);
-
-  DoFilterOnLoad(false);
-
-  // Verify that the validity was reported.
-  ASSERT_EQ(initial_untrusted + 1, histogram->SnapshotSamples()->GetCount(0));
-  ASSERT_EQ(initial_trusted + 1, histogram->SnapshotSamples()->GetCount(1));
-}
-
 TEST_P(PrefHashFilterTest, FilterSplitPrefUpdate) {
   base::DictionaryValue root_dict;
   base::DictionaryValue* dict_value = root_dict.SetDictionary(
diff --git a/services/preferences/tracked/tracked_persistent_pref_store_factory.cc b/services/preferences/tracked/tracked_persistent_pref_store_factory.cc
index 9eb846c..ac7f3a6 100644
--- a/services/preferences/tracked/tracked_persistent_pref_store_factory.cc
+++ b/services/preferences/tracked/tracked_persistent_pref_store_factory.cc
@@ -108,8 +108,8 @@
                          GetExternalVerificationPrefHashStorePair(
                              *config, temp_scoped_dir_cleaner),
                          unprotected_configuration, nullptr,
-                         validation_delegate.get(), config->reporting_ids_count,
-                         false));
+                         validation_delegate.get(),
+                         config->reporting_ids_count));
   prefs::mojom::ResetOnLoadObserverPtr reset_on_load_observer(
       std::move(config->reset_on_load_observer));
   std::unique_ptr<PrefHashFilter> protected_pref_hash_filter(new PrefHashFilter(
@@ -117,7 +117,7 @@
       GetExternalVerificationPrefHashStorePair(*config,
                                                temp_scoped_dir_cleaner),
       protected_configuration, std::move(reset_on_load_observer),
-      validation_delegate.get(), config->reporting_ids_count, true));
+      validation_delegate.get(), config->reporting_ids_count));
 
   PrefHashFilter* raw_unprotected_pref_hash_filter =
       unprotected_pref_hash_filter.get();
@@ -154,6 +154,6 @@
       CreatePrefHashStore(*configuration, false),
       GetExternalVerificationPrefHashStorePair(*configuration, nullptr),
       configuration->tracking_configuration, nullptr, nullptr,
-      configuration->reporting_ids_count, false)
+      configuration->reporting_ids_count)
       .Initialize(master_prefs);
 }
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 36cc9a82..1b5de54 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -3687,6 +3687,51 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "android_browsertests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "KTU84Z",
+              "device_os_type": "userdebug",
+              "device_type": "flo",
+              "os": "Android"
+            }
+          ],
+          "expiration": 10800,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "android_browsertests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "angle_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -9553,6 +9598,51 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "android_browsertests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "LMY49B",
+              "device_os_type": "userdebug",
+              "device_type": "flo",
+              "os": "Android"
+            }
+          ],
+          "expiration": 10800,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "android_browsertests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "android_webview_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -15441,6 +15531,51 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "android_browsertests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MRA58Z",
+              "device_os_type": "userdebug",
+              "device_type": "flo",
+              "os": "Android"
+            }
+          ],
+          "expiration": 10800,
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "android_browsertests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "android_webview_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 28e2b8da..4cab272 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -2696,6 +2696,51 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "android_browsertests"
+          ],
+          "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "cipd_packages": [
+            {
+              "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
+              "location": "bin",
+              "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c"
+            }
+          ],
+          "dimension_sets": [
+            {
+              "device_os": "MMB29Q",
+              "device_os_type": "userdebug",
+              "device_type": "bullhead",
+              "os": "Android"
+            }
+          ],
+          "output_links": [
+            {
+              "link": [
+                "https://luci-logdog.appspot.com/v/?s",
+                "=android%2Fswarming%2Flogcats%2F",
+                "${TASK_ID}%2F%2B%2Funified_logcats"
+              ],
+              "name": "shard #${SHARD_INDEX} logcats"
+            }
+          ]
+        },
+        "test": "android_browsertests"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "isolate_coverage_data": true,
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "android_webview_unittests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index 5cb7055..067a90b 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -16,17 +16,6 @@
 # The goal is to drive the number of exceptions to zero, to make all
 # the bots behave similarly.
 {
-  'android_browsertests': {
-    'remove_from': [
-      # TODO(crbug.com/961849): Remove these exceptions as the suite proves stable.
-      # chromium.android.json
-      'KitKat Tablet Tester',
-      'Lollipop Tablet Tester',
-      'Marshmallow Tablet Tester',
-      # chromium.fyi.json
-      'android-code-coverage',
-    ],
-  },
   'android_webview_unittests': {
     'remove_from': [
       # On chromium.android, these do not need to run prior to M.
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index c6e34eb..777df3f 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -1722,24 +1722,6 @@
             ]
         }
     ],
-    "DefaultSearchShortcut": [
-        {
-            "platforms": [
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DefaultSearchShortcut"
-                    ]
-                }
-            ]
-        }
-    ],
     "DialMediaRouteProvider": [
         {
             "platforms": [
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 43e79fe..1ee1037 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -115,10 +115,6 @@
 const base::Feature kOffMainThreadSharedWorkerScriptFetch{
     "OffMainThreadSharedWorkerScriptFetch", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Onion souping for all DOMStorage. https://crbug.com/781870
-const base::Feature kOnionSoupDOMStorage{"OnionSoupDOMStorage",
-                                         base::FEATURE_ENABLED_BY_DEFAULT};
-
 // Enable browser-initiated dedicated worker script loading
 // (PlzDedicatedWorker). https://crbug.com/906991
 const base::Feature kPlzDedicatedWorker{"PlzDedicatedWorker",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 551fd89e..6a688ac1 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -39,7 +39,6 @@
     kOffMainThreadDedicatedWorkerScriptFetch;
 BLINK_COMMON_EXPORT extern const base::Feature
     kOffMainThreadServiceWorkerScriptFetch;
-BLINK_COMMON_EXPORT extern const base::Feature kOnionSoupDOMStorage;
 BLINK_COMMON_EXPORT extern const base::Feature kPlzDedicatedWorker;
 BLINK_COMMON_EXPORT extern const base::Feature kPortals;
 BLINK_COMMON_EXPORT extern const base::Feature
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 7d1d7a4..04e115b 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -1343,7 +1343,6 @@
   kVRPoseAngularVelocity = 1865,
   kVRPoseAngularAcceleration = 1866,
   kCSSOverflowPaged = 1867,
-  kChildSrcAllowedWorkerThatScriptSrcBlocked = 1868,
   kHTMLTableElementPresentationAttributeBackground = 1869,
   kV8Navigator_GetInstalledRelatedApps_Method = 1870,
   kNamedAccessOnWindow_ChildBrowsingContext = 1871,
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h
index 342e17a..9ae0278 100644
--- a/third_party/blink/public/platform/platform.h
+++ b/third_party/blink/public/platform/platform.h
@@ -562,6 +562,8 @@
     return nullptr;
   }
 
+  virtual bool RTCSmoothnessAlgorithmEnabled() { return true; }
+
   // WebRTC ----------------------------------------------------------
 
   // Creates a WebRTCPeerConnectionHandler for RTCPeerConnection.
diff --git a/third_party/blink/public/platform/web_storage_area.h b/third_party/blink/public/platform/web_storage_area.h
deleted file mode 100644
index f958332..0000000
--- a/third_party/blink/public/platform/web_storage_area.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_STORAGE_AREA_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_STORAGE_AREA_H_
-
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace blink {
-
-class WebURL;
-
-class WebStorageArea {
- public:
-  virtual ~WebStorageArea() = default;
-
-  enum Result {
-    kResultOK = 0,
-    kResultBlockedByQuota,
-    kResultLast = kResultBlockedByQuota
-  };
-
-  // The number of key/value pairs in the storage area.
-  virtual unsigned length() = 0;
-
-  // Get a value for a specific key. Valid key indices are 0 through
-  // length() - 1.  Indexes may change on any Set/RemoveItem call. Will return
-  // null if the index provided is out of range.
-  // The |did_decrease_iterator| parameter is used to collect use counter data
-  // for a particular optimization in DOMStorageMap.
-  virtual WebString Key(unsigned index, bool* did_decrease_iterator) = 0;
-
-  // Get the value that corresponds to a specific key. This returns null if
-  // there is no entry for that key.
-  virtual WebString GetItem(const WebString& key) = 0;
-
-  // Set the value that corresponds to a specific key. Result will either be
-  // ResultOK or some particular error. The value is NOT set when there's an
-  // error.  |page_url| is the url that should be used if a storage event fires.
-  virtual void SetItem(const WebString& key,
-                       const WebString& new_value,
-                       const WebURL& page_url,
-                       Result& result) {
-    WebString unused;
-    SetItem(key, new_value, page_url, result, unused);
-  }
-
-  // Remove the value associated with a particular key. |page_url| is the url
-  // that should be used if a storage event fires.
-  virtual void RemoveItem(const WebString& key, const WebURL& page_url) {
-    WebString unused;
-    RemoveItem(key, page_url, unused);
-  }
-
-  // Clear all key/value pairs. |page_url| is the url that should be used if a
-  // storage event fires.
-  virtual void Clear(const WebURL& page_url) {
-    bool unused;
-    Clear(page_url, unused);
-  }
-
-  // DEPRECATED - being replaced by the async variants above which do not return
-  // old_values or block until completion.
-  virtual void SetItem(const WebString& key,
-                       const WebString& new_value,
-                       const WebURL&,
-                       Result&,
-                       WebString& old_value) {}
-  virtual void RemoveItem(const WebString& key,
-                          const WebURL& page_url,
-                          WebString& old_value) {}
-  virtual void Clear(const WebURL& page_url, bool& something_cleared) {}
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_STORAGE_AREA_H_
diff --git a/third_party/blink/public/platform/web_storage_namespace.h b/third_party/blink/public/platform/web_storage_namespace.h
deleted file mode 100644
index 6220007..0000000
--- a/third_party/blink/public/platform/web_storage_namespace.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_STORAGE_NAMESPACE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_STORAGE_NAMESPACE_H_
-
-#include "third_party/blink/public/platform/web_common.h"
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace blink {
-
-class WebStorageArea;
-class WebSecurityOrigin;
-
-// WebStorageNamespace represents a collection of StorageAreas. Typically,
-// you'll have multiple StorageNamespaces to represent the SessionStorage for
-// each tab and a single StorageNamespace to represent LocalStorage for the
-// entire browser.
-class WebStorageNamespace {
- public:
-  virtual ~WebStorageNamespace() = default;
-
-  // Create a new WebStorageArea object. Two subsequent calls with the same
-  // origin will return two different WebStorageArea objects that share the same
-  // backing store.  You should call delete on the returned object when you're
-  // finished.
-  virtual WebStorageArea* CreateStorageArea(const WebSecurityOrigin&) = 0;
-
-  virtual WebString GetNamespaceId() const = 0;
-
-  // Returns true of the two instances represent the same storage namespace.
-  virtual bool IsSameNamespace(const WebStorageNamespace&) const {
-    return false;
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_STORAGE_NAMESPACE_H_
diff --git a/third_party/blink/public/web/web_storage_event_dispatcher.h b/third_party/blink/public/web/web_storage_event_dispatcher.h
deleted file mode 100644
index e95c5d4..0000000
--- a/third_party/blink/public/web/web_storage_event_dispatcher.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_STORAGE_EVENT_DISPATCHER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_STORAGE_EVENT_DISPATCHER_H_
-
-#include "third_party/blink/public/platform/web_string.h"
-
-namespace blink {
-
-class WebStorageArea;
-class WebStorageNamespace;
-class WebURL;
-
-class WebStorageEventDispatcher {
- public:
-  // Dispatch a local storage event to appropiate documents.
-  BLINK_EXPORT static void DispatchLocalStorageEvent(
-      const WebString& key,
-      const WebString& old_value,
-      const WebString& new_value,
-      const WebURL& origin,
-      const WebURL& page_url,
-      WebStorageArea* source_area_instance);
-
-  // Dispatch a session storage event to appropiate documents.
-  BLINK_EXPORT static void DispatchSessionStorageEvent(
-      const WebString& key,
-      const WebString& old_value,
-      const WebString& new_value,
-      const WebURL& origin,
-      const WebURL& page_url,
-      const WebStorageNamespace&,
-      WebStorageArea* source_area_instance);
-
- private:
-  WebStorageEventDispatcher() = default;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_STORAGE_EVENT_DISPATCHER_H_
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h
index 5488328..6ee1e00e 100644
--- a/third_party/blink/public/web/web_widget_client.h
+++ b/third_party/blink/public/web/web_widget_client.h
@@ -218,6 +218,14 @@
   // TODO(oshima): Update the comment when the migration is completed.
   virtual void ConvertViewportToWindow(WebRect* rect) {}
 
+  // Converts the |rect| from Blink's Viewport coordinates to the
+  // coordinates in the native window used to display the content, in
+  // DIP.  They're identical in tradional world, but will differ when
+  // use-zoom-for-dsf feature is eanbled, and Viewport coordinates
+  // becomes DSF times larger than window coordinates.
+  // TODO(oshima): Update the comment when the migration is completed.
+  virtual void ConvertViewportToWindow(WebFloatRect* rect) {}
+
   // Converts the |rect| from the coordinates in native window in
   // DIP to Blink's Viewport coordinates. They're identical in
   // tradional world, but will differ when use-zoom-for-dsf feature
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc b/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc
index 2ea5a50..17703f5 100644
--- a/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc
+++ b/third_party/blink/renderer/bindings/core/v8/v8_gc_for_context_dispose.cc
@@ -113,7 +113,7 @@
 
 void V8GCForContextDispose::PseudoIdleTimerFired(TimerBase*) {
   V8PerIsolateData::MainThreadIsolate()->IdleNotificationDeadline(
-      CurrentTimeTicksInSeconds());
+      base::TimeTicks::Now().since_origin().InSecondsF());
   Reset();
 }
 
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/argument.py b/third_party/blink/renderer/bindings/scripts/web_idl/argument.py
index 82773bf..f2ec0533 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/argument.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/argument.py
@@ -2,22 +2,44 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import exceptions
 from .common import WithIdentifier
 from .common import WithExtendedAttributes
 from .common import WithCodeGeneratorInfo
 from .common import WithOwner
+from .idl_types import IdlType
+from .values import DefaultValue
 
 
 class Argument(WithIdentifier, WithExtendedAttributes, WithCodeGeneratorInfo,
                WithOwner):
+    class IR(WithIdentifier, WithExtendedAttributes, WithCodeGeneratorInfo):
+        def __init__(self,
+                     identifier,
+                     index,
+                     idl_type,
+                     default_value=None,
+                     extended_attributes=None,
+                     code_generator_info=None):
+            assert isinstance(index, int)
+            assert isinstance(idl_type, IdlType)
+            assert (default_value is None
+                    or isinstance(default_value, DefaultValue))
+
+            WithIdentifier.__init__(self, identifier)
+            WithExtendedAttributes.__init__(self, extended_attributes)
+            WithCodeGeneratorInfo.__init__(self, code_generator_info)
+
+            self.index = index
+            self.idl_type = idl_type
+            self.default_value = default_value
+
     @property
     def idl_type(self):
         """
         Returns type of this argument.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'To be implemented'
 
     @property
     def is_optional(self):
@@ -25,7 +47,7 @@
         Returns True if this argument is optional.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'To be implemented'
 
     @property
     def is_variadic(self):
@@ -33,7 +55,7 @@
         Returns True if this argument is variadic.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'To be implemented'
 
     @property
     def default_value(self):
@@ -41,7 +63,7 @@
         Returns the default value if it is specified. Otherwise, None
         @return DefaultValue
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'To be implemented'
 
     @property
     def index(self):
@@ -49,4 +71,4 @@
         Returns its index in an operation's arguments
         @return int
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'To be implemented'
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py b/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py
index 75455c66..9103a2e 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/attribute.py
@@ -3,12 +3,49 @@
 # found in the LICENSE file.
 
 import exceptions
+from .common import WithCodeGeneratorInfo
+from .common import WithComponent
+from .common import WithDebugInfo
+from .common import WithExposure
+from .common import WithExtendedAttributes
+from .common import WithIdentifier
 from .idl_member import IdlMember
+from .idl_types import IdlType
 
 
 class Attribute(IdlMember):
     """https://heycam.github.io/webidl/#idl-attributes"""
 
+    class IR(WithIdentifier, WithExtendedAttributes, WithExposure,
+             WithCodeGeneratorInfo, WithComponent, WithDebugInfo):
+        def __init__(self,
+                     identifier,
+                     idl_type,
+                     is_static=False,
+                     is_readonly=False,
+                     does_inherit_getter=False,
+                     extended_attributes=None,
+                     exposures=None,
+                     code_generator_info=None,
+                     component=None,
+                     debug_info=None):
+            assert isinstance(idl_type, IdlType)
+            assert isinstance(is_static, bool)
+            assert isinstance(is_readonly, bool)
+            assert isinstance(does_inherit_getter, bool)
+
+            WithIdentifier.__init__(self, identifier)
+            WithExtendedAttributes.__init__(self, extended_attributes)
+            WithExposure.__init__(self, exposures)
+            WithCodeGeneratorInfo.__init__(self, code_generator_info)
+            WithComponent.__init__(self, component)
+            WithDebugInfo.__init__(self, debug_info)
+
+            self.idl_type = idl_type
+            self.is_static = is_static
+            self.is_readonly = is_readonly
+            self.does_inherit_getter = does_inherit_getter
+
     @property
     def idl_type(self):
         """
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/constant.py b/third_party/blink/renderer/bindings/scripts/web_idl/constant.py
index 502077b..2722fae 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/constant.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/constant.py
@@ -2,20 +2,51 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import exceptions
+from .common import WithCodeGeneratorInfo
+from .common import WithComponent
+from .common import WithDebugInfo
+from .common import WithExtendedAttributes
+from .common import WithExposure
+from .common import WithIdentifier
 from .idl_member import IdlMember
+from .idl_types import IdlType
+from .values import ConstantValue
 
 
 class Constant(IdlMember):
     """https://heycam.github.io/webidl/#idl-constants"""
 
+    class IR(WithIdentifier, WithExtendedAttributes, WithExposure,
+             WithCodeGeneratorInfo, WithComponent, WithDebugInfo):
+        def __init__(self,
+                     identifier,
+                     value,
+                     idl_type,
+                     extended_attributes=None,
+                     exposures=None,
+                     code_generator_info=None,
+                     component=None,
+                     debug_info=None):
+            assert isinstance(value, ConstantValue)
+            assert isinstance(idl_type, IdlType)
+
+            WithIdentifier.__init__(self, identifier)
+            WithExtendedAttributes.__init__(self, extended_attributes)
+            WithExposure.__init__(self, exposures)
+            WithCodeGeneratorInfo.__init__(self, code_generator_info)
+            WithComponent.__init__(self, component)
+            WithDebugInfo.__init__(self, debug_info)
+
+            self.value = value
+            self.idl_type = idl_type
+
     @property
     def idl_type(self):
         """
         Returns the type of this constant.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'To be implemented'
 
     @property
     def value(self):
@@ -23,4 +54,4 @@
         Returns the constant value.
         @return ConstantValue
         """
-        raise exceptions.NotImplementedError()
+        assert False, 'To be implemented'
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_member.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_member.py
index 4ebf709e..92cedb5 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_member.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_member.py
@@ -15,4 +15,3 @@
                 WithExposure, WithOwner, WithComponent, WithDebugInfo):
     """IdlMember provides common APIs for IDL members; attributes, operations,
     constants, dictionary members, etc."""
-    pass
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/interface.py b/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
index 0244277b..ebfe673 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/interface.py
@@ -3,13 +3,18 @@
 # found in the LICENSE file.
 
 import exceptions
+from .attribute import Attribute
 from .common import WithCodeGeneratorInfo
 from .common import WithComponent
 from .common import WithDebugInfo
 from .common import WithExposure
 from .common import WithExtendedAttributes
+from .constant import Constant
 from .identifier_ir_map import IdentifierIRMap
 from .idl_member import IdlMember
+from .idl_reference_proxy import RefByIdFactory
+from .idl_types import IdlType
+from .operation import Operation
 from .user_defined_type import UserDefinedType
 
 
@@ -29,11 +34,40 @@
                      identifier,
                      is_partial,
                      is_mixin,
+                     inherited=None,
+                     attributes=None,
+                     constants=None,
+                     operations=None,
+                     iterable=None,
+                     setlike=None,
+                     maplike=None,
                      extended_attributes=None,
                      exposures=None,
                      code_generator_info=None,
                      component=None,
                      debug_info=None):
+            assert isinstance(is_partial, bool)
+            assert isinstance(is_mixin, bool)
+            assert inherited is None or RefByIdFactory.is_reference(inherited)
+            assert attributes is None or isinstance(attributes, (list, tuple))
+            assert constants is None or isinstance(constants, (list, tuple))
+            assert operations is None or isinstance(operations, (list, tuple))
+            assert iterable is None or isinstance(iterable, Iterable)
+            assert setlike is None or isinstance(setlike, Setlike)
+            assert maplike is None or isinstance(maplike, Maplike)
+
+            attributes = attributes or []
+            constants = constants or []
+            operations = operations or []
+            assert all(
+                isinstance(attribute, Attribute.IR)
+                for attribute in attributes)
+            assert all(
+                isinstance(constant, Constant.IR) for constant in constants)
+            assert all(
+                isinstance(operation, Operation.IR)
+                for operation in operations)
+
             kind = None
             if is_partial:
                 if is_mixin:
@@ -52,6 +86,16 @@
             WithComponent.__init__(self, component)
             WithDebugInfo.__init__(self, debug_info)
 
+            self.is_partial = is_partial
+            self.is_mixin = is_mixin
+            self.inherited = inherited
+            self.attrbiutes = list(attributes)
+            self.constants = list(constants)
+            self.operations = list(operations)
+            self.iterable = iterable
+            self.maplike = maplike
+            self.setlike = setlike
+
     @property
     def inherited_interface(self):
         """
@@ -172,36 +216,72 @@
         return True
 
 
-class Iterable(IdlMember):
+class Iterable(WithCodeGeneratorInfo, WithDebugInfo):
     """https://heycam.github.io/webidl/#idl-iterable"""
 
+    def __init__(self,
+                 key_type=None,
+                 value_type=None,
+                 code_generator_info=None,
+                 debug_info=None):
+        assert key_type is None or isinstance(key_type, IdlType)
+        # iterable is declared in either form of
+        #     iterable<value_type>
+        #     iterable<key_type, value_type>
+        # thus |value_type| can't be None.  However, we put it after |key_type|
+        # to be consistent with the format of IDL.
+        assert isinstance(value_type, IdlType), "value_type must be specified"
+
+        WithCodeGeneratorInfo.__init__(self, code_generator_info)
+        WithDebugInfo.__init__(self, debug_info)
+
+        self._key_type = key_type
+        self._value_type = value_type
+
     @property
     def key_type(self):
         """
-        Returns its key type or None.
+        Returns the key type or None.
         @return IdlType?
         """
-        raise exceptions.NotImplementedError()
+        return self._key_type
 
     @property
     def value_type(self):
         """
-        Returns its value type.
+        Returns the value type.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._value_type
 
 
-class Maplike(object):
+class Maplike(WithCodeGeneratorInfo, WithDebugInfo):
     """https://heycam.github.io/webidl/#idl-maplike"""
 
+    def __init__(self,
+                 key_type,
+                 value_type,
+                 is_readonly=False,
+                 code_generator_info=None,
+                 debug_info=None):
+        assert isinstance(key_type, IdlType)
+        assert isinstance(value_type, IdlType)
+        assert isinstance(is_readonly, bool)
+
+        WithCodeGeneratorInfo.__init__(self, code_generator_info)
+        WithDebugInfo.__init__(self, debug_info)
+
+        self._key_type = key_type
+        self._value_type = value_type
+        self._is_readonly = is_readonly
+
     @property
     def key_type(self):
         """
         Returns its key type.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._key_type
 
     @property
     def value_type(self):
@@ -209,7 +289,7 @@
         Returns its value type.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._value_type
 
     @property
     def is_readonly(self):
@@ -217,19 +297,33 @@
         Returns True if it's readonly.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return self._is_readonly
 
 
-class Setlike(object):
+class Setlike(WithCodeGeneratorInfo, WithDebugInfo):
     """https://heycam.github.io/webidl/#idl-setlike"""
 
+    def __init__(self,
+                 value_type,
+                 is_readonly=False,
+                 code_generator_info=None,
+                 debug_info=None):
+        assert isinstance(value_type, IdlType)
+        assert isinstance(is_readonly, bool)
+
+        WithCodeGeneratorInfo.__init__(self, code_generator_info)
+        WithDebugInfo.__init__(self, debug_info)
+
+        self._value_type = value_type
+        self._is_readonly = is_readonly
+
     @property
     def value_type(self):
         """
         Returns its value type.
         @return IdlType
         """
-        raise exceptions.NotImplementedError()
+        return self._value_type
 
     @property
     def is_readonly(self):
@@ -237,7 +331,7 @@
         Returns True if it's readonly.
         @return bool
         """
-        raise exceptions.NotImplementedError()
+        return self._is_readonly
 
 
 class IndexedPropertyHandler(IdlMember):
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
index c25eb711..b9f1380f 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/ir_builder.py
@@ -2,10 +2,13 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+from .argument import Argument
+from .attribute import Attribute
 from .callback_function import CallbackFunction
 from .callback_interface import CallbackInterface
 from .collection import Collection
 from .common import DebugInfo
+from .constant import Constant
 from .dictionary import Dictionary
 from .dictionary import DictionaryMember
 from .enumeration import Enumeration
@@ -18,10 +21,16 @@
 from .idl_types import SequenceType
 from .idl_types import SimpleType
 from .idl_types import UnionType
+from .idl_types import VariadicType
 from .includes import Includes
 from .interface import Interface
+from .interface import Iterable
+from .interface import Maplike
+from .interface import Setlike
 from .namespace import Namespace
+from .operation import Operation
 from .typedef import Typedef
+from .values import ConstantValue
 from .values import DefaultValue
 
 
@@ -89,14 +98,50 @@
         if node.GetProperty('CALLBACK'):
             return self._build_callback_interface(node)
 
-        interface = Interface.IR(
+        child_nodes = list(node.GetChildren())
+        extended_attributes = self._take_extended_attributes(child_nodes)
+        inherited = self._take_inheritance(child_nodes)
+        iterable = self._take_iterable(child_nodes)
+        maplike = self._take_maplike(child_nodes)
+        setlike = self._take_setlike(child_nodes)
+        # TODO(peria): Implement stringifier.
+        _ = self._take_stringifier(child_nodes)
+
+        members = map(self._build_interface_or_namespace_member, child_nodes)
+        attributes = []
+        constants = []
+        operations = []
+        property_handlers = []
+        for member in members:
+            if isinstance(member, Attribute.IR):
+                attributes.append(member)
+            elif isinstance(member, Operation.IR):
+                assert member.identifier or member.is_property_handler
+                if member.identifier:
+                    operations.append(member)
+                if member.is_property_handler:
+                    property_handlers.append(member)
+            elif isinstance(member, Constant.IR):
+                constants.append(member)
+            else:
+                assert False
+        # TODO(peria): Implement indexed/named property handlers from
+        # |property_handlers|.
+
+        return Interface.IR(
             identifier=node.GetName(),
             is_partial=bool(node.GetProperty('PARTIAL')),
             is_mixin=bool(node.GetProperty('MIXIN')),
+            inherited=inherited,
+            attributes=attributes,
+            constants=constants,
+            operations=operations,
+            iterable=iterable,
+            maplike=maplike,
+            setlike=setlike,
+            extended_attributes=extended_attributes,
             component=self._component,
             debug_info=self._build_debug_info(node))
-        # TODO(peria): Build members and register them in |interface|
-        return interface
 
     def _build_namespace(self, node):
         namespace = Namespace.IR(
@@ -107,6 +152,63 @@
         # TODO(peria): Build members and register them in |namespace|
         return namespace
 
+    def _build_interface_or_namespace_member(self, node):
+        def build_attribute(node):
+            child_nodes = list(node.GetChildren())
+            idl_type = self._take_type(child_nodes)
+            extended_attributes = self._take_extended_attributes(child_nodes)
+            assert len(child_nodes) == 0
+            return Attribute.IR(
+                identifier=node.GetName(),
+                idl_type=idl_type,
+                is_static=bool(node.GetProperty('STATIC')),
+                is_readonly=bool(node.GetProperty('READONLY')),
+                does_inherit_getter=bool(node.GetProperty('INHERIT')),
+                extended_attributes=extended_attributes,
+                component=self._component,
+                debug_info=self._build_debug_info(node))
+
+        def build_constant(node):
+            child_nodes = list(node.GetChildren())
+            value = self._take_constant_value(child_nodes)
+            extended_attributes = self._take_extended_attributes(child_nodes)
+            assert len(child_nodes) == 1, child_nodes[0].GetClass()
+            # idl_parser doesn't produce a 'Type' node for the type of a
+            # constant, hence we need to skip one level.
+            idl_type = self._build_type_internal(child_nodes)
+            return Constant.IR(
+                identifier=node.GetName(),
+                value=value,
+                idl_type=idl_type,
+                extended_attributes=extended_attributes,
+                component=self._component,
+                debug_info=self._build_debug_info(node))
+
+        def build_operation(node):
+            child_nodes = list(node.GetChildren())
+            arguments = self._take_arguments(child_nodes)
+            return_type = self._take_type(child_nodes)
+            extended_attributes = self._take_extended_attributes(child_nodes)
+            assert len(child_nodes) == 0
+            return Operation.IR(
+                identifier=node.GetName(),
+                arguments=arguments,
+                return_type=return_type,
+                is_static=bool(node.GetProperty('STATIC')),
+                is_getter=bool(node.GetProperty('GETTER')),
+                is_setter=bool(node.GetProperty('SETTER')),
+                is_deleter=bool(node.GetProperty('DELETER')),
+                extended_attributes=extended_attributes,
+                component=self._component,
+                debug_info=self._build_debug_info(node))
+
+        build_functions = {
+            'Attribute': build_attribute,
+            'Const': build_constant,
+            'Operation': build_operation,
+        }
+        return build_functions[node.GetClass()](node)
+
     def _build_dictionary(self, node):
         child_nodes = list(node.GetChildren())
         extended_attributes = self._take_extended_attributes(child_nodes)
@@ -186,6 +288,34 @@
 
     # Helper functions sorted alphabetically
 
+    def _build_arguments(self, node):
+        def build_argument(node, index):
+            assert node.GetClass() == 'Argument'
+            child_nodes = list(node.GetChildren())
+            is_optional = bool(node.GetProperty('OPTIONAL'))
+            is_variadic = bool(self._take_is_variadic_argument(child_nodes))
+            idl_type = self._take_type(
+                child_nodes, is_optional=is_optional, is_variadic=is_variadic)
+            default_value = self._take_default_value(child_nodes)
+            extended_attributes = self._take_extended_attributes(child_nodes)
+            assert len(child_nodes) == 0
+            return Argument.IR(
+                identifier=node.GetName(),
+                index=index,
+                idl_type=idl_type,
+                default_value=default_value,
+                extended_attributes=extended_attributes)
+
+        assert node.GetClass() == 'Arguments'
+        return [
+            build_argument(node, i)
+            for i, node in enumerate(node.GetChildren())
+        ]
+
+    def _build_constant_value(self, node):
+        assert node.GetClass() == 'Value'
+        return ConstantValue()
+
     def _build_debug_info(self, node):
         return DebugInfo(
             location=DebugInfo.Location(
@@ -205,13 +335,68 @@
         assert node.GetClass() == 'Inherit'
         return self._create_ref_to_idl_def(node.GetName())
 
-    def _build_type(self, node):
-        assert node.GetClass() == 'Type'
-        if node.GetProperty('NULLABLE'):
-            return NullableType(self._build_type_internal(node.GetChildren()))
-        return self._build_type_internal(node.GetChildren())
+    def _build_is_variadic_argument(self, node):
+        # idl_parser produces the following tree to indicate an argument is
+        # variadic.
+        #   Arguments
+        #     := [Argument, Argument, ...]
+        #   Argument
+        #     := [Type, Argument(Name='...')]  # Argument inside Argument
+        assert node.GetClass() == 'Argument'
+        assert node.GetName() == '...'
+        return True
 
-    def _build_type_internal(self, nodes):
+    def _build_iterable(self, node):
+        assert node.GetClass() == 'Iterable'
+        types = map(self._build_type, node.GetChildren())
+        if len(types) == 1:
+            types.insert(0, None)
+        assert len(types) == 2
+        return Iterable(
+            key_type=types[0],
+            value_type=types[1],
+            debug_info=self._build_debug_info(node))
+
+    def _build_maplike(self, node):
+        assert node.GetClass() == 'Maplike'
+        types = map(self._build_type, node.GetChildren())
+        assert len(types) == 2
+        return Maplike(
+            key_type=types[0],
+            value_type=types[1],
+            is_readonly=bool(node.GetProperty('READONLY')),
+            debug_info=self._build_debug_info(node))
+
+    def _build_setlike(self, node):
+        assert node.GetClass() == 'Setlike'
+        assert len(node.GetChildren()) == 1
+        return Setlike(
+            value_type=self._build_type(node.GetChildren()[0]),
+            is_readonly=bool(node.GetProperty('READONLY')),
+            debug_info=self._build_debug_info(node))
+
+    def _build_stringifier(self, node):
+        assert node.GetClass() == 'Stringifier'
+        return None
+
+    def _build_type(self, node, is_optional=False, is_variadic=False):
+        def build_maybe_nullable_type(node):
+            if node.GetProperty('NULLABLE'):
+                return NullableType(
+                    self._build_type_internal(node.GetChildren()),
+                    is_optional=is_optional)
+            return self._build_type_internal(
+                node.GetChildren(), is_optional=is_optional)
+
+        assert node.GetClass() == 'Type'
+        assert not (is_optional and is_variadic)
+        if is_variadic:
+            return VariadicType(
+                element_type=build_maybe_nullable_type(node),
+                debug_info=self._build_debug_info(node))
+        return build_maybe_nullable_type(node)
+
+    def _build_type_internal(self, nodes, is_optional=False):
         """
         Args:
             nodes: The child nodes of a 'Type' node.
@@ -221,6 +406,7 @@
             assert len(node.GetChildren()) == 1
             return FrozenArrayType(
                 element_type=self._build_type(node.GetChildren()[0]),
+                is_optional=is_optional,
                 extended_attributes=extended_attributes,
                 debug_info=self._build_debug_info(node))
 
@@ -228,12 +414,14 @@
             assert len(node.GetChildren()) == 1
             return PromiseType(
                 result_type=self._build_type(node.GetChildren()[0]),
+                is_optional=is_optional,
                 extended_attributes=extended_attributes,
                 debug_info=self._build_debug_info(node))
 
         def build_union_type(node, extended_attributes):
             return UnionType(
                 member_types=map(self._build_type, node.GetChildren()),
+                is_optional=is_optional,
                 extended_attributes=extended_attributes,
                 debug_info=self._build_debug_info(node))
 
@@ -244,6 +432,7 @@
                 # hence we need to skip one level.
                 key_type=self._build_type_internal([key_node]),
                 value_type=self._build_type(value_node),
+                is_optional=is_optional,
                 extended_attributes=extended_attributes,
                 debug_info=self._build_debug_info(node))
 
@@ -251,12 +440,14 @@
             identifier = node.GetName()
             return ReferenceType(
                 ref_to_idl_type=self._create_ref_to_idl_type(identifier),
+                is_optional=is_optional,
                 extended_attributes=extended_attributes,
                 debug_info=self._build_debug_info(node))
 
         def build_sequence_type(node, extended_attributes):
             return SequenceType(
                 element_type=self._build_type(node.GetChildren()[0]),
+                is_optional=is_optional,
                 extended_attributes=extended_attributes,
                 debug_info=self._build_debug_info(node))
 
@@ -269,6 +460,7 @@
                 name = 'unrestricted {}'.format(name)
             return SimpleType(
                 name=name,
+                is_optional=is_optional,
                 extended_attributes=extended_attributes,
                 debug_info=self._build_debug_info(node))
 
@@ -291,7 +483,7 @@
         return build_functions[body_node.GetClass()](body_node,
                                                      extended_attributes)
 
-    def _take_and_build(self, node_class, build_func, node_list):
+    def _take_and_build(self, node_class, build_func, node_list, **kwargs):
         """
         Takes a node of |node_class| from |node_list| if any, and then builds
         and returns an IR.  The processed node is removed from |node_list|.
@@ -300,9 +492,17 @@
         for node in node_list:
             if node.GetClass() == node_class:
                 node_list.remove(node)
-                return build_func(node)
+                return build_func(node, **kwargs)
         return None
 
+    def _take_arguments(self, node_list):
+        return self._take_and_build('Arguments', self._build_arguments,
+                                    node_list)
+
+    def _take_constant_value(self, node_list):
+        return self._take_and_build('Value', self._build_constant_value,
+                                    node_list)
+
     def _take_default_value(self, node_list):
         return self._take_and_build('Default', self._build_default_value,
                                     node_list)
@@ -315,5 +515,28 @@
         return self._take_and_build('Inherit', self._build_inheritance,
                                     node_list)
 
-    def _take_type(self, node_list):
-        return self._take_and_build('Type', self._build_type, node_list)
+    def _take_is_variadic_argument(self, node_list):
+        return self._take_and_build(
+            'Argument', self._build_is_variadic_argument, node_list)
+
+    def _take_iterable(self, node_list):
+        return self._take_and_build('Iterable', self._build_iterable,
+                                    node_list)
+
+    def _take_maplike(self, node_list):
+        return self._take_and_build('Maplike', self._build_maplike, node_list)
+
+    def _take_setlike(self, node_list):
+        return self._take_and_build('Setlike', self._build_setlike, node_list)
+
+    def _take_stringifier(self, node_list):
+        return self._take_and_build('Stringifier', self._build_stringifier,
+                                    node_list)
+
+    def _take_type(self, node_list, is_optional=False, is_variadic=False):
+        return self._take_and_build(
+            'Type',
+            self._build_type,
+            node_list,
+            is_optional=is_optional,
+            is_variadic=is_variadic)
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/operation.py b/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
index 66faa99b..7ac056a 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/operation.py
@@ -3,18 +3,61 @@
 # found in the LICENSE file.
 
 import exceptions
+from .argument import Argument
 from .common import WithCodeGeneratorInfo
 from .common import WithComponent
 from .common import WithDebugInfo
+from .common import WithExposure
+from .common import WithExtendedAttributes
 from .common import WithIdentifier
 from .common import WithOwner
 from .idl_member import IdlMember
+from .idl_types import IdlType
 
 
 class Operation(IdlMember):
     """https://heycam.github.io/webidl/#idl-operations
     https://www.w3.org/TR/WebIDL-1/#idl-special-operations"""
 
+    class IR(WithIdentifier, WithExtendedAttributes, WithExposure,
+             WithCodeGeneratorInfo, WithComponent, WithDebugInfo):
+        def __init__(self,
+                     identifier,
+                     arguments,
+                     return_type,
+                     is_static=False,
+                     is_getter=False,
+                     is_setter=False,
+                     is_deleter=False,
+                     extended_attributes=None,
+                     exposures=None,
+                     code_generator_info=None,
+                     component=None,
+                     debug_info=None):
+            assert isinstance(arguments, (list, tuple)) and all(
+                isinstance(arg, Argument.IR) for arg in arguments)
+            assert isinstance(return_type, IdlType)
+            assert isinstance(is_static, bool)
+            assert isinstance(is_getter, bool)
+            assert isinstance(is_setter, bool)
+            assert isinstance(is_deleter, bool)
+            assert int(is_getter) + int(is_setter) + int(is_deleter) <= 1
+
+            WithIdentifier.__init__(self, identifier)
+            WithExtendedAttributes.__init__(self, extended_attributes)
+            WithExposure.__init__(self, exposures)
+            WithCodeGeneratorInfo.__init__(self, code_generator_info)
+            WithComponent.__init__(self, component)
+            WithDebugInfo.__init__(self, debug_info)
+
+            self.arguments = list(arguments)
+            self.return_type = return_type
+            self.is_static = is_static
+            self.is_getter = is_getter
+            self.is_setter = is_setter
+            self.is_deleter = is_deleter
+            self.is_property_handler = is_getter or is_setter or is_deleter
+
     @property
     def is_static(self):
         """
diff --git a/third_party/blink/renderer/core/animation/compositor_animations_test.cc b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
index 6b69a6e..6fa48598 100644
--- a/third_party/blink/renderer/core/animation/compositor_animations_test.cc
+++ b/third_party/blink/renderer/core/animation/compositor_animations_test.cc
@@ -462,7 +462,7 @@
 
   void BeginFrame() {
     helper_.GetWebView()->MainFrameWidget()->BeginFrame(
-        WTF::CurrentTimeTicks(), false /* record_main_frame_metrics */);
+        base::TimeTicks::Now(), false /* record_main_frame_metrics */);
   }
 
   void ForceFullCompositingUpdate() {
diff --git a/third_party/blink/renderer/core/animation/pending_animations.cc b/third_party/blink/renderer/core/animation/pending_animations.cc
index 3f5539d6..47aa3066 100644
--- a/third_party/blink/renderer/core/animation/pending_animations.cc
+++ b/third_party/blink/renderer/core/animation/pending_animations.cc
@@ -127,7 +127,8 @@
   }
 
   // If not, go ahead and start any animations that were waiting.
-  NotifyCompositorAnimationStarted(CurrentTimeTicksInSeconds());
+  NotifyCompositorAnimationStarted(
+      base::TimeTicks::Now().since_origin().InSecondsF());
 
   DCHECK_EQ(pending_.size(), deferred.size());
   return false;
diff --git a/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc b/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
index a008c48..c2afc2d 100644
--- a/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
+++ b/third_party/blink/renderer/core/content_capture/content_capture_task_histogram_reporter.cc
@@ -29,11 +29,11 @@
 void ContentCaptureTaskHistogramReporter::OnContentChanged() {
   if (content_change_time_)
     return;
-  content_change_time_ = WTF::CurrentTimeTicks();
+  content_change_time_ = base::TimeTicks::Now();
 }
 
 void ContentCaptureTaskHistogramReporter::OnCaptureContentStarted() {
-  capture_content_start_time_ = WTF::CurrentTimeTicks();
+  capture_content_start_time_ = base::TimeTicks::Now();
 }
 
 void ContentCaptureTaskHistogramReporter::OnCaptureContentEnded(
@@ -47,17 +47,17 @@
   // Gives content_change_time_ to the change occurred while sending the
   // content.
   captured_content_change_time_ = std::move(content_change_time_);
-  base::TimeDelta delta = WTF::CurrentTimeTicks() - capture_content_start_time_;
+  base::TimeDelta delta = base::TimeTicks::Now() - capture_content_start_time_;
   capture_content_time_histogram_.CountMicroseconds(delta);
 }
 
 void ContentCaptureTaskHistogramReporter::OnSendContentStarted() {
-  send_content_start_time_ = WTF::CurrentTimeTicks();
+  send_content_start_time_ = base::TimeTicks::Now();
 }
 
 void ContentCaptureTaskHistogramReporter::OnSendContentEnded(
     size_t sent_content_count) {
-  base::TimeTicks now = WTF::CurrentTimeTicks();
+  base::TimeTicks now = base::TimeTicks::Now();
   if (captured_content_change_time_) {
     base::TimeTicks content_change_time = captured_content_change_time_.value();
     captured_content_change_time_.reset();
diff --git a/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc b/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
index 50111ce3c..80af0f3 100644
--- a/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
+++ b/third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.cc
@@ -170,6 +170,7 @@
 const CSSValue*
 AbstractPropertySetCSSStyleDeclaration::GetPropertyCSSValueInternal(
     AtomicString custom_property_name) {
+  DCHECK_EQ(CSSPropertyID::kVariable, cssPropertyID(custom_property_name));
   return PropertySet().GetPropertyCSSValue(custom_property_name);
 }
 
diff --git a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
index cab77b11..9b5dbb5 100644
--- a/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
+++ b/third_party/blink/renderer/core/css/css_computed_style_declaration.cc
@@ -554,6 +554,7 @@
 
 const CSSValue* CSSComputedStyleDeclaration::GetPropertyCSSValueInternal(
     AtomicString custom_property_name) {
+  DCHECK_EQ(CSSPropertyID::kVariable, cssPropertyID(custom_property_name));
   return GetPropertyCSSValue(custom_property_name);
 }
 
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
index 81fb66e..15f0f140 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_budget_test.cc
@@ -35,7 +35,7 @@
   void ResetDeadlineForTesting(YieldingDisplayLockBudget& budget,
                                const LifecycleData& lifecycle_data) {
     budget.deadline_ =
-        CurrentTimeTicks() + budget.GetCurrentBudget(lifecycle_data);
+        base::TimeTicks::Now() + budget.GetCurrentBudget(lifecycle_data);
   }
 
   void ResetBudget(std::unique_ptr<DisplayLockBudget> budget,
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 7f73567..181f0871 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3994,9 +3994,9 @@
   auto& before_unload_event = *MakeGarbageCollected<BeforeUnloadEvent>();
   before_unload_event.initEvent(event_type_names::kBeforeunload, false, true);
   load_event_progress_ = kBeforeUnloadEventInProgress;
-  const base::TimeTicks beforeunload_event_start = CurrentTimeTicks();
+  const base::TimeTicks beforeunload_event_start = base::TimeTicks::Now();
   dom_window_->DispatchEvent(before_unload_event, this);
-  const base::TimeTicks beforeunload_event_end = CurrentTimeTicks();
+  const base::TimeTicks beforeunload_event_end = base::TimeTicks::Now();
   load_event_progress_ = kBeforeUnloadEventCompleted;
   DEFINE_STATIC_LOCAL(
       CustomCountHistogram, beforeunload_histogram,
@@ -4053,10 +4053,11 @@
   String text = before_unload_event.returnValue();
   beforeunload_dialog_histogram.Count(
       BeforeUnloadDialogHistogramEnum::kShowDialog);
-  const base::TimeTicks beforeunload_confirmpanel_start = CurrentTimeTicks();
+  const base::TimeTicks beforeunload_confirmpanel_start =
+      base::TimeTicks::Now();
   did_allow_navigation =
       chrome_client->OpenBeforeUnloadConfirmPanel(text, frame_, is_reload);
-  const base::TimeTicks beforeunload_confirmpanel_end = CurrentTimeTicks();
+  const base::TimeTicks beforeunload_confirmpanel_end = base::TimeTicks::Now();
   if (did_allow_navigation) {
     // Only record when a navigation occurs, since we want to understand
     // the impact of the before unload dialog on overall input to navigation.
@@ -4084,11 +4085,11 @@
     if (load_event_progress_ < kPageHideInProgress) {
       load_event_progress_ = kPageHideInProgress;
       if (LocalDOMWindow* window = domWindow()) {
-        const base::TimeTicks pagehide_event_start = CurrentTimeTicks();
+        const base::TimeTicks pagehide_event_start = base::TimeTicks::Now();
         window->DispatchEvent(
             *PageTransitionEvent::Create(event_type_names::kPagehide, false),
             this);
-        const base::TimeTicks pagehide_event_end = CurrentTimeTicks();
+        const base::TimeTicks pagehide_event_end = base::TimeTicks::Now();
         DEFINE_STATIC_LOCAL(
             CustomCountHistogram, pagehide_histogram,
             ("DocumentEventTiming.PageHideDuration", 0, 10000000, 50));
@@ -4106,11 +4107,11 @@
         // Dispatch visibilitychange event, but don't bother doing
         // other notifications as we're about to be unloaded.
         const base::TimeTicks pagevisibility_hidden_event_start =
-            CurrentTimeTicks();
+            base::TimeTicks::Now();
         DispatchEvent(
             *Event::CreateBubble(event_type_names::kVisibilitychange));
         const base::TimeTicks pagevisibility_hidden_event_end =
-            CurrentTimeTicks();
+            base::TimeTicks::Now();
         DEFINE_STATIC_LOCAL(CustomCountHistogram, pagevisibility_histogram,
                             ("DocumentEventTiming.PageVibilityHiddenDuration",
                              0, 10000000, 50));
@@ -4130,10 +4131,10 @@
       if (timing && timing->UnloadEventStart().is_null() &&
           timing->UnloadEventEnd().is_null()) {
         DCHECK(!timing->NavigationStart().is_null());
-        const base::TimeTicks unload_event_start = CurrentTimeTicks();
+        const base::TimeTicks unload_event_start = base::TimeTicks::Now();
         timing->MarkUnloadEventStart(unload_event_start);
         frame_->DomWindow()->DispatchEvent(unload_event, this);
-        const base::TimeTicks unload_event_end = CurrentTimeTicks();
+        const base::TimeTicks unload_event_end = base::TimeTicks::Now();
         DEFINE_STATIC_LOCAL(
             CustomCountHistogram, unload_histogram,
             ("DocumentEventTiming.UnloadDuration", 0, 10000000, 50));
@@ -4149,11 +4150,11 @@
 }
 
 void Document::DispatchFreezeEvent() {
-  const base::TimeTicks freeze_event_start = CurrentTimeTicks();
+  const base::TimeTicks freeze_event_start = base::TimeTicks::Now();
   SetFreezingInProgress(true);
   DispatchEvent(*Event::Create(event_type_names::kFreeze));
   SetFreezingInProgress(false);
-  const base::TimeTicks freeze_event_end = CurrentTimeTicks();
+  const base::TimeTicks freeze_event_end = base::TimeTicks::Now();
   DEFINE_STATIC_LOCAL(CustomCountHistogram, freeze_histogram,
                       ("DocumentEventTiming.FreezeDuration", 0, 10000000, 50));
   freeze_histogram.CountMicroseconds(freeze_event_end - freeze_event_start);
@@ -7261,11 +7262,11 @@
     base::TimeTicks monotonic_animation_start_time) {
   if (!scripted_animation_controller_)
     return;
-  auto start_time = CurrentTimeTicks();
+  auto start_time = base::TimeTicks::Now();
   scripted_animation_controller_->ServiceScriptedAnimations(
       monotonic_animation_start_time);
   if (GetFrame()) {
-    GetFrame()->GetFrameScheduler()->AddTaskTime(CurrentTimeTicks() -
+    GetFrame()->GetFrameScheduler()->AddTaskTime(base::TimeTicks::Now() -
                                                  start_time);
   }
 }
diff --git a/third_party/blink/renderer/core/dom/document_parser_timing.cc b/third_party/blink/renderer/core/dom/document_parser_timing.cc
index 49395e9..ef292f8c 100644
--- a/third_party/blink/renderer/core/dom/document_parser_timing.cc
+++ b/third_party/blink/renderer/core/dom/document_parser_timing.cc
@@ -27,14 +27,14 @@
   if (parser_detached_ || !parser_start_.is_null())
     return;
   DCHECK(parser_stop_.is_null());
-  parser_start_ = CurrentTimeTicks();
+  parser_start_ = base::TimeTicks::Now();
   NotifyDocumentParserTimingChanged();
 }
 
 void DocumentParserTiming::MarkParserStop() {
   if (parser_detached_ || parser_start_.is_null() || !parser_stop_.is_null())
     return;
-  parser_stop_ = CurrentTimeTicks();
+  parser_stop_ = base::TimeTicks::Now();
   NotifyDocumentParserTimingChanged();
 }
 
diff --git a/third_party/blink/renderer/core/dom/document_statistics_collector.cc b/third_party/blink/renderer/core/dom/document_statistics_collector.cc
index 8e196e7..d95dbc84 100644
--- a/third_party/blink/renderer/core/dom/document_statistics_collector.cc
+++ b/third_party/blink/renderer/core/dom/document_statistics_collector.cc
@@ -205,7 +205,7 @@
 
   features.is_mobile_friendly = IsMobileFriendly(document);
 
-  base::TimeTicks start_time = CurrentTimeTicks();
+  base::TimeTicks start_time = base::TimeTicks::Now();
 
   // This should be cheap since collectStatistics is only called right after
   // layout.
@@ -215,7 +215,7 @@
   CollectFeatures(*body, features);
   features.open_graph = HasOpenGraphArticle(*head);
 
-  base::TimeDelta elapsed_time = CurrentTimeTicks() - start_time;
+  base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time;
 
   DEFINE_STATIC_LOCAL(CustomCountHistogram, distillability_histogram,
                       ("WebCore.DistillabilityUs", 1, 1000000, 50));
diff --git a/third_party/blink/renderer/core/dom/document_timing.cc b/third_party/blink/renderer/core/dom/document_timing.cc
index bf58fc5..beb3f9d 100644
--- a/third_party/blink/renderer/core/dom/document_timing.cc
+++ b/third_party/blink/renderer/core/dom/document_timing.cc
@@ -28,7 +28,7 @@
 }
 
 void DocumentTiming::MarkDomLoading() {
-  dom_loading_ = CurrentTimeTicks();
+  dom_loading_ = base::TimeTicks::Now();
   TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domLoading",
                                    dom_loading_, "frame",
                                    ToTraceValue(GetFrame()));
@@ -36,7 +36,7 @@
 }
 
 void DocumentTiming::MarkDomInteractive() {
-  dom_interactive_ = CurrentTimeTicks();
+  dom_interactive_ = base::TimeTicks::Now();
   TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domInteractive",
                                    dom_interactive_, "frame",
                                    ToTraceValue(GetFrame()));
@@ -44,7 +44,7 @@
 }
 
 void DocumentTiming::MarkDomContentLoadedEventStart() {
-  dom_content_loaded_event_start_ = CurrentTimeTicks();
+  dom_content_loaded_event_start_ = base::TimeTicks::Now();
   TRACE_EVENT_MARK_WITH_TIMESTAMP1(
       "blink.user_timing,rail", "domContentLoadedEventStart",
       dom_content_loaded_event_start_, "frame", ToTraceValue(GetFrame()));
@@ -52,7 +52,7 @@
 }
 
 void DocumentTiming::MarkDomContentLoadedEventEnd() {
-  dom_content_loaded_event_end_ = CurrentTimeTicks();
+  dom_content_loaded_event_end_ = base::TimeTicks::Now();
   TRACE_EVENT_MARK_WITH_TIMESTAMP1(
       "blink.user_timing,rail", "domContentLoadedEventEnd",
       dom_content_loaded_event_end_, "frame", ToTraceValue(GetFrame()));
@@ -65,7 +65,7 @@
 }
 
 void DocumentTiming::MarkDomComplete() {
-  dom_complete_ = CurrentTimeTicks();
+  dom_complete_ = base::TimeTicks::Now();
   TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "domComplete",
                                    dom_complete_, "frame",
                                    ToTraceValue(GetFrame()));
@@ -73,7 +73,7 @@
 }
 
 void DocumentTiming::MarkFirstLayout() {
-  first_layout_ = CurrentTimeTicks();
+  first_layout_ = base::TimeTicks::Now();
   TRACE_EVENT_MARK_WITH_TIMESTAMP1("blink.user_timing,rail", "firstLayout",
                                    first_layout_, "frame",
                                    ToTraceValue(GetFrame()));
diff --git a/third_party/blink/renderer/core/dom/events/event.cc b/third_party/blink/renderer/core/dom/events/event.cc
index e3853943..b47c354 100644
--- a/third_party/blink/renderer/core/dom/events/event.cc
+++ b/third_party/blink/renderer/core/dom/events/event.cc
@@ -80,7 +80,7 @@
             bubbles,
             cancelable,
             composed_mode,
-            CurrentTimeTicks()) {}
+            base::TimeTicks::Now()) {}
 
 Event::Event(const AtomicString& event_type,
              Bubbles bubbles,
diff --git a/third_party/blink/renderer/core/dom/events/event.h b/third_party/blink/renderer/core/dom/events/event.h
index ba3b63d..ef3858e 100644
--- a/third_party/blink/renderer/core/dom/events/event.h
+++ b/third_party/blink/renderer/core/dom/events/event.h
@@ -124,7 +124,7 @@
         const EventInit*,
         base::TimeTicks platform_time_stamp);
   Event(const AtomicString& type, const EventInit* init)
-      : Event(type, init, CurrentTimeTicks()) {}
+      : Event(type, init, base::TimeTicks::Now()) {}
   ~Event() override;
 
   void initEvent(const AtomicString& type, bool bubbles, bool cancelable);
diff --git a/third_party/blink/renderer/core/dom/events/event_target.cc b/third_party/blink/renderer/core/dom/events/event_target.cc
index 3dbe4ae..b891311 100644
--- a/third_party/blink/renderer/core/dom/events/event_target.cc
+++ b/third_party/blink/renderer/core/dom/events/event_target.cc
@@ -875,7 +875,7 @@
   base::TimeTicks now;
   bool should_report_blocked_event = false;
   if (!blocked_event_threshold.is_zero()) {
-    now = CurrentTimeTicks();
+    now = base::TimeTicks::Now();
     should_report_blocked_event =
         now - event.PlatformTimeStamp() > blocked_event_threshold;
   }
diff --git a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
index 8cd44b5..654b162 100644
--- a/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
+++ b/third_party/blink/renderer/core/dom/scripted_idle_task_controller.cc
@@ -54,7 +54,7 @@
       scoped_refptr<IdleRequestCallbackWrapper> callback_wrapper) {
     if (ScriptedIdleTaskController* controller =
             callback_wrapper->Controller()) {
-      controller->CallbackFired(callback_wrapper->Id(), CurrentTimeTicks(),
+      controller->CallbackFired(callback_wrapper->Id(), base::TimeTicks::Now(),
                                 IdleDeadline::CallbackType::kCalledByTimeout);
     }
     callback_wrapper->Cancel();
@@ -205,7 +205,7 @@
   IdleTask* idle_task = queued_idle_task->task();
   DCHECK(idle_task);
 
-  base::TimeTicks now = CurrentTimeTicks();
+  base::TimeTicks now = base::TimeTicks::Now();
   base::TimeDelta allotted_time = std::max(deadline - now, base::TimeDelta());
 
   probe::AsyncTask async_task(GetExecutionContext(), idle_task);
@@ -252,7 +252,7 @@
   Vector<CallbackId> pending_timeouts;
   pending_timeouts_.swap(pending_timeouts);
   for (auto& id : pending_timeouts)
-    RunCallback(id, CurrentTimeTicks(),
+    RunCallback(id, base::TimeTicks::Now(),
                 IdleDeadline::CallbackType::kCalledByTimeout);
 
   // Repost idle tasks for any remaining callbacks.
diff --git a/third_party/blink/renderer/core/editing/finder/find_task_controller.cc b/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
index 343cb97..adb5a8a 100644
--- a/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
+++ b/third_party/blink/renderer/core/editing/finder/find_task_controller.cc
@@ -56,7 +56,7 @@
 
   void ForceInvocationForTesting() {
     invoke(MakeGarbageCollected<IdleDeadline>(
-        CurrentTimeTicks() + kFindTaskTestTimeout,
+        base::TimeTicks::Now() + kFindTaskTestTimeout,
         IdleDeadline::CallbackType::kCalledWhenIdle));
   }
 
diff --git a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
index bcc19596..33c45dbf 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/idle_spell_check_controller.cc
@@ -229,7 +229,7 @@
     return;
 
   auto* deadline = MakeGarbageCollected<IdleDeadline>(
-      CurrentTimeTicks() + kIdleSpellcheckTestTimeout,
+      base::TimeTicks::Now() + kIdleSpellcheckTestTimeout,
       IdleDeadline::CallbackType::kCalledWhenIdle);
 
   switch (state_) {
diff --git a/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc b/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc
index f6f1c7b..f2c7ce8 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/spell_check_requester.cc
@@ -198,7 +198,7 @@
   if (!request)
     return false;
 
-  const base::TimeTicks current_request_time = CurrentTimeTicks();
+  const base::TimeTicks current_request_time = base::TimeTicks::Now();
   if (request_num == 0 && last_request_time_ > base::TimeTicks()) {
     UMA_HISTOGRAM_TIMES("WebCore.SpellChecker.RequestInterval",
                         current_request_time - last_request_time_);
diff --git a/third_party/blink/renderer/core/events/composition_event.cc b/third_party/blink/renderer/core/events/composition_event.cc
index cedcc0c..69814ff5 100644
--- a/third_party/blink/renderer/core/events/composition_event.cc
+++ b/third_party/blink/renderer/core/events/composition_event.cc
@@ -40,7 +40,7 @@
               Bubbles::kYes,
               Cancelable::kYes,
               ComposedMode::kComposed,
-              CurrentTimeTicks(),
+              base::TimeTicks::Now(),
               view,
               0,
               view ? view->GetInputDeviceCapabilities()->FiresTouchEvents(false)
diff --git a/third_party/blink/renderer/core/events/drag_event.h b/third_party/blink/renderer/core/events/drag_event.h
index a315016..25041f8 100644
--- a/third_party/blink/renderer/core/events/drag_event.h
+++ b/third_party/blink/renderer/core/events/drag_event.h
@@ -30,7 +30,7 @@
   static DragEvent* Create(const AtomicString& type,
                            const DragEventInit* initializer) {
     return MakeGarbageCollected<DragEvent>(
-        type, initializer, CurrentTimeTicks(), kRealOrIndistinguishable);
+        type, initializer, base::TimeTicks::Now(), kRealOrIndistinguishable);
   }
 
   DragEvent();
diff --git a/third_party/blink/renderer/core/events/focus_event.cc b/third_party/blink/renderer/core/events/focus_event.cc
index f34dfbc..da2ebd38 100644
--- a/third_party/blink/renderer/core/events/focus_event.cc
+++ b/third_party/blink/renderer/core/events/focus_event.cc
@@ -52,7 +52,7 @@
               bubbles,
               Cancelable::kNo,
               ComposedMode::kComposed,
-              CurrentTimeTicks(),
+              base::TimeTicks::Now(),
               view,
               detail,
               source_capabilities),
diff --git a/third_party/blink/renderer/core/events/mouse_event.cc b/third_party/blink/renderer/core/events/mouse_event.cc
index 5bd6207..9590b83 100644
--- a/third_party/blink/renderer/core/events/mouse_event.cc
+++ b/third_party/blink/renderer/core/events/mouse_event.cc
@@ -159,7 +159,7 @@
 
   base::TimeTicks timestamp = underlying_event
                                   ? underlying_event->PlatformTimeStamp()
-                                  : CurrentTimeTicks();
+                                  : base::TimeTicks::Now();
   MouseEvent* created_event = MakeGarbageCollected<MouseEvent>(
       event_type, initializer, timestamp, synthetic_type);
 
diff --git a/third_party/blink/renderer/core/events/mouse_event.h b/third_party/blink/renderer/core/events/mouse_event.h
index f232a81..83aa001 100644
--- a/third_party/blink/renderer/core/events/mouse_event.h
+++ b/third_party/blink/renderer/core/events/mouse_event.h
@@ -74,7 +74,7 @@
              SyntheticEventType = kRealOrIndistinguishable,
              WebMenuSourceType = kMenuSourceNone);
   MouseEvent(const AtomicString& type, const MouseEventInit* init)
-      : MouseEvent(type, init, CurrentTimeTicks()) {}
+      : MouseEvent(type, init, base::TimeTicks::Now()) {}
   MouseEvent();
   ~MouseEvent() override;
 
diff --git a/third_party/blink/renderer/core/events/pointer_event.h b/third_party/blink/renderer/core/events/pointer_event.h
index 1eef5f1..ec3a1adb 100644
--- a/third_party/blink/renderer/core/events/pointer_event.h
+++ b/third_party/blink/renderer/core/events/pointer_event.h
@@ -22,7 +22,7 @@
   }
   static PointerEvent* Create(const AtomicString& type,
                               const PointerEventInit* initializer) {
-    return PointerEvent::Create(type, initializer, CurrentTimeTicks());
+    return PointerEvent::Create(type, initializer, base::TimeTicks::Now());
   }
 
   PointerEvent(const AtomicString&,
diff --git a/third_party/blink/renderer/core/events/portal_activate_event.cc b/third_party/blink/renderer/core/events/portal_activate_event.cc
index cb7f5e32..ddd5dfa 100644
--- a/third_party/blink/renderer/core/events/portal_activate_event.cc
+++ b/third_party/blink/renderer/core/events/portal_activate_event.cc
@@ -53,7 +53,7 @@
     : Event(event_type_names::kPortalactivate,
             Bubbles::kNo,
             Cancelable::kNo,
-            CurrentTimeTicks()),
+            base::TimeTicks::Now()),
       document_(document),
       predecessor_portal_token_(predecessor_portal_token),
       predecessor_portal_(std::move(predecessor_portal)),
diff --git a/third_party/blink/renderer/core/events/text_event.cc b/third_party/blink/renderer/core/events/text_event.cc
index 3c7b317e..afda4ad0 100644
--- a/third_party/blink/renderer/core/events/text_event.cc
+++ b/third_party/blink/renderer/core/events/text_event.cc
@@ -71,7 +71,7 @@
               Bubbles::kYes,
               Cancelable::kYes,
               ComposedMode::kComposed,
-              CurrentTimeTicks(),
+              base::TimeTicks::Now(),
               view,
               0,
               nullptr),
@@ -90,7 +90,7 @@
               Bubbles::kYes,
               Cancelable::kYes,
               ComposedMode::kComposed,
-              CurrentTimeTicks(),
+              base::TimeTicks::Now(),
               view,
               0,
               nullptr),
diff --git a/third_party/blink/renderer/core/events/touch_event.cc b/third_party/blink/renderer/core/events/touch_event.cc
index 05e26b9..ba04bd8 100644
--- a/third_party/blink/renderer/core/events/touch_event.cc
+++ b/third_party/blink/renderer/core/events/touch_event.cc
@@ -47,161 +47,6 @@
 
 namespace {
 
-// These offsets change indicies into the ListenerHistogram
-// enumeration. The addition of a series of offsets then
-// produces the resulting ListenerHistogram value.
-// TODO(dtapuska): Remove all of these histogram counts once
-// https://crbug.com/599609 is fixed.
-const size_t kTouchTargetHistogramRootScrollerOffset = 6;
-const size_t kTouchTargetHistogramScrollableDocumentOffset = 3;
-const size_t kTouchTargetHistogramAlreadyHandledOffset = 0;
-const size_t kTouchTargetHistogramNotHandledOffset = 1;
-const size_t kTouchTargetHistogramHandledOffset = 2;
-const size_t kCapturingOffset = 0;
-const size_t kAtTargetOffset = 12;
-const size_t kBubblingOffset = 24;
-
-enum TouchTargetAndDispatchResultType {
-  // The following enums represent state captured during the CAPTURING_PHASE.
-
-  // Non-root-scroller, non-scrollable document, already handled.
-  kCapturingNonRootScrollerNonScrollableAlreadyHandled,
-  // Non-root-scroller, non-scrollable document, not handled.
-  kCapturingNonRootScrollerNonScrollableNotHandled,
-  // Non-root-scroller, non-scrollable document, handled application.
-  kCapturingNonRootScrollerNonScrollableHandled,
-  // Non-root-scroller, scrollable document, already handled.
-  kCapturingNonRootScrollerScrollableDocumentAlreadyHandled,
-  // Non-root-scroller, scrollable document, not handled.
-  kCapturingNonRootScrollerScrollableDocumentNotHandled,
-  // Non-root-scroller, scrollable document, handled application.
-  kCapturingNonRootScrollerScrollableDocumentHandled,
-  // Root-scroller, non-scrollable document, already handled.
-  kCapturingRootScrollerNonScrollableAlreadyHandled,
-  // Root-scroller, non-scrollable document, not handled.
-  kCapturingRootScrollerNonScrollableNotHandled,
-  // Root-scroller, non-scrollable document, handled.
-  kCapturingRootScrollerNonScrollableHandled,
-  // Root-scroller, scrollable document, already handled.
-  kCapturingRootScrollerScrollableDocumentAlreadyHandled,
-  // Root-scroller, scrollable document, not handled.
-  kCapturingRootScrollerScrollableDocumentNotHandled,
-  // Root-scroller, scrollable document, handled.
-  kCapturingRootScrollerScrollableDocumentHandled,
-
-  // The following enums represent state captured during the AT_TARGET phase.
-
-  // Non-root-scroller, non-scrollable document, already handled.
-  kNonRootScrollerNonScrollableAlreadyHandled,
-  // Non-root-scroller, non-scrollable document, not handled.
-  kNonRootScrollerNonScrollableNotHandled,
-  // Non-root-scroller, non-scrollable document, handled application.
-  kNonRootScrollerNonScrollableHandled,
-  // Non-root-scroller, scrollable document, already handled.
-  kNonRootScrollerScrollableDocumentAlreadyHandled,
-  // Non-root-scroller, scrollable document, not handled.
-  kNonRootScrollerScrollableDocumentNotHandled,
-  // Non-root-scroller, scrollable document, handled application.
-  kNonRootScrollerScrollableDocumentHandled,
-  // Root-scroller, non-scrollable document, already handled.
-  kRootScrollerNonScrollableAlreadyHandled,
-  // Root-scroller, non-scrollable document, not handled.
-  kRootScrollerNonScrollableNotHandled,
-  // Root-scroller, non-scrollable document, handled.
-  kRootScrollerNonScrollableHandled,
-  // Root-scroller, scrollable document, already handled.
-  kRootScrollerScrollableDocumentAlreadyHandled,
-  // Root-scroller, scrollable document, not handled.
-  kRootScrollerScrollableDocumentNotHandled,
-  // Root-scroller, scrollable document, handled.
-  kRootScrollerScrollableDocumentHandled,
-
-  // The following enums represent state captured during the BUBBLING_PHASE.
-
-  // Non-root-scroller, non-scrollable document, already handled.
-  kBubblingNonRootScrollerNonScrollableAlreadyHandled,
-  // Non-root-scroller, non-scrollable document, not handled.
-  kBubblingNonRootScrollerNonScrollableNotHandled,
-  // Non-root-scroller, non-scrollable document, handled application.
-  kBubblingNonRootScrollerNonScrollableHandled,
-  // Non-root-scroller, scrollable document, already handled.
-  kBubblingNonRootScrollerScrollableDocumentAlreadyHandled,
-  // Non-root-scroller, scrollable document, not handled.
-  kBubblingNonRootScrollerScrollableDocumentNotHandled,
-  // Non-root-scroller, scrollable document, handled application.
-  kBubblingNonRootScrollerScrollableDocumentHandled,
-  // Root-scroller, non-scrollable document, already handled.
-  kBubblingRootScrollerNonScrollableAlreadyHandled,
-  // Root-scroller, non-scrollable document, not handled.
-  kBubblingRootScrollerNonScrollableNotHandled,
-  // Root-scroller, non-scrollable document, handled.
-  kBubblingRootScrollerNonScrollableHandled,
-  // Root-scroller, scrollable document, already handled.
-  kBubblingRootScrollerScrollableDocumentAlreadyHandled,
-  // Root-scroller, scrollable document, not handled.
-  kBubblingRootScrollerScrollableDocumentNotHandled,
-  // Root-scroller, scrollable document, handled.
-  kBubblingRootScrollerScrollableDocumentHandled,
-
-  kTouchTargetAndDispatchResultTypeMax,
-};
-
-void LogTouchTargetHistogram(EventTarget* event_target,
-                             uint8_t phase,
-                             bool default_prevented_before_current_target,
-                             bool default_prevented) {
-  int result = 0;
-  Document* document = nullptr;
-
-  switch (phase) {
-    default:
-    case Event::kNone:
-      return;
-    case Event::kCapturingPhase:
-      result += kCapturingOffset;
-      break;
-    case Event::kAtTarget:
-      result += kAtTargetOffset;
-      break;
-    case Event::kBubblingPhase:
-      result += kBubblingOffset;
-      break;
-  }
-
-  if (const LocalDOMWindow* dom_window = event_target->ToLocalDOMWindow()) {
-    // Treat the window as a root scroller as well.
-    document = dom_window->document();
-    result += kTouchTargetHistogramRootScrollerOffset;
-  } else if (Node* node = event_target->ToNode()) {
-    // Report if the target node is the document or body.
-    if (node->IsDocumentNode() ||
-        node->GetDocument().documentElement() == node ||
-        node->GetDocument().body() == node) {
-      result += kTouchTargetHistogramRootScrollerOffset;
-    }
-    document = &node->GetDocument();
-  }
-
-  if (document) {
-    LocalFrameView* view = document->View();
-    if (view && view->LayoutViewport()->ScrollsOverflow())
-      result += kTouchTargetHistogramScrollableDocumentOffset;
-  }
-
-  if (default_prevented_before_current_target)
-    result += kTouchTargetHistogramAlreadyHandledOffset;
-  else if (default_prevented)
-    result += kTouchTargetHistogramHandledOffset;
-  else
-    result += kTouchTargetHistogramNotHandledOffset;
-
-  DEFINE_STATIC_LOCAL(EnumerationHistogram, root_document_listener_histogram,
-                      ("Event.Touch.TargetAndDispatchResult2",
-                       kTouchTargetAndDispatchResultTypeMax));
-  root_document_listener_histogram.Count(
-      static_cast<TouchTargetAndDispatchResultType>(result));
-}
-
 // Helper function to get WebTouchEvent from WebCoalescedInputEvent.
 const WebTouchEvent* GetWebTouchEvent(const WebCoalescedInputEvent& event) {
   return static_cast<const WebTouchEvent*>(&event.Event());
@@ -209,8 +54,7 @@
 }  // namespace
 
 TouchEvent::TouchEvent()
-    : default_prevented_before_current_target_(false),
-      current_touch_action_(TouchAction::kTouchActionAuto) {}
+    : current_touch_action_(TouchAction::kTouchActionAuto) {}
 
 TouchEvent::TouchEvent(const WebCoalescedInputEvent& event,
                        TouchList* touches,
@@ -236,7 +80,6 @@
       touches_(touches),
       target_touches_(target_touches),
       changed_touches_(changed_touches),
-      default_prevented_before_current_target_(false),
       current_touch_action_(current_touch_action) {
   DCHECK(WebInputEvent::IsTouchEventType(event.Event().GetType()));
   native_event_.reset(new WebCoalescedInputEvent(event));
@@ -329,20 +172,6 @@
   return GetWebTouchEvent(*native_event_)->touch_start_or_first_touch_move;
 }
 
-void TouchEvent::DoneDispatchingEventAtCurrentTarget() {
-  // Do not log for non-cancelable events, events that don't block
-  // scrolling, have more than one touch point or aren't on the main frame.
-  if (!cancelable() || !IsTouchStartOrFirstTouchMove() ||
-      !(touches_ && touches_->length() == 1) ||
-      !(view() && view()->GetFrame() && view()->GetFrame()->IsMainFrame()))
-    return;
-
-  bool canceled = defaultPrevented();
-  LogTouchTargetHistogram(currentTarget(), eventPhase(),
-                          default_prevented_before_current_target_, canceled);
-  default_prevented_before_current_target_ = canceled;
-}
-
 void TouchEvent::Trace(blink::Visitor* visitor) {
   visitor->Trace(touches_);
   visitor->Trace(target_touches_);
diff --git a/third_party/blink/renderer/core/events/touch_event.h b/third_party/blink/renderer/core/events/touch_event.h
index f180f0a..674a084e 100644
--- a/third_party/blink/renderer/core/events/touch_event.h
+++ b/third_party/blink/renderer/core/events/touch_event.h
@@ -91,8 +91,6 @@
 
   void preventDefault() override;
 
-  void DoneDispatchingEventAtCurrentTarget() override;
-
   const WebCoalescedInputEvent* NativeEvent() const {
     return native_event_.get();
   }
@@ -108,8 +106,6 @@
   Member<TouchList> target_touches_;
   Member<TouchList> changed_touches_;
 
-  bool default_prevented_before_current_target_;
-
   // The current effective touch action computed before each
   // touchstart event is generated. It is used for UMA histograms.
   TouchAction current_touch_action_;
diff --git a/third_party/blink/renderer/core/events/ui_event.h b/third_party/blink/renderer/core/events/ui_event.h
index 7ad0643..26bb1daa 100644
--- a/third_party/blink/renderer/core/events/ui_event.h
+++ b/third_party/blink/renderer/core/events/ui_event.h
@@ -59,7 +59,7 @@
           const UIEventInit*,
           base::TimeTicks platform_time_stamp);
   UIEvent(const AtomicString& type, const UIEventInit* init)
-      : UIEvent(type, init, CurrentTimeTicks()) {}
+      : UIEvent(type, init, base::TimeTicks::Now()) {}
   ~UIEvent() override;
 
   void initUIEvent(const AtomicString& type,
diff --git a/third_party/blink/renderer/core/events/ui_event_with_key_state.h b/third_party/blink/renderer/core/events/ui_event_with_key_state.h
index d2374e2..20f22b5 100644
--- a/third_party/blink/renderer/core/events/ui_event_with_key_state.h
+++ b/third_party/blink/renderer/core/events/ui_event_with_key_state.h
@@ -79,7 +79,7 @@
                       base::TimeTicks platform_time_stamp);
   UIEventWithKeyState(const AtomicString& type,
                       const EventModifierInit* initializer)
-      : UIEventWithKeyState(type, initializer, CurrentTimeTicks()) {}
+      : UIEventWithKeyState(type, initializer, base::TimeTicks::Now()) {}
   void InitModifiers(bool ctrl_key,
                      bool alt_key,
                      bool shift_key,
diff --git a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
index 0cc00fef..633f611 100644
--- a/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_dev_tools_agent_impl.cc
@@ -413,7 +413,7 @@
   HitTestRequest request(hit_type);
   WebMouseEvent dummy_event(WebInputEvent::kMouseDown,
                             WebInputEvent::kNoModifiers,
-                            WTF::CurrentTimeTicks());
+                            base::TimeTicks::Now());
   dummy_event.SetPositionInWidget(point.x, point.y);
   IntPoint transformed_point = FlooredIntPoint(
       TransformWebMouseEvent(web_local_frame_impl_->GetFrameView(), dummy_event)
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 7b75657..534d545 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -11095,7 +11095,7 @@
       WebFloatPoint(div1_tag->OffsetLeft() + 5, div1_tag->OffsetTop() + 5),
       WebFloatPoint(div1_tag->OffsetLeft() + 5, div1_tag->OffsetTop() + 5),
       WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_move_over_link_event.SetFrameScale(1);
   document->GetFrame()->GetEventHandler().HandleMouseMoveEvent(
       mouse_move_over_link_event, Vector<WebMouseEvent>(),
@@ -11115,7 +11115,7 @@
       WebFloatPoint(div2_tag->OffsetLeft() + 5, div2_tag->OffsetTop() + 5),
       WebFloatPoint(div2_tag->OffsetLeft() + 5, div2_tag->OffsetTop() + 5),
       WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_move_event.SetFrameScale(1);
   document->GetFrame()->GetEventHandler().HandleMouseMoveEvent(
       mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
index 35b0cd87..40ab28f 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.cc
@@ -370,7 +370,7 @@
     return;
   // FIXME: This should use lastFrameTimeMonotonic but doing so
   // breaks tests.
-  PageWidgetDelegate::Animate(*page_, CurrentTimeTicks());
+  PageWidgetDelegate::Animate(*page_, base::TimeTicks::Now());
 }
 
 void WebPagePopupImpl::UpdateLifecycle(LifecycleUpdate requested_update,
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
index 9dd0d74..f10c1301 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1502,7 +1502,7 @@
 
 void WebViewImpl::BeginRafAlignedInput() {
   if (MainFrameImpl()) {
-    raf_aligned_input_start_time_.emplace(CurrentTimeTicks());
+    raf_aligned_input_start_time_.emplace(base::TimeTicks::Now());
   }
 }
 
@@ -1511,14 +1511,14 @@
     DCHECK(raf_aligned_input_start_time_);
     MainFrameImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
         LocalFrameUkmAggregator::kHandleInputEvents,
-        raf_aligned_input_start_time_.value(), CurrentTimeTicks());
+        raf_aligned_input_start_time_.value(), base::TimeTicks::Now());
   }
   raf_aligned_input_start_time_.reset();
 }
 
 void WebViewImpl::BeginUpdateLayers() {
   if (MainFrameImpl())
-    update_layers_start_time_.emplace(CurrentTimeTicks());
+    update_layers_start_time_.emplace(base::TimeTicks::Now());
 }
 
 void WebViewImpl::EndUpdateLayers() {
@@ -1526,14 +1526,14 @@
     DCHECK(update_layers_start_time_);
     MainFrameImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
         LocalFrameUkmAggregator::kUpdateLayers,
-        update_layers_start_time_.value(), CurrentTimeTicks());
+        update_layers_start_time_.value(), base::TimeTicks::Now());
   }
   update_layers_start_time_.reset();
 }
 
 void WebViewImpl::BeginCommitCompositorFrame() {
   if (MainFrameImpl()) {
-    commit_compositor_frame_start_time_.emplace(CurrentTimeTicks());
+    commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
   }
 }
 
@@ -1542,7 +1542,7 @@
   if (MainFrameImpl() && commit_compositor_frame_start_time_) {
     MainFrameImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
         LocalFrameUkmAggregator::kProxyCommit,
-        commit_compositor_frame_start_time_.value(), CurrentTimeTicks());
+        commit_compositor_frame_start_time_.value(), base::TimeTicks::Now());
   }
   commit_compositor_frame_start_time_.reset();
 }
@@ -1562,7 +1562,7 @@
       ->GetFrame()
       ->View()
       ->EnsureUkmAggregator()
-      .RecordEndOfFrameMetrics(frame_begin_time, CurrentTimeTicks());
+      .RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now());
 }
 
 void WebViewImpl::UpdateLifecycle(LifecycleUpdate requested_update,
@@ -3172,9 +3172,9 @@
   if (!main_frame)
     return HitTestResult();
 
-  WebGestureEvent tap_event(
-      WebInputEvent::kGestureTap, WebInputEvent::kNoModifiers,
-      WTF::CurrentTimeTicks(), WebGestureDevice::kTouchscreen);
+  WebGestureEvent tap_event(WebInputEvent::kGestureTap,
+                            WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
+                            WebGestureDevice::kTouchscreen);
   // GestureTap is only ever from a touchscreen.
   tap_event.SetPositionInWidget(FloatPoint(IntPoint(tap_point_window_pos)));
   tap_event.data.tap.tap_count = 1;
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc
index 4649719c..5bfd589b 100644
--- a/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -425,12 +425,6 @@
                              "for more details.",
                              MilestoneString(kM62))};
 
-    case WebFeature::kChildSrcAllowedWorkerThatScriptSrcBlocked:
-      return {"ChildSrcAllowedWorkerThatScriptSrcBlocked", kM60,
-              ReplacedWillBeRemoved("The 'child-src' directive",
-                                    "the 'script-src' directive for Workers",
-                                    kM60, "5922594955984896")};
-
     case WebFeature::kCanRequestURLHTTPContainingNewline:
       return {
           "CanRequestURLHTTPContainingNewline", kUnknown,
diff --git a/third_party/blink/renderer/core/frame/frame_serializer.cc b/third_party/blink/renderer/core/frame/frame_serializer.cc
index 32389d8..af85556 100644
--- a/third_party/blink/renderer/core/frame/frame_serializer.cc
+++ b/third_party/blink/renderer/core/frame/frame_serializer.cc
@@ -69,11 +69,11 @@
 #include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
 #include "third_party/blink/renderer/platform/mhtml/serialized_resource.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace {
 
@@ -219,7 +219,7 @@
 
     StringBuilder pseudo_sheet_url_builder;
     pseudo_sheet_url_builder.Append("cid:css-");
-    pseudo_sheet_url_builder.Append(CreateCanonicalUUIDString());
+    pseudo_sheet_url_builder.Append(WTF::CreateCanonicalUUIDString());
     pseudo_sheet_url_builder.Append("@mhtml.blink");
     KURL pseudo_sheet_url = KURL(pseudo_sheet_url_builder.ToString());
 
@@ -439,7 +439,7 @@
   base::TimeTicks css_start_time;
   if (!is_serializing_css_) {
     is_serializing_css_ = true;
-    css_start_time = CurrentTimeTicks();
+    css_start_time = base::TimeTicks::Now();
   }
 
   // If this CSS is inlined its definition was already serialized with the frame
@@ -481,7 +481,7 @@
     DEFINE_STATIC_LOCAL(CustomCountHistogram, css_histogram,
                         ("PageSerialization.SerializationTime.CSSElement", 0,
                          maxSerializationTimeUmaMicroseconds, 50));
-    css_histogram.CountMicroseconds(CurrentTimeTicks() - css_start_time);
+    css_histogram.CountMicroseconds(base::TimeTicks::Now() - css_start_time);
   }
 }
 
@@ -563,7 +563,7 @@
 
   TRACE_EVENT2("page-serialization", "FrameSerializer::addImageToResources",
                "type", "image", "url", url.ElidedString().Utf8());
-  base::TimeTicks image_start_time = CurrentTimeTicks();
+  base::TimeTicks image_start_time = base::TimeTicks::Now();
 
   scoped_refptr<const SharedBuffer> data = image->GetImage()->Data();
   AddToResources(image->GetResponse().MimeType(),
@@ -575,7 +575,8 @@
     DEFINE_STATIC_LOCAL(CustomCountHistogram, image_histogram,
                         ("PageSerialization.SerializationTime.ImageElement", 0,
                          maxSerializationTimeUmaMicroseconds, 50));
-    image_histogram.CountMicroseconds(CurrentTimeTicks() - image_start_time);
+    image_histogram.CountMicroseconds(base::TimeTicks::Now() -
+                                      image_start_time);
   }
 }
 
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index d29c6bbd..81f9708 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -516,9 +516,9 @@
 
 void LocalFrame::DidResume() {
   if (GetDocument()) {
-    const base::TimeTicks resume_event_start = CurrentTimeTicks();
+    const base::TimeTicks resume_event_start = base::TimeTicks::Now();
     GetDocument()->DispatchEvent(*Event::Create(event_type_names::kResume));
-    const base::TimeTicks resume_event_end = CurrentTimeTicks();
+    const base::TimeTicks resume_event_end = base::TimeTicks::Now();
     DEFINE_STATIC_LOCAL(
         CustomCountHistogram, resume_histogram,
         ("DocumentEventTiming.ResumeDuration", 0, 10000000, 50));
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
index e7f0785..f412f4c 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -934,7 +934,7 @@
   forced_layout_stack_depth_++;
   if (forced_layout_stack_depth_ > 1)
     return;
-  forced_layout_start_time_ = CurrentTimeTicks();
+  forced_layout_start_time_ = base::TimeTicks::Now();
 }
 
 void LocalFrameView::DidFinishForcedLayout() {
@@ -944,7 +944,7 @@
     LocalFrameUkmAggregator& aggregator = EnsureUkmAggregator();
     aggregator.RecordSample(
         (size_t)LocalFrameUkmAggregator::kForcedStyleAndLayout,
-        forced_layout_start_time_, CurrentTimeTicks());
+        forced_layout_start_time_, base::TimeTicks::Now());
   }
 }
 
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
index def1482..a5e3a68 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -216,7 +216,7 @@
   WebMouseEvent fake_mouse_move(
       WebInputEvent::kMouseMove, point_in_root_frame, screen_point,
       WebPointerProperties::Button::kLeft, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   fake_mouse_move.SetFrameScale(1);
   local_root_->GetFrame()->GetEventHandler().DragSourceEndedAt(
       fake_mouse_move, static_cast<DragOperation>(operation));
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
index 2fcd0d1..4947926 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
@@ -292,7 +292,7 @@
 
 void WebFrameWidgetImpl::BeginRafAlignedInput() {
   if (LocalRootImpl()) {
-    raf_aligned_input_start_time_.emplace(CurrentTimeTicks());
+    raf_aligned_input_start_time_.emplace(base::TimeTicks::Now());
   }
 }
 
@@ -301,14 +301,14 @@
     DCHECK(raf_aligned_input_start_time_);
     LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
         LocalFrameUkmAggregator::kHandleInputEvents,
-        raf_aligned_input_start_time_.value(), CurrentTimeTicks());
+        raf_aligned_input_start_time_.value(), base::TimeTicks::Now());
   }
   raf_aligned_input_start_time_.reset();
 }
 
 void WebFrameWidgetImpl::BeginUpdateLayers() {
   if (LocalRootImpl())
-    update_layers_start_time_.emplace(CurrentTimeTicks());
+    update_layers_start_time_.emplace(base::TimeTicks::Now());
 }
 
 void WebFrameWidgetImpl::EndUpdateLayers() {
@@ -316,14 +316,14 @@
     DCHECK(update_layers_start_time_);
     LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
         LocalFrameUkmAggregator::kUpdateLayers,
-        update_layers_start_time_.value(), CurrentTimeTicks());
+        update_layers_start_time_.value(), base::TimeTicks::Now());
   }
   update_layers_start_time_.reset();
 }
 
 void WebFrameWidgetImpl::BeginCommitCompositorFrame() {
   if (LocalRootImpl()) {
-    commit_compositor_frame_start_time_.emplace(CurrentTimeTicks());
+    commit_compositor_frame_start_time_.emplace(base::TimeTicks::Now());
   }
 }
 
@@ -333,7 +333,7 @@
     // timing data.
     LocalRootImpl()->GetFrame()->View()->EnsureUkmAggregator().RecordSample(
         LocalFrameUkmAggregator::kProxyCommit,
-        commit_compositor_frame_start_time_.value(), CurrentTimeTicks());
+        commit_compositor_frame_start_time_.value(), base::TimeTicks::Now());
   }
   commit_compositor_frame_start_time_.reset();
 }
@@ -354,7 +354,7 @@
       ->GetFrame()
       ->View()
       ->EnsureUkmAggregator()
-      .RecordEndOfFrameMetrics(frame_begin_time, CurrentTimeTicks());
+      .RecordEndOfFrameMetrics(frame_begin_time, base::TimeTicks::Now());
 }
 
 void WebFrameWidgetImpl::UpdateLifecycle(LifecycleUpdate requested_update,
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
index 4838ac5c..47778033 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -60,7 +60,7 @@
 #endif
 
 bool IsCreateBlobDeadlineNearOrPassed(base::TimeTicks deadline) {
-  return CurrentTimeTicks() >= deadline - kCreateBlobSlackBeforeDeadline;
+  return base::TimeTicks::Now() >= deadline - kCreateBlobSlackBeforeDeadline;
 }
 
 bool IsEncodeRowDeadlineNearOrPassed(base::TimeTicks deadline,
@@ -71,7 +71,7 @@
                            (image_width / 4000.0);
   base::TimeDelta row_encode_time_delta =
       base::TimeDelta::FromMicroseconds(row_encode_time_us);
-  return CurrentTimeTicks() >=
+  return base::TimeTicks::Now() >=
          deadline - row_encode_time_delta - kEncodeRowSlackBeforeDeadline;
 }
 
@@ -343,7 +343,7 @@
 }
 
 void CanvasAsyncBlobCreator::ScheduleInitiateEncoding(double quality) {
-  schedule_idle_task_start_time_ = WTF::CurrentTimeTicks();
+  schedule_idle_task_start_time_ = base::TimeTicks::Now();
   ThreadScheduler::Current()->PostIdleTask(
       FROM_HERE, WTF::Bind(&CanvasAsyncBlobCreator::InitiateEncoding,
                            WrapPersistent(this), quality));
@@ -355,7 +355,7 @@
     return;
   }
   RecordInitiateEncodingTimeHistogram(
-      mime_type_, WTF::CurrentTimeTicks() - schedule_idle_task_start_time_);
+      mime_type_, base::TimeTicks::Now() - schedule_idle_task_start_time_);
 
   DCHECK(idle_task_status_ == kIdleTaskNotStarted);
   idle_task_status_ = kIdleTaskStarted;
@@ -366,7 +366,7 @@
   }
 
   // Re-use this time variable to collect data on complete encoding delay
-  schedule_idle_task_start_time_ = WTF::CurrentTimeTicks();
+  schedule_idle_task_start_time_ = base::TimeTicks::Now();
   IdleEncodeRows(deadline);
 }
 
@@ -394,7 +394,7 @@
 
   idle_task_status_ = kIdleTaskCompleted;
   base::TimeDelta elapsed_time =
-      WTF::CurrentTimeTicks() - schedule_idle_task_start_time_;
+      base::TimeTicks::Now() - schedule_idle_task_start_time_;
   RecordCompleteEncodingTimeHistogram(mime_type_, elapsed_time);
   if (IsCreateBlobDeadlineNearOrPassed(deadline)) {
     context_->GetTaskRunner(TaskType::kCanvasBlobSerialization)
@@ -451,7 +451,7 @@
   }
 
   RecordScaledDurationHistogram(mime_type_,
-                                WTF::CurrentTimeTicks() - start_time_,
+                                base::TimeTicks::Now() - start_time_,
                                 image_->width(), image_->height());
   // Avoid unwanted retention, see dispose().
   Dispose();
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
index 810bef07..f5d9fdc 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -17,18 +17,18 @@
 
 namespace blink {
 
-CanvasRenderingContextHost::CanvasRenderingContextHost() = default;
+CanvasRenderingContextHost::CanvasRenderingContextHost(HostType host_type)
+    : host_type_(host_type) {}
 
-void CanvasRenderingContextHost::RecordCanvasSizeToUMA(const IntSize& size,
-                                                       HostType hostType) {
+void CanvasRenderingContextHost::RecordCanvasSizeToUMA(const IntSize& size) {
   if (did_record_canvas_size_to_uma_)
     return;
   did_record_canvas_size_to_uma_ = true;
 
-  if (hostType == kCanvasHost) {
+  if (host_type_ == kCanvasHost) {
     UMA_HISTOGRAM_CUSTOM_COUNTS("Blink.Canvas.SqrtNumberOfPixels",
                                 std::sqrt(size.Area()), 1, 5000, 100);
-  } else if (hostType == kOffscreenCanvasHost) {
+  } else if (host_type_ == kOffscreenCanvasHost) {
     UMA_HISTOGRAM_CUSTOM_COUNTS("Blink.OffscreenCanvas.SqrtNumberOfPixels",
                                 std::sqrt(size.Area()), 1, 5000, 100);
   } else {
@@ -207,7 +207,7 @@
     return ScriptPromise();
   }
 
-  base::TimeTicks start_time = WTF::CurrentTimeTicks();
+  base::TimeTicks start_time = base::TimeTicks::Now();
   scoped_refptr<StaticBitmapImage> image_bitmap =
       RenderingContext()->GetImage(kPreferNoAcceleration);
   if (image_bitmap) {
@@ -229,4 +229,8 @@
   return ScriptPromise();
 }
 
+bool CanvasRenderingContextHost::IsOffscreenCanvas() const {
+  return host_type_ == kOffscreenCanvasHost;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
index daea7c9a..d90f197 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
@@ -32,14 +32,15 @@
                                                public CanvasImageSource,
                                                public GarbageCollectedMixin {
  public:
-  CanvasRenderingContextHost();
-
   enum HostType {
+    kNone,
     kCanvasHost,
     kOffscreenCanvasHost,
   };
+  CanvasRenderingContextHost(HostType host_type);
 
-  void RecordCanvasSizeToUMA(const IntSize&, HostType);
+  void RecordCanvasSizeToUMA(const IntSize&);
+
   virtual void DetachContext() = 0;
 
   virtual void DidDraw(const FloatRect& rect) = 0;
@@ -98,6 +99,9 @@
                               const ImageEncodeOptions*,
                               ExceptionState&) const;
 
+  // blink::CanvasImageSource
+  bool IsOffscreenCanvas() const override;
+
  protected:
   ~CanvasRenderingContextHost() override {}
 
@@ -105,6 +109,7 @@
 
   bool did_fail_to_create_resource_provider_ = false;
   bool did_record_canvas_size_to_uma_ = false;
+  HostType host_type_ = kNone;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index 7f2b98c1..3088a07 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -127,6 +127,8 @@
     : HTMLElement(kCanvasTag, document),
       ContextLifecycleObserver(&document),
       PageVisibilityObserver(document.GetPage()),
+      CanvasRenderingContextHost(
+          CanvasRenderingContextHost::HostType::kCanvasHost),
       size_(kDefaultCanvasWidth, kDefaultCanvasHeight),
       context_creation_was_blocked_(false),
       ignore_reset_(false),
@@ -137,7 +139,6 @@
       gpu_readback_invoked_in_current_frame_(false),
       gpu_readback_successive_frames_(0) {
   UseCounter::Count(document, WebFeature::kHTMLCanvasElement);
-
   GetDocument().IncrementNumberOfCanvases();
 }
 
@@ -413,8 +414,7 @@
 
 void HTMLCanvasElement::FinalizeFrame() {
   TRACE_EVENT0("blink", "HTMLCanvasElement::FinalizeFrame");
-  RecordCanvasSizeToUMA(size_,
-                        CanvasRenderingContextHost::HostType::kCanvasHost);
+  RecordCanvasSizeToUMA(size_);
 
   // FinalizeFrame indicates the end of a script task that may have rendered
   // into the canvas, now is a good time to unlock cache entries.
@@ -465,7 +465,7 @@
           context_->PaintRenderingResultsToCanvas(kBackBuffer);
       }
 
-      const base::TimeTicks start_time = WTF::CurrentTimeTicks();
+      const base::TimeTicks start_time = base::TimeTicks::Now();
       const scoped_refptr<CanvasResource> canvas_resource =
           ResourceProvider()->ProduceCanvasResource();
       const FloatRect src_rect(0, 0, Size().Width(), Size().Height());
@@ -975,7 +975,7 @@
     return;
   }
 
-  base::TimeTicks start_time = WTF::CurrentTimeTicks();
+  base::TimeTicks start_time = base::TimeTicks::Now();
   double quality = kUndefinedQualityValue;
   if (!quality_argument.IsEmpty()) {
     v8::Local<v8::Value> v8_value = quality_argument.V8Value();
diff --git a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
index a9a5c6b..17a280c 100644
--- a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
+++ b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
@@ -222,7 +222,7 @@
     return;
 
   DCHECK(time_when_first_visible_.is_null());
-  time_when_first_visible_ = CurrentTimeTicks();
+  time_when_first_visible_ = base::TimeTicks::Now();
   RecordVisibilityMetricsIfLoadedAndVisible();
 
   visibility_metrics_observer_->disconnect();
@@ -261,7 +261,7 @@
 void LazyLoadFrameObserver::RecordMetricsOnLoadFinished() {
   if (!time_when_first_load_finished_.is_null())
     return;
-  time_when_first_load_finished_ = CurrentTimeTicks();
+  time_when_first_load_finished_ = base::TimeTicks::Now();
   RecordVisibilityMetricsIfLoadedAndVisible();
 }
 
diff --git a/third_party/blink/renderer/core/html/lazy_load_image_observer.cc b/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
index ba2253e6..a2e500b 100644
--- a/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
+++ b/third_party/blink/renderer/core/html/lazy_load_image_observer.cc
@@ -221,8 +221,8 @@
 
   base::TimeDelta visible_load_delay;
   if (!visible_load_time_metrics.time_when_first_visible.is_null()) {
-    visible_load_delay =
-        CurrentTimeTicks() - visible_load_time_metrics.time_when_first_visible;
+    visible_load_delay = base::TimeTicks::Now() -
+                         visible_load_time_metrics.time_when_first_visible;
   }
 
   switch (GetNetworkStateNotifier().EffectiveType()) {
@@ -297,7 +297,8 @@
       }
       if (entry->isIntersecting()) {
         DCHECK(visible_load_time_metrics.time_when_first_visible.is_null());
-        visible_load_time_metrics.time_when_first_visible = CurrentTimeTicks();
+        visible_load_time_metrics.time_when_first_visible =
+            base::TimeTicks::Now();
 
         if (visible_load_time_metrics.record_visibility_metrics &&
             image_element->GetDocument().GetFrame()) {
diff --git a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
index c9d37f2..8d53080 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
+++ b/third_party/blink/renderer/core/html/media/autoplay_uma_helper.cc
@@ -215,9 +215,9 @@
 
   if (is_visible) {
     muted_video_autoplay_offscreen_duration_ +=
-        CurrentTimeTicks() - muted_video_autoplay_offscreen_start_time_;
+        base::TimeTicks::Now() - muted_video_autoplay_offscreen_start_time_;
   } else {
-    muted_video_autoplay_offscreen_start_time_ = CurrentTimeTicks();
+    muted_video_autoplay_offscreen_start_time_ = base::TimeTicks::Now();
   }
 
   is_visible_ = is_visible;
@@ -288,7 +288,7 @@
     return;
 
   // Start recording muted video playing offscreen duration.
-  muted_video_autoplay_offscreen_start_time_ = CurrentTimeTicks();
+  muted_video_autoplay_offscreen_start_time_ = base::TimeTicks::Now();
   is_visible_ = false;
   muted_video_offscreen_duration_intersection_observer_ =
       IntersectionObserver::Create(
@@ -309,7 +309,7 @@
 
   if (!is_visible_) {
     muted_video_autoplay_offscreen_duration_ +=
-        CurrentTimeTicks() - muted_video_autoplay_offscreen_start_time_;
+        base::TimeTicks::Now() - muted_video_autoplay_offscreen_start_time_;
   }
 
   DCHECK(sources_.Contains(AutoplaySource::kMethod));
diff --git a/third_party/blink/renderer/core/html/resources/controls_refresh.css b/third_party/blink/renderer/core/html/resources/controls_refresh.css
index 69b6bb18..d4de809 100644
--- a/third_party/blink/renderer/core/html/resources/controls_refresh.css
+++ b/third_party/blink/renderer/core/html/resources/controls_refresh.css
@@ -8,16 +8,38 @@
  * using the refreshed controls UI.
  */
 
-input, textarea {
+input,
+textarea {
   background-color: #ffffff;
   border-color: #cecece;
 }
 
-input:hover, textarea:hover {
+input:hover,
+textarea:hover {
   border-color: #9d9d9d;
 }
 
-input:disabled, textarea:disabled {
+input:disabled,
+textarea:disabled {
   background-color: #ffffff;
   border-color: #c5c5c5;
 }
+
+input[type="button" i],
+input[type="submit" i],
+input[type="reset" i],
+input[type="color" i],
+input[type="file" i]::-webkit-file-upload-button,
+button {
+  background-color: #efefef;
+  border-color: #cecece;
+}
+
+input[type="button" i]:disabled,
+input[type="submit" i]:disabled,
+input[type="reset" i]:disabled,
+input[type="color" i]:disabled,
+input[type="file" i]:disabled::-webkit-file-upload-button,
+button:disabled {
+  border-color: #c5c5c5;
+}
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index 3b6a911..7a43661 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -1499,7 +1499,7 @@
   DCHECK(!targeted_event.Event().IsScrollEvent());
 
   if (targeted_event.Event().GetType() == WebInputEvent::kGestureShowPress)
-    last_show_press_timestamp_ = CurrentTimeTicks();
+    last_show_press_timestamp_ = base::TimeTicks::Now();
 
   // Update mouseout/leave/over/enter events before jumping directly to the
   // inner most frame.
@@ -1827,7 +1827,8 @@
     // If the Tap is received very shortly after ShowPress, we want to
     // delay clearing of the active state so that it's visible to the user
     // for at least a couple of frames.
-    active_interval = CurrentTimeTicks() - last_show_press_timestamp_.value();
+    active_interval =
+        base::TimeTicks::Now() - last_show_press_timestamp_.value();
     should_keep_active_for_min_interval =
         active_interval < kMinimumActiveInterval;
     if (should_keep_active_for_min_interval)
@@ -2085,7 +2086,7 @@
       WebFloatPoint(location_in_root_frame.X(), location_in_root_frame.Y()),
       WebFloatPoint(global_position.X(), global_position.Y()),
       WebPointerProperties::Button::kNoButton, /* clickCount */ 0,
-      WebInputEvent::kNoModifiers, CurrentTimeTicks(), source_type);
+      WebInputEvent::kNoModifiers, base::TimeTicks::Now(), source_type);
 
   // TODO(dtapuska): Transition the mouseEvent to be created really in viewport
   // coordinates instead of root frame coordinates.
diff --git a/third_party/blink/renderer/core/input/event_handler_test.cc b/third_party/blink/renderer/core/input/event_handler_test.cc
index 7837fa7..c9060ab2 100644
--- a/third_party/blink/renderer/core/input/event_handler_test.cc
+++ b/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -64,7 +64,7 @@
   TapEventBuilder(FloatPoint position, int tap_count)
       : WebGestureEvent(WebInputEvent::kGestureTap,
                         WebInputEvent::kNoModifiers,
-                        CurrentTimeTicks(),
+                        base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen) {
     SetPositionInWidget(position);
     SetPositionInScreen(position);
@@ -80,7 +80,7 @@
   TapDownEventBuilder(FloatPoint position)
       : WebGestureEvent(WebInputEvent::kGestureTapDown,
                         WebInputEvent::kNoModifiers,
-                        CurrentTimeTicks(),
+                        base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen) {
     SetPositionInWidget(position);
     SetPositionInScreen(position);
@@ -95,7 +95,7 @@
   ShowPressEventBuilder(FloatPoint position)
       : WebGestureEvent(WebInputEvent::kGestureShowPress,
                         WebInputEvent::kNoModifiers,
-                        CurrentTimeTicks(),
+                        base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen) {
     SetPositionInWidget(position);
     SetPositionInScreen(position);
@@ -110,7 +110,7 @@
   LongPressEventBuilder(FloatPoint position)
       : WebGestureEvent(WebInputEvent::kGestureLongPress,
                         WebInputEvent::kNoModifiers,
-                        CurrentTimeTicks(),
+                        base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen) {
     SetPositionInWidget(position);
     SetPositionInScreen(position);
@@ -127,7 +127,7 @@
                          WebMouseEvent::Button button_param)
       : WebMouseEvent(WebInputEvent::kMouseDown,
                       WebInputEvent::kNoModifiers,
-                      CurrentTimeTicks()) {
+                      base::TimeTicks::Now()) {
     click_count = click_count_param;
     button = button_param;
     SetPositionInWidget(position_param.X(), position_param.Y());
@@ -198,7 +198,7 @@
       mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
 
   GetPage().GetAutoscrollController().Animate();
-  GetPage().Animator().ServiceScriptedAnimations(WTF::CurrentTimeTicks());
+  GetPage().Animator().ServiceScriptedAnimations(base::TimeTicks::Now());
 
   WebMouseEvent mouse_up_event(
       WebMouseEvent::kMouseUp, WebFloatPoint(100, 50), WebFloatPoint(200, 250),
@@ -642,7 +642,7 @@
   WebMouseEvent mouse_down_event(
       WebMouseEvent::kMouseDown, WebFloatPoint(0, 0), WebFloatPoint(100, 200),
       WebPointerProperties::Button::kRight, 1,
-      WebInputEvent::Modifiers::kRightButtonDown, CurrentTimeTicks());
+      WebInputEvent::Modifiers::kRightButtonDown, base::TimeTicks::Now());
   mouse_down_event.SetFrameScale(1);
   EXPECT_EQ(WebInputEventResult::kHandledApplication,
             GetDocument().GetFrame()->GetEventHandler().SendContextMenuEvent(
@@ -799,7 +799,7 @@
   WebMouseEvent mouse_down_event(
       WebInputEvent::kMouseDown, WebFloatPoint(50, 50), WebFloatPoint(50, 50),
       WebPointerProperties::Button::kLeft, 1,
-      WebInputEvent::Modifiers::kLeftButtonDown, CurrentTimeTicks());
+      WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now());
   mouse_down_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
       mouse_down_event);
@@ -807,7 +807,7 @@
   WebMouseEvent mouse_move_event(
       WebInputEvent::kMouseMove, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
       WebPointerProperties::Button::kLeft, 1,
-      WebInputEvent::Modifiers::kLeftButtonDown, CurrentTimeTicks());
+      WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now());
   mouse_move_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
       mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
@@ -818,10 +818,10 @@
   // this contrived test. Given the current code, it is unclear how the
   // dragSourceEndedAt() call could occur before a drag operation is started.
 
-  WebMouseEvent mouse_up_event(WebInputEvent::kMouseUp, WebFloatPoint(100, 50),
-                               WebFloatPoint(200, 250),
-                               WebPointerProperties::Button::kLeft, 1,
-                               WebInputEvent::kNoModifiers, CurrentTimeTicks());
+  WebMouseEvent mouse_up_event(
+      WebInputEvent::kMouseUp, WebFloatPoint(100, 50), WebFloatPoint(200, 250),
+      WebPointerProperties::Button::kLeft, 1, WebInputEvent::kNoModifiers,
+      base::TimeTicks::Now());
   mouse_up_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().DragSourceEndedAt(
       mouse_up_event, kDragOperationNone);
@@ -911,7 +911,7 @@
   WebMouseEvent mouse_move_event(
       WebInputEvent::kMouseMove, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
       WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_move_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
       mouse_move_event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
@@ -921,7 +921,7 @@
   WebMouseEvent mouse_leave_event(
       WebInputEvent::kMouseLeave, WebFloatPoint(0, 0), WebFloatPoint(0, 0),
       WebPointerProperties::Button::kNoButton, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_leave_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseLeaveEvent(
       mouse_leave_event);
@@ -981,7 +981,7 @@
   WebMouseEvent mouse_press_event(
       WebInputEvent::kMouseDown, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
       WebPointerProperties::Button::kLeft, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_press_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(
       mouse_press_event);
@@ -1039,7 +1039,7 @@
   WebMouseEvent mouse_back_event(
       WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
       WebPointerProperties::Button::kBack, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_back_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
       mouse_back_event);
@@ -1049,7 +1049,7 @@
   WebMouseEvent mouse_forward_event(
       WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
       WebPointerProperties::Button::kForward, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_forward_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
       mouse_forward_event);
@@ -1071,7 +1071,7 @@
   WebMouseEvent mouse_back_event(
       WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
       WebPointerProperties::Button::kBack, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_back_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
       mouse_back_event);
@@ -1081,7 +1081,7 @@
   WebMouseEvent mouse_forward_event(
       WebInputEvent::kMouseUp, WebFloatPoint(51, 50), WebFloatPoint(51, 50),
       WebPointerProperties::Button::kForward, 0, WebInputEvent::kNoModifiers,
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   mouse_forward_event.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(
       mouse_forward_event);
@@ -1131,7 +1131,7 @@
   WebMouseEvent mouse_down(WebInputEvent::kMouseDown, scrollbar_forward_track,
                            scrollbar_forward_track,
                            WebPointerProperties::Button::kLeft, 0,
-                           WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                           WebInputEvent::kNoModifiers, base::TimeTicks::Now());
   mouse_down.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(mouse_down);
 
@@ -1149,7 +1149,8 @@
   const WebFloatPoint middle_of_page(100, 100);
   WebMouseEvent mouse_move(WebInputEvent::kMouseMove, middle_of_page,
                            middle_of_page, WebPointerProperties::Button::kLeft,
-                           0, WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                           0, WebInputEvent::kNoModifiers,
+                           base::TimeTicks::Now());
   mouse_move.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
       mouse_move, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
@@ -1163,7 +1164,7 @@
 
   WebMouseEvent mouse_up(WebInputEvent::kMouseUp, middle_of_page,
                          middle_of_page, WebPointerProperties::Button::kLeft, 0,
-                         WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                         WebInputEvent::kNoModifiers, base::TimeTicks::Now());
   mouse_up.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(mouse_up);
 
@@ -1198,7 +1199,8 @@
   const WebFloatPoint middle_of_page(100, 100);
   WebMouseEvent mouse_down(WebInputEvent::kMouseDown, middle_of_page,
                            middle_of_page, WebPointerProperties::Button::kLeft,
-                           0, WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                           0, WebInputEvent::kNoModifiers,
+                           base::TimeTicks::Now());
   mouse_down.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(mouse_down);
 
@@ -1209,7 +1211,7 @@
   WebMouseEvent mouse_move(WebInputEvent::kMouseMove, scrollbar_forward_track,
                            scrollbar_forward_track,
                            WebPointerProperties::Button::kLeft, 0,
-                           WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                           WebInputEvent::kNoModifiers, base::TimeTicks::Now());
   mouse_move.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
       mouse_move, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
@@ -1220,7 +1222,7 @@
   WebMouseEvent mouse_up(WebInputEvent::kMouseUp, scrollbar_forward_track,
                          scrollbar_forward_track,
                          WebPointerProperties::Button::kLeft, 0,
-                         WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                         WebInputEvent::kNoModifiers, base::TimeTicks::Now());
   mouse_up.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(mouse_up);
 
@@ -1250,7 +1252,7 @@
   WebMouseEvent mouse_down(WebInputEvent::kMouseDown, scrollbar_forward_track,
                            scrollbar_forward_track,
                            WebPointerProperties::Button::kRight, 0,
-                           WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                           WebInputEvent::kNoModifiers, base::TimeTicks::Now());
   mouse_down.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(mouse_down);
 
@@ -1259,7 +1261,7 @@
   WebMouseEvent mouse_up(WebInputEvent::kMouseUp, scrollbar_forward_track,
                          scrollbar_forward_track,
                          WebPointerProperties::Button::kRight, 0,
-                         WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                         WebInputEvent::kNoModifiers, base::TimeTicks::Now());
   mouse_up.SetFrameScale(1);
   GetDocument().GetFrame()->GetEventHandler().HandleMouseReleaseEvent(mouse_up);
 
diff --git a/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc b/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
index 543f5f2..925a4a56 100644
--- a/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
+++ b/third_party/blink/renderer/core/input/fallback_cursor_event_manager_test.cc
@@ -85,7 +85,7 @@
     WebMouseEvent event(WebInputEvent::kMouseMove, WebFloatPoint(x, y),
                         WebFloatPoint(x, y),
                         WebPointerProperties::Button::kNoButton, 0,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now());
     event.SetFrameScale(scale);
     GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
         event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
@@ -103,7 +103,7 @@
     WebMouseEvent event(WebInputEvent::kMouseMove, root_frame_point,
                         root_frame_point,
                         WebPointerProperties::Button::kNoButton, 0,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now());
     event.SetFrameScale(1.0f);
     GetDocument().GetFrame()->GetEventHandler().HandleMouseMoveEvent(
         event, Vector<WebMouseEvent>(), Vector<WebMouseEvent>());
@@ -113,7 +113,7 @@
     WebMouseEvent event(
         WebInputEvent::kMouseDown, WebFloatPoint(x, y), WebFloatPoint(x, y),
         WebPointerProperties::Button::kLeft, 0,
-        WebInputEvent::Modifiers::kLeftButtonDown, CurrentTimeTicks());
+        WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(event);
   }
diff --git a/third_party/blink/renderer/core/input/mouse_event_manager.cc b/third_party/blink/renderer/core/input/mouse_event_manager.cc
index a28e23c0..d878700 100644
--- a/third_party/blink/renderer/core/input/mouse_event_manager.cc
+++ b/third_party/blink/renderer/core/input/mouse_event_manager.cc
@@ -423,7 +423,7 @@
   WebMouseEvent fake_mouse_move_event(WebInputEvent::kMouseMove,
                                       last_known_mouse_position_,
                                       last_known_mouse_screen_position_, button,
-                                      0, modifiers, CurrentTimeTicks());
+                                      0, modifiers, base::TimeTicks::Now());
   Vector<WebMouseEvent> coalesced_events, predicted_events;
   frame_->GetEventHandler().HandleMouseMoveEvent(
       TransformWebMouseEvent(view, fake_mouse_move_event), coalesced_events,
@@ -807,7 +807,7 @@
         WebPointerProperties::Button::kLeft, 1,
         modifiers | WebInputEvent::Modifiers::kLeftButtonDown |
             WebInputEvent::Modifiers::kIsCompatibilityEventForTouch,
-        CurrentTimeTicks());
+        base::TimeTicks::Now());
     mouse_down_ = mouse_down_event;
 
     WebMouseEvent mouse_drag_event(
@@ -815,7 +815,7 @@
         WebPointerProperties::Button::kLeft, 1,
         modifiers | WebInputEvent::Modifiers::kLeftButtonDown |
             WebInputEvent::Modifiers::kIsCompatibilityEventForTouch,
-        CurrentTimeTicks());
+        base::TimeTicks::Now());
     HitTestRequest request(HitTestRequest::kReadOnly);
     MouseEventWithHitTestResults mev =
         event_handling_util::PerformMouseEventHitTest(frame_, request,
diff --git a/third_party/blink/renderer/core/input/overscroll_behavior_test.cc b/third_party/blink/renderer/core/input/overscroll_behavior_test.cc
index 25584c71..06b3363 100644
--- a/third_party/blink/renderer/core/input/overscroll_behavior_test.cc
+++ b/third_party/blink/renderer/core/input/overscroll_behavior_test.cc
@@ -71,7 +71,7 @@
 
 void OverscrollBehaviorTest::ScrollBegin(double hint_x, double hint_y) {
   WebGestureEvent event(WebInputEvent::kGestureScrollBegin,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks(),
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen);
   event.SetPositionInWidget(WebFloatPoint(20, 20));
   event.SetPositionInScreen(WebFloatPoint(20, 20));
@@ -84,7 +84,7 @@
 
 void OverscrollBehaviorTest::ScrollUpdate(double delta_x, double delta_y) {
   WebGestureEvent event(WebInputEvent::kGestureScrollUpdate,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks(),
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen);
   event.SetPositionInWidget(WebFloatPoint(20, 20));
   event.SetPositionInScreen(WebFloatPoint(20, 20));
@@ -96,7 +96,7 @@
 
 void OverscrollBehaviorTest::ScrollEnd() {
   WebGestureEvent event(WebInputEvent::kGestureScrollEnd,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks(),
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen);
   event.SetPositionInWidget(WebFloatPoint(20, 20));
   event.SetPositionInScreen(WebFloatPoint(20, 20));
diff --git a/third_party/blink/renderer/core/input/scroll_snap_test.cc b/third_party/blink/renderer/core/input/scroll_snap_test.cc
index 0f93fef..b385e838 100644
--- a/third_party/blink/renderer/core/input/scroll_snap_test.cc
+++ b/third_party/blink/renderer/core/input/scroll_snap_test.cc
@@ -90,7 +90,7 @@
                                  double hint_x,
                                  double hint_y) {
   WebGestureEvent event(WebInputEvent::kGestureScrollBegin,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks(),
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen);
   event.SetPositionInWidget(WebFloatPoint(x, y));
   event.SetPositionInScreen(WebFloatPoint(x, y));
@@ -107,7 +107,7 @@
                                   double delta_y,
                                   bool is_in_inertial_phase) {
   WebGestureEvent event(WebInputEvent::kGestureScrollUpdate,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks(),
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen);
   event.SetPositionInWidget(WebFloatPoint(x, y));
   event.SetPositionInScreen(WebFloatPoint(x, y));
@@ -124,7 +124,7 @@
 
 void ScrollSnapTest::ScrollEnd(double x, double y, bool is_in_inertial_phase) {
   WebGestureEvent event(WebInputEvent::kGestureScrollEnd,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks(),
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now(),
                         WebGestureDevice::kTouchscreen);
   event.SetPositionInWidget(WebFloatPoint(x, y));
   event.SetPositionInScreen(WebFloatPoint(x, y));
diff --git a/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc b/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc
index e366189..27d45c4 100644
--- a/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_layer_tree_agent.cc
@@ -173,16 +173,13 @@
   return constraints_obj;
 }
 
-static bool IsUsingLayerLists(const cc::Layer* root) {
-  return root->layer_tree_host() &&
-         root->layer_tree_host()->IsUsingLayerLists();
-}
-
 static std::unique_ptr<protocol::LayerTree::Layer> BuildObjectForLayer(
     const cc::Layer* root,
     const cc::Layer* layer,
     bool report_wheel_event_listeners) {
-  bool is_using_layer_lists = IsUsingLayerLists(root);
+  bool using_layer_list =
+      RuntimeEnabledFeatures::CompositeAfterPaintEnabled() ||
+      RuntimeEnabledFeatures::BlinkGenPropertyTreesEnabled();
 
   // When the front-end doesn't show internal layers, it will use the the first
   // DrawsContent layer as the root of the shown layer tree. This doesn't work
@@ -190,13 +187,13 @@
   // all DrawsContent layers. We have to cheat the front-end by setting
   // drawsContent to true for the root layer.
   bool draws_content =
-      (is_using_layer_lists && root == layer) || layer->DrawsContent();
+      (using_layer_list && root == layer) || layer->DrawsContent();
 
   std::unique_ptr<protocol::LayerTree::Layer> layer_object =
       protocol::LayerTree::Layer::create()
           .setLayerId(IdForLayer(layer))
-          .setOffsetX(is_using_layer_lists ? 0 : layer->position().x())
-          .setOffsetY(is_using_layer_lists ? 0 : layer->position().y())
+          .setOffsetX(using_layer_list ? 0 : layer->position().x())
+          .setOffsetY(using_layer_list ? 0 : layer->position().y())
           .setWidth(layer->bounds().width())
           .setHeight(layer->bounds().height())
           .setPaintCount(layer->paint_count())
@@ -211,7 +208,7 @@
 
   gfx::Transform transform;
   gfx::Point3F transform_origin;
-  if (is_using_layer_lists) {
+  if (using_layer_list) {
     transform = layer->ScreenSpaceTransform();
   } else {
     transform = layer->transform();
@@ -238,7 +235,6 @@
     }
     layer_object->setAnchorZ(transform_origin.z());
   }
-
   std::unique_ptr<Array<protocol::LayerTree::ScrollRect>> scroll_rects =
       BuildScrollRectsForLayer(layer, report_wheel_event_listeners);
   if (scroll_rects)
@@ -352,11 +348,6 @@
           root_frame, cc::EventListenerClass::kMouseWheel) ==
       cc::EventListenerProperties::kBlocking;
 
-  // Update layers' ScreenSpaceTransform() which will be used during
-  // GatherLayers().
-  if (IsUsingLayerLists(root_layer))
-    root_layer->layer_tree_host()->UpdateLayers();
-
   GatherLayers(root_layer, layers, have_blocking_wheel_event_handlers,
                scrolling_layer_id);
   return layers;
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index f664d848..57521c2 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -723,7 +723,7 @@
   String request_id = IdentifiersFactory::RequestId(loader, identifier);
   String protocol_reason = BuildBlockedReason(reason);
   GetFrontend()->loadingFailed(
-      request_id, CurrentTimeTicksInSeconds(),
+      request_id, base::TimeTicks::Now().since_origin().InSecondsF(),
       InspectorPageAgent::ResourceTypeJson(
           resources_data_->GetResourceType(request_id)),
       String(), false, protocol_reason);
@@ -734,9 +734,9 @@
     uint64_t identifier,
     ResourceLoadPriority load_priority) {
   String request_id = IdentifiersFactory::RequestId(loader, identifier);
-  GetFrontend()->resourceChangedPriority(request_id,
-                                         ResourcePriorityJSON(load_priority),
-                                         CurrentTimeTicksInSeconds());
+  GetFrontend()->resourceChangedPriority(
+      request_id, ResourcePriorityJSON(load_priority),
+      base::TimeTicks::Now().since_origin().InSecondsF());
 }
 
 void InspectorNetworkAgent::WillSendRequestInternal(
@@ -804,7 +804,8 @@
     maybe_frame_id = frame_id;
   GetFrontend()->requestWillBeSent(
       request_id, loader_id, documentURL, std::move(request_info),
-      CurrentTimeTicksInSeconds(), CurrentTime(), std::move(initiator_object),
+      base::TimeTicks::Now().since_origin().InSecondsF(), CurrentTime(),
+      std::move(initiator_object),
       BuildObjectForResourceResponse(redirect_response), resource_type,
       std::move(maybe_frame_id), request.HasUserGesture());
   if (is_handling_sync_xhr_)
@@ -971,7 +972,8 @@
     if (!frame_id.IsEmpty())
       maybe_frame_id = frame_id;
     GetFrontend()->responseReceived(
-        request_id, loader_id, CurrentTimeTicksInSeconds(),
+        request_id, loader_id,
+        base::TimeTicks::Now().since_origin().InSecondsF(),
         InspectorPageAgent::ResourceTypeJson(type),
         std::move(resource_response), std::move(maybe_frame_id));
   }
@@ -1006,7 +1008,8 @@
   }
 
   GetFrontend()->dataReceived(
-      request_id, CurrentTimeTicksInSeconds(), static_cast<int>(data_length),
+      request_id, base::TimeTicks::Now().since_origin().InSecondsF(),
+      static_cast<int>(data_length),
       static_cast<int>(
           resources_data_->GetAndClearPendingEncodedDataLength(request_id)));
 }
@@ -1040,8 +1043,9 @@
   int pending_encoded_data_length = static_cast<int>(
       resources_data_->GetAndClearPendingEncodedDataLength(request_id));
   if (pending_encoded_data_length > 0) {
-    GetFrontend()->dataReceived(request_id, CurrentTimeTicksInSeconds(), 0,
-                                pending_encoded_data_length);
+    GetFrontend()->dataReceived(
+        request_id, base::TimeTicks::Now().since_origin().InSecondsF(), 0,
+        pending_encoded_data_length);
   }
 
   if (resource_data &&
@@ -1054,7 +1058,7 @@
 
   resources_data_->MaybeDecodeDataToContent(request_id);
   if (monotonic_finish_time.is_null())
-    monotonic_finish_time = CurrentTimeTicks();
+    monotonic_finish_time = base::TimeTicks::Now();
 
   is_handling_sync_xhr_ = false;
   // TODO(npm): Use base::TimeTicks in Network.h.
@@ -1088,7 +1092,7 @@
   }
   is_handling_sync_xhr_ = false;
   GetFrontend()->loadingFailed(
-      request_id, CurrentTimeTicksInSeconds(),
+      request_id, base::TimeTicks::Now().since_origin().InSecondsF(),
       InspectorPageAgent::ResourceTypeJson(
           resources_data_->GetResourceType(request_id)),
       error.LocalizedDescription(), canceled, std::move(blocked_reason));
@@ -1146,8 +1150,8 @@
     const String& data) {
   GetFrontend()->eventSourceMessageReceived(
       IdentifiersFactory::SubresourceRequestId(identifier),
-      CurrentTimeTicksInSeconds(), event_name.GetString(), event_id.GetString(),
-      data);
+      base::TimeTicks::Now().since_origin().InSecondsF(),
+      event_name.GetString(), event_id.GetString(), data);
 }
 
 std::unique_ptr<protocol::Network::Initiator>
@@ -1241,7 +1245,8 @@
           .build();
   GetFrontend()->webSocketWillSendHandshakeRequest(
       IdentifiersFactory::SubresourceRequestId(identifier),
-      CurrentTimeTicksInSeconds(), CurrentTime(), std::move(request_object));
+      base::TimeTicks::Now().since_origin().InSecondsF(), CurrentTime(),
+      std::move(request_object));
 }
 
 void InspectorNetworkAgent::DidReceiveWebSocketHandshakeResponse(
@@ -1284,14 +1289,15 @@
 
   GetFrontend()->webSocketHandshakeResponseReceived(
       IdentifiersFactory::SubresourceRequestId(identifier),
-      CurrentTimeTicksInSeconds(), std::move(response_object));
+      base::TimeTicks::Now().since_origin().InSecondsF(),
+      std::move(response_object));
 }
 
 void InspectorNetworkAgent::DidCloseWebSocket(ExecutionContext*,
                                               uint64_t identifier) {
   GetFrontend()->webSocketClosed(
       IdentifiersFactory::SubresourceRequestId(identifier),
-      CurrentTimeTicksInSeconds());
+      base::TimeTicks::Now().since_origin().InSecondsF());
 }
 
 void InspectorNetworkAgent::DidReceiveWebSocketMessage(
@@ -1310,7 +1316,7 @@
   }
   GetFrontend()->webSocketFrameReceived(
       IdentifiersFactory::SubresourceRequestId(identifier),
-      CurrentTimeTicksInSeconds(),
+      base::TimeTicks::Now().since_origin().InSecondsF(),
       WebSocketMessageToProtocol(op_code, masked, flatten.data(),
                                  flatten.size()));
 }
@@ -1322,7 +1328,7 @@
                                                     size_t payload_length) {
   GetFrontend()->webSocketFrameSent(
       IdentifiersFactory::RequestId(nullptr, identifier),
-      CurrentTimeTicksInSeconds(),
+      base::TimeTicks::Now().since_origin().InSecondsF(),
       WebSocketMessageToProtocol(op_code, masked, payload, payload_length));
 }
 
@@ -1331,7 +1337,7 @@
     const String& error_message) {
   GetFrontend()->webSocketFrameError(
       IdentifiersFactory::RequestId(nullptr, identifier),
-      CurrentTimeTicksInSeconds(), error_message);
+      base::TimeTicks::Now().since_origin().InSecondsF(), error_message);
 }
 
 Response InspectorNetworkAgent::enable(Maybe<int> total_buffer_size,
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
index 6553a17b..53e27cc 100644
--- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
@@ -883,7 +883,7 @@
 }
 
 void InspectorPageAgent::DomContentLoadedEventFired(LocalFrame* frame) {
-  double timestamp = CurrentTimeTicksInSeconds();
+  double timestamp = base::TimeTicks::Now().since_origin().InSecondsF();
   if (frame == inspected_frames_->Root())
     GetFrontend()->domContentEventFired(timestamp);
   DocumentLoader* loader = frame->Loader().GetDocumentLoader();
@@ -891,7 +891,7 @@
 }
 
 void InspectorPageAgent::LoadEventFired(LocalFrame* frame) {
-  double timestamp = CurrentTimeTicksInSeconds();
+  double timestamp = base::TimeTicks::Now().since_origin().InSecondsF();
   if (frame == inspected_frames_->Root())
     GetFrontend()->loadEventFired(timestamp);
   DocumentLoader* loader = frame->Loader().GetDocumentLoader();
diff --git a/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc b/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc
index c553b0b..e315558 100644
--- a/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_performance_agent.cc
@@ -135,7 +135,7 @@
       std::make_unique<protocol::Array<protocol::Performance::Metric>>();
 
   AppendMetric(result.get(), "Timestamp",
-               CurrentTimeTicks().since_origin().InSecondsF());
+               base::TimeTicks::Now().since_origin().InSecondsF());
 
   // Renderer instance counters.
   for (size_t i = 0; i < ARRAY_SIZE(kInstanceCounterNames); ++i) {
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc
index 76042746..d3e2b755 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -3090,12 +3090,6 @@
                                                   : nullptr;
 }
 
-static bool IsMergeableAnonymousBlock(const LayoutBlockFlow* block) {
-  return block->IsAnonymousBlock() && !block->Continuation() &&
-         !block->BeingDestroyed() && !block->IsRubyRun() &&
-         !block->IsRubyBase();
-}
-
 void LayoutBlockFlow::AddChild(LayoutObject* new_child,
                                LayoutObject* before_child) {
   if (LayoutMultiColumnFlowThread* flow_thread = MultiColumnFlowThread()) {
@@ -3120,12 +3114,6 @@
   bool child_is_block_level =
       !new_child->IsInline() && !new_child->IsFloatingOrOutOfFlowPositioned();
 
-  // LayoutNG we considers a block with only floats or OOF-positioned nodes as
-  // block-level. This changes the static-position of OOF-positioned nodes.
-  if (IsLayoutNGContainingBlock(this) &&
-      new_child->IsFloatingOrOutOfFlowPositioned())
-    child_is_block_level = !FirstChild();
-
   if (ChildrenInline()) {
     if (child_is_block_level) {
       // Wrap the inline content in anonymous blocks, to allow for the new block
@@ -3164,14 +3152,6 @@
       new_block->ReparentPrecedingFloatingOrOutOfFlowSiblings();
       new_block->AddChild(new_child);
       new_block->ReparentSubsequentFloatingOrOutOfFlowSiblings();
-
-      // Moving the preceding/subsequent (block-level) floats/out-of-flow
-      // siblings may have left us as a single (inline-level) anonymous block.
-      // We can pull the content now back up into our box.
-      if (!new_block->PreviousSibling() && !new_block->NextSibling()) {
-        if (IsMergeableAnonymousBlock(new_block))
-          CollapseAnonymousBlockChild(new_block);
-      }
       return;
     }
   }
@@ -3187,6 +3167,12 @@
   }
 }
 
+static bool IsMergeableAnonymousBlock(const LayoutBlockFlow* block) {
+  return block->IsAnonymousBlock() && !block->Continuation() &&
+         !block->BeingDestroyed() && !block->IsRubyRun() &&
+         !block->IsRubyBase();
+}
+
 void LayoutBlockFlow::RemoveChild(LayoutObject* old_child) {
   // No need to waste time in merging or removing empty anonymous blocks.
   // We can just bail out if our document is getting destroyed.
diff --git a/third_party/blink/renderer/core/layout/layout_progress.cc b/third_party/blink/renderer/core/layout/layout_progress.cc
index 25c8830..85384a00 100644
--- a/third_party/blink/renderer/core/layout/layout_progress.cc
+++ b/third_party/blink/renderer/core/layout/layout_progress.cc
@@ -61,7 +61,7 @@
 double LayoutProgress::AnimationProgress() const {
   if (!animating_)
     return 0;
-  base::TimeDelta elapsed = CurrentTimeTicks() - animation_start_time_;
+  base::TimeDelta elapsed = base::TimeTicks::Now() - animation_start_time_;
   return (elapsed % animation_duration_).InSecondsF() /
          animation_duration_.InSecondsF();
 }
@@ -98,7 +98,7 @@
 
   animating_ = animating;
   if (animating_) {
-    animation_start_time_ = CurrentTimeTicks();
+    animation_start_time_ = base::TimeTicks::Now();
     animation_timer_.StartOneShot(animation_repeat_interval_, FROM_HERE);
   } else {
     animation_timer_.Stop();
diff --git a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
index 960fd956..5c914ba 100644
--- a/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_shift_tracker_test.cc
@@ -29,7 +29,7 @@
     GetLayoutShiftTracker().NotifyInput(WebMouseEvent(
         WebInputEvent::kMouseDown, WebFloatPoint(), WebFloatPoint(),
         WebPointerProperties::Button::kLeft, 0,
-        WebInputEvent::Modifiers::kLeftButtonDown, CurrentTimeTicks()));
+        WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now()));
   }
 
   void UpdateAllLifecyclePhases() {
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc
index 46efead2..255d4aa 100644
--- a/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -69,11 +69,11 @@
 class HitTestLatencyRecorder {
  public:
   HitTestLatencyRecorder(bool allows_child_frame_content)
-      : start_(CurrentTimeTicks()),
+      : start_(base::TimeTicks::Now()),
         allows_child_frame_content_(allows_child_frame_content) {}
 
   ~HitTestLatencyRecorder() {
-    base::TimeDelta duration = CurrentTimeTicks() - start_;
+    base::TimeDelta duration = base::TimeTicks::Now() - start_;
     if (allows_child_frame_content_) {
       DEFINE_STATIC_LOCAL(CustomCountHistogram, recursive_latency_histogram,
                           ("Event.Latency.HitTestRecursive", 0, 10000000, 100));
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
index fa5e9a5..2e844d2 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -752,6 +752,25 @@
   EXPECT_FALSE(next->GetLayoutObject()->NeedsCollectInlines());
 }
 
+TEST_F(NGInlineNodeTest, NeedsCollectInlinesOnInsertToOutOfFlowButton) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+    #xflex { display: flex; }
+    </style>
+    <div id="container">
+      <button id="flex" style="position: absolute"></button>
+    </div>
+  )HTML");
+
+  Element* container = GetElementById("container");
+  Element* parent = ElementTraversal::FirstChild(*container);
+  Element* child = GetDocument().CreateRawElement(html_names::kDivTag);
+  parent->appendChild(child);
+  GetDocument().UpdateStyleAndLayoutTree();
+
+  EXPECT_FALSE(container->GetLayoutObject()->NeedsCollectInlines());
+}
+
 class NodeRemoveTest : public NGInlineNodeTest,
                        public testing::WithParamInterface<const char*> {};
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
index 3cc8c83..986c3484 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -1358,18 +1358,24 @@
   const auto* empty2_fragment = iterator.NextChild(&offset);
   // 0, vertical margins got collapsed
   EXPECT_THAT(LayoutUnit(), offset.top);
-  // 35 = empty1's padding(20) + empty2's margin(15)
+  // 35 = empty1's padding(20) + empty2's padding(15)
   EXPECT_THAT(offset.left, LayoutUnit(35));
 
-  offset = empty2_fragment->Children()[0].offset;
-  // inline 25 = left float's margin(10) + empty2's padding(15).
-  // block 10 = left float's margin
-  EXPECT_THAT(offset, PhysicalOffset(25, 10));
+  const auto* linebox_fragment = empty2_fragment->Children()[0].fragment;
 
-  offset = empty2_fragment->Children()[1].offset;
-  // inline offset 140 = right float's margin(10) + right float offset(140)
+  offset =
+      To<NGPhysicalLineBoxFragment>(linebox_fragment)->Children()[0].offset;
+  // The floats are positioned outside the line-box as the line-box is
+  // "avoiding" these floats.
+  // inline -35 = inline-size of left-float (including margins).
+  // block 10 = left float's margin
+  EXPECT_THAT(offset, PhysicalOffset(-35, 10));
+
+  offset =
+      To<NGPhysicalLineBoxFragment>(linebox_fragment)->Children()[1].offset;
+  // inline offset 90 = right float's margin(10) + right float offset(80)
   // block offset 15 = right float's margin
-  LayoutUnit right_float_offset = LayoutUnit(140);
+  LayoutUnit right_float_offset = LayoutUnit(80);
   EXPECT_THAT(offset, PhysicalOffset(LayoutUnit(10) + right_float_offset,
                                      LayoutUnit(15)));
 
@@ -2269,7 +2275,10 @@
   EXPECT_EQ(PhysicalSize(150, 60), fragment->Size());
   ASSERT_TRUE(!fragment->BreakToken() || fragment->BreakToken()->IsFinished());
 
-  const auto* float2 = fragment->Children()[1].fragment;
+  const auto* linebox =
+      To<NGPhysicalBoxFragment>(fragment.get())->Children()[0].fragment;
+  const auto* float2 =
+      To<NGPhysicalLineBoxFragment>(linebox)->Children()[1].fragment;
 
   // float2 should only have one fragment.
   EXPECT_EQ(PhysicalSize(60, 200), float2->Size());
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
index 8190b80..c368ceb 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
@@ -112,7 +112,7 @@
   )HTML");
   NGBlockNode container(ToLayoutBox(GetLayoutObjectByElementId("container")));
   NGLayoutInputNode child1 = container.FirstChild();
-  EXPECT_TRUE(child1 && child1.IsBlock());
+  EXPECT_TRUE(child1 && child1.IsInline());
   NGLayoutInputNode child2 = child1.NextSibling();
   EXPECT_EQ(child2, nullptr);
 }
@@ -129,7 +129,7 @@
   )HTML");
   NGBlockNode container(ToLayoutBox(GetLayoutObjectByElementId("container")));
   NGLayoutInputNode child1 = container.FirstChild();
-  EXPECT_TRUE(child1 && child1.IsBlock());
+  EXPECT_TRUE(child1 && child1.IsInline());
   NGLayoutInputNode child2 = child1.NextSibling();
   EXPECT_EQ(child2, nullptr);
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
index c91c05b..877ec83 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -2937,6 +2937,7 @@
     offset:0,0 size:320x100
       offset:0,0 size:100x100
         offset:0,0 size:222x100
+          offset:0,0 size:0x0
           offset:0,0 size:111x50
       offset:110,0 size:100x100
         offset:0,0 size:222x100
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
index ab1718d..1eb6c26b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
@@ -262,8 +262,9 @@
   offset:unplaced size:1000x323
     offset:0,0 size:126x323
       offset:13,0 size:50x200
-        offset:0,0 size:25x200
-        offset:25,0 size:25x200
+        offset:50,0 size:0x0
+          offset:-50,0 size:25x200
+          offset:-25,0 size:25x200
       offset:3,200 size:120x120
         offset:10,10 size:100x100
 )DUMP";
diff --git a/third_party/blink/renderer/core/layout/scrollbars_test.cc b/third_party/blink/renderer/core/layout/scrollbars_test.cc
index 4409bb67..ce300815 100644
--- a/third_party/blink/renderer/core/layout/scrollbars_test.cc
+++ b/third_party/blink/renderer/core/layout/scrollbars_test.cc
@@ -49,7 +49,7 @@
     WebMouseEvent event(WebInputEvent::kMouseMove, WebFloatPoint(x, y),
                         WebFloatPoint(x, y),
                         WebPointerProperties::Button::kNoButton, 0,
-                        WebInputEvent::kNoModifiers, CurrentTimeTicks());
+                        WebInputEvent::kNoModifiers, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetEventHandler().HandleMouseMoveEvent(event, Vector<WebMouseEvent>(),
                                            Vector<WebMouseEvent>());
@@ -59,7 +59,7 @@
     WebMouseEvent event(
         WebInputEvent::kMouseDown, WebFloatPoint(x, y), WebFloatPoint(x, y),
         WebPointerProperties::Button::kLeft, 0,
-        WebInputEvent::Modifiers::kLeftButtonDown, CurrentTimeTicks());
+        WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetEventHandler().HandleMousePressEvent(event);
   }
@@ -68,7 +68,7 @@
     WebMouseEvent event(
         WebInputEvent::kMouseDown, WebFloatPoint(x, y), WebFloatPoint(x, y),
         WebPointerProperties::Button::kNoButton, 0,
-        WebInputEvent::Modifiers::kNoModifiers, CurrentTimeTicks());
+        WebInputEvent::Modifiers::kNoModifiers, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetEventHandler().SendContextMenuEvent(event);
   }
@@ -77,7 +77,7 @@
     WebMouseEvent event(
         WebInputEvent::kMouseUp, WebFloatPoint(x, y), WebFloatPoint(x, y),
         WebPointerProperties::Button::kLeft, 0,
-        WebInputEvent::Modifiers::kNoModifiers, CurrentTimeTicks());
+        WebInputEvent::Modifiers::kNoModifiers, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetEventHandler().HandleMouseReleaseEvent(event);
   }
@@ -86,7 +86,7 @@
     WebMouseEvent event(
         WebInputEvent::kMouseDown, WebFloatPoint(x, y), WebFloatPoint(x, y),
         WebPointerProperties::Button::kMiddle, 0,
-        WebInputEvent::Modifiers::kMiddleButtonDown, CurrentTimeTicks());
+        WebInputEvent::Modifiers::kMiddleButtonDown, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetEventHandler().HandleMousePressEvent(event);
   }
@@ -95,7 +95,7 @@
     WebMouseEvent event(
         WebInputEvent::kMouseUp, WebFloatPoint(x, y), WebFloatPoint(x, y),
         WebPointerProperties::Button::kMiddle, 0,
-        WebInputEvent::Modifiers::kMiddleButtonDown, CurrentTimeTicks());
+        WebInputEvent::Modifiers::kMiddleButtonDown, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetEventHandler().HandleMouseReleaseEvent(event);
   }
@@ -104,7 +104,7 @@
     WebMouseEvent event(
         WebInputEvent::kMouseMove, WebFloatPoint(1, 1), WebFloatPoint(1, 1),
         WebPointerProperties::Button::kLeft, 0,
-        WebInputEvent::Modifiers::kLeftButtonDown, CurrentTimeTicks());
+        WebInputEvent::Modifiers::kLeftButtonDown, base::TimeTicks::Now());
     event.SetFrameScale(1);
     GetEventHandler().HandleMouseLeaveEvent(event);
   }
@@ -142,8 +142,8 @@
                                               WebGestureDevice device,
                                               const IntPoint& position,
                                               ScrollOffset offset) {
-    WebGestureEvent event(type, WebInputEvent::kNoModifiers, CurrentTimeTicks(),
-                          device);
+    WebGestureEvent event(type, WebInputEvent::kNoModifiers,
+                          base::TimeTicks::Now(), device);
 
     event.SetPositionInWidget(WebFloatPoint(position.X(), position.Y()));
 
@@ -503,9 +503,9 @@
   ScrollableArea* scrollable_area =
       ToLayoutBox(scrollable->GetLayoutObject())->GetScrollableArea();
   DCHECK(scrollable_area->VerticalScrollbar());
-  WebGestureEvent scroll_begin(WebInputEvent::kGestureScrollBegin,
-                               WebInputEvent::kNoModifiers, CurrentTimeTicks(),
-                               WebGestureDevice::kTouchpad);
+  WebGestureEvent scroll_begin(
+      WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+      base::TimeTicks::Now(), WebGestureDevice::kTouchpad);
   scroll_begin.SetPositionInWidget(
       WebFloatPoint(scrollable->OffsetLeft() + scrollable->OffsetWidth() - 2,
                     scrollable->OffsetTop()));
@@ -2223,7 +2223,7 @@
   WebMouseEvent event(WebInputEvent::kMouseMove, WebFloatPoint(5, 5),
                       WebFloatPoint(5, 5), WebPointerProperties::Button::kLeft,
                       0, WebInputEvent::Modifiers::kLeftButtonDown,
-                      CurrentTimeTicks());
+                      base::TimeTicks::Now());
   event.SetFrameScale(1);
   GetEventHandler().HandleMouseLeaveEvent(event);
   EXPECT_EQ(scrollbar->PressedPart(), ScrollbarPart::kThumbPart);
diff --git a/third_party/blink/renderer/core/loader/document_load_timing_test.cc b/third_party/blink/renderer/core/loader/document_load_timing_test.cc
index 12ac1d7..f837f61 100644
--- a/third_party/blink/renderer/core/loader/document_load_timing_test.cc
+++ b/third_party/blink/renderer/core/loader/document_load_timing_test.cc
@@ -18,7 +18,8 @@
   DocumentLoadTiming timing(*(dummy_page->GetDocument().Loader()));
 
   double delta = -1000;
-  double embedder_navigation_start = CurrentTimeTicksInSeconds() + delta;
+  double embedder_navigation_start =
+      base::TimeTicks::Now().since_origin().InSecondsF() + delta;
   timing.SetNavigationStart(base::TimeTicks() + base::TimeDelta::FromSecondsD(
                                                     embedder_navigation_start));
 
@@ -34,7 +35,8 @@
   DocumentLoadTiming timing(*(dummy_page->GetDocument().Loader()));
 
   double navigation_start_delta = -456;
-  double current_monotonic_time = CurrentTimeTicksInSeconds();
+  double current_monotonic_time =
+      base::TimeTicks::Now().since_origin().InSecondsF();
   double embedder_navigation_start =
       current_monotonic_time + navigation_start_delta;
 
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index b409ff0c..7498f40 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1111,7 +1111,8 @@
 }
 
 void DocumentLoader::StartLoading() {
-  probe::LifecycleEvent(frame_, this, "init", CurrentTimeTicksInSeconds());
+  probe::LifecycleEvent(frame_, this, "init",
+                        base::TimeTicks::Now().since_origin().InSecondsF());
   StartLoadingInternal();
   params_ = nullptr;
 }
@@ -1274,7 +1275,7 @@
   if (loading_mhtml_archive_ || loading_url_as_empty_document_) {
     // Finish the load of an empty document if the URL was meant to load as an
     // empty document or the load of the MHTML archive failed.
-    FinishedLoading(CurrentTimeTicks());
+    FinishedLoading(base::TimeTicks::Now());
     return;
   }
 
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index cdfe8e7..7775189 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -320,7 +320,7 @@
 
 void FrameLoader::DidExplicitOpen() {
   probe::LifecycleEvent(frame_, GetDocumentLoader(), "init",
-                        CurrentTimeTicksInSeconds());
+                        base::TimeTicks::Now().since_origin().InSecondsF());
   // Calling document.open counts as committing the first real document load.
   if (!state_machine_.CommittedFirstRealDocumentLoad())
     state_machine_.AdvanceTo(FrameLoaderStateMachine::kCommittedFirstRealLoad);
diff --git a/third_party/blink/renderer/core/loader/interactive_detector.h b/third_party/blink/renderer/core/loader/interactive_detector.h
index 4b47fdf..ffe5ca4 100644
--- a/third_party/blink/renderer/core/loader/interactive_detector.h
+++ b/third_party/blink/renderer/core/loader/interactive_detector.h
@@ -67,9 +67,9 @@
   explicit InteractiveDetector(Document&, NetworkActivityChecker*);
   ~InteractiveDetector() override = default;
 
-  // Calls to CurrentTimeTicksInSeconds is expensive, so we try not to call it
-  // unless we really have to. If we already have the event time available, we
-  // pass it in as an argument.
+  // Calls to base::TimeTicks::Now().since_origin().InSecondsF() is expensive,
+  // so we try not to call it unless we really have to. If we already have the
+  // event time available, we pass it in as an argument.
   void OnResourceLoadBegin(base::Optional<base::TimeTicks> load_begin_time);
   void OnResourceLoadEnd(base::Optional<base::TimeTicks> load_finish_time);
 
@@ -189,7 +189,7 @@
   Vector<VisibilityChangeEvent> visibility_change_events_;
   bool initially_hidden_;
   // Returns true if page was ever backgrounded in the range
-  // [event_time, CurrentTimeTicks()].
+  // [event_time, base::TimeTicks::Now()].
   bool PageWasBackgroundedSinceEvent(base::TimeTicks event_time);
 
   // Finds a window of length kTimeToInteractiveWindowSeconds after lower_bound
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource.cc b/third_party/blink/renderer/core/loader/resource/image_resource.cc
index e7f549e..5674b55 100644
--- a/third_party/blink/renderer/core/loader/resource/image_resource.cc
+++ b/third_party/blink/renderer/core/loader/resource/image_resource.cc
@@ -351,7 +351,7 @@
     if (!is_pending_flushing_) {
       scoped_refptr<base::SingleThreadTaskRunner> task_runner =
           Loader()->GetLoadingTaskRunner();
-      base::TimeTicks now = CurrentTimeTicks();
+      base::TimeTicks now = base::TimeTicks::Now();
       if (last_flush_time_.is_null())
         last_flush_time_ = now;
 
@@ -371,7 +371,7 @@
   // We might have already loaded the image fully, in which case we don't need
   // to call |updateImage()|.
   if (IsLoading()) {
-    last_flush_time_ = CurrentTimeTicks();
+    last_flush_time_ = base::TimeTicks::Now();
     UpdateImage(Data(), ImageResourceContent::kUpdateImage, false);
   }
   is_pending_flushing_ = false;
@@ -394,7 +394,8 @@
     // Observers are notified via ImageResource::finish().
     // TODO(hiroshige): Do not call didFinishLoading() directly.
     Loader()->AbortResponseBodyLoading();
-    Loader()->DidFinishLoading(CurrentTimeTicks(), size, size, size, false, {});
+    Loader()->DidFinishLoading(base::TimeTicks::Now(), size, size, size, false,
+                               {});
   } else {
     auto result = GetContent()->UpdateImage(
         nullptr, GetStatus(),
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
index 82fd9ca..735e2b2 100644
--- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
+++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -264,7 +264,7 @@
   Document& document = frame_or_imported_document_->GetDocument();
   if (auto* interactive_detector = InteractiveDetector::From(document)) {
     // We have not yet recorded load_finish_time. Pass nullopt here; we will
-    // call CurrentTimeTicksInSeconds lazily when we need it.
+    // call base::TimeTicks::Now() lazily when we need it.
     interactive_detector->OnResourceLoadEnd(base::nullopt);
   }
   if (LocalFrame* frame = document.GetFrame()) {
diff --git a/third_party/blink/renderer/core/loader/threadable_loader.cc b/third_party/blink/renderer/core/loader/threadable_loader.cc
index 315de07f..71ff8f7f 100644
--- a/third_party/blink/renderer/core/loader/threadable_loader.cc
+++ b/third_party/blink/renderer/core/loader/threadable_loader.cc
@@ -269,7 +269,7 @@
     return;
   }
 
-  request_started_ = CurrentTimeTicks();
+  request_started_ = base::TimeTicks::Now();
 
   // Save any headers on the request here. If this request redirects
   // cross-origin, we cancel the old request create a new one, and copy these
@@ -500,7 +500,7 @@
   // was initially sent, however other uses of this method may need to
   // behave differently, in which case this should be re-arranged somehow.
   if (!timeout_.is_zero()) {
-    base::TimeDelta elapsed_time = CurrentTimeTicks() - request_started_;
+    base::TimeDelta elapsed_time = base::TimeTicks::Now() - request_started_;
     base::TimeDelta resolved_time =
         std::max(timeout_ - elapsed_time, base::TimeDelta());
     timeout_timer_.StartOneShot(resolved_time, FROM_HERE);
diff --git a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
index eda7b801d..475e73e 100644
--- a/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
+++ b/third_party/blink/renderer/core/offscreencanvas/offscreen_canvas.cc
@@ -34,7 +34,10 @@
 
 namespace blink {
 
-OffscreenCanvas::OffscreenCanvas(const IntSize& size) : size_(size) {
+OffscreenCanvas::OffscreenCanvas(const IntSize& size)
+    : CanvasRenderingContextHost(
+          CanvasRenderingContextHost::HostType::kOffscreenCanvasHost),
+      size_(size) {
   UpdateMemoryUsage();
 }
 
@@ -53,10 +56,9 @@
                              const SkIRect& damage_rect) {
   if (!HasPlaceholderCanvas() || !canvas_resource)
     return;
-  RecordCanvasSizeToUMA(
-      Size(), CanvasRenderingContextHost::HostType::kOffscreenCanvasHost);
+  RecordCanvasSizeToUMA(Size());
 
-  base::TimeTicks commit_start_time = WTF::CurrentTimeTicks();
+  base::TimeTicks commit_start_time = base::TimeTicks::Now();
   current_frame_damage_rect_.join(damage_rect);
   GetOrCreateResourceDispatcher()->DispatchFrameSync(
       std::move(canvas_resource), commit_start_time, current_frame_damage_rect_,
@@ -411,7 +413,7 @@
   current_frame_damage_rect_.join(damage_rect);
   if (current_frame_damage_rect_.isEmpty() || !canvas_resource)
     return;
-  const base::TimeTicks commit_start_time = WTF::CurrentTimeTicks();
+  const base::TimeTicks commit_start_time = base::TimeTicks::Now();
   GetOrCreateResourceDispatcher()->DispatchFrame(
       std::move(canvas_resource), commit_start_time, current_frame_damage_rect_,
       !RenderingContext()->IsOriginTopLeft() /* needs_vertical_flip */,
diff --git a/third_party/blink/renderer/core/page/autoscroll_controller.cc b/third_party/blink/renderer/core/page/autoscroll_controller.cc
index df7cdfe..efb54520 100644
--- a/third_party/blink/renderer/core/page/autoscroll_controller.cc
+++ b/third_party/blink/renderer/core/page/autoscroll_controller.cc
@@ -342,7 +342,7 @@
   switch (autoscroll_type_) {
     case kAutoscrollForDragAndDrop:
       ScheduleMainThreadAnimation();
-      if ((CurrentTimeTicks() - drag_and_drop_autoscroll_start_time_) >
+      if ((base::TimeTicks::Now() - drag_and_drop_autoscroll_start_time_) >
           kAutoscrollDelay)
         autoscroll_layout_object_->Autoscroll(
             drag_and_drop_autoscroll_reference_position_);
diff --git a/third_party/blink/renderer/core/page/autoscroll_controller_test.cc b/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
index f73bdc2..bf08c82 100644
--- a/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
+++ b/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
@@ -59,7 +59,7 @@
   WebMouseEvent event(WebInputEvent::kMouseDown, WebFloatPoint(5, 5),
                       WebFloatPoint(5, 5), WebPointerProperties::Button::kLeft,
                       0, WebInputEvent::Modifiers::kLeftButtonDown,
-                      CurrentTimeTicks());
+                      base::TimeTicks::Now());
   event.SetFrameScale(1);
 
   GetDocument().GetFrame()->GetEventHandler().HandleMousePressEvent(event);
@@ -92,7 +92,7 @@
 
   WebMouseEvent mouse_leave_event(WebInputEvent::kMouseLeave,
                                   WebInputEvent::kNoModifiers,
-                                  CurrentTimeTicks());
+                                  base::TimeTicks::Now());
   mouse_leave_event.SetFrameScale(1);
 
   frame->GetEventHandler().HandleMouseLeaveEvent(mouse_leave_event);
diff --git a/third_party/blink/renderer/core/page/drag_controller.cc b/third_party/blink/renderer/core/page/drag_controller.cc
index e8d5d0d..df4db49 100644
--- a/third_party/blink/renderer/core/page/drag_controller.cc
+++ b/third_party/blink/renderer/core/page/drag_controller.cc
@@ -128,7 +128,7 @@
       WebInputEvent::kMouseMove, drag_data->ClientPosition(),
       drag_data->GlobalPosition(), WebPointerProperties::Button::kLeft, 0,
       static_cast<WebInputEvent::Modifiers>(drag_data->GetModifiers()),
-      CurrentTimeTicks());
+      base::TimeTicks::Now());
   // TODO(dtapuska): Really we should chnage DragData to store the viewport
   // coordinates and scale.
   result.SetFrameScale(1);
diff --git a/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc b/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc
index 8d49e807..8cd487ec 100644
--- a/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/scroll_metrics_test.cc
@@ -60,7 +60,7 @@
                           WebGestureDevice device)
       : WebGestureEvent(WebInputEvent::kGestureScrollBegin,
                         WebInputEvent::kNoModifiers,
-                        CurrentTimeTicks(),
+                        base::TimeTicks::Now(),
                         device) {
     SetPositionInWidget(position);
     SetPositionInScreen(position);
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
index 908b16b..a9f439bd 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.cc
@@ -15,7 +15,7 @@
 
 void TextFragmentAnchorMetrics::DidCreateAnchor(int selector_count) {
   UseCounter::Count(document_, WebFeature::kTextFragmentAnchor);
-  create_time_ = WTF::CurrentTimeTicks();
+  create_time_ = base::TimeTicks::Now();
   selector_count_ = selector_count;
 }
 
@@ -37,7 +37,7 @@
 
 void TextFragmentAnchorMetrics::DidScroll() {
   if (first_scroll_into_view_time_.is_null())
-    first_scroll_into_view_time_ = WTF::CurrentTimeTicks();
+    first_scroll_into_view_time_ = base::TimeTicks::Now();
 }
 
 void TextFragmentAnchorMetrics::DidNonZeroScroll() {
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
index c21c4ac..9352019f 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation_controller.cc
@@ -475,7 +475,7 @@
   WebMouseEvent fake_mouse_move_event(
       WebInputEvent::kMouseMove, event_position, event_position_screen,
       WebPointerProperties::Button::kNoButton, click_count,
-      WebInputEvent::kRelativeMotionEvent, CurrentTimeTicks());
+      WebInputEvent::kRelativeMotionEvent, base::TimeTicks::Now());
   Vector<WebMouseEvent> coalesced_events, predicted_events;
 
   DCHECK(IsA<LocalFrame>(page_->MainFrame()));
diff --git a/third_party/blink/renderer/core/page/validation_message_client_impl.cc b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
index fa294261..7ab6b3b 100644
--- a/third_party/blink/renderer/core/page/validation_message_client_impl.cc
+++ b/third_party/blink/renderer/core/page/validation_message_client_impl.cc
@@ -72,7 +72,7 @@
       base::TimeDelta::FromSeconds(5);
   constexpr auto kTimePerCharacter = base::TimeDelta::FromMilliseconds(50);
   finish_time_ =
-      CurrentTimeTicks() +
+      base::TimeTicks::Now() +
       std::max(kMinimumTimeToShowValidationMessage,
                (message.length() + sub_message.length()) * kTimePerCharacter);
 
@@ -164,7 +164,7 @@
 void ValidationMessageClientImpl::CheckAnchorStatus(TimerBase*) {
   DCHECK(current_anchor_);
   if ((!WebTestSupport::IsRunningWebTest() &&
-       CurrentTimeTicks() >= finish_time_) ||
+       base::TimeTicks::Now() >= finish_time_) ||
       !CurrentView()) {
     HideValidationMessage(*current_anchor_);
     return;
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn
index af7fb5f8..d187252 100644
--- a/third_party/blink/renderer/core/paint/BUILD.gn
+++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -69,6 +69,8 @@
     "details_marker_painter.h",
     "document_marker_painter.cc",
     "document_marker_painter.h",
+    "element_timing_utils.cc",
+    "element_timing_utils.h",
     "ellipsis_box_painter.cc",
     "ellipsis_box_painter.h",
     "embedded_content_painter.cc",
diff --git a/third_party/blink/renderer/core/paint/element_timing_utils.cc b/third_party/blink/renderer/core/paint/element_timing_utils.cc
new file mode 100644
index 0000000..71d29db
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/element_timing_utils.cc
@@ -0,0 +1,39 @@
+// 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 "third_party/blink/renderer/core/paint/element_timing_utils.h"
+
+#include "third_party/blink/public/platform/web_float_rect.h"
+#include "third_party/blink/public/web/web_widget_client.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
+#include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
+#include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
+
+namespace blink {
+
+// static
+FloatRect ElementTimingUtils::ComputeIntersectionRect(
+    LocalFrame* frame,
+    const IntRect& int_visual_rect,
+    const PropertyTreeState& current_paint_chunk_properties) {
+  // Compute the visible part of the image rect.
+  FloatClipRect visual_rect = FloatClipRect(FloatRect(int_visual_rect));
+  GeometryMapper::LocalToAncestorVisualRect(current_paint_chunk_properties,
+                                            frame->View()
+                                                ->GetLayoutView()
+                                                ->FirstFragment()
+                                                .LocalBorderBoxProperties(),
+                                            visual_rect);
+  WebFloatRect intersection_rect = visual_rect.Rect();
+  WebFrameWidgetBase* widget =
+      WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
+  DCHECK(widget);
+  widget->Client()->ConvertViewportToWindow(&intersection_rect);
+  return intersection_rect;
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/element_timing_utils.h b/third_party/blink/renderer/core/paint/element_timing_utils.h
new file mode 100644
index 0000000..c959eae
--- /dev/null
+++ b/third_party/blink/renderer/core/paint/element_timing_utils.h
@@ -0,0 +1,29 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ELEMENT_TIMING_UTILS_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ELEMENT_TIMING_UTILS_H_
+
+#include "third_party/blink/renderer/platform/geometry/float_rect.h"
+
+namespace blink {
+
+class IntRect;
+class LocalFrame;
+class PropertyTreeState;
+
+// Class containing methods shared between ImageElementTiming and
+// TextElementTiming.
+class ElementTimingUtils {
+ public:
+  // Computes the part a rect in a local transform space that is visible in the
+  // specified frame, and returns a result in DIPs.
+  static FloatRect ComputeIntersectionRect(LocalFrame*,
+                                           const IntRect&,
+                                           const PropertyTreeState&);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_ELEMENT_TIMING_UTILS_H_
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.cc b/third_party/blink/renderer/core/paint/image_element_timing.cc
index d580430..3b0650d 100644
--- a/third_party/blink/renderer/core/paint/image_element_timing.cc
+++ b/third_party/blink/renderer/core/paint/image_element_timing.cc
@@ -9,11 +9,11 @@
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
+#include "third_party/blink/renderer/core/paint/element_timing_utils.h"
 #include "third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h"
 #include "third_party/blink/renderer/core/style/style_image.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/window_performance.h"
-#include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h"
 #include "third_party/blink/renderer/platform/graphics/paint/property_tree_state.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
@@ -112,8 +112,9 @@
   if (!layout_object.HasNonZeroEffectiveOpacity())
     return;
 
-  FloatRect intersection_rect = ComputeIntersectionRect(
-      frame, layout_object, current_paint_chunk_properties);
+  FloatRect intersection_rect = ElementTimingUtils::ComputeIntersectionRect(
+      frame, layout_object.FirstFragment().VisualRect(),
+      current_paint_chunk_properties);
   const AtomicString attr =
       element->FastGetAttribute(html_names::kElementtimingAttr);
 
@@ -189,23 +190,6 @@
   }
 }
 
-FloatRect ImageElementTiming::ComputeIntersectionRect(
-    const LocalFrame* frame,
-    const LayoutObject& layout_object,
-    const PropertyTreeState& current_paint_chunk_properties) {
-  // Compute the visible part of the image rect.
-  IntRect image_visual_rect = layout_object.FirstFragment().VisualRect();
-
-  FloatClipRect visual_rect = FloatClipRect(FloatRect(image_visual_rect));
-  GeometryMapper::LocalToAncestorVisualRect(current_paint_chunk_properties,
-                                            frame->View()
-                                                ->GetLayoutView()
-                                                ->FirstFragment()
-                                                .LocalBorderBoxProperties(),
-                                            visual_rect);
-  return visual_rect.Rect();
-}
-
 void ImageElementTiming::ReportImagePaintSwapTime(WebWidgetClient::SwapResult,
                                                   base::TimeTicks timestamp) {
   WindowPerformance* performance =
diff --git a/third_party/blink/renderer/core/paint/image_element_timing.h b/third_party/blink/renderer/core/paint/image_element_timing.h
index 04de9035..468d4ef 100644
--- a/third_party/blink/renderer/core/paint/image_element_timing.h
+++ b/third_party/blink/renderer/core/paint/image_element_timing.h
@@ -70,11 +70,6 @@
       const ImageResourceContent& cached_image,
       const PropertyTreeState& current_paint_chunk_properties);
 
-  // Computes the intersection rect.
-  FloatRect ComputeIntersectionRect(const LocalFrame*,
-                                    const LayoutObject&,
-                                    const PropertyTreeState&);
-
   // Callback for the swap promise. Reports paint timestamps.
   void ReportImagePaintSwapTime(WebWidgetClient::SwapResult,
                                 base::TimeTicks timestamp);
diff --git a/third_party/blink/renderer/core/paint/image_element_timing_test.cc b/third_party/blink/renderer/core/paint/image_element_timing_test.cc
index 3cc3813..d658088 100644
--- a/third_party/blink/renderer/core/paint/image_element_timing_test.cc
+++ b/third_party/blink/renderer/core/paint/image_element_timing_test.cc
@@ -4,11 +4,13 @@
 
 #include "third_party/blink/renderer/core/paint/image_element_timing.h"
 
+#include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
+#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/layout/layout_image.h"
 #include "third_party/blink/renderer/core/layout/svg/layout_svg_image.h"
 #include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
-#include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 #include "third_party/blink/renderer/platform/graphics/static_bitmap_image.h"
+#include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
@@ -20,13 +22,27 @@
 
 }
 
-class ImageElementTimingTest : public RenderingTest {
+class ImageElementTimingTest : public testing::Test {
  protected:
+  void SetUp() override {
+    web_view_helper_.Initialize();
+    frame_test_helpers::LoadFrame(
+        web_view_helper_.GetWebView()->MainFrameImpl(), "about:blank");
+    WebURL base_url_ = url_test_helpers::ToKURL("http://www.test.com/");
+    // Enable compositing on the page.
+    web_view_helper_.GetWebView()
+        ->GetPage()
+        ->GetSettings()
+        .SetAcceleratedCompositingEnabled(true);
+    GetDoc()->View()->SetParentVisible(true);
+    GetDoc()->View()->SetSelfVisible(true);
+  }
+
   // Sets an image resource for the LayoutImage with the given |id| and return
   // the LayoutImage.
   LayoutImage* SetImageResource(const char* id, int width, int height) {
     ImageResourceContent* content = CreateImageForTest(width, height);
-    auto* layout_image = ToLayoutImage(GetLayoutObjectByElementId(id));
+    auto* layout_image = ToLayoutImage(GetLayoutObjectById(id));
     layout_image->ImageResource()->SetImageResource(content);
     return layout_image;
   }
@@ -34,23 +50,45 @@
   // Similar to above but for a LayoutSVGImage.
   LayoutSVGImage* SetSVGImageResource(const char* id, int width, int height) {
     ImageResourceContent* content = CreateImageForTest(width, height);
-    auto* layout_image = ToLayoutSVGImage(GetLayoutObjectByElementId(id));
+    auto* layout_image = ToLayoutSVGImage(GetLayoutObjectById(id));
     layout_image->ImageResource()->SetImageResource(content);
     return layout_image;
   }
 
   const WTF::HashSet<const LayoutObject*>& GetImagesNotified() {
-    return ImageElementTiming::From(*GetDocument().domWindow())
-        .images_notified_;
+    return ImageElementTiming::From(*GetDoc()->domWindow()).images_notified_;
+  }
+
+  Document* GetDoc() {
+    return web_view_helper_.GetWebView()
+        ->MainFrameImpl()
+        ->GetFrame()
+        ->GetDocument();
+  }
+
+  LayoutObject* GetLayoutObjectById(const char* id) {
+    return GetDoc()->getElementById(id)->GetLayoutObject();
   }
 
   const WTF::HashSet<
       std::pair<const LayoutObject*, const ImageResourceContent*>>&
   GetBackgroundImagesNotified() {
-    return ImageElementTiming::From(*GetDocument().domWindow())
+    return ImageElementTiming::From(*GetDoc()->domWindow())
         .background_images_notified_;
   }
 
+  void UpdateAllLifecyclePhases() {
+    web_view_helper_.GetWebView()
+        ->MainFrameImpl()
+        ->GetFrame()
+        ->View()
+        ->UpdateAllLifecyclePhases(
+            DocumentLifecycle::LifecycleUpdateReason::kTest);
+  }
+
+  frame_test_helpers::WebViewHelper web_view_helper_;
+  WebURL base_url_;
+
  private:
   ImageResourceContent* CreateImageForTest(int width, int height) {
     sk_sp<SkColorSpace> src_rgb_color_space = SkColorSpace::MakeSRGB();
@@ -66,35 +104,33 @@
 };
 
 TEST_F(ImageElementTimingTest, TestIsExplicitlyRegisteredForTiming) {
-  EnableCompositing();
-  GetDocument().SetBaseURLOverride(KURL("http://test.com"));
-  SetBodyInnerHTML(R"HTML(
+  frame_test_helpers::LoadHTMLString(
+      web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
     <img id="missing-attribute" style='width: 100px; height: 100px;'/>
     <img id="unset-attribute" elementtiming style='width: 100px; height: 100px;'/>
     <img id="empty-attribute" elementtiming="" style='width: 100px; height: 100px;'/>
     <img id="valid-attribute" elementtiming="valid-id" style='width: 100px; height: 100px;'/>
-  )HTML");
+  )HTML",
+      base_url_);
 
-  LayoutObject* without_attribute =
-      GetLayoutObjectByElementId("missing-attribute");
+  LayoutObject* without_attribute = GetLayoutObjectById("missing-attribute");
   bool actual = internal::IsExplicitlyRegisteredForTiming(without_attribute);
   EXPECT_FALSE(actual) << "Nodes without an 'elementtiming' attribute should "
                           "not be explicitly registered.";
 
   LayoutObject* with_undefined_attribute =
-      GetLayoutObjectByElementId("unset-attribute");
+      GetLayoutObjectById("unset-attribute");
   actual = internal::IsExplicitlyRegisteredForTiming(with_undefined_attribute);
   EXPECT_FALSE(actual) << "Nodes with undefined 'elementtiming' attribute "
                           "should not be explicitly registered.";
 
-  LayoutObject* with_empty_attribute =
-      GetLayoutObjectByElementId("empty-attribute");
+  LayoutObject* with_empty_attribute = GetLayoutObjectById("empty-attribute");
   actual = internal::IsExplicitlyRegisteredForTiming(with_empty_attribute);
   EXPECT_FALSE(actual) << "Nodes with an empty 'elementtiming' attribute "
                           "should not be explicitly registered.";
 
   LayoutObject* with_explicit_element_timing =
-      GetLayoutObjectByElementId("valid-attribute");
+      GetLayoutObjectById("valid-attribute");
   actual =
       internal::IsExplicitlyRegisteredForTiming(with_explicit_element_timing);
   EXPECT_TRUE(actual) << "Nodes with a non-empty 'elementtiming' attribute "
@@ -104,20 +140,20 @@
 TEST_F(ImageElementTimingTest, IgnoresUnmarkedElement) {
   // Tests that, if the 'elementtiming' attribute is missing, the element isn't
   // considered by ImageElementTiming.
-  EnableCompositing();
-  GetDocument().SetBaseURLOverride(KURL("http://test.com"));
-  SetBodyInnerHTML(R"HTML(
+  frame_test_helpers::LoadHTMLString(
+      web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
     <img id="target" style='width: 100px; height: 100px;'/>
-  )HTML");
+  )HTML",
+      base_url_);
   LayoutImage* layout_image = SetImageResource("target", 5, 5);
   ASSERT_TRUE(layout_image);
-  UpdateAllLifecyclePhasesForTest();
+  UpdateAllLifecyclePhases();
   EXPECT_FALSE(GetImagesNotified().Contains(layout_image));
 }
 
 TEST_F(ImageElementTimingTest, ImageInsideSVG) {
-  GetDocument().SetBaseURLOverride(KURL("http://test.com"));
-  SetBodyInnerHTML(R"HTML(
+  frame_test_helpers::LoadHTMLString(
+      web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
     <svg mask="url(#mask)">
       <mask id="mask">
         <foreignObject width="100" height="100">
@@ -126,72 +162,74 @@
       </mask>
       <rect width="100" height="100" fill="green"/>
     </svg>
-  )HTML");
+  )HTML",
+      base_url_);
   LayoutImage* layout_image = SetImageResource("target", 5, 5);
   ASSERT_TRUE(layout_image);
-  // Enable compositing and also update document lifecycle.
-  EnableCompositing();
+  UpdateAllLifecyclePhases();
 
   // |layout_image| should have had its paint notified to ImageElementTiming.
   EXPECT_TRUE(GetImagesNotified().Contains(layout_image));
 }
 
 TEST_F(ImageElementTimingTest, ImageRemoved) {
-  EnableCompositing();
-  GetDocument().SetBaseURLOverride(KURL("http://test.com"));
-  SetBodyInnerHTML(R"HTML(
+  frame_test_helpers::LoadHTMLString(
+      web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
     <img elementtiming="will-be-removed" id="target" style='width: 100px; height: 100px;'/>
-  )HTML");
+  )HTML",
+      base_url_);
   LayoutImage* layout_image = SetImageResource("target", 5, 5);
   ASSERT_TRUE(layout_image);
-  UpdateAllLifecyclePhasesForTest();
+  UpdateAllLifecyclePhases();
   EXPECT_TRUE(GetImagesNotified().Contains(layout_image));
 
-  GetDocument().getElementById("target")->remove();
+  GetDoc()->getElementById("target")->remove();
   // |layout_image| should no longer be part of |images_notified| since it will
   // be destroyed.
   EXPECT_TRUE(GetImagesNotified().IsEmpty());
 }
 
 TEST_F(ImageElementTimingTest, SVGImageRemoved) {
-  EnableCompositing();
-  GetDocument().SetBaseURLOverride(KURL("http://test.com"));
-  SetBodyInnerHTML(R"HTML(
+  frame_test_helpers::LoadHTMLString(
+      web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
     <svg>
       <image elementtiming="svg-will-be-removed" id="target" style='width: 100px; height: 100px;'/>
     </svg>
-  )HTML");
+  )HTML",
+      base_url_);
   LayoutSVGImage* layout_image = SetSVGImageResource("target", 5, 5);
   ASSERT_TRUE(layout_image);
-  UpdateAllLifecyclePhasesForTest();
+  UpdateAllLifecyclePhases();
   EXPECT_TRUE(GetImagesNotified().Contains(layout_image));
 
-  GetDocument().getElementById("target")->remove();
+  GetDoc()->getElementById("target")->remove();
   // |layout_image| should no longer be part of |images_notified| since it will
   // be destroyed.
   EXPECT_TRUE(GetImagesNotified().IsEmpty());
 }
 
 TEST_F(ImageElementTimingTest, BackgroundImageRemoved) {
-  EnableCompositing();
-  GetDocument().SetBaseURLOverride(KURL("http://test.com"));
-  SetBodyInnerHTML(R"HTML(
+  frame_test_helpers::LoadHTMLString(
+      web_view_helper_.GetWebView()->MainFrameImpl(), R"HTML(
     <style>
       #target {
+        width: 100px;
+        height: 100px;
         background: url(data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==);
       }
     </style>
-    <div elementtiming="time-my-background-image" id="target">/div>
-  )HTML");
-  LayoutObject* object = GetLayoutObjectByElementId("target");
+    <div elementtiming="time-my-background-image" id="target"></div>
+  )HTML",
+      base_url_);
+  LayoutObject* object = GetLayoutObjectById("target");
   ImageResourceContent* content =
       object->Style()->BackgroundLayers().GetImage()->CachedImage();
-  UpdateAllLifecyclePhasesForTest();
+  UpdateAllLifecyclePhases();
   EXPECT_EQ(GetBackgroundImagesNotified().size(), 1u);
   EXPECT_TRUE(
       GetBackgroundImagesNotified().Contains(std::make_pair(object, content)));
 
-  GetDocument().getElementById("target")->remove();
+  GetDoc()->getElementById("target")->remove();
   EXPECT_TRUE(GetBackgroundImagesNotified().IsEmpty());
 }
 
diff --git a/third_party/blink/renderer/core/paint/link_highlight_impl.cc b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
index 406da55..2fd5f1c5 100644
--- a/third_party/blink/renderer/core/paint/link_highlight_impl.cc
+++ b/third_party/blink/renderer/core/paint/link_highlight_impl.cc
@@ -105,7 +105,7 @@
       offset_from_transform_node_(FloatPoint()),
       geometry_needs_update_(false),
       is_animating_(false),
-      start_time_(CurrentTimeTicks()),
+      start_time_(base::TimeTicks::Now()),
       element_id_(NewElementId()) {
   DCHECK(node_);
   fragments_.emplace_back();
@@ -374,7 +374,7 @@
   // to fade out.
   base::TimeDelta extra_duration_required =
       std::max(base::TimeDelta(),
-               kMinPreFadeDuration - (CurrentTimeTicks() - start_time_));
+               kMinPreFadeDuration - (base::TimeTicks::Now() - start_time_));
   if (!extra_duration_required.is_zero()) {
     curve->AddKeyframe(CompositorFloatKeyframe(
         extra_duration_required.InSecondsF(), kStartOpacity, timing_function));
diff --git a/third_party/blink/renderer/core/paint/text_element_timing.cc b/third_party/blink/renderer/core/paint/text_element_timing.cc
index d61c176..53caeae3 100644
--- a/third_party/blink/renderer/core/paint/text_element_timing.cc
+++ b/third_party/blink/renderer/core/paint/text_element_timing.cc
@@ -7,6 +7,8 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/paint/element_timing_utils.h"
+#include "third_party/blink/renderer/core/paint/image_element_timing.h"
 #include "third_party/blink/renderer/core/paint/text_paint_timing_detector.h"
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/platform/geometry/int_rect.h"
@@ -48,13 +50,8 @@
   if (!NeededForElementTiming(*node))
     return FloatRect();
 
-  FloatClipRect float_clip_visual_rect =
-      FloatClipRect(FloatRect(aggregated_visual_rect));
-  GeometryMapper::LocalToAncestorVisualRect(
-      property_tree_state,
-      frame_view->GetLayoutView()->FirstFragment().LocalBorderBoxProperties(),
-      float_clip_visual_rect);
-  return float_clip_visual_rect.Rect();
+  return ElementTimingUtils::ComputeIntersectionRect(
+      &frame_view->GetFrame(), aggregated_visual_rect, property_tree_state);
 }
 
 void TextElementTiming::OnTextObjectsPainted(
diff --git a/third_party/blink/renderer/core/probe/core_probes.cc b/third_party/blink/renderer/core/probe/core_probes.cc
index 25cf12f..59539512 100644
--- a/third_party/blink/renderer/core/probe/core_probes.cc
+++ b/third_party/blink/renderer/core/probe/core_probes.cc
@@ -49,13 +49,13 @@
 
 base::TimeTicks ProbeBase::CaptureStartTime() const {
   if (start_time_.is_null())
-    start_time_ = CurrentTimeTicks();
+    start_time_ = base::TimeTicks::Now();
   return start_time_;
 }
 
 base::TimeTicks ProbeBase::CaptureEndTime() const {
   if (end_time_.is_null())
-    end_time_ = CurrentTimeTicks();
+    end_time_ = base::TimeTicks::Now();
   return end_time_;
 }
 
diff --git a/third_party/blink/renderer/core/script/pending_script.cc b/third_party/blink/renderer/core/script/pending_script.cc
index 1ed28b36..b8fe2d8a 100644
--- a/third_party/blink/renderer/core/script/pending_script.cc
+++ b/third_party/blink/renderer/core/script/pending_script.cc
@@ -122,7 +122,7 @@
 
 void PendingScript::MarkParserBlockingLoadStartTime() {
   DCHECK(parser_blocking_load_start_time_.is_null());
-  parser_blocking_load_start_time_ = CurrentTimeTicks();
+  parser_blocking_load_start_time_ = base::TimeTicks::Now();
 }
 
 // <specdef href="https://html.spec.whatwg.org/C/#execute-the-script-block">
@@ -207,14 +207,14 @@
   if (parser_blocking_load_start_time > base::TimeTicks()) {
     DocumentParserTiming::From(element_document)
         .RecordParserBlockedOnScriptLoadDuration(
-            CurrentTimeTicks() - parser_blocking_load_start_time,
+            base::TimeTicks::Now() - parser_blocking_load_start_time,
             created_during_document_write);
   }
 
   if (was_canceled)
     return;
 
-  base::TimeTicks script_exec_start_time = CurrentTimeTicks();
+  base::TimeTicks script_exec_start_time = base::TimeTicks::Now();
 
   {
     if (element->ElementHasDuplicateAttributes()) {
@@ -292,7 +292,7 @@
   if (!is_controlled_by_script_runner) {
     DocumentParserTiming::From(element_document)
         .RecordParserBlockedOnScriptExecutionDuration(
-            CurrentTimeTicks() - script_exec_start_time,
+            base::TimeTicks::Now() - script_exec_start_time,
             created_during_document_write);
   }
 
diff --git a/third_party/blink/renderer/core/scroll/scroll_animator.cc b/third_party/blink/renderer/core/scroll/scroll_animator.cc
index 053cd8d9..c0b959b 100644
--- a/third_party/blink/renderer/core/scroll/scroll_animator.cc
+++ b/third_party/blink/renderer/core/scroll/scroll_animator.cc
@@ -55,8 +55,11 @@
 
 ScrollAnimatorBase* ScrollAnimatorBase::Create(
     ScrollableArea* scrollable_area) {
-  if (scrollable_area && scrollable_area->ScrollAnimatorEnabled())
-    return MakeGarbageCollected<ScrollAnimator>(scrollable_area);
+  if (scrollable_area && scrollable_area->ScrollAnimatorEnabled()) {
+    return MakeGarbageCollected<ScrollAnimator>(scrollable_area, [] {
+      return base::TimeTicks::Now().since_origin().InSecondsF();
+    });
+  }
   return MakeGarbageCollected<ScrollAnimatorBase>(scrollable_area);
 }
 
diff --git a/third_party/blink/renderer/core/scroll/scroll_animator.h b/third_party/blink/renderer/core/scroll/scroll_animator.h
index 269affe9..b94f9a9 100644
--- a/third_party/blink/renderer/core/scroll/scroll_animator.h
+++ b/third_party/blink/renderer/core/scroll/scroll_animator.h
@@ -100,8 +100,7 @@
 class CORE_EXPORT ScrollAnimator : public ScrollAnimatorBase {
  public:
   using TimeFunction = double (*)();
-  explicit ScrollAnimator(ScrollableArea*,
-                          TimeFunction = WTF::CurrentTimeTicksInSeconds);
+  ScrollAnimator(ScrollableArea*, TimeFunction);
   ~ScrollAnimator() override;
 
   bool HasRunningAnimation() const override;
diff --git a/third_party/blink/renderer/core/svg/animation/smil_time_container.cc b/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
index 097b331..99d2858 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
+++ b/third_party/blink/renderer/core/svg/animation/smil_time_container.cc
@@ -99,11 +99,9 @@
   DCHECK(!prevent_scheduled_animations_changes_);
 #endif
 
-  auto& attribute_map =
-      scheduled_animations_.insert(target, AttributeMap()).stored_value->value;
-
+  auto key = std::make_pair(target, attribute_name);
   auto& scheduled =
-      attribute_map.insert(attribute_name, nullptr).stored_value->value;
+      scheduled_animations_.insert(key, nullptr).stored_value->value;
   if (!scheduled)
     scheduled = MakeGarbageCollected<ScheduledVector>();
 
@@ -124,20 +122,16 @@
   DCHECK(!prevent_scheduled_animations_changes_);
 #endif
 
-  AnimationsMap::iterator it = scheduled_animations_.find(target);
+  auto key = std::make_pair(target, attribute_name);
+  AnimationsMap::iterator it = scheduled_animations_.find(key);
   CHECK(it != scheduled_animations_.end());
-  AttributeMap& attribute_map = it->value;
-  AttributeMap::iterator attribute_map_it = attribute_map.find(attribute_name);
-  DCHECK(attribute_map_it != attribute_map.end());
-  auto& scheduled = *(attribute_map_it->value);
+  auto& scheduled = *(it->value);
 
   auto* position = std::find(scheduled.begin(), scheduled.end(), animation);
   DCHECK(scheduled.end() != position);
   scheduled.erase(position);
 
   if (scheduled.IsEmpty())
-    attribute_map.erase(attribute_map_it);
-  if (attribute_map.IsEmpty())
     scheduled_animations_.erase(it);
 }
 
@@ -256,11 +250,9 @@
 #if DCHECK_IS_ON()
   prevent_scheduled_animations_changes_ = true;
 #endif
-  for (const auto& attribute_entry : scheduled_animations_) {
-    for (const auto& entry : attribute_entry.value) {
-      for (SVGSMILElement* element : *entry.value) {
-        element->Reset();
-      }
+  for (const auto& entry : scheduled_animations_) {
+    for (SVGSMILElement* element : *entry.value) {
+      element->Reset();
     }
   }
 #if DCHECK_IS_ON()
@@ -436,37 +428,34 @@
   if (document_order_indexes_dirty_)
     UpdateDocumentOrderIndexes();
 
-  for (auto& attribute_entry : scheduled_animations_) {
-    AttributeMap& attribute_map = attribute_entry.value;
-    Vector<QualifiedName> invalid_keys;
-    for (auto& entry : attribute_map) {
-      if (entry.value->IsEmpty())
+  {
+    Vector<AnimationId> invalid_keys;
+    for (auto& entry : scheduled_animations_) {
+      if (entry.value->IsEmpty()) {
         invalid_keys.push_back(entry.key);
+      }
     }
-    attribute_map.RemoveAll(invalid_keys);
+    scheduled_animations_.RemoveAll(invalid_keys);
   }
 
   active_sandwiches_.ReserveCapacity(scheduled_animations_.size());
   SMILTime earliest_fire_time = SMILTime::Unresolved();
-  for (auto& attribute_entry : scheduled_animations_) {
-    AttributeMap& attribute_map = attribute_entry.value;
-    for (auto& entry : attribute_map) {
-      auto& scheduled = *entry.value;
-      if (!std::is_sorted(scheduled.begin(), scheduled.end(),
-                          PriorityCompare(elapsed))) {
-        // TODO: Replace this with inline insertion sort.
-        std::sort(scheduled.begin(), scheduled.end(), PriorityCompare(elapsed));
-      }
-      auto* sandwich = MakeGarbageCollected<SMILAnimationSandwich>(
-          scheduled, elapsed, seek_to_time);
+  for (auto& entry : scheduled_animations_) {
+    auto& scheduled = *entry.value;
+    if (!std::is_sorted(scheduled.begin(), scheduled.end(),
+                        PriorityCompare(elapsed))) {
+      // TODO: Replace this with inline insertion sort.
+      std::sort(scheduled.begin(), scheduled.end(), PriorityCompare(elapsed));
+    }
+    auto* sandwich = MakeGarbageCollected<SMILAnimationSandwich>(
+        scheduled, elapsed, seek_to_time);
 
-      SMILTime next_fire_time = sandwich->GetNextFireTime();
-      if (next_fire_time.IsFinite())
-        earliest_fire_time = std::min(next_fire_time, earliest_fire_time);
+    SMILTime next_fire_time = sandwich->GetNextFireTime();
+    if (next_fire_time.IsFinite())
+      earliest_fire_time = std::min(next_fire_time, earliest_fire_time);
 
-      if (!sandwich->IsEmpty()) {
-        active_sandwiches_.push_back(sandwich);
-      }
+    if (!sandwich->IsEmpty()) {
+      active_sandwiches_.push_back(sandwich);
     }
   }
 
diff --git a/third_party/blink/renderer/core/svg/animation/smil_time_container.h b/third_party/blink/renderer/core/svg/animation/smil_time_container.h
index e3b2ddb5..775e4da 100644
--- a/third_party/blink/renderer/core/svg/animation/smil_time_container.h
+++ b/third_party/blink/renderer/core/svg/animation/smil_time_container.h
@@ -47,8 +47,8 @@
  public:
   // Sorted list
   using ScheduledVector = SMILAnimationSandwich::ScheduledVector;
-  using AttributeMap = HeapHashMap<QualifiedName, Member<ScheduledVector>>;
-  using AnimationsMap = HeapHashMap<WeakMember<SVGElement>, AttributeMap>;
+  using AnimationId = std::pair<WeakMember<SVGElement>, QualifiedName>;
+  using AnimationsMap = HeapHashMap<AnimationId, Member<ScheduledVector>>;
 
   explicit SMILTimeContainer(SVGSVGElement& owner);
   ~SMILTimeContainer();
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
index 92cb5a7..141c30d0 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image_chrome_client.cc
@@ -131,7 +131,7 @@
   if (!image_->GetImageObserver())
     return;
 
-  image_->ServiceAnimations(CurrentTimeTicks());
+  image_->ServiceAnimations(base::TimeTicks::Now());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
index 4a740ca..b477c81 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_compositor.cc
@@ -23,7 +23,7 @@
 
 SimCompositor::SimCompositor() {
   LocalFrameView::SetInitialTracksPaintInvalidationsForTesting(true);
-  last_frame_time_ = WTF::CurrentTimeTicks();
+  last_frame_time_ = base::TimeTicks::Now();
 }
 
 SimCompositor::~SimCompositor() {
diff --git a/third_party/blink/renderer/core/timing/event_timing.cc b/third_party/blink/renderer/core/timing/event_timing.cc
index eda6d81..f45a5a3c 100644
--- a/third_party/blink/renderer/core/timing/event_timing.cc
+++ b/third_party/blink/renderer/core/timing/event_timing.cc
@@ -12,14 +12,13 @@
 #include "third_party/blink/renderer/core/timing/dom_window_performance.h"
 #include "third_party/blink/renderer/core/timing/performance_event_timing.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/wtf/time.h"
 
 namespace {
 const base::TickClock* g_clock_for_testing = nullptr;
 
 static base::TimeTicks Now() {
   return g_clock_for_testing ? g_clock_for_testing->NowTicks()
-                             : CurrentTimeTicks();
+                             : base::TimeTicks::Now();
 }
 }  // namespace
 
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.cc b/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
index 1e25325..09824cf 100644
--- a/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
+++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.cc
@@ -10,14 +10,15 @@
 
 namespace blink {
 
-LargestContentfulPaint::LargestContentfulPaint(double paint_time,
+LargestContentfulPaint::LargestContentfulPaint(double render_time,
                                                uint64_t size,
                                                double response_end,
                                                const AtomicString& id,
                                                const String& url,
                                                Element* element)
-    : PerformanceEntry(g_empty_atom, paint_time, paint_time),
+    : PerformanceEntry(g_empty_atom, 0, 0),
       size_(size),
+      render_time_(render_time),
       response_end_(response_end),
       id_(id),
       url_(url),
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.h b/third_party/blink/renderer/core/timing/largest_contentful_paint.h
index 0b9ce41..8dc5ccb 100644
--- a/third_party/blink/renderer/core/timing/largest_contentful_paint.h
+++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.h
@@ -17,7 +17,7 @@
   DEFINE_WRAPPERTYPEINFO();
 
  public:
-  LargestContentfulPaint(double paint_time,
+  LargestContentfulPaint(double render_time,
                          uint64_t size,
                          double response_end,
                          const AtomicString& id,
@@ -29,6 +29,7 @@
   PerformanceEntryType EntryTypeEnum() const override;
 
   uint64_t size() const { return size_; }
+  DOMHighResTimeStamp renderTime() const { return render_time_; }
   DOMHighResTimeStamp responseEnd() const { return response_end_; }
   const AtomicString& id() const { return id_; }
   const String& url() const { return url_; }
@@ -40,6 +41,7 @@
   void BuildJSONValue(V8ObjectBuilder&) const override;
 
   uint64_t size_;
+  DOMHighResTimeStamp render_time_;
   DOMHighResTimeStamp response_end_;
   AtomicString id_;
   String url_;
diff --git a/third_party/blink/renderer/core/timing/largest_contentful_paint.idl b/third_party/blink/renderer/core/timing/largest_contentful_paint.idl
index 2c7ff70..d50a313 100644
--- a/third_party/blink/renderer/core/timing/largest_contentful_paint.idl
+++ b/third_party/blink/renderer/core/timing/largest_contentful_paint.idl
@@ -5,8 +5,9 @@
 // https://github.com/WICG/LargestContentfulPaint
 [Exposed=Window, RuntimeEnabled=LargestContentfulPaint]
 interface LargestContentfulPaint : PerformanceEntry {
-    readonly attribute unsigned long long size;
+    readonly attribute DOMHighResTimeStamp renderTime;
     readonly attribute DOMHighResTimeStamp responseEnd;
+    readonly attribute unsigned long long size;
     readonly attribute DOMString id;
     readonly attribute DOMString url;
     readonly attribute Element? element;
diff --git a/third_party/blink/renderer/core/timing/performance.cc b/third_party/blink/renderer/core/timing/performance.cc
index 6e9fa6a..965ed76c 100644
--- a/third_party/blink/renderer/core/timing/performance.cc
+++ b/third_party/blink/renderer/core/timing/performance.cc
@@ -716,46 +716,38 @@
       return MeasureWithDetail(script_state, measure_name, options->start(),
                                options->end(), options->detail(),
                                exception_state);
-    } else {
-      // measure("name", "mark1", *)
-      StringOrDouble converted_start;
-      if (start_or_options.IsString()) {
-        converted_start =
-            StringOrDouble::FromString(start_or_options.GetAsString());
-      } else {
-        DCHECK(start_or_options.IsNull() ||
-               start_or_options.IsPerformanceMeasureOptions());
-        converted_start = NativeValueTraits<StringOrDouble>::NullValue();
-      }
-      // We let |end| behave the same whether it's empty, undefined or null in
-      // JS, as long as |end| is null in C++.
-      return MeasureWithDetail(
-          script_state, measure_name, converted_start,
-          end ? StringOrDouble::FromString(*end)
-              : NativeValueTraits<StringOrDouble>::NullValue(),
-          ScriptValue::CreateNull(script_state), exception_state);
     }
-  } else {
-    // For consistency with UserTimingL2: the L2 API took |start| as a string,
-    // so any object passed in became a string '[object, object]', null became
-    // string 'null'.
+    // measure("name", "mark1", *)
     StringOrDouble converted_start;
-    if (start_or_options.IsPerformanceMeasureOptions()) {
-      converted_start = NativeValueTraits<StringOrDouble>::NullValue();
-    } else {
-      // |start_or_options| is not nullable.
-      DCHECK(start_or_options.IsString());
+    if (start_or_options.IsString()) {
       converted_start =
           StringOrDouble::FromString(start_or_options.GetAsString());
     }
-
-    MeasureWithDetail(script_state, measure_name, converted_start,
-                      end ? StringOrDouble::FromString(*end)
-                          : NativeValueTraits<StringOrDouble>::NullValue(),
-                      ScriptValue::CreateNull(script_state), exception_state);
-    // Return nullptr to distinguish from L3.
-    return nullptr;
+    // We let |end| behave the same whether it's empty, undefined or null in
+    // JS, as long as |end| is null in C++.
+    return MeasureWithDetail(
+        script_state, measure_name, converted_start,
+        end ? StringOrDouble::FromString(*end)
+            : NativeValueTraits<StringOrDouble>::NullValue(),
+        ScriptValue::CreateNull(script_state), exception_state);
   }
+  // For consistency with UserTimingL2: the L2 API took |start| as a string,
+  // so any object passed in became a string '[object, object]', null became
+  // string 'null'.
+  StringOrDouble converted_start;
+  if (!start_or_options.IsPerformanceMeasureOptions()) {
+    // |start_or_options| is not nullable.
+    DCHECK(start_or_options.IsString());
+    converted_start =
+        StringOrDouble::FromString(start_or_options.GetAsString());
+  }
+
+  MeasureWithDetail(script_state, measure_name, converted_start,
+                    end ? StringOrDouble::FromString(*end)
+                        : NativeValueTraits<StringOrDouble>::NullValue(),
+                    ScriptValue::CreateNull(script_state), exception_state);
+  // Return nullptr to distinguish from L3.
+  return nullptr;
 }
 
 PerformanceMeasure* Performance::MeasureWithDetail(
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.cc b/third_party/blink/renderer/core/timing/performance_element_timing.cc
index bb6401b6..b369d6f4 100644
--- a/third_party/blink/renderer/core/timing/performance_element_timing.cc
+++ b/third_party/blink/renderer/core/timing/performance_element_timing.cc
@@ -14,7 +14,7 @@
     const AtomicString& name,
     const String& url,
     const FloatRect& intersection_rect,
-    DOMHighResTimeStamp start_time,
+    DOMHighResTimeStamp render_time,
     DOMHighResTimeStamp response_end,
     const AtomicString& identifier,
     int naturalWidth,
@@ -27,7 +27,7 @@
   DCHECK_GE(naturalHeight, 0);
   DCHECK(element);
   return MakeGarbageCollected<PerformanceElementTiming>(
-      name, url, intersection_rect, start_time, response_end, identifier,
+      name, url, intersection_rect, render_time, response_end, identifier,
       naturalWidth, naturalHeight, id, element);
 }
 
@@ -35,16 +35,17 @@
     const AtomicString& name,
     const String& url,
     const FloatRect& intersection_rect,
-    DOMHighResTimeStamp start_time,
+    DOMHighResTimeStamp render_time,
     DOMHighResTimeStamp response_end,
     const AtomicString& identifier,
     int naturalWidth,
     int naturalHeight,
     const AtomicString& id,
     Element* element)
-    : PerformanceEntry(name, start_time, start_time),
+    : PerformanceEntry(name, 0, 0),
       element_(element),
       intersection_rect_(DOMRectReadOnly::FromFloatRect(intersection_rect)),
+      render_time_(render_time),
       response_end_(response_end),
       identifier_(identifier),
       naturalWidth_(naturalWidth),
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.h b/third_party/blink/renderer/core/timing/performance_element_timing.h
index 3075a6ac..575b09a 100644
--- a/third_party/blink/renderer/core/timing/performance_element_timing.h
+++ b/third_party/blink/renderer/core/timing/performance_element_timing.h
@@ -24,7 +24,7 @@
   static PerformanceElementTiming* Create(const AtomicString& name,
                                           const String& url,
                                           const FloatRect& intersection_rect,
-                                          DOMHighResTimeStamp start_time,
+                                          DOMHighResTimeStamp render_time,
                                           DOMHighResTimeStamp response_end,
                                           const AtomicString& identifier,
                                           int naturalWidth,
@@ -34,7 +34,7 @@
   PerformanceElementTiming(const AtomicString& name,
                            const String& url,
                            const FloatRect& intersection_rect,
-                           DOMHighResTimeStamp start_time,
+                           DOMHighResTimeStamp render_time,
                            DOMHighResTimeStamp response_end,
                            const AtomicString& identifier,
                            int naturalWidth,
@@ -48,19 +48,13 @@
   PerformanceEntryType EntryTypeEnum() const override;
 
   DOMRectReadOnly* intersectionRect() const { return intersection_rect_; }
-
+  DOMHighResTimeStamp renderTime() const { return render_time_; }
   DOMHighResTimeStamp responseEnd() const { return response_end_; }
-
   AtomicString identifier() const { return identifier_; }
-
   unsigned naturalWidth() const { return naturalWidth_; }
-
   unsigned naturalHeight() const { return naturalHeight_; }
-
   AtomicString id() const { return id_; }
-
   String url() const { return url_; }
-
   Element* element() const;
 
   void Trace(blink::Visitor*) override;
@@ -70,6 +64,7 @@
 
   WeakMember<Element> element_;
   Member<DOMRectReadOnly> intersection_rect_;
+  DOMHighResTimeStamp render_time_;
   DOMHighResTimeStamp response_end_;
   AtomicString identifier_;
   unsigned naturalWidth_;
diff --git a/third_party/blink/renderer/core/timing/performance_element_timing.idl b/third_party/blink/renderer/core/timing/performance_element_timing.idl
index ad4ae4d..0d7c088 100644
--- a/third_party/blink/renderer/core/timing/performance_element_timing.idl
+++ b/third_party/blink/renderer/core/timing/performance_element_timing.idl
@@ -5,8 +5,9 @@
 // https://wicg.github.io/element-timing/#sec-performance-element-timing
 [RuntimeEnabled=ElementTiming]
 interface PerformanceElementTiming : PerformanceEntry {
-    readonly attribute DOMRectReadOnly intersectionRect;
+    readonly attribute DOMHighResTimeStamp renderTime;
     readonly attribute DOMHighResTimeStamp responseEnd;
+    readonly attribute DOMRectReadOnly intersectionRect;
     readonly attribute DOMString identifier;
     readonly attribute unsigned long naturalWidth;
     readonly attribute unsigned long naturalHeight;
diff --git a/third_party/blink/renderer/core/timing/window_performance_test.cc b/third_party/blink/renderer/core/timing/window_performance_test.cc
index fbfdce17..8fe7b956 100644
--- a/third_party/blink/renderer/core/timing/window_performance_test.cc
+++ b/third_party/blink/renderer/core/timing/window_performance_test.cc
@@ -173,7 +173,7 @@
 
   auto* document_loader = page_holder->GetFrame().Loader().GetDocumentLoader();
   ASSERT_TRUE(document_loader);
-  document_loader->GetTiming().SetNavigationStart(CurrentTimeTicks());
+  document_loader->GetTiming().SetNavigationStart(base::TimeTicks::Now());
 
   EXPECT_EQ(&page_holder->GetFrame(), perf->GetFrame());
   EXPECT_EQ(&page_holder->GetFrame(), timing->GetFrame());
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
index 14f6f3f..9f4f4a7 100644
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
@@ -433,7 +433,7 @@
 }
 
 WorkerThread::WorkerThread(WorkerReportingProxy& worker_reporting_proxy)
-    : time_origin_(CurrentTimeTicks()),
+    : time_origin_(base::TimeTicks::Now()),
       worker_thread_id_(GetNextWorkerThreadId()),
       forcible_termination_delay_(kForcibleTerminationDelay),
       worker_reporting_proxy_(worker_reporting_proxy),
diff --git a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
index b76e7dd..c87e752 100644
--- a/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
+++ b/third_party/blink/renderer/core/workers/worker_thread_test_helper.h
@@ -49,7 +49,7 @@
       WorkerThread* thread)
       : WorkerGlobalScope(std::move(creation_params),
                           thread,
-                          CurrentTimeTicks()) {
+                          base::TimeTicks::Now()) {
     ReadyToRunWorkerScript();
   }
 
diff --git a/third_party/blink/renderer/devtools/front_end/coverage/module.json b/third_party/blink/renderer/devtools/front_end/coverage/module.json
index ca5239f..cbbb2fc 100644
--- a/third_party/blink/renderer/devtools/front_end/coverage/module.json
+++ b/third_party/blink/renderer/devtools/front_end/coverage/module.json
@@ -18,6 +18,7 @@
             "type": "action",
             "actionId": "coverage.toggle-recording",
             "iconClass": "largeicon-start-recording",
+            "toggleable": true,
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
             "className": "Coverage.CoverageView.ActionDelegate",
diff --git a/third_party/blink/renderer/devtools/front_end/elements/module.json b/third_party/blink/renderer/devtools/front_end/elements/module.json
index 739a586..37666e0 100644
--- a/third_party/blink/renderer/devtools/front_end/elements/module.json
+++ b/third_party/blink/renderer/devtools/front_end/elements/module.json
@@ -217,6 +217,7 @@
         {
             "type": "action",
             "actionId": "elements.toggle-element-search",
+            "toggleable": true,
             "className": "Elements.InspectElementModeController.ToggleSearchActionDelegate",
             "title": "Select an element in the page to inspect it",
             "iconClass": "largeicon-node-search",
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/module.json b/third_party/blink/renderer/devtools/front_end/emulation/module.json
index 7968cff7..f79e7e45 100644
--- a/third_party/blink/renderer/devtools/front_end/emulation/module.json
+++ b/third_party/blink/renderer/devtools/front_end/emulation/module.json
@@ -10,6 +10,7 @@
             "type": "action",
             "category": "Mobile",
             "actionId": "emulation.toggle-device-mode",
+            "toggleable": true,
             "className": "Emulation.DeviceModeWrapper.ActionDelegate",
             "condition": "can_dock",
             "title": "Toggle device toolbar",
diff --git a/third_party/blink/renderer/devtools/front_end/network/module.json b/third_party/blink/renderer/devtools/front_end/network/module.json
index bf275b4..a8acd65 100644
--- a/third_party/blink/renderer/devtools/front_end/network/module.json
+++ b/third_party/blink/renderer/devtools/front_end/network/module.json
@@ -74,6 +74,7 @@
             "type": "action",
             "actionId": "network.toggle-recording",
             "iconClass": "largeicon-start-recording",
+            "toggleable": true,
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
             "contextTypes": [
diff --git a/third_party/blink/renderer/devtools/front_end/profiler/module.json b/third_party/blink/renderer/devtools/front_end/profiler/module.json
index 12cd02d2..bd35e85 100644
--- a/third_party/blink/renderer/devtools/front_end/profiler/module.json
+++ b/third_party/blink/renderer/devtools/front_end/profiler/module.json
@@ -45,6 +45,7 @@
             "type": "action",
             "actionId": "live-heap-profile.toggle-recording",
             "iconClass": "largeicon-start-recording",
+            "toggleable": true,
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
             "className": "Profiler.LiveHeapProfileView.ActionDelegate",
@@ -72,6 +73,7 @@
             "type": "action",
             "actionId": "profiler.heap-toggle-recording",
             "iconClass": "largeicon-start-recording",
+            "toggleable": true,
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
             "contextTypes": [
@@ -93,6 +95,7 @@
             "type": "action",
             "actionId": "profiler.js-toggle-recording",
             "iconClass": "largeicon-start-recording",
+            "toggleable": true,
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
             "contextTypes": [
diff --git a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
index 05a63172..a1461d6 100644
--- a/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
+++ b/third_party/blink/renderer/devtools/front_end/resources/BackgroundServiceView.js
@@ -55,7 +55,7 @@
 
     /** @const {!UI.Action} */
     this._recordAction = /** @type {!UI.Action} */ (UI.actionRegistry.action('background-service.toggle-recording'));
-    /** @type {?UI.ToolbarToggle} */
+    /** @type {?UI.ToolbarButton} */
     this._recordButton = null;
 
     /** @type {?UI.ToolbarCheckbox} */
diff --git a/third_party/blink/renderer/devtools/front_end/resources/module.json b/third_party/blink/renderer/devtools/front_end/resources/module.json
index 6b962ca..9dbc544 100644
--- a/third_party/blink/renderer/devtools/front_end/resources/module.json
+++ b/third_party/blink/renderer/devtools/front_end/resources/module.json
@@ -28,6 +28,7 @@
           "type": "action",
           "actionId": "background-service.toggle-recording",
           "iconClass": "largeicon-start-recording",
+          "toggleable": true,
           "toggledIconClass": "largeicon-stop-recording",
           "toggleWithRedColor": true,
           "contextTypes": [
diff --git a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
index 7185708..c51f6527 100644
--- a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
+++ b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
@@ -693,8 +693,8 @@
     const terminateExecutionButton =
         new UI.ToolbarButton(ls`Terminate current JavaScript call`, 'largeicon-terminate-execution');
     terminateExecutionButton.addEventListener(UI.ToolbarButton.Events.Click, this._terminateExecution, this);
-    debugToolbar.appendToolbarItem(
-        UI.Toolbar.createActionButton(this._togglePauseAction, [terminateExecutionButton, longResumeButton], []));
+    debugToolbar.appendToolbarItem(UI.Toolbar.createLongPressActionButton(
+        this._togglePauseAction, [terminateExecutionButton, longResumeButton], []));
 
     debugToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._stepOverAction));
     debugToolbar.appendToolbarItem(UI.Toolbar.createActionButton(this._stepIntoAction));
diff --git a/third_party/blink/renderer/devtools/front_end/sources/module.json b/third_party/blink/renderer/devtools/front_end/sources/module.json
index 65b16f3..a796cf20 100644
--- a/third_party/blink/renderer/devtools/front_end/sources/module.json
+++ b/third_party/blink/renderer/devtools/front_end/sources/module.json
@@ -24,6 +24,7 @@
             "category": "Debugger",
             "actionId": "debugger.toggle-pause",
             "iconClass": "largeicon-pause",
+            "toggleable": true,
             "toggledIconClass": "largeicon-resume",
             "className": "Sources.SourcesPanel.RevealingActionDelegate",
             "contextTypes": [
@@ -155,6 +156,7 @@
             "category": "Debugger",
             "actionId": "debugger.toggle-breakpoints-active",
             "iconClass": "largeicon-deactivate-breakpoints",
+            "toggleable": true,
             "toggledIconClass": "largeicon-activate-breakpoints",
             "className": "Sources.SourcesPanel.DebuggingActionDelegate",
             "contextTypes": [
diff --git a/third_party/blink/renderer/devtools/front_end/timeline/module.json b/third_party/blink/renderer/devtools/front_end/timeline/module.json
index f175531..7a17009 100644
--- a/third_party/blink/renderer/devtools/front_end/timeline/module.json
+++ b/third_party/blink/renderer/devtools/front_end/timeline/module.json
@@ -37,6 +37,7 @@
             "type": "action",
             "actionId": "timeline.toggle-recording",
             "iconClass": "largeicon-start-recording",
+            "toggleable": true,
             "toggledIconClass": "largeicon-stop-recording",
             "toggleWithRedColor": true,
             "contextTypes": [
diff --git a/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js b/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js
index a1479039..aa73fff 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js
+++ b/third_party/blink/renderer/devtools/front_end/ui/ActionRegistry.js
@@ -166,6 +166,13 @@
   }
 
   /**
+   * @return {boolean}
+   */
+  toggleable() {
+    return !!this._extension.descriptor()['toggleable'];
+  }
+
+  /**
    * @return {string}
    */
   title() {
@@ -191,6 +198,7 @@
    * @param {boolean} toggled
    */
   setToggled(toggled) {
+    console.assert(this.toggleable(), 'Shouldn\'t be toggling an untoggleable action', this.id());
     if (this._toggled === toggled)
       return;
 
diff --git a/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js b/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
index 664588a..48ca8a9 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
+++ b/third_party/blink/renderer/devtools/front_end/ui/Toolbar.js
@@ -50,43 +50,25 @@
 
   /**
    * @param {!UI.Action} action
-   * @param {!Array<!UI.ToolbarButton>=} toggledOptions
-   * @param {!Array<!UI.ToolbarButton>=} untoggledOptions
-   * @param {boolean=} showLabel
-   * @return {!UI.ToolbarToggle}
+   * @param {!Array<!UI.ToolbarButton>} toggledOptions
+   * @param {!Array<!UI.ToolbarButton>} untoggledOptions
+   * @return {!UI.ToolbarButton}
    */
-  static createActionButton(action, toggledOptions, untoggledOptions, showLabel) {
-    const button = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon());
-    if (showLabel)
-      button.setText(action.title());
-    button.setToggleWithRedColor(action.toggleWithRedColor());
-    button.addEventListener(UI.ToolbarButton.Events.Click, action.execute, action);
-    action.addEventListener(UI.Action.Events.Enabled, enabledChanged);
-    action.addEventListener(UI.Action.Events.Toggled, toggled);
+  static createLongPressActionButton(action, toggledOptions, untoggledOptions) {
+    const button = UI.Toolbar.createActionButton(action);
+    const mainButtonClone = UI.Toolbar.createActionButton(action);
+
     /** @type {?UI.LongClickController} */
     let longClickController = null;
     /** @type {?Array<!UI.ToolbarButton>} */
     let longClickButtons = null;
     /** @type {?Element} */
     let longClickGlyph = null;
-    toggled();
-    button.setEnabled(action.enabled());
+
+    action.addEventListener(UI.Action.Events.Toggled, updateOptions);
+    updateOptions();
     return button;
 
-    /**
-     * @param {!Common.Event} event
-     */
-    function enabledChanged(event) {
-      button.setEnabled(/** @type {boolean} */ (event.data));
-    }
-
-    function toggled() {
-      button.setToggled(action.toggled());
-      if (action.title())
-        UI.Tooltip.install(button.element, action.title(), action.id());
-      updateOptions();
-    }
-
     function updateOptions() {
       const buttons = action.toggled() ? (toggledOptions || null) : (untoggledOptions || null);
 
@@ -110,17 +92,6 @@
 
     function showOptions() {
       let buttons = longClickButtons.slice();
-      const mainButtonClone = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon());
-      mainButtonClone.addEventListener(UI.ToolbarButton.Events.Click, clicked);
-
-      /**
-       * @param {!Common.Event} event
-       */
-      function clicked(event) {
-        button._clicked(/** @type {!Event} */ (event.data));
-      }
-
-      mainButtonClone.setToggled(action.toggled());
       buttons.push(mainButtonClone);
 
       const document = button.element.ownerDocument;
@@ -187,14 +158,54 @@
   }
 
   /**
+   * @param {!UI.Action} action
+   * @param {boolean=} showLabel
+   * @return {!UI.ToolbarButton}
+   */
+  static createActionButton(action, showLabel) {
+    const button = makeButtonOrToggle();
+    if (showLabel)
+      button.setText(action.title());
+    button.addEventListener(UI.ToolbarButton.Events.Click, action.execute, action);
+    action.addEventListener(UI.Action.Events.Enabled, enabledChanged);
+    button.setEnabled(action.enabled());
+    return button;
+
+    /**
+     * @return {!UI.ToolbarButton}
+     */
+    function makeButtonOrToggle() {
+      if (!action.toggleable())
+        return new UI.ToolbarButton(action.title(), action.icon());
+      const toggleButton = new UI.ToolbarToggle(action.title(), action.icon(), action.toggledIcon());
+      toggleButton.setToggleWithRedColor(action.toggleWithRedColor());
+      action.addEventListener(UI.Action.Events.Toggled, toggled);
+      toggled();
+      return toggleButton;
+
+      function toggled() {
+        toggleButton.setToggled(action.toggled());
+        if (action.title())
+          UI.Tooltip.install(toggleButton.element, action.title(), action.id());
+      }
+    }
+
+    /**
+     * @param {!Common.Event} event
+     */
+    function enabledChanged(event) {
+      button.setEnabled(/** @type {boolean} */ (event.data));
+    }
+  }
+
+  /**
    * @param {string} actionId
    * @param {boolean=} showLabel
-   * @return {!UI.ToolbarToggle}
+   * @return {!UI.ToolbarButton}
    */
   static createActionButtonForId(actionId, showLabel) {
     const action = UI.actionRegistry.action(actionId);
-    return UI.Toolbar.createActionButton(
-        /** @type {!UI.Action} */ (action), undefined, undefined, showLabel);
+    return UI.Toolbar.createActionButton(/** @type {!UI.Action} */ (action), showLabel);
   }
 
   /**
diff --git a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
index ba90907..6495a8bc1 100644
--- a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
+++ b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
@@ -2012,7 +2012,7 @@
 };
 
 /**
- * @param {!UI.ToolbarToggle} toolbarButton
+ * @param {!UI.ToolbarButton} toolbarButton
  * @return {!Element}
  */
 UI.createInlineButton = function(toolbarButton) {
diff --git a/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js b/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
index bec1895..50a2859 100644
--- a/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
+++ b/third_party/blink/renderer/devtools/scripts/check_localizable_resources.js
@@ -25,15 +25,12 @@
 
 async function main() {
   try {
-    await checkLocalizedStrings.parseLocalizableResourceMaps(false);
-    const frontendStrings = checkLocalizedStrings.frontendStrings;
-    const IDSkeys = checkLocalizedStrings.IDSkeys;
+    await checkLocalizedStrings.parseLocalizableResourceMaps();
 
-    if (process.argv.includes('--autofix')) {
-      await autofix(frontendStrings, IDSkeys);
-    } else {
-      await getErrors(frontendStrings, IDSkeys);
-    }
+    if (process.argv.includes('--autofix'))
+      await autofix();
+    else
+      await getErrors();
   } catch (e) {
     console.log(`Error: ${e.message}`);
     process.exit(1);
@@ -42,10 +39,10 @@
 
 main();
 
-async function getErrors(frontendStrings, IDSkeys) {
-  const toAddError = await checkLocalizedStrings.getAndReportResourcesToAdd(frontendStrings, IDSkeys);
+async function getErrors() {
+  const toAddError = await checkLocalizedStrings.getAndReportResourcesToAdd();
   const toModifyError = checkLocalizedStrings.getAndReportIDSKeysToModify();
-  const toRemoveError = checkLocalizedStrings.getAndReportResourcesToRemove(frontendStrings, IDSkeys);
+  const toRemoveError = checkLocalizedStrings.getAndReportResourcesToRemove();
   let error = `${toAddError || ''}${toModifyError || ''}${toRemoveError || ''}`;
 
   if (error === '') {
@@ -58,9 +55,9 @@
   throw new Error(error);
 }
 
-async function autofix(frontendStrings, IDSkeys) {
-  const keysToAddToGRD = checkLocalizedStrings.getDifference(IDSkeys, frontendStrings);
-  const keysToRemoveFromGRD = checkLocalizedStrings.getDifference(frontendStrings, IDSkeys);
+async function autofix() {
+  const keysToAddToGRD = checkLocalizedStrings.getMessagesToAdd();
+  const keysToRemoveFromGRD = checkLocalizedStrings.getMessagesToRemove();
   const resourceAdded = await addResourcesToGRDP(keysToAddToGRD, keysToRemoveFromGRD);
   const resourceModified = await modifyResourcesInGRDP();
   const resourceRemoved = await removeResourcesFromGRDP(keysToRemoveFromGRD);
@@ -74,10 +71,20 @@
       'Found changes to localizable DevTools strings.\nDevTools localizable resources checker has updated the appropriate grdp file(s).';
   if (resourceAdded)
     message += '\nManually write a description for any new <message> entries.';
+  if (resourceRemoved && duplicateRemoved(keysToRemoveFromGRD))
+    message += '\nDuplicate <message> entries are removed. Please verify the retained descriptions are correct.';
   message += '\nUse git status to see what has changed.';
   throw new Error(message);
 }
 
+function duplicateRemoved(keysToRemoveFromGRD) {
+  for (const [_, messages] of keysToRemoveFromGRD) {
+    if (messages.length > 1)
+      return true;
+  }
+  return false;
+}
+
 // Return true if any resources are added
 async function addResourcesToGRDP(keysToAddToGRD, keysToRemoveFromGRD) {
   function mapGRDPFilePathToStrings(keysToAddToGRD, keysToRemoveFromGRD) {
@@ -92,7 +99,7 @@
       // If the same key is to be removed, this is likely a string copy
       // to another folder. Keep the description.
       if (keysToRemoveFromGRD.has(key))
-        stringObj.description = keysToRemoveFromGRD.get(key).description;
+        stringObj.description = checkLocalizedStrings.getLongestDescription(keysToRemoveFromGRD.get(key));
       grdpFilePathToStrings.get(stringObj.grdpPath).push(stringObj);
     }
     return grdpFilePathToStrings;
@@ -215,8 +222,15 @@
 
 // Return true if any resources are removed
 async function removeResourcesFromGRDP(keysToRemoveFromGRD) {
-  function lineContainsIDS(line, messages) {
-    return messages.some(message => line.includes(message.ids));
+  function indexOfFirstMatchingMessage(line, messages) {
+    for (let i = 0; i < messages.length; i++) {
+      const message = messages[i];
+      const match =
+          line.match(new RegExp(`<message[^>]*name="${message.ids}"[^>]*desc="${message.description}"[^>]*>`));
+      if (match)
+        return i;
+    }
+    return -1;
   }
 
   if (keysToRemoveFromGRD.size === 0)
@@ -230,13 +244,15 @@
     const grdpFileLines = grdpFileContent.split('\n');
 
     for (let i = 0; i < grdpFileLines.length; i++) {
-      if (!lineContainsIDS(grdpFileLines[i], messages)) {
+      const index = indexOfFirstMatchingMessage(grdpFileLines[i], messages);
+      if (index === -1) {
         newGrdpFileContent += grdpFileLines[i];
         if (i < grdpFileLines.length - 1)
           newGrdpFileContent += '\n';
         continue;
       }
 
+      messages.splice(index, 1);
       while (!grdpFileLines[i].includes('</message>'))
         i++;
     }
@@ -252,12 +268,14 @@
 // `ids` set to the key.
 function mapGRDPFilePathToMessages(keyToMessages) {
   const grdpFilePathToMessages = new Map();
-  for (const [ids, message] of keyToMessages) {
-    if (!grdpFilePathToMessages.has(message.grdpPath))
-      grdpFilePathToMessages.set(message.grdpPath, []);
+  for (const [ids, messages] of keyToMessages) {
+    for (const message of messages) {
+      if (!grdpFilePathToMessages.has(message.grdpPath))
+        grdpFilePathToMessages.set(message.grdpPath, []);
 
-    message.ids = ids;
-    grdpFilePathToMessages.get(message.grdpPath).push(message);
+      message.ids = ids;
+      grdpFilePathToMessages.get(message.grdpPath).push(message);
+    }
   }
   return grdpFilePathToMessages;
 }
diff --git a/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
index 32e1dde3..117b2fa 100644
--- a/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
+++ b/third_party/blink/renderer/devtools/scripts/localization_utils/check_localized_strings.js
@@ -8,10 +8,7 @@
  * files and report error if present.
  */
 
-const fs = require('fs');
 const path = require('path');
-const {promisify} = require('util');
-const writeFileAsync = promisify(fs.writeFile);
 const localizationUtils = require('./localization_utils');
 const escodegen = localizationUtils.escodegen;
 const esprimaTypes = localizationUtils.esprimaTypes;
@@ -41,10 +38,10 @@
 
 // Format
 // {
-//   IDS_KEY => {
+//   IDS_KEY => a list of {
 //     actualIDSKey: string,  // the IDS key in the message tag
 //     description: string,
-//     filepath: string,
+//     grdpPath: string,
 //     location: {
 //       start: {
 //         line: number
@@ -60,7 +57,7 @@
 
 const devtoolsFrontendPath = path.resolve(__dirname, '..', '..', 'front_end');
 
-async function parseLocalizableResourceMaps(isDebug) {
+async function parseLocalizableResourceMaps() {
   const grdpToFiles = new Map();
   const dirs = await localizationUtils.getChildDirectoriesFromDirectory(devtoolsFrontendPath);
   const grdpToFilesPromises = dirs.map(dir => {
@@ -70,12 +67,15 @@
   });
   await Promise.all(grdpToFilesPromises);
 
-  const promises = [parseIDSKeys(localizationUtils.GRD_PATH, isDebug)];
+  const promises = [];
   for (const [grdpPath, files] of grdpToFiles) {
     files.forEach(file => fileToGRDPMap.set(file, grdpPath));
-    promises.push(parseLocalizableStrings(files, isDebug));
+    promises.push(parseLocalizableStrings(files));
   }
   await Promise.all(promises);
+  // Parse grd(p) files after frontend strings are processed so we know
+  // what to add or remove based on frontend strings
+  await parseIDSKeys(localizationUtils.GRD_PATH);
 }
 
 /**
@@ -83,11 +83,9 @@
  * Common.UIStringFormat, UI.formatLocalized or ls``) from devtools frontend files.
  */
 
-async function parseLocalizableStrings(devtoolsFiles, isDebug) {
+async function parseLocalizableStrings(devtoolsFiles) {
   const promises = devtoolsFiles.map(filePath => parseLocalizableStringsFromFile(filePath));
   await Promise.all(promises);
-  if (isDebug)
-    await writeFileAsync(path.resolve(__dirname, 'localizable_strings.json'), JSON.stringify(frontendStrings));
 }
 
 async function parseLocalizableStringsFromFile(filePath) {
@@ -225,12 +223,10 @@
  * devtools frontend grdp files.
  */
 
-async function parseIDSKeys(grdFilePath, isDebug) {
+async function parseIDSKeys(grdFilePath) {
   // NOTE: this function assumes that no <message> tags are present in the parent
   const grdpFilePaths = await parseGRDFile(grdFilePath);
   await parseGRDPFiles(grdpFilePaths);
-  if (isDebug)
-    await writeFileAsync(path.resolve(__dirname, 'IDS_Keys.json'), JSON.stringify(IDSkeys));
 }
 
 async function parseGRDFile(grdFilePath) {
@@ -317,17 +313,24 @@
     message = localizationUtils.sanitizeStringIntoFrontendFormat(message);
 
     const ids = localizationUtils.getIDSKey(message);
-    IDSkeys.set(ids, {actualIDSKey, grdpPath: filePath, location: {start: {line}, end: {line}}, description});
+    addMessage(ids, actualIDSKey, filePath, line, description);
   }
 }
 
+function addMessage(expectedIDSKey, actualIDSKey, grdpPath, line, description) {
+  if (!IDSkeys.has(expectedIDSKey))
+    IDSkeys.set(expectedIDSKey, []);
+
+  IDSkeys.get(expectedIDSKey).push({actualIDSKey, grdpPath, location: {start: {line}, end: {line}}, description});
+}
+
 /**
  * The following functions compare frontend localizable strings
  * with grdp <message>s and report error of resources to add,
  * remove or modify.
  */
-async function getAndReportResourcesToAdd(frontendStrings, IDSkeys) {
-  const keysToAddToGRD = getDifference(IDSkeys, frontendStrings);
+async function getAndReportResourcesToAdd() {
+  const keysToAddToGRD = getMessagesToAdd();
   if (keysToAddToGRD.size === 0)
     return;
 
@@ -350,18 +353,19 @@
   return errorStr;
 }
 
-function getAndReportResourcesToRemove(frontendStrings, IDSkeys) {
-  const keysToRemoveFromGRD = getDifference(frontendStrings, IDSkeys);
+function getAndReportResourcesToRemove() {
+  const keysToRemoveFromGRD = getMessagesToRemove();
   if (keysToRemoveFromGRD.size === 0)
     return;
 
   let errorStr =
       '\nThe message(s) associated with the following IDS key(s) should be removed from its GRD/GRDP file(s):\n';
   // Example error message:
-  // third_party/blink/renderer/devtools/front_end/help/help_strings.grdp Line 18: IDS_DEVTOOLS_7d0ee6fed10d3d4e5c9ee496729ab519
-  for (const [key, keyObj] of keysToRemoveFromGRD) {
-    errorStr += `${localizationUtils.getRelativeFilePathFromSrc(keyObj.grdpPath)}${
-        localizationUtils.getLocationMessage(keyObj.location)}: ${key}\n\n`;
+  // third_party/blink/renderer/devtools/front_end/accessibility/accessibility_strings.grdp Line 300: IDS_DEVTOOLS_c9bbad3047af039c14d0e7ec957bb867
+  for (const [ids, messages] of keysToRemoveFromGRD) {
+    messages.forEach(
+        message => errorStr += `${localizationUtils.getRelativeFilePathFromSrc(message.grdpPath)}${
+            localizationUtils.getLocationMessage(message.location)}: ${ids}\n\n`);
   }
   return errorStr;
 }
@@ -374,36 +378,96 @@
   let errorStr = '\nThe following GRD/GRDP message(s) do not have the correct IDS key.\n';
   errorStr += 'Please update the key(s) by changing the "name" value.\n\n';
 
-  for (const [expectedIDSKey, message] of messagesToModify) {
-    errorStr += `${localizationUtils.getRelativeFilePathFromSrc(message.grdpPath)}${
-        localizationUtils.getLocationMessage(message.location)}:\n`;
-    errorStr += `${message.actualIDSKey} --> ${expectedIDSKey}\n\n`;
+  for (const [expectedIDSKey, messages] of messagesToModify) {
+    messages.forEach(
+        message => errorStr += `${localizationUtils.getRelativeFilePathFromSrc(message.grdpPath)}${
+            localizationUtils.getLocationMessage(
+                message.location)}:\n${message.actualIDSKey} --> ${expectedIDSKey}\n\n`);
   }
   return errorStr;
 }
 
-/**
- * Output a Map containing sorted entries that are in @comparison but not @reference,
- * or entries that are in both but belong to different grdp files.
- */
-function getDifference(reference, comparison) {
+function getMessagesToAdd() {
+  // If a message with ids key exists in grdpPath
+  function messageExists(ids, grdpPath) {
+    const messages = IDSkeys.get(ids);
+    return messages.some(message => message.grdpPath === grdpPath);
+  }
+
   const difference = [];
-  for (const [key, value] of comparison) {
-    if (!reference.has(key) || reference.get(key).grdpPath !== value.grdpPath)
-      difference.push([key, value]);
+  for (const [ids, frontendString] of frontendStrings) {
+    if (!IDSkeys.has(ids) || !messageExists(ids, frontendString.grdpPath))
+      difference.push([ids, frontendString]);
   }
   return new Map(difference.sort());
 }
 
+// Return a map from the expected IDS key to a list of messages
+// whose actual IDS keys need to be modified.
 function getIDSKeysToModify() {
   const messagesToModify = new Map();
-  for (const [expectedIDSKey, message] of IDSkeys) {
-    if (expectedIDSKey !== message.actualIDSKey)
-      messagesToModify.set(expectedIDSKey, message);
+  for (const [expectedIDSKey, messages] of IDSkeys) {
+    for (const message of messages) {
+      if (expectedIDSKey !== message.actualIDSKey) {
+        if (messagesToModify.has(expectedIDSKey))
+          messagesToModify.get(expectedIDSKey).push(message);
+        else
+          messagesToModify.set(expectedIDSKey, [message]);
+      }
+    }
   }
   return messagesToModify;
 }
 
+function getMessagesToRemove() {
+  const difference = new Map();
+  for (const [ids, messages] of IDSkeys) {
+    if (!frontendStrings.has(ids)) {
+      difference.set(ids, messages);
+      continue;
+    }
+
+    const expectedGrdpPath = frontendStrings.get(ids).grdpPath;
+    const messagesInGrdp = [];
+    const messagesToRemove = [];
+    messages.forEach(message => {
+      if (message.grdpPath !== expectedGrdpPath)
+        messagesToRemove.push(message);
+      else
+        messagesInGrdp.push(message);
+    });
+
+    if (messagesToRemove.length === 0 && messagesInGrdp.length === 1)
+      continue;
+
+    if (messagesInGrdp.length > 1) {
+      // If there are more than one messages with ids in the
+      // expected grdp file, keep one with the longest
+      // description and delete all the other messages
+      const longestDescription = getLongestDescription(messagesInGrdp);
+      let foundMessageToKeep = false;
+      for (const message of messagesInGrdp) {
+        if (message.description === longestDescription && !foundMessageToKeep) {
+          foundMessageToKeep = true;
+          continue;
+        }
+        messagesToRemove.push(message);
+      }
+    }
+    difference.set(ids, messagesToRemove);
+  }
+  return difference;
+}
+
+function getLongestDescription(messages) {
+  let longestDescription = '';
+  messages.forEach(message => {
+    if (message.description.length > longestDescription.length)
+      longestDescription = message.description;
+  });
+  return longestDescription;
+}
+
 module.exports = {
   frontendStrings,
   IDSkeys,
@@ -411,6 +475,8 @@
   getAndReportIDSKeysToModify,
   getAndReportResourcesToAdd,
   getAndReportResourcesToRemove,
-  getDifference,
-  getIDSKeysToModify
+  getIDSKeysToModify,
+  getLongestDescription,
+  getMessagesToAdd,
+  getMessagesToRemove,
 };
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
index 2ba341c..2fb29d7 100644
--- a/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
+++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.cc
@@ -5,10 +5,10 @@
 #include "third_party/blink/renderer/modules/bluetooth/bluetooth_uuid.h"
 
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -333,7 +333,7 @@
   String name_str = name.GetAsString();
 
   // If name is a valid UUID, return name and abort these steps.
-  if (IsValidUUID(name_str))
+  if (WTF::IsValidUUID(name_str))
     return name_str;
 
   // If name is in the corresponding attribute map return
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
index 0913ea9..ce1213e 100644
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
@@ -54,11 +54,6 @@
 
 namespace {
 
-void RecordResponseTypeForAdd(const Member<Response>& response) {
-  UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.Cache.AddResponseType",
-                            response->GetResponse()->GetType());
-}
-
 bool VaryHeaderContainsAsterisk(const Response* response) {
   const FetchHeaderList* headers = response->headers()->HeaderList();
   String varyHeader;
@@ -179,9 +174,6 @@
       }
     }
 
-    for (const auto& response : responses)
-      RecordResponseTypeForAdd(response);
-
     ScriptPromise put_promise =
         cache_->PutImpl(GetScriptState(), method_name_, requests_, responses,
                         exception_state, trace_id_);
diff --git a/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc b/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc
index e809a9f..6d6517f9 100644
--- a/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc
+++ b/third_party/blink/renderer/modules/document_metadata/copyless_paste_extractor.cc
@@ -296,9 +296,9 @@
   WebPagePtr page = WebPage::New();
 
   // Traverse the DOM tree and extract the metadata.
-  base::TimeTicks start_time = CurrentTimeTicks();
+  base::TimeTicks start_time = base::TimeTicks::Now();
   ExtractionStatus status = ExtractMetadata(*html, page->entities);
-  base::TimeDelta elapsed_time = CurrentTimeTicks() - start_time;
+  base::TimeDelta elapsed_time = base::TimeTicks::Now() - start_time;
 
   DEFINE_STATIC_LOCAL(EnumerationHistogram, status_histogram,
                       ("CopylessPaste.ExtractionStatus", kCount));
diff --git a/third_party/blink/renderer/modules/exported/web_storage_event_dispatcher_impl.cc b/third_party/blink/renderer/modules/exported/web_storage_event_dispatcher_impl.cc
deleted file mode 100644
index fb66ef8..0000000
--- a/third_party/blink/renderer/modules/exported/web_storage_event_dispatcher_impl.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "third_party/blink/public/web/web_storage_event_dispatcher.h"
-
-#include "third_party/blink/public/platform/web_url.h"
-#include "third_party/blink/renderer/core/exported/web_view_impl.h"
-#include "third_party/blink/renderer/modules/storage/storage_area.h"
-#include "third_party/blink/renderer/platform/weborigin/kurl.h"
-#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
-
-namespace blink {
-
-void WebStorageEventDispatcher::DispatchLocalStorageEvent(
-    const WebString& key,
-    const WebString& old_value,
-    const WebString& new_value,
-    const WebURL& origin,
-    const WebURL& page_url,
-    WebStorageArea* source_area_instance) {
-  scoped_refptr<const SecurityOrigin> security_origin =
-      SecurityOrigin::Create(origin);
-  StorageArea::DispatchLocalStorageEvent(key, old_value, new_value,
-                                         security_origin.get(), page_url,
-                                         source_area_instance);
-}
-
-void WebStorageEventDispatcher::DispatchSessionStorageEvent(
-    const WebString& key,
-    const WebString& old_value,
-    const WebString& new_value,
-    const WebURL& origin,
-    const WebURL& page_url,
-    const WebStorageNamespace& session_namespace,
-    WebStorageArea* source_area_instance) {
-  scoped_refptr<const SecurityOrigin> security_origin =
-      SecurityOrigin::Create(origin);
-  StorageArea::DispatchSessionStorageEvent(
-      key, old_value, new_value, security_origin.get(), page_url,
-      session_namespace, source_area_instance);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/image_downloader/fetcher/multi_resolution_image_resource_fetcher.cc b/third_party/blink/renderer/modules/image_downloader/fetcher/multi_resolution_image_resource_fetcher.cc
index 24c2dd8..0260c6e0 100644
--- a/third_party/blink/renderer/modules/image_downloader/fetcher/multi_resolution_image_resource_fetcher.cc
+++ b/third_party/blink/renderer/modules/image_downloader/fetcher/multi_resolution_image_resource_fetcher.cc
@@ -59,8 +59,8 @@
   fetcher_->Start(
       frame, request_context, network::mojom::RequestMode::kNoCors,
       network::mojom::CredentialsMode::kInclude,
-      base::BindOnce(&MultiResolutionImageResourceFetcher::OnURLFetchComplete,
-                     base::Unretained(this)));
+      WTF::Bind(&MultiResolutionImageResourceFetcher::OnURLFetchComplete,
+                WrapPersistent(this)));
 }
 
 MultiResolutionImageResourceFetcher::~MultiResolutionImageResourceFetcher() {}
diff --git a/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc b/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc
index b397517..f91b081 100644
--- a/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc
+++ b/third_party/blink/renderer/modules/media_controls/elements/media_control_timeline_metrics.cc
@@ -213,7 +213,7 @@
 void MediaControlTimelineMetrics::StartGesture(bool from_thumb) {
   // Initialize gesture tracking.
   state_ = from_thumb ? State::kGestureFromThumb : State::kGestureFromElsewhere;
-  drag_start_time_ticks_ = CurrentTimeTicks();
+  drag_start_time_ticks_ = base::TimeTicks::Now();
   drag_delta_media_seconds_ = 0;
   drag_sum_abs_delta_media_seconds_ = 0;
 }
@@ -249,8 +249,8 @@
   if (seek_type == SeekType::kClick)
     return;  // Metrics below are only for drags.
 
-  RecordDragGestureDurationByWidth(timeline_width,
-                                   CurrentTimeTicks() - drag_start_time_ticks_);
+  RecordDragGestureDurationByWidth(
+      timeline_width, base::TimeTicks::Now() - drag_start_time_ticks_);
   if (std::isfinite(media_duration_seconds)) {
     RecordDragPercentByWidth(timeline_width, 100.0 * drag_delta_media_seconds_ /
                                                  media_duration_seconds);
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
index d54cc4c..7903f2e 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate_test.cc
@@ -91,13 +91,13 @@
 void DidEnterFullscreen(Document* document) {
   DCHECK(document);
   Fullscreen::DidEnterFullscreen(*document);
-  document->ServiceScriptedAnimations(WTF::CurrentTimeTicks());
+  document->ServiceScriptedAnimations(base::TimeTicks::Now());
 }
 
 void DidExitFullscreen(Document* document) {
   DCHECK(document);
   Fullscreen::DidExitFullscreen(*document);
-  document->ServiceScriptedAnimations(WTF::CurrentTimeTicks());
+  document->ServiceScriptedAnimations(base::TimeTicks::Now());
 }
 
 class MockChromeClientForOrientationLockDelegate final
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
index c048895..cf821cb 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/html_media_element_capture.cc
@@ -23,7 +23,7 @@
 #include "third_party/blink/renderer/modules/mediacapturefromelement/html_video_element_capturer_source.h"
 #include "third_party/blink/renderer/modules/mediastream/media_stream.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_center.h"
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -52,7 +52,7 @@
       new MediaStreamVideoCapturerSource(
           WebPlatformMediaStreamSource::SourceStoppedCallback(),
           std::move(video_source));
-  const WebString track_id(CreateCanonicalUUIDString());
+  const WebString track_id(WTF::CreateCanonicalUUIDString());
   WebMediaStreamSource web_media_stream_source;
   web_media_stream_source.Initialize(track_id, WebMediaStreamSource::kTypeVideo,
                                      track_id, is_remote);
@@ -96,7 +96,7 @@
 
   blink::WebMediaStreamSource web_media_stream_source;
   blink::WebMediaStreamTrack web_media_stream_track;
-  const WebString track_id(CreateCanonicalUUIDString());
+  const WebString track_id(WTF::CreateCanonicalUUIDString());
 
   web_media_stream_source.Initialize(track_id,
                                      blink::WebMediaStreamSource::kTypeAudio,
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index 776068d..ae6b629 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -750,7 +750,7 @@
           "presentation/presentation_connection_available_event_init.idl",
           "presentation/presentation_connection_close_event_init.idl",
           "push_messaging/push_event_init.idl",
-          "push_messaging/push_subscription_change_init.idl",
+          "push_messaging/push_subscription_change_event_init.idl",
           "push_messaging/push_subscription_options_init.idl",
           "quota/storage_estimate.idl",
           "quota/storage_usage_details.idl",
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc
index eb983d3..f51de9f 100644
--- a/third_party/blink/renderer/modules/payments/payment_request.cc
+++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -58,10 +58,10 @@
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/mojo/mojo_helper.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace {
 
@@ -1082,7 +1082,7 @@
   PaymentDetailsPtr validated_details =
       payments::mojom::blink::PaymentDetails::New();
   validated_details->id = id_ =
-      details->hasId() ? details->id() : CreateCanonicalUUIDString();
+      details->hasId() ? details->id() : WTF::CreateCanonicalUUIDString();
 
   Vector<payments::mojom::blink::PaymentMethodDataPtr> validated_method_data;
   ValidateAndConvertPaymentMethodData(method_data, validated_method_data,
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.cc b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.cc
index 53dc293..86e6bf9 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.cc
+++ b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.cc
@@ -4,7 +4,7 @@
 
 #include "third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.h"
 
-#include "third_party/blink/renderer/modules/push_messaging/push_subscription_change_init.h"
+#include "third_party/blink/renderer/modules/push_messaging/push_subscription_change_event_init.h"
 
 namespace blink {
 
@@ -19,7 +19,7 @@
 
 PushSubscriptionChangeEvent::PushSubscriptionChangeEvent(
     const AtomicString& type,
-    PushSubscriptionChangeInit* initializer)
+    PushSubscriptionChangeEventInit* initializer)
     : ExtendableEvent(type, initializer) {
   if (initializer->hasNewSubscription())
     new_subscription_ = initializer->newSubscription();
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.h b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.h
index 51a023c0f..58895ad 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.h
+++ b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.h
@@ -14,7 +14,7 @@
 
 namespace blink {
 
-class PushSubscriptionChangeInit;
+class PushSubscriptionChangeEventInit;
 
 class MODULES_EXPORT PushSubscriptionChangeEvent final
     : public ExtendableEvent {
@@ -30,7 +30,7 @@
   }
   static PushSubscriptionChangeEvent* Create(
       const AtomicString& type,
-      PushSubscriptionChangeInit* initializer) {
+      PushSubscriptionChangeEventInit* initializer) {
     return MakeGarbageCollected<PushSubscriptionChangeEvent>(type, initializer);
   }
 
@@ -39,7 +39,7 @@
                               PushSubscription* old_subscription,
                               WaitUntilObserver* observer);
   PushSubscriptionChangeEvent(const AtomicString& type,
-                              PushSubscriptionChangeInit* initializer);
+                              PushSubscriptionChangeEventInit* initializer);
   ~PushSubscriptionChangeEvent() override;
 
   PushSubscription* newSubscription() const;
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.idl b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.idl
index be0e7e39..0c64c45 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.idl
+++ b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event.idl
@@ -5,7 +5,7 @@
 // https://w3c.github.io/push-api/#pushsubscriptionchangeevent-interface
 
 [
-    Constructor(DOMString type, optional PushSubscriptionChangeInit eventInitDict),
+    Constructor(DOMString type, optional PushSubscriptionChangeEventInit eventInitDict),
     Exposed=ServiceWorker,
     RuntimeEnabled=PushMessagingSubscriptionChange
 ] interface PushSubscriptionChangeEvent : ExtendableEvent {
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_init.idl b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event_init.idl
similarity index 82%
rename from third_party/blink/renderer/modules/push_messaging/push_subscription_change_init.idl
rename to third_party/blink/renderer/modules/push_messaging/push_subscription_change_event_init.idl
index d376723a..94a48a2 100644
--- a/third_party/blink/renderer/modules/push_messaging/push_subscription_change_init.idl
+++ b/third_party/blink/renderer/modules/push_messaging/push_subscription_change_event_init.idl
@@ -4,7 +4,7 @@
 
 // https://w3c.github.io/push-api/#pushsubscriptionchangeevent-interface
 
-dictionary PushSubscriptionChangeInit : ExtendableEventInit {
+dictionary PushSubscriptionChangeEventInit : ExtendableEventInit {
   PushSubscription newSubscription = null;
   PushSubscription oldSubscription = null;
 };
diff --git a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc b/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc
index 4860784..77d2c2d 100644
--- a/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc
+++ b/third_party/blink/renderer/modules/sensor/sensor_inspector_agent.cc
@@ -48,7 +48,8 @@
                                 double gamma,
                                 device::SensorReading* reading) {
   FillQuaternion(alpha, beta, gamma, &reading->orientation_quat);
-  reading->orientation_quat.timestamp = WTF::CurrentTimeTicksInSeconds();
+  reading->orientation_quat.timestamp =
+      base::TimeTicks::Now().since_origin().InSecondsF();
 }
 
 const char kInspectorConsoleMessage[] =
diff --git a/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc b/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
index 30e962d..beab6fb2e 100644
--- a/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
+++ b/third_party/blink/renderer/modules/service_worker/respond_with_observer.cc
@@ -18,7 +18,7 @@
 namespace blink {
 
 void RespondWithObserver::WillDispatchEvent() {
-  event_dispatch_time_ = WTF::CurrentTimeTicks();
+  event_dispatch_time_ = base::TimeTicks::Now();
 }
 
 void RespondWithObserver::DidDispatchEvent(
diff --git a/third_party/blink/renderer/modules/storage/storage_controller_test.cc b/third_party/blink/renderer/modules/storage/storage_controller_test.cc
index 4b80a98..34f0a607 100644
--- a/third_party/blink/renderer/modules/storage/storage_controller_test.cc
+++ b/third_party/blink/renderer/modules/storage/storage_controller_test.cc
@@ -15,8 +15,8 @@
 #include "third_party/blink/renderer/modules/storage/testing/fake_area_source.h"
 #include "third_party/blink/renderer/modules/storage/testing/mock_storage_area.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 namespace {
@@ -94,8 +94,8 @@
 }
 
 TEST(StorageControllerTest, CacheLimitSessionStorage) {
-  const String kNamespace1 = CreateCanonicalUUIDString();
-  const String kNamespace2 = CreateCanonicalUUIDString();
+  const String kNamespace1 = WTF::CreateCanonicalUUIDString();
+  const String kNamespace2 = WTF::CreateCanonicalUUIDString();
   const auto kOrigin = SecurityOrigin::CreateFromString("http://dom_storage1/");
   const auto kOrigin2 =
       SecurityOrigin::CreateFromString("http://dom_storage2/");
diff --git a/third_party/blink/renderer/modules/storage/storage_namespace_test.cc b/third_party/blink/renderer/modules/storage/storage_namespace_test.cc
index 2b674db8..e4752c3 100644
--- a/third_party/blink/renderer/modules/storage/storage_namespace_test.cc
+++ b/third_party/blink/renderer/modules/storage/storage_namespace_test.cc
@@ -12,8 +12,8 @@
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/renderer/modules/storage/testing/fake_area_source.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 namespace {
diff --git a/third_party/blink/renderer/modules/vr/vr_display.cc b/third_party/blink/renderer/modules/vr/vr_display.cc
index fedc5e2..1d8a68ba 100644
--- a/third_party/blink/renderer/modules/vr/vr_display.cc
+++ b/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -80,7 +80,7 @@
       return;
     base::TimeTicks monotonic_time;
     if (!vr_display_->GetDocument() || !vr_display_->GetDocument()->Loader()) {
-      monotonic_time = WTF::CurrentTimeTicks();
+      monotonic_time = base::TimeTicks::Now();
     } else {
       // Convert document-zero time back to monotonic time.
       base::TimeTicks reference_monotonic_time = vr_display_->GetDocument()
@@ -298,7 +298,7 @@
     if (pending_non_immersive_vsync_)
       return;
     non_immersive_vsync_waiting_for_pose_.Reset();
-    non_immersive_pose_request_time_ = WTF::CurrentTimeTicks();
+    non_immersive_pose_request_time_ = base::TimeTicks::Now();
 
     if (non_immersive_provider_) {
       non_immersive_provider_->GetFrameData(
@@ -720,7 +720,7 @@
   // Run window.rAF once manually so that applications get a chance to
   // schedule a VRDisplay.rAF in case they do so only while presenting.
   if (doc && !pending_vrdisplay_raf_ && !capabilities_->hasExternalDisplay()) {
-    base::TimeTicks timestamp = WTF::CurrentTimeTicks();
+    base::TimeTicks timestamp = base::TimeTicks::Now();
     doc->GetTaskRunner(blink::TaskType::kInternalMedia)
         ->PostTask(FROM_HERE,
                    WTF::Bind(&VRDisplay::ProcessScheduledWindowAnimations,
@@ -1142,7 +1142,7 @@
     return;
   vr_frame_id_ = -1;
   base::TimeDelta pose_age =
-      WTF::CurrentTimeTicks() - non_immersive_pose_received_time_;
+      base::TimeTicks::Now() - non_immersive_pose_received_time_;
   if (pose_age >= kNonImmersivePoseAgeThreshold &&
       non_immersive_pose_request_time_ > non_immersive_pose_received_time_) {
     // The VSync got triggered before ever receiving a pose, or the pose is
@@ -1161,7 +1161,7 @@
 
 void VRDisplay::OnNonImmersiveFrameData(
     device::mojom::blink::XRFrameDataPtr data) {
-  non_immersive_pose_received_time_ = WTF::CurrentTimeTicks();
+  non_immersive_pose_received_time_ = base::TimeTicks::Now();
   if (data) {
     if (!in_animation_frame_) {
       frame_pose_ = std::move(data->pose);
diff --git a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
index 60407bad..69c0bc3 100644
--- a/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/base_audio_context.cc
@@ -74,9 +74,9 @@
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/histogram.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 #include <algorithm>
 
@@ -96,7 +96,7 @@
       destination_node_(nullptr),
       is_resolving_resume_promises_(false),
       task_runner_(document->GetTaskRunner(TaskType::kInternalMedia)),
-      uuid_(CreateCanonicalUUIDString()),
+      uuid_(WTF::CreateCanonicalUUIDString()),
       is_cleared_(false),
       has_posted_cleanup_task_(false),
       deferred_task_handler_(DeferredTaskHandler::Create(
diff --git a/third_party/blink/renderer/modules/webaudio/docs/convolver.md b/third_party/blink/renderer/modules/webaudio/docs/convolver.md
deleted file mode 100644
index d35d9cd9..0000000
--- a/third_party/blink/renderer/modules/webaudio/docs/convolver.md
+++ /dev/null
@@ -1,190 +0,0 @@
-# Convolution Reverb
-
-A [convolution reverb](http://en.wikipedia.org/wiki/Convolution_reverb) can be used
-to simulate an acoustic space with very high quality. It can also be
-used as the basis for creating a vast number of unique and interesting
-special effects.  This technique is widely used in modern professional
-audio and motion picture production, and is an excellent choice to
-create room effects in a game engine.
-
-Creating a well-optimized real-time convolution engine is one of the
-more challenging parts of the Web Audio API implementation.  When
-convolving an input audio stream of unknown (or theoretically
-infinite) length, the
-[overlap-add](http://en.wikipedia.org/wiki/Overlap-add_method)
-approach is used, chopping the input stream into pieces of length L,
-performing the convolution on each piece, then re-constructing the
-output signal by delaying each result and summing.
-
-
-## Overlap-Add Convolution
-
-![Depiction of overlap-add algorithm](http://upload.wikimedia.org/wikipedia/commons/7/77/Depiction_of_overlap-add_algorithm.png)
-  
-  
-Direct convolution is far too computationally expensive due to the
-extremely long impulse responses typically used.  Therefore an
-approach using [FFTs](http://en.wikipedia.org/wiki/FFT) must be used.
-But naively doing a standard overlap-add FFT convolution using an FFT
-of size N with L=N/2, where N is chosen to be at least twice the
-length of the convolution kernel (zero-padding the kernel) to perform
-each convolution operation in the diagram above would incur a
-substantial input to output pipeline latency on the order of L
-samples.  Because of the enormous audible delay, this simple method
-cannot be used.  Aside from the enormous delay, the size N of the FFT
-could be extremely large.  For example, with an impulse response of 10
-seconds at 44.1Khz, N would equal 1048576 (2^20).  This would take a
-very long time to evaluate.  Furthermore, such large FFTs are not
-practical due to substantial phase errors.
-
-
-## Optimizations and Tricks
-
-There exist several clever tricks which break the impulse response
-into smaller pieces, performing separate convolutions, then combining
-the results (exploiting the property of linearity).  The best ones use
-a divide and conquer approach using different size FFTs and a direct
-convolution for the initial (leading) portion of the impulse response
-to achieve a zero-latency output.  There are additional optimizations
-which can be done exploiting the fact that the tail of the reverb
-typically contains very little or no high-frequency energy.  For this
-part, the convolution may be done at a lower sample-rate...
-
-Performance can be quite good, easily done in real-time without
-creating undo stress on modern mid-range CPUs.  A multi-threaded
-implementation is really required if low (or zero) latency is required
-because of the way the buffering / processing chunking works.
-Achieving good performance requires a highly optimized FFT algorithm.
-
-### Multi-channel convolution
-
-It should be noted that a convolution reverb typically involves two
-convolution operations, with separate impulse responses for the left
-and right channels in the stereo case.  For 5.1 surround, at least
-five separate convolution operations are necessary to generate output
-for each of the five channels.
-
-### Impulse Responses
-
-Similar to other assets such as JPEG images, WAV sound files, MP4
-videos, shaders, and geometry, impulse responses can be considered as
-multi-media assets.  As with these other assets, they require work to
-produce, and the high-quality ones are considered valuable.  For
-example, a company called Audio Ease makes a fairly expensive ($500 -
-$1000) product called
-[Altiverb](http://www.audioease.com/Pages/Altiverb/AltiverbMain.html)
-containing several nicely recorded impulse responses along with a
-convolution reverb engine.
-
-
-# Convolution Engine Implementation
-    
-    
-## FFTConvolver (short convolutions)
-
-The `FFTConvolver` is able to do short convolutions with
-the FFT size N being at least twice as large as the length of the
-short impulse response.  It incurs a latency of N/2 sample-frames.
-Because of this latency and performance considerations, it is not
-suitable for long convolutions.  Multiple instances of this building
-block can be used to perform extremely long convolutions.
-    
-![description of FFT convolver](images/fft-convolver.png)
-    
-
-## ReverbConvolver (long convolutions)
-
-The `ReverbConvolver` is able to perform extremely long
-real-time convolutions on a single audio channel.  It uses multiple
-`FFTConvolver` objects as well as an input buffer and an
-accumulation buffer.  Note that it's possible to get a multi-threaded
-implementation by exploiting the parallelism.  Also note that the
-leading sections of the long impulse response are processed in the
-real-time thread for minimum latency.  In theory it's possible to get
-zero latency if the very first FFTConvolver is replaced with a
-DirectConvolver (not using a FFT).
-    
-![description of reverb convolver](images/reverb-convolver.png)
-
-    
-## Reverb Effect (with matrixing)
-![description of reverb matrixing](images/reverb-matrixing.png)
-
-
-
-
-
-# Recording Impulse Responses
-
-
-![impulse-response waveforms](images/impulse-response.png)
-
-
-The most
-[modern](http://pcfarina.eng.unipr.it/Public/Papers/226-AES122.pdf)
-and accurate way to record the impulse response of a real acoustic
-space is to use a long exponential sine sweep. The test-tone can be as
-long as 20 or 30 seconds, or longer.
-
-
-
-
-Several recordings of the test tone played through a speaker can be
-made with microphones placed and oriented at various positions in the
-room.  It's important to document speaker placement/orientation, the
-types of microphones, their settings, placement, and orientations for
-each recording taken.
-
-Post-processing is required for each of these recordings by performing
-an inverse-convolution with the test tone, yielding the impulse
-response of the room with the corresponding microphone placement.
-These impulse responses are then ready to be loaded into the
-convolution reverb engine to re-create the sound of being in the room.
-
-# Tools
-
-Two command-line tools have been written:
-
-`generate_testtones` generates an exponential sine-sweep
-test-tone and its inverse.  Another tool `convolve` was
-written for post-processing.  With these tools, anybody with recording
-equipment can record their own impulse responses.  To test the tools
-in practice, several recordings were made in a warehouse space with
-interesting acoustics.  These were later post-processed with the
-command-line tools.  </p>
-
-```shell
-    % generate_testtones -h
-    Usage: generate_testtone
-    	[-o /Path/To/File/To/Create] Two files will be created: .tone and .inverse
-    	[-rate &lt;sample rate&gt;] sample rate of the generated test tones
-    	[-duration &lt;duration&gt;] The duration, in seconds, of the generated files
-    	[-min_freq &lt;min_freq&gt;] The minimum frequency, in hertz, for the sine sweep
-
-    % convolve -h
-    Usage: convolve input_file impulse_response_file output_file
-```
-
-
-# Recording Setup
-![photograph of recording setup](images/recording-setup.png)
-
-
-Audio Interface: Metric Halo Mobile I/O 2882 
-
-
-
-
-![microphones and speakers used](images/microphones-speaker.png)
-
-
-![microphone used)](images/microphone.png)
-![speakers used](images/speaker.png)
-
-Microphones: AKG 414s, Speaker: Mackie HR824
-
-
-
-# The Warehouse Space
-
-![photo of the warehouse used](images/warehouse.png)
diff --git a/third_party/blink/renderer/modules/webaudio/docs/convolver_reverb.md b/third_party/blink/renderer/modules/webaudio/docs/convolver_reverb.md
new file mode 100644
index 0000000..f29f0d5
--- /dev/null
+++ b/third_party/blink/renderer/modules/webaudio/docs/convolver_reverb.md
@@ -0,0 +1,90 @@
+# Convolution Reverb
+
+A [convolution reverb](http://en.wikipedia.org/wiki/Convolution_reverb) can be
+used to simulate an acoustic space with very high quality. It can also be used
+as the basis for creating a vast number of unique and interesting special
+effects.  This technique is widely used in modern professional audio and motion
+picture production, and is an excellent choice to create room effects in a game
+engine.
+
+Creating a well-optimized real-time convolution engine is one of the more
+challenging parts of the Web Audio API implementation.  When convolving an input
+audio stream of unknown (or theoretically infinite) length, the
+[overlap-add](http://en.wikipedia.org/wiki/Overlap-add_method) approach is used,
+chopping the input stream into pieces of length L, performing the convolution on
+each piece, then re-constructing the output signal by delaying each result and
+summing.
+
+
+## Overlap-Add Convolution
+
+![Depiction of overlap-add
+algorithm](http://upload.wikimedia.org/wikipedia/commons/7/77/Depiction_of_overlap-add_algorithm.png)
+
+Direct convolution is far too computationally expensive due to the extremely
+long impulse responses typically used.  Therefore an approach using
+[FFTs](http://en.wikipedia.org/wiki/FFT) must be used.  But naively doing a
+standard overlap-add FFT convolution using an FFT of size N with L=N/2, where N
+is chosen to be at least twice the length of the convolution kernel
+(zero-padding the kernel) to perform each convolution operation in the diagram
+above would incur a substantial input to output pipeline latency on the order of
+L samples.  Because of the enormous audible delay, this simple method cannot be
+used.  Aside from the enormous delay, the size N of the FFT could be extremely
+large.  For example, with an impulse response of 10 seconds at 44.1Khz, N would
+equal 1048576 (2^20).  This would take a very long time to evaluate.
+Furthermore, such large FFTs are not practical due to substantial phase errors.
+
+## Optimizations and Tricks
+
+There exist several clever tricks which break the impulse response into smaller
+pieces, performing separate convolutions, then combining the results (exploiting
+the property of linearity).  The best ones use a divide and conquer approach
+using different size FFTs and a direct convolution for the initial (leading)
+portion of the impulse response to achieve a zero-latency output.  There are
+additional optimizations which can be done exploiting the fact that the tail of
+the reverb typically contains very little or no high-frequency energy.  For this
+part, the convolution may be done at a lower sample-rate...
+
+Performance can be quite good, easily done in real-time without creating undo
+stress on modern mid-range CPUs.  A multi-threaded implementation is really
+required if low (or zero) latency is required because of the way the buffering /
+processing chunking works.  Achieving good performance requires a highly
+optimized FFT algorithm.
+
+### Multi-channel convolution
+
+It should be noted that a convolution reverb typically involves two convolution
+operations, with separate impulse responses for the left and right channels in
+the stereo case.  For 5.1 surround, at least five separate convolution
+operations are necessary to generate output for each of the five channels.
+However, we only need to support stereo, as given in [Channel Configurations for
+Input, Impulse Response and
+Output](https://webaudio.github.io/web-audio-api/#Convolution-channel-configurations).
+
+# Convolution Engine Implementation
+
+## FFTConvolver (short convolutions)
+
+The
+[`FFTConvolver`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/audio/fft_convolver.h)
+is able to do short convolutions with the FFT size N being at least twice as
+large as the length of the short impulse response.  It incurs a latency of N/2
+sample-frames.  Because of this latency and performance considerations, it is
+not suitable for long convolutions.  Multiple instances of this building block
+can be used to perform extremely long convolutions.
+
+![description of FFT convolver](images/fft-convolver.png)
+
+## ReverbConvolver (long convolutions)
+
+The
+[`ReverbConvolver`](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/audio/reverb_convolver.h)
+is able to perform extremely long real-time convolutions on a single audio
+channel.  It uses multiple `FFTConvolver` objects as well as an input buffer and
+an accumulation buffer.  Note that it's possible to get a multi-threaded
+implementation by exploiting the parallelism.  Also note that the leading
+sections of the long impulse response are processed in the real-time thread for
+minimum latency.  In theory it's possible to get zero latency if the very first
+FFTConvolver is replaced with a DirectConvolver (not using a FFT).
+
+![description of reverb convolver](images/reverb-convolver.png)
diff --git a/third_party/blink/renderer/modules/webaudio/docs/images/microphone.png b/third_party/blink/renderer/modules/webaudio/docs/images/microphone.png
deleted file mode 100644
index 130fbed5..0000000
--- a/third_party/blink/renderer/modules/webaudio/docs/images/microphone.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/renderer/modules/webaudio/docs/images/microphones-speaker.png b/third_party/blink/renderer/modules/webaudio/docs/images/microphones-speaker.png
deleted file mode 100644
index 4b27fa2..0000000
--- a/third_party/blink/renderer/modules/webaudio/docs/images/microphones-speaker.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/renderer/modules/webaudio/docs/images/recording-setup.png b/third_party/blink/renderer/modules/webaudio/docs/images/recording-setup.png
deleted file mode 100644
index c7b64e8..0000000
--- a/third_party/blink/renderer/modules/webaudio/docs/images/recording-setup.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/renderer/modules/webaudio/docs/images/reverb-matrixing.png b/third_party/blink/renderer/modules/webaudio/docs/images/reverb-matrixing.png
deleted file mode 100644
index f05f048..0000000
--- a/third_party/blink/renderer/modules/webaudio/docs/images/reverb-matrixing.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/renderer/modules/webaudio/docs/images/speaker.png b/third_party/blink/renderer/modules/webaudio/docs/images/speaker.png
deleted file mode 100644
index 7137a98e..0000000
--- a/third_party/blink/renderer/modules/webaudio/docs/images/speaker.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/renderer/modules/webaudio/docs/images/warehouse.png b/third_party/blink/renderer/modules/webaudio/docs/images/warehouse.png
deleted file mode 100644
index 3a760d5..0000000
--- a/third_party/blink/renderer/modules/webaudio/docs/images/warehouse.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/renderer/modules/webaudio/inspector_helper_mixin.h b/third_party/blink/renderer/modules/webaudio/inspector_helper_mixin.h
index 847e42e..06321c30 100644
--- a/third_party/blink/renderer/modules/webaudio/inspector_helper_mixin.h
+++ b/third_party/blink/renderer/modules/webaudio/inspector_helper_mixin.h
@@ -6,7 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBAUDIO_INSPECTOR_HELPER_MIXIN_H_
 
 #include <memory>
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -16,8 +16,7 @@
 class InspectorHelperMixin {
  public:
   explicit InspectorHelperMixin(const String& parent_uuid)
-      : uuid_(CreateCanonicalUUIDString()),
-        parent_uuid_(parent_uuid) {}
+      : uuid_(WTF::CreateCanonicalUUIDString()), parent_uuid_(parent_uuid) {}
   ~InspectorHelperMixin() = default;
 
   const String& Uuid() const { return uuid_; }
diff --git a/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc b/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
index 4fd481d9..ec7420f 100644
--- a/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
+++ b/third_party/blink/renderer/modules/webaudio/media_stream_audio_destination_node.cc
@@ -34,7 +34,7 @@
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_center.h"
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -176,7 +176,7 @@
     uint32_t number_of_channels)
     : AudioBasicInspectorNode(context),
       source_(MakeGarbageCollected<MediaStreamSource>(
-          "WebAudio-" + CreateCanonicalUUIDString(),
+          "WebAudio-" + WTF::CreateCanonicalUUIDString(),
           MediaStreamSource::kTypeAudio,
           "MediaStreamAudioDestinationNode",
           false,
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 20851fcc..01612f63 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
+#include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h"
 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
 #include "third_party/blink/renderer/core/html/canvas/image_data.h"
 #include "third_party/blink/renderer/core/html/html_image_element.h"
@@ -743,8 +744,9 @@
 }
 
 void WebGLRenderingContextBase::commit() {
-  if (!GetDrawingBuffer())
+  if (!GetDrawingBuffer() || (Host() && Host()->IsOffscreenCanvas()))
     return;
+
   int width = GetDrawingBuffer()->Size().Width();
   int height = GetDrawingBuffer()->Size().Height();
 
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl b/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl
index bd748351..eeb87a9 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_color_state_descriptor.idl
@@ -7,7 +7,7 @@
 dictionary GPUColorStateDescriptor {
     required GPUTextureFormat format;
 
-    required GPUBlendDescriptor alphaBlend;
-    required GPUBlendDescriptor colorBlend;
+    GPUBlendDescriptor alphaBlend;
+    GPUBlendDescriptor colorBlend;
     GPUColorWriteFlags writeMask = 15;  // GPUColorWrite.ALL
 };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc b/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc
index ab52a396..7bdadc11 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.cc
@@ -41,8 +41,17 @@
 
   DawnColorStateDescriptor dawn_desc;
   dawn_desc.nextInChain = nullptr;
-  dawn_desc.alphaBlend = AsDawnType(webgpu_desc->alphaBlend());
-  dawn_desc.colorBlend = AsDawnType(webgpu_desc->colorBlend());
+
+  GPUBlendDescriptor* gpu_alpha_blend = webgpu_desc->hasAlphaBlend()
+                                            ? webgpu_desc->alphaBlend()
+                                            : GPUBlendDescriptor::Create();
+  dawn_desc.alphaBlend = AsDawnType(gpu_alpha_blend);
+
+  GPUBlendDescriptor* gpu_color_blend = webgpu_desc->hasColorBlend()
+                                            ? webgpu_desc->colorBlend()
+                                            : GPUBlendDescriptor::Create();
+  dawn_desc.colorBlend = AsDawnType(gpu_color_blend);
+
   dawn_desc.writeMask =
       AsDawnEnum<DawnColorWriteMask>(webgpu_desc->writeMask());
   dawn_desc.format = AsDawnEnum<DawnTextureFormat>(webgpu_desc->format());
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 68ccb03..097cd2f 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1326,8 +1326,6 @@
     "transforms/transformation_matrix.h",
     "transforms/translate_transform_operation.cc",
     "transforms/translate_transform_operation.h",
-    "uuid.cc",
-    "uuid.h",
     "web_gesture_event.cc",
     "web_icon_sizes_parser.cc",
     "web_mouse_event.cc",
@@ -1777,7 +1775,6 @@
     "transforms/rotation_test.cc",
     "transforms/transform_operations_test.cc",
     "transforms/transformation_matrix_test.cc",
-    "uuid_test.cc",
     "web_icon_sizes_parser_test.cc",
     "web_screen_info_test.cc",
     "web_vector_test.cc",
diff --git a/third_party/blink/renderer/platform/bindings/parkable_string_test.cc b/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
index e746515f..1797cab 100644
--- a/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
+++ b/third_party/blink/renderer/platform/bindings/parkable_string_test.cc
@@ -45,7 +45,7 @@
                          ThreadPoolExecutionMode::DEFAULT)
       : ::testing::Test(),
         scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             thread_pool_execution_mode) {}
 
  protected:
diff --git a/third_party/blink/renderer/platform/blob/DEPS b/third_party/blink/renderer/platform/blob/DEPS
index d6479c8..a1d21dc 100644
--- a/third_party/blink/renderer/platform/blob/DEPS
+++ b/third_party/blink/renderer/platform/blob/DEPS
@@ -11,7 +11,7 @@
     "+third_party/blink/renderer/platform/platform_export.h",
     "+third_party/blink/renderer/platform/scheduler/public",
     "+third_party/blink/renderer/platform/testing",
-    "+third_party/blink/renderer/platform/uuid.h",
+    "+third_party/blink/renderer/platform/wtf/uuid.h",
     "+third_party/blink/renderer/platform/weborigin",
     "+third_party/blink/renderer/platform/web_task_runner.h",
     "+third_party/blink/renderer/platform/wtf",
diff --git a/third_party/blink/renderer/platform/blob/blob_data.cc b/third_party/blink/renderer/platform/blob/blob_data.cc
index 195e5e4..d1e69472 100644
--- a/third_party/blink/renderer/platform/blob/blob_data.cc
+++ b/third_party/blink/renderer/platform/blob/blob_data.cc
@@ -48,10 +48,10 @@
 #include "third_party/blink/renderer/platform/blob/blob_registry.h"
 #include "third_party/blink/renderer/platform/histogram.h"
 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/line_ending.h"
 #include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
@@ -321,7 +321,7 @@
 }
 
 BlobDataHandle::BlobDataHandle()
-    : uuid_(CreateCanonicalUUIDString()),
+    : uuid_(WTF::CreateCanonicalUUIDString()),
       size_(0),
       is_single_unknown_size_file_(false) {
   GetThreadSpecificRegistry()->Register(MakeRequest(&blob_info_), uuid_, "", "",
@@ -329,7 +329,7 @@
 }
 
 BlobDataHandle::BlobDataHandle(std::unique_ptr<BlobData> data, uint64_t size)
-    : uuid_(CreateCanonicalUUIDString()),
+    : uuid_(WTF::CreateCanonicalUUIDString()),
       type_(data->ContentType().IsolatedCopy()),
       size_(size),
       is_single_unknown_size_file_(data->IsSingleUnknownSizeFile()) {
diff --git a/third_party/blink/renderer/platform/blob/blob_data_test.cc b/third_party/blink/renderer/platform/blob/blob_data_test.cc
index 6d733071..6933be5a 100644
--- a/third_party/blink/renderer/platform/blob/blob_data_test.cc
+++ b/third_party/blink/renderer/platform/blob/blob_data_test.cc
@@ -19,7 +19,7 @@
 #include "third_party/blink/renderer/platform/blob/blob_bytes_provider.h"
 #include "third_party/blink/renderer/platform/blob/testing/fake_blob_registry.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -264,7 +264,7 @@
 }
 
 TEST_F(BlobDataHandleTest, CreateFromUUID) {
-  String kUuid = CreateCanonicalUUIDString();
+  String kUuid = WTF::CreateCanonicalUUIDString();
   String kType = "content/type";
   uint64_t kSize = 1234;
 
diff --git a/third_party/blink/renderer/platform/blob/blob_url.cc b/third_party/blink/renderer/platform/blob/blob_url.cc
index ac38073..08d382a8 100644
--- a/third_party/blink/renderer/platform/blob/blob_url.cc
+++ b/third_party/blink/renderer/platform/blob/blob_url.cc
@@ -30,10 +30,10 @@
 
 #include "third_party/blink/renderer/platform/blob/blob_url.h"
 
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -55,7 +55,7 @@
 KURL BlobURL::CreateBlobURL(const String& origin_string) {
   DCHECK(!origin_string.IsEmpty());
   String url_string =
-      "blob:" + origin_string + '/' + CreateCanonicalUUIDString();
+      "blob:" + origin_string + '/' + WTF::CreateCanonicalUUIDString();
   return KURL::CreateIsolated(url_string);
 }
 
diff --git a/third_party/blink/renderer/platform/exported/web_media_stream.cc b/third_party/blink/renderer/platform/exported/web_media_stream.cc
index cd532c63..4f61fea 100644
--- a/third_party/blink/renderer/platform/exported/web_media_stream.cc
+++ b/third_party/blink/renderer/platform/exported/web_media_stream.cc
@@ -32,8 +32,8 @@
 #include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
-#include "third_party/blink/renderer/platform/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
 
 namespace blink {
@@ -128,7 +128,7 @@
 void WebMediaStream::Initialize(
     const WebVector<WebMediaStreamTrack>& audio_tracks,
     const WebVector<WebMediaStreamTrack>& video_tracks) {
-  Initialize(CreateCanonicalUUIDString(), audio_tracks, video_tracks);
+  Initialize(WTF::CreateCanonicalUUIDString(), audio_tracks, video_tracks);
 }
 
 void WebMediaStream::Initialize(
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc
index d2530d9c..e84ee65 100644
--- a/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -175,6 +175,8 @@
   resource_request_->SetHttpReferrer(
       Referrer(referrer, referrer_policy),
       ResourceRequest::SetHttpReferrerLocation::kWebURLRequest);
+  resource_request_->SetReferrerString(
+      referrer, ResourceRequest::SetReferrerStringLocation::kWebURLRequest);
 }
 
 void WebURLRequest::AddHttpHeaderField(const WebString& name,
diff --git a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
index d7be56d..16e6508 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/xr_frame_transport.cc
@@ -240,14 +240,14 @@
 
 base::TimeDelta XRFrameTransport::WaitForPreviousRenderToFinish() {
   TRACE_EVENT0("gpu", "waitForPreviousRenderToFinish");
-  base::TimeTicks start = WTF::CurrentTimeTicks();
+  base::TimeTicks start = base::TimeTicks::Now();
   while (waiting_for_previous_frame_render_) {
     if (!submit_frame_client_binding_.WaitForIncomingMethodCall()) {
       DLOG(ERROR) << __FUNCTION__ << ": Failed to receive response";
       break;
     }
   }
-  return WTF::CurrentTimeTicks() - start;
+  return base::TimeTicks::Now() - start;
 }
 
 void XRFrameTransport::OnSubmitFrameGpuFence(
@@ -259,14 +259,14 @@
 
 base::TimeDelta XRFrameTransport::WaitForGpuFenceReceived() {
   TRACE_EVENT0("gpu", "WaitForGpuFenceReceived");
-  base::TimeTicks start = WTF::CurrentTimeTicks();
+  base::TimeTicks start = base::TimeTicks::Now();
   while (waiting_for_previous_frame_fence_) {
     if (!submit_frame_client_binding_.WaitForIncomingMethodCall()) {
       DLOG(ERROR) << __FUNCTION__ << ": Failed to receive response";
       break;
     }
   }
-  return WTF::CurrentTimeTicks() - start;
+  return base::TimeTicks::Now() - start;
 }
 
 void XRFrameTransport::Trace(blink::Visitor* visitor) {}
diff --git a/third_party/blink/renderer/platform/graphics/picture_snapshot.cc b/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
index 68e7860d..f994a1fc 100644
--- a/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
+++ b/third_party/blink/renderer/platform/graphics/picture_snapshot.cc
@@ -137,7 +137,7 @@
       SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()));
   bitmap.eraseARGB(0, 0, 0, 0);
 
-  base::TimeTicks now = WTF::CurrentTimeTicks();
+  base::TimeTicks now = base::TimeTicks::Now();
   base::TimeTicks stop_time = now + min_duration;
   for (unsigned step = 0; step < min_repeat_count || now < stop_time; ++step) {
     Vector<base::TimeDelta> current_timings;
@@ -153,7 +153,7 @@
     canvas.SetTimings(&current_timings);
     picture_->playback(&canvas);
     timings.push_back(std::move(current_timings));
-    now = WTF::CurrentTimeTicks();
+    now = base::TimeTicks::Now();
   }
   return timings;
 }
diff --git a/third_party/blink/renderer/platform/graphics/profiling_canvas.cc b/third_party/blink/renderer/platform/graphics/profiling_canvas.cc
index 24cecaa..0476093dc 100644
--- a/third_party/blink/renderer/platform/graphics/profiling_canvas.cc
+++ b/third_party/blink/renderer/platform/graphics/profiling_canvas.cc
@@ -30,18 +30,16 @@
 
 #include "third_party/blink/renderer/platform/graphics/profiling_canvas.h"
 
-#include "third_party/blink/renderer/platform/wtf/time.h"
-
 namespace blink {
 
 CanvasInterceptor<ProfilingCanvas>::CanvasInterceptor(
     InterceptingCanvasBase* canvas)
-    : CanvasInterceptorBase(canvas), start_time_(WTF::CurrentTimeTicks()) {}
+    : CanvasInterceptorBase(canvas), start_time_(base::TimeTicks::Now()) {}
 
 CanvasInterceptor<ProfilingCanvas>::~CanvasInterceptor() {
   if (!TopLevelCall())
     return;
-  base::TimeDelta delta = WTF::CurrentTimeTicks() - start_time_;
+  base::TimeDelta delta = base::TimeTicks::Now() - start_time_;
   if (auto* timings = Canvas()->timings_) {
     DCHECK_EQ(timings->size(), Canvas()->CallCount());
     timings->push_back(delta);
diff --git a/third_party/blink/renderer/platform/heap/BlinkGCDesign.md b/third_party/blink/renderer/platform/heap/BlinkGCDesign.md
index cbac6aa5..e19b9e4b 100644
--- a/third_party/blink/renderer/platform/heap/BlinkGCDesign.md
+++ b/third_party/blink/renderer/platform/heap/BlinkGCDesign.md
@@ -38,7 +38,6 @@
 
 For example
 - objects over 64KiB goes into `kLargeObjectArenaIndex`
-- objects that have an eager finalizer goes into `kEagerSweepArenaIndex`
 - objects that is a collection backing goes into one of the collection backing
 arenas
 - objects that is a Node or a CSSValue goes into one of the typed arenas
@@ -90,13 +89,9 @@
 Thus the pre-finalizers are allowed to touch any other on-heap objects
 (which may get destructed in this sweeping phase).
 
-Step 2. Invokes destructors of dead objects that are marked as
-eagerly-finalized. See the following notes for more details about the
-eagerly-finalized objects.
+Step 2. The thread resumes mutator's execution. (A mutator means user code.)
 
-Step 3. The thread resumes mutator's execution. (A mutator means user code.)
-
-Step 4. As the mutator allocates new objects, lazy sweeping invokes
+Step 3. As the mutator allocates new objects, lazy sweeping invokes
 destructors of the remaining dead objects incrementally.
 
 There is no guarantee of the order in which the destructors are invoked.
@@ -131,10 +126,3 @@
 at each sweeping phase to determine which pre-finalizers to be invoked
 (the thread needs to invoke pre-finalizers of dead objects). Adding
 pre-finalizers to frequently created objects should be avoided.
-
-* Eagerly-finalized objects are guaranteed to get destructed before the
-mutator resumes its execution. This means that a destructor of
-an eagerly-finalized object is allowed to touch other not-eagerly-finalized
-objects whereas it's not allowed to touch other eagerly-finalized objects.
-This notion is useful for some objects, but nasty.
-We're planning to replace most eagerly-finalized objects with pre-finalizers.
diff --git a/third_party/blink/renderer/platform/heap/heap.cc b/third_party/blink/renderer/platform/heap/heap.cc
index c4fb9e6..8382606 100644
--- a/third_party/blink/renderer/platform/heap/heap.cc
+++ b/third_party/blink/renderer/platform/heap/heap.cc
@@ -273,7 +273,7 @@
     callback(item);
     processed_callback_count++;
     if (++processed_callback_count == kDeadlineCheckInterval) {
-      if (deadline <= CurrentTimeTicks()) {
+      if (deadline <= base::TimeTicks::Now()) {
         return false;
       }
       processed_callback_count = 0;
@@ -609,7 +609,7 @@
     // lazySweepWithDeadline() won't check the deadline until it sweeps
     // 10 pages. So we give a small slack for safety.
     const base::TimeDelta remaining_budget =
-        deadline - slack - CurrentTimeTicks();
+        deadline - slack - base::TimeTicks::Now();
     if (remaining_budget <= base::TimeDelta() ||
         !arenas_[i]->LazySweepWithDeadline(deadline)) {
       return false;
diff --git a/third_party/blink/renderer/platform/heap/heap_page.cc b/third_party/blink/renderer/platform/heap/heap_page.cc
index 222645e..8335908 100644
--- a/third_party/blink/renderer/platform/heap/heap_page.cc
+++ b/third_party/blink/renderer/platform/heap/heap_page.cc
@@ -323,7 +323,7 @@
   while (BasePage* page = unswept_pages_.PopLocked()) {
     SweepUnsweptPage(page);
     if (page_count % kDeadlineCheckInterval == 0) {
-      if (deadline <= CurrentTimeTicks()) {
+      if (deadline <= base::TimeTicks::Now()) {
         // Deadline has come.
         return SweepingAndFinalizationCompleted();
       }
@@ -334,7 +334,7 @@
     swept_pages_.PushLocked(page);
     page->FinalizeSweep(SweepResult::kPageNotEmpty);
     if (page_count % kDeadlineCheckInterval == 0) {
-      if (deadline <= CurrentTimeTicks()) {
+      if (deadline <= base::TimeTicks::Now()) {
         // Deadline has come.
         return SweepingAndFinalizationCompleted();
       }
@@ -344,7 +344,7 @@
   while (BasePage* page = swept_unfinalized_empty_pages_.PopLocked()) {
     page->FinalizeSweep(SweepResult::kPageEmpty);
     if (page_count % kDeadlineCheckInterval == 0) {
-      if (deadline <= CurrentTimeTicks()) {
+      if (deadline <= base::TimeTicks::Now()) {
         // Deadline has come.
         return SweepingAndFinalizationCompleted();
       }
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.cc b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
index 86ed09e..4bce2aa 100644
--- a/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
+++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
@@ -202,11 +202,7 @@
   // Note that scopes added here also have to have a proper BlinkGCInV8Scope
   // scope if they are nested in a V8 scope.
   return incremental_marking_time() + atomic_marking_time() +
-         atomic_sweep_and_compact_time() +
-         scope_data[ThreadHeapStatsCollector::kAtomicPauseSweepAndCompact] +
-         scope_data[ThreadHeapStatsCollector::kCompleteSweep] +
-         scope_data[ThreadHeapStatsCollector::kLazySweepInIdle] +
-         scope_data[ThreadHeapStatsCollector::kLazySweepOnAllocation];
+         atomic_sweep_and_compact_time() + foreground_sweeping_time();
 }
 
 base::TimeDelta ThreadHeapStatsCollector::Event::atomic_pause_time() const {
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.h b/third_party/blink/renderer/platform/heap/heap_stats_collector.h
index 4cdf21db..0076af7d 100644
--- a/third_party/blink/renderer/platform/heap/heap_stats_collector.h
+++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.h
@@ -143,7 +143,7 @@
     inline InternalScope(ThreadHeapStatsCollector* tracer,
                          IdType id,
                          Args... args)
-        : tracer_(tracer), start_time_(WTF::CurrentTimeTicks()), id_(id) {
+        : tracer_(tracer), start_time_(base::TimeTicks::Now()), id_(id) {
       StartTrace(id, args...);
     }
 
@@ -187,12 +187,12 @@
     }
 
     void IncreaseScopeTime(Id) {
-      tracer_->IncreaseScopeTime(id_, WTF::CurrentTimeTicks() - start_time_);
+      tracer_->IncreaseScopeTime(id_, base::TimeTicks::Now() - start_time_);
     }
 
     void IncreaseScopeTime(ConcurrentId) {
       tracer_->IncreaseConcurrentScopeTime(
-          id_, WTF::CurrentTimeTicks() - start_time_);
+          id_, base::TimeTicks::Now() - start_time_);
     }
 
     ThreadHeapStatsCollector* const tracer_;
@@ -216,11 +216,11 @@
    public:
     template <typename... Args>
     BlinkGCInV8Scope(ThreadHeapStatsCollector* tracer)
-        : tracer_(tracer), start_time_(WTF::CurrentTimeTicks()) {}
+        : tracer_(tracer), start_time_(base::TimeTicks::Now()) {}
 
     ~BlinkGCInV8Scope() {
       if (tracer_)
-        tracer_->gc_nested_in_v8_ += WTF::CurrentTimeTicks() - start_time_;
+        tracer_->gc_nested_in_v8_ += base::TimeTicks::Now() - start_time_;
     }
 
    private:
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc
index e6eff474..f039e74 100644
--- a/third_party/blink/renderer/platform/heap/thread_state.cc
+++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -633,7 +633,7 @@
     SweepForbiddenScope scope(this);
     ThreadHeapStatsCollector::EnabledScope stats_scope(
         Heap().stats_collector(), ThreadHeapStatsCollector::kLazySweepInIdle,
-        "idleDeltaInSeconds", (deadline - CurrentTimeTicks()).InSecondsF());
+        "idleDeltaInSeconds", (deadline - base::TimeTicks::Now()).InSecondsF());
     sweep_completed = Heap().AdvanceLazySweep(deadline);
     // We couldn't finish the sweeping within the deadline.
     // We request another idle task for the remaining sweeping.
@@ -1331,7 +1331,7 @@
     Heap().FlushNotFullyConstructedObjects();
   }
   const bool complete = MarkPhaseAdvanceMarking(
-      CurrentTimeTicks() + next_incremental_marking_step_duration_);
+      base::TimeTicks::Now() + next_incremental_marking_step_duration_);
   if (complete) {
     if (IsUnifiedGCMarkingInProgress()) {
       // If there are no more objects to mark for unified garbage collections
@@ -1395,7 +1395,7 @@
   if (SweepForbidden())
     return;
 
-  base::TimeTicks start_total_collect_garbage_time = WTF::CurrentTimeTicks();
+  base::TimeTicks start_total_collect_garbage_time = base::TimeTicks::Now();
   RUNTIME_CALL_TIMER_SCOPE_IF_ISOLATE_EXISTS(
       GetIsolate(), RuntimeCallStats::CounterId::kCollectGarbage);
 
@@ -1418,7 +1418,7 @@
   }
 
   const base::TimeDelta total_collect_garbage_time =
-      WTF::CurrentTimeTicks() - start_total_collect_garbage_time;
+      base::TimeTicks::Now() - start_total_collect_garbage_time;
   UMA_HISTOGRAM_TIMES("BlinkGC.TimeForTotalCollectGarbage",
                       total_collect_garbage_time);
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc b/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
index 09b5f26..bd09b46c 100644
--- a/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/buffering_bytes_consumer_test.cc
@@ -21,7 +21,7 @@
  public:
   BufferingBytesConsumerTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   using Command = ReplayingBytesConsumer::Command;
   using Result = BytesConsumer::Result;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 2e89b6a..af4b4fa 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -670,7 +670,7 @@
     // Resources loaded from memory cache should be reported the first time
     // they're used.
     scoped_refptr<ResourceTimingInfo> info = ResourceTimingInfo::Create(
-        resource->Options().initiator_info.name, CurrentTimeTicks());
+        resource->Options().initiator_info.name, base::TimeTicks::Now());
     // TODO(yoav): GetInitialUrlForResourceTiming() is only needed until
     // Out-of-Blink CORS lands: https://crbug.com/736308
     info->SetInitialURL(
@@ -1254,7 +1254,7 @@
     return;
 
   scoped_refptr<ResourceTimingInfo> info =
-      ResourceTimingInfo::Create(fetch_initiator, CurrentTimeTicks());
+      ResourceTimingInfo::Create(fetch_initiator, base::TimeTicks::Now());
 
   resource_timing_info_map_.insert(resource, std::move(info));
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
index 8e329875..2cab29ecf 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -294,7 +294,7 @@
 
 TEST_F(ResourceFetcherTest, ResourceTimingInfo) {
   auto info = ResourceTimingInfo::Create(fetch_initiator_type_names::kDocument,
-                                         CurrentTimeTicks());
+                                         base::TimeTicks::Now());
   info->AddFinalTransferSize(5);
   EXPECT_EQ(info->TransferSize(), static_cast<uint64_t>(5));
   ResourceResponse redirect_response(KURL("https://example.com/original"));
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index 0f78f24b3c..2cd490a 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -1290,8 +1290,8 @@
       OnProgress(blob->size());
     FinishedCreatingBlob(blob);
   }
-  DidFinishLoading(CurrentTimeTicks(), encoded_data_length, encoded_body_length,
-                   decoded_body_length, false, {});
+  DidFinishLoading(base::TimeTicks::Now(), encoded_data_length,
+                   encoded_body_length, decoded_body_length, false, {});
 }
 
 void ResourceLoader::RequestAsynchronously(const ResourceRequest& request) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index c3b3345..16e8f82 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -67,6 +67,8 @@
 
  public:
   enum class RedirectStatus : uint8_t { kFollowedRedirect, kNoRedirect };
+  // TODO(domfarolino): Remove these location enums when Referer header crash
+  // debugging is done.
   enum class SetHttpReferrerLocation : uint8_t {
     kCreateRedirectRequest,
     kFrameLoaderResourceRequestForReload,
@@ -89,6 +91,7 @@
     kThreadableLoaderCreateAccessControlPreflightRequest,
     kThreadableLoaderPrepareCrossOriginRequest,
     kWebLocalFrameImpl,
+    kWebURLRequest,
   };
   enum class SetReferrerPolicyLocation : uint8_t {
     kAnchorElement,
diff --git a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
index c00566f..c20cf6b 100644
--- a/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/stale_revalidation_resource_client.cc
@@ -11,7 +11,7 @@
 
 StaleRevalidationResourceClient::StaleRevalidationResourceClient(
     Resource* stale_resource)
-    : start_time_(CurrentTimeTicks()), stale_resource_(stale_resource) {}
+    : start_time_(base::TimeTicks::Now()), stale_resource_(stale_resource) {}
 
 StaleRevalidationResourceClient::~StaleRevalidationResourceClient() = default;
 
diff --git a/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc b/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc
index 93c06911..66346d0 100644
--- a/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc
+++ b/third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.cc
@@ -87,10 +87,10 @@
     // Clear |client_| to avoid any extra notifications from reentrancy.
     WebNavigationBodyLoader::Client* client = client_;
     client_ = nullptr;
-    client->BodyLoadingFinished(CurrentTimeTicks(), total_encoded_data_length_,
-                                total_encoded_data_length_,
-                                total_encoded_data_length_, false,
-                                base::nullopt);
+    client->BodyLoadingFinished(
+        base::TimeTicks::Now(), total_encoded_data_length_,
+        total_encoded_data_length_, total_encoded_data_length_, false,
+        base::nullopt);
     // |this| can be destroyed from BodyLoadingFinished.
     if (!weak_self)
       return;
diff --git a/third_party/blink/renderer/platform/mediastream/DEPS b/third_party/blink/renderer/platform/mediastream/DEPS
index f0b3614..f18ab77 100644
--- a/third_party/blink/renderer/platform/mediastream/DEPS
+++ b/third_party/blink/renderer/platform/mediastream/DEPS
@@ -9,6 +9,6 @@
     "+third_party/blink/renderer/platform/audio",
     "+third_party/blink/renderer/platform/heap",
     "+third_party/blink/renderer/platform/platform_export.h",
-    "+third_party/blink/renderer/platform/uuid.h",
+    "+third_party/blink/renderer/platform/wtf/uuid.h",
     "+third_party/blink/renderer/platform/wtf",
 ]
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_component.cc b/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
index 662358b..de2c065 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_component.cc
@@ -37,7 +37,7 @@
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_center.h"
 #include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -53,7 +53,7 @@
 }
 
 MediaStreamComponent::MediaStreamComponent(MediaStreamSource* source)
-    : MediaStreamComponent(CreateCanonicalUUIDString(), source) {}
+    : MediaStreamComponent(WTF::CreateCanonicalUUIDString(), source) {}
 MediaStreamComponent::MediaStreamComponent(const String& id,
                                            MediaStreamSource* source)
     : source_(source), id_(id), unique_id_(GenerateUniqueId()) {
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc b/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
index b113929f..0f3c348 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_descriptor.cc
@@ -33,7 +33,7 @@
 
 #include "third_party/blink/public/platform/web_media_stream.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 namespace blink {
 
@@ -126,7 +126,7 @@
 MediaStreamDescriptor::MediaStreamDescriptor(
     const MediaStreamSourceVector& audio_sources,
     const MediaStreamSourceVector& video_sources)
-    : MediaStreamDescriptor(CreateCanonicalUUIDString(),
+    : MediaStreamDescriptor(WTF::CreateCanonicalUUIDString(),
                             audio_sources,
                             video_sources) {}
 
@@ -150,7 +150,7 @@
 MediaStreamDescriptor::MediaStreamDescriptor(
     const MediaStreamComponentVector& audio_components,
     const MediaStreamComponentVector& video_components)
-    : MediaStreamDescriptor(CreateCanonicalUUIDString(),
+    : MediaStreamDescriptor(WTF::CreateCanonicalUUIDString(),
                             audio_components,
                             video_components) {}
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
index ccb4a0c..c01f067 100644
--- a/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/scheduler_helper_unittest.cc
@@ -52,7 +52,7 @@
  public:
   SchedulerHelperTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
                 QUEUED) {
     sequence_manager_ = base::sequence_manager::SequenceManagerForTest::Create(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
index 5857c68..5f5f869 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/deadline_task_runner_unittest.cc
@@ -19,10 +19,9 @@
  public:
   DeadlineTaskRunnerTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
-                QUEUED) {
-  }
+                QUEUED) {}
   ~DeadlineTaskRunnerTest() override = default;
 
   void SetUp() override {
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 163238f..1b50eca 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -456,9 +456,6 @@
     case TaskType::kInternalFreezableIPC:
       return FreezableTaskQueueTraits();
     case TaskType::kInternalIPC:
-    // The TaskType of Inspector tasks needs to be unpausable because they need
-    // to run even on a paused page.
-    case TaskType::kInternalInspector:
     // Some tasks in the tests need to run when objects are paused e.g. to hook
     // when recovering from debugger JavaScript statetment.
     case TaskType::kInternalTest:
@@ -468,6 +465,9 @@
       return UnpausableTaskQueueTraits();
     case TaskType::kInternalTranslation:
       return ForegroundOnlyTaskQueueTraits();
+    // The TaskType of Inspector tasks need to be unpausable and should not use virtual time
+    // because they need to run on a paused page or when virtual time is paused.
+    case TaskType::kInternalInspector:
     // Navigation IPCs do not run using virtual time to avoid hanging.
     case TaskType::kInternalNavigationAssociated:
       return DoesNotUseVirtualTimeTaskQueueTraits();
@@ -515,8 +515,6 @@
       return frame_task_queue_controller_->LoadingTaskQueue();
     case TaskType::kNetworkingControl:
       return frame_task_queue_controller_->LoadingControlTaskQueue();
-    case TaskType::kInternalInspector:
-      return frame_task_queue_controller_->InspectorTaskQueue();
     case TaskType::kInternalContentCapture:
       return frame_task_queue_controller_->BestEffortTaskQueue();
     default:
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index 238470b..f0c6ea9b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -59,7 +59,7 @@
  public:
   FrameSchedulerImplTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
                 QUEUED) {}
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
index f1d31aa..9549699 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.cc
@@ -53,18 +53,6 @@
 }
 
 scoped_refptr<MainThreadTaskQueue>
-FrameTaskQueueController::InspectorTaskQueue() {
-  if (!inspector_task_queue_) {
-    inspector_task_queue_ = main_thread_scheduler_impl_->NewTaskQueue(
-        MainThreadTaskQueue::QueueCreationParams(
-            MainThreadTaskQueue::QueueType::kDefault)
-            .SetFrameScheduler(frame_scheduler_impl_));
-    TaskQueueCreated(inspector_task_queue_);
-  }
-  return inspector_task_queue_;
-}
-
-scoped_refptr<MainThreadTaskQueue>
 FrameTaskQueueController::BestEffortTaskQueue() {
   if (!best_effort_task_queue_) {
     best_effort_task_queue_ = main_thread_scheduler_impl_->NewTaskQueue(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
index 41b8307..5d4a555 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller.h
@@ -72,9 +72,6 @@
   // Return the loading control task queue and create it if it doesn't exist.
   scoped_refptr<MainThreadTaskQueue> LoadingControlTaskQueue();
 
-  // Return the inspector task queue and create it if it doesn't exist.
-  scoped_refptr<MainThreadTaskQueue> InspectorTaskQueue();
-
   // Return the best effort task queue and create it if it doesn't exist.
   scoped_refptr<MainThreadTaskQueue> BestEffortTaskQueue();
 
@@ -134,10 +131,6 @@
   scoped_refptr<MainThreadTaskQueue> loading_task_queue_;
   scoped_refptr<MainThreadTaskQueue> loading_control_task_queue_;
 
-  // Keep the inspector queue separately. It needs to mimic the IPC task queue
-  // behavior as far as virtual time is concerned.
-  scoped_refptr<MainThreadTaskQueue> inspector_task_queue_;
-
   scoped_refptr<MainThreadTaskQueue> best_effort_task_queue_;
 
   scoped_refptr<MainThreadTaskQueue> very_high_priority_task_queue_;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
index f7915be..d2ea65b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_task_queue_controller_unittest.cc
@@ -35,7 +35,7 @@
  public:
   FrameTaskQueueControllerTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         task_queue_created_count_(0) {}
 
@@ -155,12 +155,6 @@
   all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
   EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
 
-  // Add inspector task queue.
-  task_queue = frame_task_queue_controller_->InspectorTaskQueue();
-  EXPECT_FALSE(all_task_queues.Contains(task_queue));
-  all_task_queues.insert(task_queue.get(), QueueCheckResult::kDidNotSeeQueue);
-  EXPECT_EQ(all_task_queues.size(), task_queue_created_count());
-
   // Add best effort task queue.
   task_queue = frame_task_queue_controller_->BestEffortTaskQueue();
   EXPECT_FALSE(all_task_queues.Contains(task_queue));
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
index 52b7f459..8ec25e228 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/idle_time_estimator_unittest.cc
@@ -37,10 +37,9 @@
  public:
   IdleTimeEstimatorTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
-        frame_length_(base::TimeDelta::FromMilliseconds(16)) {
-  }
+        frame_length_(base::TimeDelta::FromMilliseconds(16)) {}
 
   ~IdleTimeEstimatorTest() override = default;
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
index b9f99e5..cd716509 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_metrics_helper_unittest.cc
@@ -50,10 +50,9 @@
  public:
   MainThreadMetricsHelperTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::
-                QUEUED) {
-  }
+                QUEUED) {}
 
   ~MainThreadMetricsHelperTest() override = default;
 
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
index 972caf9d4..ed49f69 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_scheduler_proxy_unittest.cc
@@ -103,7 +103,7 @@
  public:
   WorkerSchedulerProxyTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         main_thread_scheduler_(std::make_unique<MainThreadSchedulerImpl>(
             base::sequence_manager::SequenceManagerForTest::Create(
diff --git a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
index 26a426d..1b4c4b2 100644
--- a/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/worker/worker_thread_scheduler_unittest.cc
@@ -140,7 +140,7 @@
  public:
   WorkerThreadSchedulerTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         sequence_manager_(
             base::sequence_manager::SequenceManagerForTest::Create(
@@ -474,7 +474,7 @@
  public:
   WorkerThreadSchedulerWithProxyTest()
       : task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME,
             base::test::ScopedTaskEnvironment::ThreadPoolExecutionMode::QUEUED),
         sequence_manager_(
             base::sequence_manager::SequenceManagerForTest::Create(
diff --git a/third_party/blink/renderer/platform/wtf/BUILD.gn b/third_party/blink/renderer/platform/wtf/BUILD.gn
index 4fd97c2..1095c9ee 100644
--- a/third_party/blink/renderer/platform/wtf/BUILD.gn
+++ b/third_party/blink/renderer/platform/wtf/BUILD.gn
@@ -206,6 +206,8 @@
     "typed_arrays/uint32_array.h",
     "typed_arrays/uint8_array.h",
     "typed_arrays/uint8_clamped_array.h",
+    "uuid.cc",
+    "uuid.h",
     "vector.h",
     "vector_traits.h",
     "wtf.cc",
@@ -316,6 +318,7 @@
     "threading_primitives_test.cc",
     "tree_node_test.cc",
     "type_traits_test.cc",
+    "uuid_test.cc",
     "vector_test.cc",
   ]
 
diff --git a/third_party/blink/renderer/platform/wtf/time.cc b/third_party/blink/renderer/platform/wtf/time.cc
index a8e90f8..7ae6220 100644
--- a/third_party/blink/renderer/platform/wtf/time.cc
+++ b/third_party/blink/renderer/platform/wtf/time.cc
@@ -38,16 +38,4 @@
   return base::Time::Now().ToDoubleT();
 }
 
-base::TimeTicks CurrentTimeTicks() {
-  return base::TimeTicks::Now();
-}
-
-double CurrentTimeTicksInSeconds() {
-  return CurrentTimeTicks().since_origin().InSecondsF();
-}
-
-double CurrentTimeTicksInMilliseconds() {
-  return CurrentTimeTicks().since_origin().InMillisecondsF();
-}
-
 }  // namespace WTF
diff --git a/third_party/blink/renderer/platform/wtf/time.h b/third_party/blink/renderer/platform/wtf/time.h
index 71373e1..9c03b6c 100644
--- a/third_party/blink/renderer/platform/wtf/time.h
+++ b/third_party/blink/renderer/platform/wtf/time.h
@@ -20,21 +20,9 @@
   return CurrentTime() * 1000.0;
 }
 
-// Monotonically increasing clock time since an arbitrary and unspecified origin
-// time. Mockable using SetTimeFunctionsForTesting().
-WTF_EXPORT base::TimeTicks CurrentTimeTicks();
-// Convenience functions that return seconds and milliseconds since the origin
-// time. Prefer CurrentTimeTicks() where possible to avoid potential unit
-// confusion errors.
-WTF_EXPORT double CurrentTimeTicksInSeconds();
-WTF_EXPORT double CurrentTimeTicksInMilliseconds();
-
 }  // namespace WTF
 
 using WTF::CurrentTime;
 using WTF::CurrentTimeMS;
-using WTF::CurrentTimeTicks;
-using WTF::CurrentTimeTicksInMilliseconds;
-using WTF::CurrentTimeTicksInSeconds;
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_TIME_H_
diff --git a/third_party/blink/renderer/platform/uuid.cc b/third_party/blink/renderer/platform/wtf/uuid.cc
similarity index 87%
rename from third_party/blink/renderer/platform/uuid.cc
rename to third_party/blink/renderer/platform/wtf/uuid.cc
index f4b035e..c86497c 100644
--- a/third_party/blink/renderer/platform/uuid.cc
+++ b/third_party/blink/renderer/platform/wtf/uuid.cc
@@ -2,12 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 #include "base/guid.h"
 #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
 
-namespace blink {
+namespace WTF {
 
 String CreateCanonicalUUIDString() {
   std::string uuid = base::GenerateGUID();
@@ -21,4 +21,4 @@
   return base::IsValidGUIDOutputString(utf8.AsStringPiece());
 }
 
-}  // namespace blink
+}  // namespace WTF
diff --git a/third_party/blink/renderer/platform/uuid.h b/third_party/blink/renderer/platform/wtf/uuid.h
similarity index 76%
rename from third_party/blink/renderer/platform/uuid.h
rename to third_party/blink/renderer/platform/wtf/uuid.h
index e7908e7..afeb3dc 100644
--- a/third_party/blink/renderer/platform/uuid.h
+++ b/third_party/blink/renderer/platform/wtf/uuid.h
@@ -1,12 +1,12 @@
 /*
-* Copyright (C) 2010 Google Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*
-*     * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
  *     * Redistributions in binary form must reproduce the above
  * copyright notice, this list of conditions and the following disclaimer
  * in the documentation and/or other materials provided with the
@@ -28,13 +28,13 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_UUID_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_UUID_H_
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_UUID_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WTF_UUID_H_
 
-#include "third_party/blink/renderer/platform/platform_export.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
+#include "third_party/blink/renderer/platform/wtf/wtf_export.h"
 
-namespace blink {
+namespace WTF {
 
 // Creates a UUID that consists of 32 hexadecimal digits and returns its
 // canonical form.  The canonical form is displayed in 5 groups separated by
@@ -47,13 +47,13 @@
 // pseudorandom data source. Version 4 UUIDs have the form
 // xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx with hexadecimal digits for x and one of
 // 8, 9, A, or B for y.
-PLATFORM_EXPORT String CreateCanonicalUUIDString();
+WTF_EXPORT String CreateCanonicalUUIDString();
 
 // Check that the UUID is a valid UUID. A valid UUID is a string made out of 5
 // groups of lower case hexadecimal characters separated by hyphens, in the form
 // 8-4-4-4-12.
-PLATFORM_EXPORT bool IsValidUUID(const String& uuid);
+WTF_EXPORT bool IsValidUUID(const String& uuid);
 
-}  // namespace blink
+}  // namespace WTF
 
 #endif
diff --git a/third_party/blink/renderer/platform/uuid_test.cc b/third_party/blink/renderer/platform/wtf/uuid_test.cc
similarity index 97%
rename from third_party/blink/renderer/platform/uuid_test.cc
rename to third_party/blink/renderer/platform/wtf/uuid_test.cc
index 36f3367d..3c01ce74 100644
--- a/third_party/blink/renderer/platform/uuid_test.cc
+++ b/third_party/blink/renderer/platform/wtf/uuid_test.cc
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/platform/uuid.h"
+#include "third_party/blink/renderer/platform/wtf/uuid.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace blink {
+namespace WTF {
 
 TEST(UUIDTest, BaseUUID) {
   EXPECT_TRUE(IsValidUUID("00000000-0000-0000-0000-000000000000"));
@@ -73,4 +73,4 @@
   EXPECT_FALSE(IsValidUUID("00000000 0000 0000 0000 000000000000"));
 }
 
-}  // namespace blink
+}  // namespace WTF
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
index 0ab2b6b..7af98ee 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
+++ b/third_party/blink/web_tests/FlagExpectations/disable-blink-features=LayoutNG
@@ -287,3 +287,6 @@
 crbug.com/591099 virtual/omt-worker-fetch/external/wpt/service-workers/service-worker/registration-updateviacache.https.html [ Failure ]
 
 crbug.com/591099 external/wpt/css/css-tables/absolute-tables-002.html [ Failure ]
+
+crbug.com/591099 virtual/scalefactor200/external/wpt/element-timing/observe-text.html [ Failure ]
+crbug.com/591099 virtual/scalefactor200withoutzoom/external/wpt/element-timing/css-generated-text.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index f1141cc..43349ff 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -366,8 +366,7 @@
 
 # ====== Layout team owned tests from here ======
 
-crbug.com/983322 css3/masking/clip-path-selection.html [ Failure ]
-crbug.com/983593 external/wpt/quirks/table-cell-width-calculation.html [ Failure ]
+crbug.com/980908 wpt_internal/css/css-position/static-position/inline-level-absolute-float-quirk.html [ Failure ]
 
 crbug.com/974853 external/wpt/css/CSS2/abspos/hypothetical-box-dynamic.html [ Failure ]
 
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 29fe14a..c9eed1bf 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -338,6 +338,16 @@
     "args": ["--force-device-scale-factor=2"]
   },
   {
+    "prefix": "scalefactor200",
+    "base": "external/wpt/element-timing",
+    "args": ["--force-device-scale-factor=2"]
+  },
+  {
+    "prefix": "scalefactor200withoutzoom",
+    "base": "external/wpt/element-timing",
+    "args": ["--force-device-scale-factor=2", "--enable-use-zoom-for-dsf=false"]
+  },
+  {
     "prefix": "scalefactor150",
     "base": "fast/hidpi/static",
     "args": ["--force-device-scale-factor=1.5"]
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child-expected.txt b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child-expected.txt
index 8bfeb04..b65f6d5 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-child-expected.txt
@@ -86,7 +86,7 @@
       "bounds": [281, 281],
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (positioned) DIV class='box middle'",
           "rect": [0, 0, 142, 142],
           "reason": "background"
         }
@@ -144,7 +144,7 @@
       "bounds": [281, 281],
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (positioned) DIV class='box middle'",
           "rect": [0, 0, 142, 142],
           "reason": "background"
         },
diff --git a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
index d26d52d..3fcd38a 100644
--- a/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
+++ b/third_party/blink/web_tests/compositing/squashing/squash-transform-repainting-transformed-child-expected.txt
@@ -86,7 +86,7 @@
       "bounds": [276, 276],
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (positioned) DIV class='box middle'",
           "rect": [0, 0, 132, 132],
           "reason": "background"
         }
@@ -144,7 +144,7 @@
       "bounds": [276, 276],
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV class='box middle'",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (positioned) DIV class='box middle'",
           "rect": [0, 0, 132, 132],
           "reason": "background"
         },
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
index ad849d4e..fb39edd 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -146784,6 +146784,9 @@
    "css/cssom-view/resources/iframe2.html": [
     []
    ],
+   "css/cssom-view/scrollIntoView-horizontal-tb-writing-mode-and-rtl-direction-expected.txt": [
+    []
+   ],
    "css/cssom-view/scrollIntoView-vertical-lr-writing-mode-and-rtl-direction-expected.txt": [
     []
    ],
@@ -398349,6 +398352,10 @@
    "cc67ce76ed9d432656b37c9c81a20e86d1bafc8d",
    "testharness"
   ],
+  "css/cssom-view/scrollIntoView-horizontal-tb-writing-mode-and-rtl-direction-expected.txt": [
+   "1ee45e2e10c2b83122b35b7baf10622f3853e6a6",
+   "support"
+  ],
   "css/cssom-view/scrollIntoView-horizontal-tb-writing-mode-and-rtl-direction.html": [
    "3ef9d62a3654c5ab2dd061e34799053daeefc3a4",
    "testharness"
@@ -469266,11 +469273,11 @@
    "manual"
   ],
   "speech-api/historical-expected.txt": [
-   "ebdbc55fd4658f55caf39ddafb50524125f0907f",
+   "8dd3037396aa064e341bfb2ee93ae16d5026b5d5",
    "support"
   ],
   "speech-api/historical.html": [
-   "2fb0ccd4b905b4503f0affa4c8c7be3141871fe3",
+   "6dd4bd9f9ef0ee1b4856011fce0ddcf951d6052c",
    "testharness"
   ],
   "speech-api/idlharness.window-expected.txt": [
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/cross-origin-element.sub.html b/third_party/blink/web_tests/external/wpt/element-timing/cross-origin-element.sub.html
index 40a97056..eef69a1 100644
--- a/third_party/blink/web_tests/external/wpt/element-timing/cross-origin-element.sub.html
+++ b/third_party/blink/web_tests/external/wpt/element-timing/cross-origin-element.sub.html
@@ -1,6 +1,6 @@
 <!DOCTYPE HTML>
 <meta charset=utf-8>
-<title>Element Timing: observe cross-origin images but without startTime</title>
+<title>Element Timing: observe cross-origin images but without renderTime</title>
 <body>
 <style>
 body {
@@ -23,8 +23,8 @@
         assert_equals(entryList.getEntries().length, 1);
         const entry = entryList.getEntries()[0];
         checkElement(entry, pathname, 'my_image', 'the_id', 0, img);
-        assert_equals(entry.startTime, 0,
-          'The startTime of a cross-origin image should be 0.');
+        assert_equals(entry.renderTime, 0,
+          'The renderTime of a cross-origin image should be 0.');
         checkRect(entry, [0, 100, 0, 100]);
         checkNaturalSize(entry, 100, 100);
       })
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/image-TAO.sub.html b/third_party/blink/web_tests/external/wpt/element-timing/image-TAO.sub.html
index 83a7a5ca..032ae6b 100644
--- a/third_party/blink/web_tests/external/wpt/element-timing/image-TAO.sub.html
+++ b/third_party/blink/web_tests/external/wpt/element-timing/image-TAO.sub.html
@@ -39,7 +39,7 @@
           if (valid_tao.includes(tao)) {
             checkElement(entry, remote_img + tao, tao, 'id_' + tao, beforeRender, img);
           } else if (invalid_tao.includes(tao)) {
-            assert_equals(entry.startTime, 0, 'Entry with tao=' + tao + ' must have a startTime of 0');
+            assert_equals(entry.renderTime, 0, 'Entry with tao=' + tao + ' must have a renderTime of 0');
             checkElement(entry, remote_img + tao, tao, 'id_' + tao, 0, img);
           }
           else {
@@ -51,6 +51,6 @@
         });
       })
     ).observe({type: 'element', buffered: true});
-  }, 'Cross-origin elements with valid TAO have correct startTime, with invalid TAO have startTime set to 0.');
+  }, 'Cross-origin elements with valid TAO have correct renderTime, with invalid TAO have renderTime set to 0.');
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js b/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js
index 6c0aec8..f98f9b2 100644
--- a/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js
+++ b/third_party/blink/web_tests/external/wpt/element-timing/resources/element-timing-helpers.js
@@ -4,16 +4,17 @@
   assert_equals(entry.entryType, 'element');
   assert_equals(entry.url, expectedUrl);
   assert_equals(entry.identifier, expectedIdentifier);
+  assert_equals(entry.startTime, 0);
   assert_equals(entry.duration, 0);
   assert_equals(entry.id, expectedID);
-  assert_greater_than_equal(entry.startTime, beforeRender);
-  assert_greater_than_equal(performance.now(), entry.startTime);
+  assert_greater_than_equal(entry.renderTime, beforeRender);
+  assert_greater_than_equal(performance.now(), entry.renderTime);
   if (expectedElement !== null)
     assert_equals(entry.element, expectedElement);
 }
 
 // Checks that this is an ElementTiming entry with url |expectedUrl|. It also
-// does a very basic check on |startTime|: after |beforeRender| and before now().
+// does a very basic check on |renderTime|: after |beforeRender| and before now().
 function checkElement(entry, expectedUrl, expectedIdentifier, expectedID, beforeRender,
     expectedElement) {
   checkElementInternal(entry, expectedUrl, expectedIdentifier, expectedID, beforeRender,
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html
index fd4844d1..6e86f13 100644
--- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html
+++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/cross-origin-image.sub.html
@@ -1,6 +1,6 @@
 <!DOCTYPE HTML>
 <meta charset=utf-8>
-<title>Largest Contentful Paint: observe cross-origin images but without startTime.</title>
+<title>Largest Contentful Paint: observe cross-origin images but without renderTime.</title>
 <body>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
@@ -14,7 +14,8 @@
         assert_equals(entryList.getEntries().length, 1);
         const entry = entryList.getEntries()[0];
         assert_equals(entry.entryType, 'largest-contentful-paint');
-        assert_equals(entry.startTime, 0, 'The startTime value should be 0 for a cross origin image.');
+        assert_equals(entry.renderTime, 0, 'The renderTime value should be 0 for a cross origin image.');
+        assert_equals(entry.startTime, 0);
         assert_equals(entry.duration, 0);
         // blue.png is 133 x 106.
         assert_equals(entry.size, 14098);
@@ -27,7 +28,7 @@
       })
     );
     observer.observe({type: 'largest-contentful-paint', buffered: true});
-  }, 'Cross-origin image is observable, with startTime equal to 0.');
+  }, 'Cross-origin image is observable, with renderTime equal to 0.');
 </script>
 
 <img src='http://{{domains[www]}}:{{ports[http][1]}}/images/blue.png' id='image_id'/>
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html
index a1ecbce..4d56cc2 100644
--- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html
+++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-image.html
@@ -15,10 +15,11 @@
         assert_equals(entryList.getEntries().length, 1);
         const entry = entryList.getEntries()[0];
         assert_equals(entry.entryType, 'largest-contentful-paint');
-        assert_greater_than_equal(entry.startTime, beforeRender,
+        assert_greater_than_equal(entry.renderTime, beforeRender,
           'The rendering timestamp should occur after script starts running.');
-        assert_greater_than_equal(performance.now(), entry.startTime,
+        assert_greater_than_equal(performance.now(), entry.renderTime,
           'The rendering timestamp should occur before the entry is dispatched to the observer.');
+        assert_equals(entry.startTime, 0);
         assert_equals(entry.duration, 0);
         // blue.png is 133 x 106.
         assert_equals(entry.size, 14098);
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html
index 5889790..7dbfbe52 100644
--- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html
+++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/observe-text.html
@@ -20,8 +20,9 @@
         assert_equals(entryList.getEntries().length, 1);
         const entry = entryList.getEntries()[0];
         assert_equals(entry.entryType, 'largest-contentful-paint');
-        assert_greater_than_equal(entry.startTime, beforeRender);
-        assert_greater_than_equal(performance.now(), entry.startTime);
+        assert_greater_than_equal(entry.renderTime, beforeRender);
+        assert_greater_than_equal(performance.now(), entry.renderTime);
+        assert_equals(entry.startTime, 0);
         assert_equals(entry.duration, 0);
         // Some lower bound: height of at least 12 px.
         // Width of at least 100 px.
diff --git a/third_party/blink/web_tests/external/wpt/speech-api/historical-expected.txt b/third_party/blink/web_tests/external/wpt/speech-api/historical-expected.txt
index ebdbc55..8dd3037 100644
--- a/third_party/blink/web_tests/external/wpt/speech-api/historical-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/speech-api/historical-expected.txt
@@ -5,5 +5,6 @@
 FAIL webkitSpeechRecognition interface should not exist assert_false: expected false got true
 FAIL webkitSpeechRecognitionError interface should not exist assert_false: expected false got true
 FAIL webkitSpeechRecognitionEvent interface should not exist assert_false: expected false got true
+PASS SpeechRecognition's serviceURI attribute should not exist
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/speech-api/historical.html b/third_party/blink/web_tests/external/wpt/speech-api/historical.html
index 2fb0ccd4..6dd4bd9 100644
--- a/third_party/blink/web_tests/external/wpt/speech-api/historical.html
+++ b/third_party/blink/web_tests/external/wpt/speech-api/historical.html
@@ -12,8 +12,17 @@
   "webkitSpeechRecognitionError",
   "webkitSpeechRecognitionEvent",
 ].forEach(name => {
-  test(function() {
+  test(() => {
     assert_false(name in window);
   }, name + " interface should not exist");
 });
+
+test(() => {
+  if (!window.SpeechRecognition) {
+    // TODO(foolip): use `t.skip()` after
+    // https://github.com/web-platform-tests/rfcs/pull/16 is done.
+    return;
+  }
+  assert_false("serviceURI" in SpeechRecognition.prototype);
+}, "SpeechRecognition's serviceURI attribute should not exist");
 </script>
diff --git a/third_party/blink/web_tests/fast/block/float/4145535Crash-expected.txt b/third_party/blink/web_tests/fast/block/float/4145535Crash-expected.txt
new file mode 100644
index 0000000..8392a7b
--- /dev/null
+++ b/third_party/blink/web_tests/fast/block/float/4145535Crash-expected.txt
@@ -0,0 +1 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
diff --git a/third_party/blink/web_tests/fast/dom/Window/window-closed-during-layout-dump-expected.txt b/third_party/blink/web_tests/fast/dom/Window/window-closed-during-layout-dump-expected.txt
deleted file mode 100644
index ed8e358..0000000
--- a/third_party/blink/web_tests/fast/dom/Window/window-closed-during-layout-dump-expected.txt
+++ /dev/null
@@ -1 +0,0 @@
-FAIL: main window was destroyed
diff --git a/third_party/blink/web_tests/fast/dom/Window/window-closed-during-layout-dump.html b/third_party/blink/web_tests/fast/dom/Window/window-closed-during-layout-dump.html
deleted file mode 100644
index f6d83af..0000000
--- a/third_party/blink/web_tests/fast/dom/Window/window-closed-during-layout-dump.html
+++ /dev/null
@@ -1,10 +0,0 @@
-<script>
-// Regression test for a layout test harness crash when the main test
-// window is closed while waiting for layout dump from subframes.
-// See also https://crbug.com/798598.
-if (testRunner) {
-  testRunner.dumpAsText();
-  testRunner.dumpChildFrames();
-}
-window.close();
-</script>
diff --git a/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash-expected.txt b/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash-expected.txt
index 78085d7..e094f8f 100644
--- a/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash-expected.txt
+++ b/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash-expected.txt
@@ -1,2 +1,6 @@
 CONSOLE WARNING: line 4: document.registerElement is deprecated and will be removed in M80, around February 2020. Please use window.customElements.define instead. See https://www.chromestatus.com/features/4642138092470272 and https://developers.google.com/web/updates/2019/07/web-components-time-to-upgrade for more details.
-If this doesn't crash, it passed. 
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
+If this doesn't crash, it passed.
diff --git a/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash.html b/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash.html
index 4e57a4f..2d8e42b 100644
--- a/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash.html
+++ b/third_party/blink/web_tests/fast/dom/custom/reparent-unwrapped-custom-element-crash.html
@@ -1,10 +1,10 @@
-<script src="../../../js-test.js"></script>
+<script src="../../../resources/js-test.js"></script>
 <body>
 If this doesn't crash, it passed.
 <iframe id=iframe src=resources/empty-custom-body.html></iframe>
 </body>
 <script>
-jsTestIsAsync = true;
+window.jsTestIsAsync = true;
 
 if (window.testRunner)
   testRunner.dumpAsText();
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..3088a96
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/button/button-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/button/button-appearance-basic.html
new file mode 100644
index 0000000..c51da2a
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/button/button-appearance-basic.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<script src="../../../../resources/run-after-layout-and-paint.js"></script>
+<body>
+
+<!-- no style for reference -->
+<ul>
+  <li>Button: <button>button</button></li>
+  <li>Type button: <input type="button" value="button"/></li>
+  <li>Type submit: <input type="submit" /></li>
+  <li>Type reset: <input type="reset" /></li>
+  <li>Type file: <input type="file" /></li>
+</ul>
+
+<!-- disabled -->
+<input type="button" disabled value="button"> <br>
+
+<!-- border -->
+<input type="button" style="border: 3px solid lime;" value="button">
+<input type="button" style="border-radius: 6px;" value="button"> <br>
+
+<!-- background -->
+<input type="button" style="background: linear-gradient(to bottom, #dea 0%,#9c7 44%,#494 100%);" value="button"> <br>
+
+<!-- shadow -->
+<input type="button" style="box-shadow: 4px 4px 10px rgba(255,0,0,0.5), inset 4px 4px 4px rgba(0,255,0,0.5);" value="button"> <br>
+
+<!-- size -->
+<input type="button" style="width: 2px; height: 2px; padding: 0;" value="button">
+<input type="button" style="width: 8px; height: 8px;" value="button">
+<input type="button" style="width: 16px; height: 16px;" value="button">
+<input type="button" style="width: 24px; height: 24px;" value="button">
+<input type="button" style="width: 26px; height: 20px;" value="button">
+<input type="button" style="width: 60px; height: 60px;" value="button"> <br>
+
+<!-- zoom -->
+<input type="button" style="zoom: 1.5;" value="button">
+<input type="button" style="zoom: 3;" value="button">
+
+<!-- webkit-appearance -->
+<div style="-webkit-appearance: button; width: 50px; height: 30px;">button</div>
+
+<script>
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+
+</script>
+</body>
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..3ae94cd1
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/forms/controls-new-ui/file/file-appearance-basic.html b/third_party/blink/web_tests/fast/forms/controls-new-ui/file/file-appearance-basic.html
new file mode 100644
index 0000000..14aecbd
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/controls-new-ui/file/file-appearance-basic.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<script src="../../resources/common.js"></script>
+<body style="background-color: red">
+
+<!-- no style for reference -->
+<ul>
+  <li>File: <input type="file" /></li>
+</ul>
+
+<!-- disabled -->
+<ul>
+  <li>File disabled: <input type="file" disabled/></li>
+</ul>
+
+<!-- zoom -->
+<ul>
+  <li>File zoom: 1.5: <input type="file" style="zoom: 1.5;"/></li>
+  <li>File zoom: 4: <input type="file" style="zoom: 4;"/></li>
+</ul>
+
+<script>
+
+if (window.testRunner)
+  testRunner.setUseMockTheme(false);
+
+</script>
+
+</body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/frames/freed-frame.html b/third_party/blink/web_tests/fast/frames/freed-frame.html
index 70b6ad2..605f683 100644
--- a/third_party/blink/web_tests/fast/frames/freed-frame.html
+++ b/third_party/blink/web_tests/fast/frames/freed-frame.html
@@ -23,10 +23,14 @@
 function callback2() {
     o2.src = 'resources/freed-frame-helper.html';
 }
+var iterations = 0;
 function called_from_helper() {
-    o1.appendChild(o2);
+  if (++iterations > 20) {
     if (window.testRunner) {
-        testRunner.notifyDone();
+      testRunner.notifyDone();
     }
+    return;
+  }
+  o1.appendChild(o2);
 }
-</script>
\ No newline at end of file
+</script>
diff --git a/third_party/blink/web_tests/fast/layers/clip-rects-transformed-2-expected.txt b/third_party/blink/web_tests/fast/layers/clip-rects-transformed-2-expected.txt
index a2ae41e1..d105fadd 100644
--- a/third_party/blink/web_tests/fast/layers/clip-rects-transformed-2-expected.txt
+++ b/third_party/blink/web_tests/fast/layers/clip-rects-transformed-2-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 Test 2/2 for rdar://problem/7398987 Assertion failure in Layer::updateClipRects when a plugin’s enclosing layer is enclosed by a transformed layer.
 
 This test should not cause an assertion faliure.
diff --git a/third_party/blink/web_tests/fast/layers/clip-rects-transformed-expected.txt b/third_party/blink/web_tests/fast/layers/clip-rects-transformed-expected.txt
index 8652bd5..2640e7d6 100644
--- a/third_party/blink/web_tests/fast/layers/clip-rects-transformed-expected.txt
+++ b/third_party/blink/web_tests/fast/layers/clip-rects-transformed-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 Test 1/2 for rdar://problem/7398987 Assertion failure in Layer::updateClipRects when a plugin’s enclosing layer is enclosed by a transformed layer.
 
 This test should not cause an assertion faliure.
diff --git a/third_party/blink/web_tests/fast/loader/module-no-crash-expected.txt b/third_party/blink/web_tests/fast/loader/module-no-crash-expected.txt
index dde43bd..1dd2df540 100644
--- a/third_party/blink/web_tests/fast/loader/module-no-crash-expected.txt
+++ b/third_party/blink/web_tests/fast/loader/module-no-crash-expected.txt
@@ -1 +1 @@
- Tests that storing module cache does not crash with detached frame. Note that crash does only reproduce in ~20% of the runs, depending on timing.
+Tests that storing module cache does not crash with detached frame. Note that crash does only reproduce in ~20% of the runs, depending on timing.
diff --git a/third_party/blink/web_tests/fast/loader/subframe-removes-itself-expected.txt b/third_party/blink/web_tests/fast/loader/subframe-removes-itself-expected.txt
index 8c814e7..fd0fc3c 100644
--- a/third_party/blink/web_tests/fast/loader/subframe-removes-itself-expected.txt
+++ b/third_party/blink/web_tests/fast/loader/subframe-removes-itself-expected.txt
@@ -8,4 +8,4 @@
 frame "<!--framePath //<!--frame0-->-->" - didFailLoadWithError
 main frame - didHandleOnloadEventsForFrame
 main frame - didFinishLoadForFrame
-This tests a subframe that removes itself to make sure a delegate message to indicate the interrupted load fires. 
+This tests a subframe that removes itself to make sure a delegate message to indicate the interrupted load fires.
diff --git a/third_party/blink/web_tests/http/tests/misc/object-image-error-with-onload-expected.txt b/third_party/blink/web_tests/http/tests/misc/object-image-error-with-onload-expected.txt
index 7d631dbb..513b225 100644
--- a/third_party/blink/web_tests/http/tests/misc/object-image-error-with-onload-expected.txt
+++ b/third_party/blink/web_tests/http/tests/misc/object-image-error-with-onload-expected.txt
@@ -1,3 +1,3 @@
 Test for Bug https://bugs.webkit.org/show_bug.cgi?id=19891 Broken HTML object elements cause de-reference of pointer to freed memory
 
- Pass if there is no crash or ASSERT.
+Pass if there is no crash or ASSERT.
diff --git a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-no-url-allowed-expected.txt b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-no-url-allowed-expected.txt
index 6d4b9480..652878c 100644
--- a/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-no-url-allowed-expected.txt
+++ b/third_party/blink/web_tests/http/tests/security/contentSecurityPolicy/object-src-no-url-allowed-expected.txt
@@ -1 +1,2 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 This test passes if there isn't a console message saying the plugin was blocked. 
diff --git a/third_party/blink/web_tests/media/audio-no-installed-engines-expected.txt b/third_party/blink/web_tests/media/audio-no-installed-engines-expected.txt
index 2570ae9..7d72bbb9 100644
--- a/third_party/blink/web_tests/media/audio-no-installed-engines-expected.txt
+++ b/third_party/blink/web_tests/media/audio-no-installed-engines-expected.txt
@@ -1 +1,2 @@
+CONSOLE ERROR: Uncaught (in promise) NotSupportedError: Failed to load because no supported source was found.
 PASSED -- crash using Audio with no installed engines bug 27479.
diff --git a/third_party/blink/web_tests/paint/invalidation/background/background-misaligned-expected.txt b/third_party/blink/web_tests/paint/invalidation/background/background-misaligned-expected.txt
index 35eca091..8b085536 100644
--- a/third_party/blink/web_tests/paint/invalidation/background/background-misaligned-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/background/background-misaligned-expected.txt
@@ -18,7 +18,7 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV id='target'",
+          "object": "LayoutBlockFlow (positioned) DIV id='target'",
           "rect": [238, 241, 40, 40],
           "reason": "disappeared"
         }
diff --git a/third_party/blink/web_tests/paint/invalidation/float-new-in-block-expected.txt b/third_party/blink/web_tests/paint/invalidation/float-new-in-block-expected.txt
index e535ce6..3e68d9d 100644
--- a/third_party/blink/web_tests/paint/invalidation/float-new-in-block-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/float-new-in-block-expected.txt
@@ -18,7 +18,7 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (floating) DIV id='target'",
+          "object": "LayoutBlockFlow (floating) DIV id='target'",
           "rect": [8, 8, 100, 100],
           "reason": "appeared"
         }
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..34531e7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..2da3403f8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-expected.txt
index d70a5abf..9f53dca 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-right-expected.txt b/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-right-expected.txt
index 3d1fa6e..c407f370 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-right-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/paint/invalidation/overflow/float-overflow-right-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..6bd6518
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..31ff285
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/outline/focus-ring-on-child-move-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
new file mode 100644
index 0000000..cccefe52
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
@@ -0,0 +1,34 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='child'",
+          "rect": [300, 50, 20, 300],
+          "reason": "geometry"
+        },
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='child'",
+          "rect": [150, 50, 20, 300],
+          "reason": "geometry"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-expected.txt
index d70a5abf..9f53dca 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-right-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-right-expected.txt
index 3d1fa6e..c407f370 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-right-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/overflow/float-overflow-right-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/scroll/fixed-under-composited-fixed-scrolled-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/scroll/fixed-under-composited-fixed-scrolled-expected.txt
index 7e4267f..93d31d6 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/scroll/fixed-under-composited-fixed-scrolled-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/scroll/fixed-under-composited-fixed-scrolled-expected.txt
@@ -37,6 +37,18 @@
       "contentsOpaque": true,
       "backfaceVisibility": "hidden",
       "backgroundColor": "#008000",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='fixed-container'",
+          "rect": [0, 0, 785, 600],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (positioned) DIV id='fixed-container'",
+          "rect": [0, 0, 785, 600],
+          "reason": "disappeared"
+        }
+      ],
       "transform": 1
     }
   ],
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/svg-background-partial-redraw-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/svg-background-partial-redraw-expected.txt
index a62997b..02d09b4 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/svg-background-partial-redraw-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/svg-background-partial-redraw-expected.txt
@@ -18,6 +18,16 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
+          "object": "LayoutNGBlockFlow (relative positioned) DIV id='test' class='revealed'",
+          "rect": [8, 52, 200, 200],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV id='test'",
+          "rect": [8, 52, 200, 200],
+          "reason": "disappeared"
+        },
+        {
           "object": "LayoutNGBlockFlow (positioned) DIV id='revealer'",
           "rect": [9, 153, 200, 100],
           "reason": "disappeared"
diff --git a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
index a1a8964..db3a3fcf 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/virtual/disable-blink-gen-property-trees/paint/invalidation/svg/transform-focus-ring-repaint-expected.txt
@@ -24,13 +24,13 @@
     {
       "name": "LayoutNGBlockFlow (positioned) DIV id='target'",
       "position": [7, 57],
-      "bounds": [402, 542],
+      "bounds": [202, 202],
       "backfaceVisibility": "hidden",
       "backgroundColor": "#FFFF00",
       "paintInvalidations": [
         {
           "object": "LayoutNGBlockFlow (positioned) DIV id='target'",
-          "rect": [0, 0, 402, 542],
+          "rect": [0, 0, 202, 202],
           "reason": "full layer"
         },
         {
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..fd18e9a0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..33c3d1c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..ee542b56
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..b80feeb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..ff78e7b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..ef2ff08
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..ee542b56
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..b80feeb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..bdcbfff
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..54e9d04
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/background/background-misaligned-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/background/background-misaligned-expected.txt
new file mode 100644
index 0000000..c8560b88
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/background/background-misaligned-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (relative positioned) DIV",
+          "rect": [8, 8, 273, 276],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV",
+          "rect": [8, 8, 273, 276],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='target'",
+          "rect": [238, 241, 40, 40],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/float-new-in-block-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/float-new-in-block-expected.txt
new file mode 100644
index 0000000..c551980
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/float-new-in-block-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [8, 8, 784, 20],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+          "rect": [8, 8, 784, 20],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow (floating) DIV id='target'",
+          "rect": [8, 8, 100, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/outline/focus-ring-on-child-move-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
index bbebea3..cccefe52 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
@@ -18,11 +18,6 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV",
-          "rect": [96, 46, 308, 308],
-          "reason": "outline"
-        },
-        {
           "object": "LayoutNGBlockFlow (positioned) DIV id='child'",
           "rect": [300, 50, 20, 300],
           "reason": "geometry"
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..ee542b56
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..b80feeb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/background/background-misaligned-expected.txt b/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/background/background-misaligned-expected.txt
new file mode 100644
index 0000000..c8560b88
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/background/background-misaligned-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (relative positioned) DIV",
+          "rect": [8, 8, 273, 276],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV",
+          "rect": [8, 8, 273, 276],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='target'",
+          "rect": [238, 241, 40, 40],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/float-new-in-block-expected.txt b/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/float-new-in-block-expected.txt
new file mode 100644
index 0000000..c551980
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/float-new-in-block-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [8, 8, 784, 20],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+          "rect": [8, 8, 784, 20],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow (floating) DIV id='target'",
+          "rect": [8, 8, 100, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/outline/focus-ring-on-child-move-expected.txt b/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
index bbebea3..cccefe52 100644
--- a/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-retina/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
@@ -18,11 +18,6 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV",
-          "rect": [96, 46, 308, 308],
-          "reason": "outline"
-        },
-        {
           "object": "LayoutNGBlockFlow (positioned) DIV id='child'",
           "rect": [300, 50, 20, 300],
           "reason": "geometry"
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..ee542b56
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..b80feeb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..68527420
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..8270b43
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-expected.txt
index 337006f..9a24436d 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-right-expected.txt b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-right-expected.txt
index 7c5ccf7..65ac2ac 100644
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-right-expected.txt
+++ b/third_party/blink/web_tests/platform/mac/paint/invalidation/overflow/float-overflow-right-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..ee542b56
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..b80feeb
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/background/background-misaligned-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/background/background-misaligned-expected.txt
new file mode 100644
index 0000000..c8560b88
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/background/background-misaligned-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow (relative positioned) DIV",
+          "rect": [8, 8, 273, 276],
+          "reason": "appeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow (relative positioned) DIV",
+          "rect": [8, 8, 273, 276],
+          "reason": "disappeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow (positioned) DIV id='target'",
+          "rect": [238, 241, 40, 40],
+          "reason": "disappeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/box/hover-pseudo-borders-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/box/hover-pseudo-borders-expected.txt
index 70d711f..a03acc9c 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/box/hover-pseudo-borders-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/box/hover-pseudo-borders-expected.txt
@@ -23,7 +23,7 @@
           "reason": "style change"
         },
         {
-          "object": "LayoutNGBlockFlow DIV class='hitregion'",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV class='hitregion'",
           "rect": [8, 8, 100, 100],
           "reason": "background"
         }
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/float-new-in-block-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/float-new-in-block-expected.txt
new file mode 100644
index 0000000..c551980
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/float-new-in-block-expected.txt
@@ -0,0 +1,39 @@
+{
+  "layers": [
+    {
+      "name": "LayoutView #document",
+      "bounds": [800, 600],
+      "drawsContent": false,
+      "backgroundColor": "#FFFFFF"
+    },
+    {
+      "name": "Scrolling Layer",
+      "bounds": [800, 600],
+      "drawsContent": false
+    },
+    {
+      "name": "Scrolling Contents Layer",
+      "bounds": [800, 600],
+      "contentsOpaque": true,
+      "backgroundColor": "#FFFFFF",
+      "paintInvalidations": [
+        {
+          "object": "LayoutNGBlockFlow DIV",
+          "rect": [8, 8, 784, 20],
+          "reason": "disappeared"
+        },
+        {
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
+          "rect": [8, 8, 784, 20],
+          "reason": "appeared"
+        },
+        {
+          "object": "LayoutNGBlockFlow (floating) DIV id='target'",
+          "rect": [8, 8, 100, 100],
+          "reason": "appeared"
+        }
+      ]
+    }
+  ]
+}
+
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/outline/focus-ring-on-child-move-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
index 55b3f2c7..cccefe52 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/outline/focus-ring-on-child-move-expected.txt
@@ -18,11 +18,6 @@
       "backgroundColor": "#FFFFFF",
       "paintInvalidations": [
         {
-          "object": "LayoutNGBlockFlow (positioned) DIV",
-          "rect": [99, 49, 302, 302],
-          "reason": "outline"
-        },
-        {
           "object": "LayoutNGBlockFlow (positioned) DIV id='child'",
           "rect": [300, 50, 20, 300],
           "reason": "geometry"
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-expected.txt
index 554045a..1ad6d2c 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [69, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [67, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-right-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-right-expected.txt
index 62047a4..8d203a5 100644
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-right-expected.txt
+++ b/third_party/blink/web_tests/platform/win/paint/invalidation/overflow/float-overflow-right-expected.txt
@@ -158,32 +158,32 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 504, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 498, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 465, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 459, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 426, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 420, 50, 10],
           "reason": "geometry"
         },
@@ -198,82 +198,82 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 177, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 171, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 138, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 132, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 99, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 93, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 60, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 54, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 21, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [683, 15, 50, 10],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 374, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 368, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 335, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 329, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 296, 42, 12],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGTableCell TD",
+          "object": "NGPhysicalBoxFragment LayoutNGTableCell TD",
           "rect": [689, 290, 42, 12],
           "reason": "geometry"
         },
@@ -418,12 +418,12 @@
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 543, 32, 20],
           "reason": "geometry"
         },
         {
-          "object": "LayoutNGBlockFlow DIV",
+          "object": "NGPhysicalBoxFragment LayoutNGBlockFlow DIV",
           "rect": [701, 537, 32, 20],
           "reason": "geometry"
         },
diff --git a/third_party/blink/web_tests/plugins/mouse-click-iframe-to-plugin-expected.txt b/third_party/blink/web_tests/plugins/mouse-click-iframe-to-plugin-expected.txt
index d95403e6..2fc0ebc 100644
--- a/third_party/blink/web_tests/plugins/mouse-click-iframe-to-plugin-expected.txt
+++ b/third_party/blink/web_tests/plugins/mouse-click-iframe-to-plugin-expected.txt
@@ -1,3 +1,4 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 
 
 PASSED
diff --git a/third_party/blink/web_tests/plugins/mouse-move-over-plugin-in-frame-expected.txt b/third_party/blink/web_tests/plugins/mouse-move-over-plugin-in-frame-expected.txt
index ead8fb5..179c32a 100644
--- a/third_party/blink/web_tests/plugins/mouse-move-over-plugin-in-frame-expected.txt
+++ b/third_party/blink/web_tests/plugins/mouse-move-over-plugin-in-frame-expected.txt
@@ -1 +1,2 @@
+CONSOLE MESSAGE: Blink Test Plugin: initializing
 Test for bug 47956: Crash when mouse is over plugin inside a frame.
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
new file mode 100644
index 0000000..94a4387
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/button/button-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
new file mode 100644
index 0000000..598f6a2
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/fast/forms/controls-new-ui/file/file-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/scalefactor200/external/wpt/element-timing/README.txt b/third_party/blink/web_tests/virtual/scalefactor200/external/wpt/element-timing/README.txt
new file mode 100644
index 0000000..c1916b7
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/scalefactor200/external/wpt/element-timing/README.txt
@@ -0,0 +1,2 @@
+# This suite runs the tests in LayoutTests/external/wpt/element-timing/
+# with the flag --force-device-scale-factor=2.
diff --git a/third_party/blink/web_tests/virtual/scalefactor200withoutzoom/external/wpt/element-timing/README.txt b/third_party/blink/web_tests/virtual/scalefactor200withoutzoom/external/wpt/element-timing/README.txt
new file mode 100644
index 0000000..9267226f
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/scalefactor200withoutzoom/external/wpt/element-timing/README.txt
@@ -0,0 +1,3 @@
+# This suite runs the tests in LayoutTests/external/wpt/element-timing/
+# with the flags --force-device-scale-factor=2 and --enable-use-zoom-for-dsf=false
+# TODO(npm): Remove this virtual test when all platforms are migrated to use zoom for dsf.
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index eb72f2d..6d756176 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -4400,6 +4400,7 @@
     attribute @@toStringTag
     getter element
     getter id
+    getter renderTime
     getter responseEnd
     getter size
     getter url
@@ -5403,6 +5404,7 @@
     getter intersectionRect
     getter naturalHeight
     getter naturalWidth
+    getter renderTime
     getter responseEnd
     getter url
     method constructor
diff --git a/third_party/instrumented_libraries/OWNERS b/third_party/instrumented_libraries/OWNERS
index e01f8c7..5ab51c29 100644
--- a/third_party/instrumented_libraries/OWNERS
+++ b/third_party/instrumented_libraries/OWNERS
@@ -1,4 +1,3 @@
-eugenis@chromium.org
 glider@chromium.org
-inferno@chromium.org
-ochang@chromium.org
+eugenis@chromium.org
+
diff --git a/third_party/polymer/OWNERS b/third_party/polymer/OWNERS
index 0e971c4f..d4423e5 100644
--- a/third_party/polymer/OWNERS
+++ b/third_party/polymer/OWNERS
@@ -1,3 +1,5 @@
 dbeam@chromium.org
 dpapad@chromium.org
 michaelpg@chromium.org
+
+# COMPONENT: UI>Browser>WebUI
diff --git a/third_party/quic_trace/OWNERS b/third_party/quic_trace/OWNERS
index 3a9a3cb..09bebb7 100644
--- a/third_party/quic_trace/OWNERS
+++ b/third_party/quic_trace/OWNERS
@@ -3,3 +3,4 @@
 zhongyi@chromium.org
 
 file://net/OWNERS
+# COMPONENT: Internals>Network>QUIC
diff --git a/third_party/web-animations-js/OWNERS b/third_party/web-animations-js/OWNERS
index 0e971c4f..d4423e5 100644
--- a/third_party/web-animations-js/OWNERS
+++ b/third_party/web-animations-js/OWNERS
@@ -1,3 +1,5 @@
 dbeam@chromium.org
 dpapad@chromium.org
 michaelpg@chromium.org
+
+# COMPONENT: UI>Browser>WebUI
diff --git a/tools/binary_size/libsupersize/archive.py b/tools/binary_size/libsupersize/archive.py
index e77c58f..96d2fc0 100644
--- a/tools/binary_size/libsupersize/archive.py
+++ b/tools/binary_size/libsupersize/archive.py
@@ -1116,30 +1116,9 @@
   return section_sizes, 0
 
 
-def _LoadResourcesPathmap(pathmap_path):
-  """Load the pathmap of obfuscated resource paths.
-
-  Returns: A dict mapping from obfuscated paths to original paths or an
-           empty dict if passed a None |pathmap_path|.
-  """
-  if pathmap_path is None:
-    return {}
-
-  pathmap = {}
-  with open(pathmap_path, 'r') as f:
-    for line in f:
-      line = line.strip()
-      if line.startswith('--') or line == '':
-        continue
-      original, renamed = line.split(' -> ')
-      pathmap[renamed] = original
-  return pathmap
-
-
 def _ParseApkOtherSymbols(section_sizes, apk_path, apk_so_path,
-                          resources_pathmap_path, size_info_prefix, knobs):
+                          size_info_prefix, knobs):
   res_source_mapper = _ResourceSourceMapper(size_info_prefix, knobs)
-  resources_pathmap = _LoadResourcesPathmap(resources_pathmap_path)
   apk_symbols = []
   dex_size = 0
   zip_info_total = 0
@@ -1154,17 +1133,13 @@
         dex_size += zip_info.file_size
         continue
 
-      resource_filename = resources_pathmap.get(zip_info.filename,
-                                                zip_info.filename)
-      source_path = res_source_mapper.FindSourceForPath(resource_filename)
+      source_path = res_source_mapper.FindSourceForPath(zip_info.filename)
       if source_path is None:
-        source_path = os.path.join(models.APK_PREFIX_PATH, resource_filename)
-      apk_symbols.append(
-          models.Symbol(
-              models.SECTION_OTHER,
-              zip_info.compress_size,
-              source_path=source_path,
-              full_name=resource_filename))  # Full name must disambiguate
+        source_path = os.path.join(models.APK_PREFIX_PATH, zip_info.filename)
+      apk_symbols.append(models.Symbol(
+            models.SECTION_OTHER, zip_info.compress_size,
+            source_path=source_path,
+            full_name=zip_info.filename))  # Full name must disambiguate
   overhead_size = os.path.getsize(apk_path) - zip_info_total
   assert overhead_size >= 0, 'Apk overhead must be non-negative'
   zip_overhead_symbol = models.Symbol(
@@ -1250,21 +1225,11 @@
   return 0
 
 
-def CreateSectionSizesAndSymbols(map_path=None,
-                                 tool_prefix=None,
-                                 output_directory=None,
-                                 elf_path=None,
-                                 apk_path=None,
-                                 mapping_path=None,
-                                 resources_pathmap_path=None,
-                                 track_string_literals=True,
-                                 metadata=None,
-                                 apk_so_path=None,
-                                 pak_files=None,
-                                 pak_info_file=None,
-                                 linker_name=None,
-                                 size_info_prefix=None,
-                                 knobs=None):
+def CreateSectionSizesAndSymbols(
+      map_path=None, tool_prefix=None, output_directory=None, elf_path=None,
+      apk_path=None, mapping_path=None, track_string_literals=True,
+      metadata=None, apk_so_path=None, pak_files=None, pak_info_file=None,
+      linker_name=None, size_info_prefix=None, knobs=None):
   """Creates sections sizes and symbols for a SizeInfo.
 
   Args:
@@ -1275,8 +1240,6 @@
     elf_path: Path to the corresponding unstripped ELF file. Used to find symbol
         aliases and inlined functions. Can be None.
     apk_path: Path to the .apk file to measure.
-    resources_pathmap_path: Path to the pathmap file that maps original
-        resource paths to shortened resource paths.
     track_string_literals: Whether to break down "** merge string" sections into
         smaller symbols (requires output_directory).
     metadata: Metadata dict from CreateMetadata().
@@ -1352,8 +1315,7 @@
         apk_path, mapping_path, size_info_prefix, output_directory)
     raw_symbols.extend(dex_symbols)
     dex_size, other_symbols = _ParseApkOtherSymbols(
-        section_sizes, apk_path, apk_so_path, resources_pathmap_path,
-        size_info_prefix, knobs)
+        section_sizes, apk_path, apk_so_path, size_info_prefix, knobs)
     raw_symbols.extend(other_symbols)
 
     # We can't meaningfully track section size of dex methods vs other, so just
@@ -1524,9 +1486,6 @@
   parser.add_argument('--apk-file',
                       help='.apk file to measure. Other flags can generally be '
                            'derived when this is used.')
-  parser.add_argument('--resources-pathmap-file',
-                      help='.pathmap.txt file that contains a maping from '
-                      'original resource paths to shortened resource paths.')
   parser.add_argument('--minimal-apks-file',
                       help='.minimal.apks file to measure. Other flags can '
                            'generally be derived when this is used.')
@@ -1578,7 +1537,6 @@
 
   aab_or_apk = args.apk_file or args.minimal_apks_file
   mapping_path = args.mapping_file
-  resources_pathmap_path = args.resources_pathmap_file
   if aab_or_apk:
     # Allow either .minimal.apks or just .apks.
     aab_or_apk = aab_or_apk.replace('.minimal.apks', '.aab')
@@ -1586,17 +1544,6 @@
     if not mapping_path:
       mapping_path = aab_or_apk + '.mapping'
       logging.debug('Detected --mapping-file=%s', mapping_path)
-    if not resources_pathmap_path:
-      possible_pathmap_path = aab_or_apk + '.pathmap.txt'
-      # This could be pointing to a stale pathmap file if path shortening was
-      # previously enabled but is disabled for the current build. However, since
-      # current apk/aab will have unshortened paths, looking those paths up in
-      # the stale pathmap which is keyed by shortened paths would not find any
-      # mapping and thus should not cause any issues.
-      if os.path.exists(possible_pathmap_path):
-        resources_pathmap_path = possible_pathmap_path
-        logging.debug('Detected --resources-pathmap-file=%s',
-                      resources_pathmap_path)
 
   apk_path = extracted_minimal_apk_path or args.apk_file
   apk_so_path = None
@@ -1647,8 +1594,7 @@
         output_directory, 'size-info', os.path.basename(aab_or_apk))
 
   return (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path,
-          elf_path, map_path, resources_pathmap_path, linker_name,
-          size_info_prefix)
+          elf_path, map_path, linker_name, size_info_prefix)
 
 
 def Run(args, parser):
@@ -1679,8 +1625,7 @@
 
 def _RunInternal(args, parser, extracted_minimal_apk_path):
   (output_directory, tool_prefix, apk_path, mapping_path, apk_so_path, elf_path,
-   map_path, resources_pathmap_path,
-   linker_name, size_info_prefix) = _DeduceMainPaths(
+   map_path, linker_name, size_info_prefix) = _DeduceMainPaths(
        args, parser, extracted_minimal_apk_path)
 
   metadata = CreateMetadata(map_path, elf_path, args.apk_file,
@@ -1692,21 +1637,13 @@
     knobs.src_root = args.source_directory
 
   section_sizes, raw_symbols = CreateSectionSizesAndSymbols(
-      map_path=map_path,
-      tool_prefix=tool_prefix,
-      elf_path=elf_path,
-      apk_path=apk_path,
-      mapping_path=mapping_path,
+      map_path=map_path, tool_prefix=tool_prefix, elf_path=elf_path,
+      apk_path=apk_path, mapping_path=mapping_path,
       output_directory=output_directory,
-      resources_pathmap_path=resources_pathmap_path,
       track_string_literals=args.track_string_literals,
-      metadata=metadata,
-      apk_so_path=apk_so_path,
-      pak_files=args.pak_file,
-      pak_info_file=args.pak_info_file,
-      linker_name=linker_name,
-      size_info_prefix=size_info_prefix,
-      knobs=knobs)
+      metadata=metadata, apk_so_path=apk_so_path,
+      pak_files=args.pak_file, pak_info_file=args.pak_info_file,
+      linker_name=linker_name, size_info_prefix=size_info_prefix, knobs=knobs)
   size_info = CreateSizeInfo(
       section_sizes, raw_symbols, metadata=metadata, normalize_names=False)
 
diff --git a/tools/binary_size/supersize.pydeps b/tools/binary_size/supersize.pydeps
index 9765409..5b4b556 100644
--- a/tools/binary_size/supersize.pydeps
+++ b/tools/binary_size/supersize.pydeps
@@ -28,6 +28,7 @@
 ../grit/grit/lazy_re.py
 ../grit/grit/node/__init__.py
 ../grit/grit/node/base.py
+../grit/grit/node/brotli_util.py
 ../grit/grit/node/include.py
 ../grit/grit/node/message.py
 ../grit/grit/node/misc.py
diff --git a/tools/grit/BUILD.gn b/tools/grit/BUILD.gn
index f0368850..d48a778 100644
--- a/tools/grit/BUILD.gn
+++ b/tools/grit/BUILD.gn
@@ -5,6 +5,9 @@
 # This target creates a stamp file that depends on all the sources in the grit
 # directory. By depending on this, a target can force itself to be rebuilt if
 # grit itself changes.
+
+import("//build/config/sanitizers/sanitizers.gni")
+
 action("grit_sources") {
   depfile = "$target_out_dir/grit_sources.d"
   script = "stamp_grit_sources.py"
@@ -37,3 +40,15 @@
     "//third_party/catapult/third_party/typ/",
   ]
 }
+
+# See https://crbug.com/983200
+if (is_mac && is_asan) {
+  create_bundle("brotli_mac_asan_workaround") {
+    bundle_root_dir = "$target_out_dir/$target_name"
+    bundle_executable_dir = bundle_root_dir
+
+    public_deps = [
+      "//third_party/brotli:brotli($host_toolchain)",
+    ]
+  }
+}
diff --git a/tools/grit/grit/constants.py b/tools/grit/grit/constants.py
index 3a05c11..65ff0655 100644
--- a/tools/grit/grit/constants.py
+++ b/tools/grit/grit/constants.py
@@ -16,3 +16,8 @@
 CONSTANT_LANGUAGE = 'x_constant'
 
 FAKE_BIDI = 'fake-bidi'
+
+# Magic number added to the header of resources brotli compressed by grit. Used
+# to easily identify resources as being brotli compressed. See
+# ui/base/resource/resource_bundle.h for decompression usage.
+BROTLI_CONST = '\x1e\x9b'
\ No newline at end of file
diff --git a/tools/grit/grit/format/policy_templates_json_unittest.py b/tools/grit/grit/format/policy_templates_json_unittest.py
index 64eae1b..bf797004 100755
--- a/tools/grit/grit/format/policy_templates_json_unittest.py
+++ b/tools/grit/grit/format/policy_templates_json_unittest.py
@@ -125,7 +125,7 @@
     grd_string_io = StringIO.StringIO(grd_text)
 
     # Parse the grit tree and load the policies' JSON with a gatherer.
-    grd = grd_reader.Parse(grd_string_io, dir=tmp_dir_name)
+    grd = grd_reader.Parse(grd_string_io, dir=tmp_dir_name, defines={'_google_chrome': True})
     grd.SetOutputLanguage('en')
     grd.RunGatherers()
 
diff --git a/tools/grit/grit/format/rc.py b/tools/grit/grit/format/rc.py
index 7037278..ac65f34 100644
--- a/tools/grit/grit/format/rc.py
+++ b/tools/grit/grit/format/rc.py
@@ -259,14 +259,14 @@
 # being generated.
 
 def GetLangCharsetPair(language):
-  if _LANGUAGE_CHARSET_PAIR.has_key(language):
+  if language in _LANGUAGE_CHARSET_PAIR:
     return _LANGUAGE_CHARSET_PAIR[language]
   if language != 'no-specific-language':
     print('Warning:GetLangCharsetPair() found undefined language %s' % language)
   return ''
 
 def GetLangDirectivePair(language):
-  if _LANGUAGE_DIRECTIVE_PAIR.has_key(language):
+  if language in _LANGUAGE_DIRECTIVE_PAIR:
     return _LANGUAGE_DIRECTIVE_PAIR[language]
 
   # We don't check for 'no-specific-language' here because this
@@ -277,7 +277,7 @@
   return 'unknown language: see tools/grit/format/rc.py'
 
 def GetLangIdHex(language):
-  if _LANGUAGE_CHARSET_PAIR.has_key(language):
+  if language in _LANGUAGE_CHARSET_PAIR:
     langcharset = _LANGUAGE_CHARSET_PAIR[language]
     lang_id = '0x' + langcharset[0:4]
     return lang_id
@@ -287,7 +287,7 @@
 
 
 def GetCharsetIdDecimal(language):
-  if _LANGUAGE_CHARSET_PAIR.has_key(language):
+  if language in _LANGUAGE_CHARSET_PAIR:
     langcharset = _LANGUAGE_CHARSET_PAIR[language]
     charset_decimal = int(langcharset[4:], 16)
     return str(charset_decimal)
diff --git a/tools/grit/grit/gather/policy_json.py b/tools/grit/grit/gather/policy_json.py
index 7fd5cec..386b8078 100644
--- a/tools/grit/grit/gather/policy_json.py
+++ b/tools/grit/grit/gather/policy_json.py
@@ -59,9 +59,15 @@
     if example_text == []:
       # In such cases the original text is okay for an example.
       example_text = text
+
+    replaced_text = self.Escape(''.join(text).strip())
+    replaced_text = replaced_text.replace('$1', self._config['app_name'])
+    replaced_text = replaced_text.replace('$2', self._config['os_name'])
+    replaced_text = replaced_text.replace('$3', self._config['frame_name'])
+
     msg.AppendPlaceholder(tclib.Placeholder(
         placeholder.attributes['name'].value,
-        self.Escape(''.join(text).strip()),
+        replaced_text,
         ''.join(example_text).strip()))
 
   def _ParseMessage(self, string, desc):
@@ -293,3 +299,24 @@
 
   def Escape(self, text):
     return json.dumps(text, ensure_ascii=False)[1:-1]
+
+  def SetDefines(self, defines):
+    if not defines:
+      raise Exception('Must pass valid defines')
+
+    if '_chromium' in defines:
+      self._config = {
+        'build': 'chromium',
+        'app_name': 'Chromium',
+        'frame_name': 'Chromium Frame',
+        'os_name': 'Chromium OS',
+      }
+    elif '_google_chrome' in defines:
+      self._config = {
+        'build': 'chrome',
+        'app_name': 'Google Chrome',
+        'frame_name': 'Google Chrome Frame',
+        'os_name': 'Google Chrome OS',
+      }
+    else:
+      raise Exception('Unknown build')
diff --git a/tools/grit/grit/gather/policy_json_unittest.py b/tools/grit/grit/gather/policy_json_unittest.py
index e99fa66..11666ec 100755
--- a/tools/grit/grit/gather/policy_json_unittest.py
+++ b/tools/grit/grit/gather/policy_json_unittest.py
@@ -262,7 +262,7 @@
     expected = self.GetExpectedOutput(original)
     self.failUnless(expected == json.loads(gatherer.Translate('en')))
 
-  def testPlaceholders(self):
+  def testPlaceholdersChromium(self):
     original = """{
         "policy_definitions": [
           {
@@ -274,20 +274,47 @@
         "messages": {}
 }"""
     gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+    gatherer.SetDefines({'_chromium': True})
     gatherer.Parse()
     self.failUnless(len(gatherer.GetCliques()) == 1)
-    expected = json.loads(re.sub('<ph.*ph>', '$1', original))
+    expected = json.loads(re.sub('<ph.*ph>', 'Chromium', original))
     self.failUnless(expected == json.loads(gatherer.Translate('en')))
     self.failUnless(gatherer.GetCliques()[0].translateable)
     msg = gatherer.GetCliques()[0].GetMessage()
     self.failUnless(len(msg.GetPlaceholders()) == 1)
     ph = msg.GetPlaceholders()[0]
-    self.failUnless(ph.GetOriginal() == '$1')
+    self.failUnless(ph.GetOriginal() == 'Chromium')
+    self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
+    self.failUnless(ph.GetExample() == 'Google Chrome')
+
+  def testPlaceholdersChrome(self):
+    original = """{
+        "policy_definitions": [
+          {
+            "name": "Policy1",
+            "caption": "Please install\\n<ph name=\\"PRODUCT_NAME\\">$1<ex>Google Chrome</ex></ph>."
+          }
+        ],
+        "policy_atomic_group_definitions": [],
+        "messages": {}
+}"""
+    gatherer = policy_json.PolicyJson(StringIO.StringIO(original))
+    gatherer.SetDefines({'_google_chrome': True})
+    gatherer.Parse()
+    self.failUnless(len(gatherer.GetCliques()) == 1)
+    expected = json.loads(re.sub('<ph.*ph>', 'Google Chrome', original))
+    self.failUnless(expected == json.loads(gatherer.Translate('en')))
+    self.failUnless(gatherer.GetCliques()[0].translateable)
+    msg = gatherer.GetCliques()[0].GetMessage()
+    self.failUnless(len(msg.GetPlaceholders()) == 1)
+    ph = msg.GetPlaceholders()[0]
+    self.failUnless(ph.GetOriginal() == 'Google Chrome')
     self.failUnless(ph.GetPresentation() == 'PRODUCT_NAME')
     self.failUnless(ph.GetExample() == 'Google Chrome')
 
   def testGetDescription(self):
     gatherer = policy_json.PolicyJson({})
+    gatherer.SetDefines({'_google_chrome': True})
     self.assertEquals(
         gatherer._GetDescription({'name': 'Policy1'}, 'policy', None, 'desc'),
         'Description of the policy named Policy1')
diff --git a/tools/grit/grit/gather/regexp.py b/tools/grit/grit/gather/regexp.py
index d06bf9c..bc6dfe1 100644
--- a/tools/grit/grit/gather/regexp.py
+++ b/tools/grit/grit/gather/regexp.py
@@ -32,7 +32,7 @@
   # Contextualization elements. Used for adding additional information
   # to the message bundle description string from RC files.
   def AddDescriptionElement(self, string):
-    if self.DescriptionMapping_.has_key(string):
+    if string in self.DescriptionMapping_:
       description = self.DescriptionMapping_[string]
     else:
       description = string
diff --git a/tools/grit/grit/node/base.py b/tools/grit/grit/node/base.py
index ca92a91..7b3e515 100644
--- a/tools/grit/grit/node/base.py
+++ b/tools/grit/grit/node/base.py
@@ -9,13 +9,16 @@
 
 import ast
 import os
+import struct
 import sys
 import types
 from xml.sax import saxutils
 
+from grit import constants
 from grit import clique
 from grit import exception
 from grit import util
+from grit.node import brotli_util
 import grit.format.gzip_string
 
 
@@ -604,18 +607,36 @@
     Args:
       data: The data to compressed.
     Returns:
-      The data in compressed format. If the format was unknown then this returns
-      the data uncompressed.
+      The data in gzipped or brotli compressed format. If the format is
+      unspecified then this returns the data uncompressed.
     '''
-    if self.attrs.get('compress') != 'gzip':
+    if self.attrs.get('compress') == 'gzip':
+      # We only use rsyncable compression on Linux.
+      # We exclude ChromeOS since ChromeOS bots are Linux based but do not have
+      # the --rsyncable option built in for gzip. See crbug.com/617950.
+      if sys.platform == 'linux2' and 'chromeos' not in self.GetRoot().defines:
+        return grit.format.gzip_string.GzipStringRsyncable(data)
+      return grit.format.gzip_string.GzipString(data)
+
+    elif self.attrs.get('compress') == 'brotli':
+      # The length of the uncompressed data as 8 bytes little-endian.
+      size_bytes = struct.pack("<q", len(data))
+      data = brotli_util.BrotliCompress(data)
+      # BROTLI_CONST is prepended to brotli decompressed data in order to
+      # easily check if a resource has been brotli compressed.
+      # The length of the uncompressed data is also appended to the start,
+      # truncated to 6 bytes, little-endian. size_bytes is 8 bytes,
+      # need to truncate further to 6.
+      formatter = '%ds %dx %ds' % (6, 2, len(size_bytes) - 8)
+      return (constants.BROTLI_CONST +
+             b''.join(struct.unpack(formatter, size_bytes)) +
+             data)
+
+    elif self.attrs.get('compress') == 'false':
       return data
 
-    # We only use rsyncable compression on Linux.
-    # We exclude ChromeOS since ChromeOS bots are Linux based but do not have
-    # the --rsyncable option built in for gzip. See crbug.com/617950.
-    if sys.platform == 'linux2' and 'chromeos' not in self.GetRoot().defines:
-      return grit.format.gzip_string.GzipStringRsyncable(data)
-    return grit.format.gzip_string.GzipString(data)
+    else:
+      raise Exception('Invalid value for compression')
 
 
 class ContentNode(Node):
diff --git a/tools/grit/grit/node/brotli_util.py b/tools/grit/grit/node/brotli_util.py
new file mode 100644
index 0000000..d518215
--- /dev/null
+++ b/tools/grit/grit/node/brotli_util.py
@@ -0,0 +1,24 @@
+# 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.
+
+"""Framework for compressing resources using Brotli."""
+
+import subprocess
+
+__brotli_executable = None
+
+
+def SetBrotliCommand(brotli):
+  # brotli is a list. In production it contains the path to the Brotli executable.
+  # During testing it contains [python, mock_brotli.py] for testing on Windows.
+  global __brotli_executable
+  __brotli_executable = brotli
+
+
+def BrotliCompress(data):
+  if not __brotli_executable:
+    raise Exception('SetBrotliCommand has not been called yet!')
+  compress = subprocess.Popen(__brotli_executable + ['-', '-f'],
+                              stdin=subprocess.PIPE, stdout=subprocess.PIPE)
+  return compress.communicate(data)[0]
diff --git a/tools/grit/grit/node/mock_brotli.py b/tools/grit/grit/node/mock_brotli.py
new file mode 100755
index 0000000..14237aa
--- /dev/null
+++ b/tools/grit/grit/node/mock_brotli.py
@@ -0,0 +1,10 @@
+#!/usr/bin/env python
+# 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.
+
+"""Mock Brotli Executable for testing purposes."""
+
+import sys
+
+sys.stdout.write('This has been mock compressed!')
diff --git a/tools/grit/grit/node/structure_unittest.py b/tools/grit/grit/node/structure_unittest.py
index 64ed9b27..2bf8e84 100755
--- a/tools/grit/grit/node/structure_unittest.py
+++ b/tools/grit/grit/node/structure_unittest.py
@@ -19,8 +19,11 @@
 import tempfile
 import unittest
 import StringIO
+import struct
 
+from grit import constants
 from grit import util
+from grit.node import brotli_util
 from grit.node import empty
 from grit.node import misc
 from grit.node import structure
@@ -106,27 +109,57 @@
           <structure name="TEST_TXT" file="test_text.txt"
                    compress="gzip" type="chrome_html" />
         </structures>''', base_dir=test_data_root)
-    struct, = root.GetChildrenOfType(structure.StructureNode)
-    struct.RunPreSubstitutionGatherer()
-    compressed = struct.GetDataPackValue(lang='en', encoding=1)
+    node, = root.GetChildrenOfType(structure.StructureNode)
+    node.RunPreSubstitutionGatherer()
+    compressed = node.GetDataPackValue(lang='en', encoding=1)
 
     decompressed_data = zlib.decompress(compressed, 16 + zlib.MAX_WBITS)
     self.assertEqual(util.ReadFile(
-        os.path.join(test_data_root, "test_text.txt"), util.BINARY),
+        os.path.join(test_data_root, 'test_text.txt'), util.BINARY),
                      decompressed_data)
 
+  def testCompressBrotli(self):
+    test_data_root = util.PathFromRoot('grit/testdata')
+    root = util.ParseGrdForUnittest(
+        '''
+        <structures>
+          <structure name="TEST_TXT" file="test_text.txt"
+                   compress="brotli" type="chrome_html" />
+        </structures>''',
+        base_dir=test_data_root)
+    node, = root.GetChildrenOfType(structure.StructureNode)
+    node.RunPreSubstitutionGatherer()
+
+    # Using the mock brotli decompression executable.
+    brotli_util.SetBrotliCommand([sys.executable,
+                                 os.path.join(os.path.dirname(__file__),
+                                 'mock_brotli.py')])
+    compressed = node.GetDataPackValue(lang='en', encoding=1)
+    # Assert that the first two bytes in compressed format is BROTLI_CONST.
+    self.assertEqual(constants.BROTLI_CONST, compressed[0:2])
+
+    # Compare the actual size of the uncompressed test data with
+    # the size appended during compression.
+    actual_size = len(util.ReadFile(
+        os.path.join(test_data_root, 'test_text.txt'), util.BINARY))
+    uncompress_size = struct.unpack('<i', compressed[2:6])[0]
+    uncompress_size += struct.unpack('<h', compressed[6:8])[0] << 4*8
+    self.assertEqual(actual_size, uncompress_size)
+
+    self.assertEqual('This has been mock compressed!', compressed[8:])
+
   def testNotCompressed(self):
     test_data_root = util.PathFromRoot('grit/testdata')
     root = util.ParseGrdForUnittest('''
         <structures>
           <structure name="TEST_TXT" file="test_text.txt" type="chrome_html" />
         </structures>''', base_dir=test_data_root)
-    struct, = root.GetChildrenOfType(structure.StructureNode)
-    struct.RunPreSubstitutionGatherer()
-    data = struct.GetDataPackValue(lang='en', encoding=1)
+    node, = root.GetChildrenOfType(structure.StructureNode)
+    node.RunPreSubstitutionGatherer()
+    data = node.GetDataPackValue(lang='en', encoding=1)
 
     self.assertEqual(util.ReadFile(
-        os.path.join(test_data_root, "test_text.txt"), util.BINARY), data)
+        os.path.join(test_data_root, 'test_text.txt'), util.BINARY), data)
 
 
 if __name__ == '__main__':
diff --git a/tools/grit/grit/node/variant.py b/tools/grit/grit/node/variant.py
index ab183f0..9f5845f 100644
--- a/tools/grit/grit/node/variant.py
+++ b/tools/grit/grit/node/variant.py
@@ -26,7 +26,7 @@
     return {'encoding' : ''}
 
   def _ContentType(self):
-    if self.attrs.has_key('file'):
+    if 'file' in self.attrs:
       return self._CONTENT_TYPE_NONE
     else:
       return self._CONTENT_TYPE_CDATA
diff --git a/tools/grit/grit/tclib.py b/tools/grit/grit/tclib.py
index c73664f..23bef75 100644
--- a/tools/grit/grit/tclib.py
+++ b/tools/grit/grit/tclib.py
@@ -67,7 +67,7 @@
 
         for chunk in chunked_text:
           if chunk: # ignore empty chunk
-            if tag_map.has_key(chunk):
+            if chunk in tag_map:
               self.AppendPlaceholder(tag_map[chunk][0])
               tag_map[chunk][1] += 1 # increase placeholder use count
             else:
diff --git a/tools/grit/grit/tool/build.py b/tools/grit/grit/tool/build.py
index fde614d..436830a 100644
--- a/tools/grit/grit/tool/build.py
+++ b/tools/grit/grit/tool/build.py
@@ -18,6 +18,7 @@
 from grit import shortcuts
 from grit import util
 from grit.format import minifier
+from grit.node import brotli_util
 from grit.node import include
 from grit.node import message
 from grit.node import structure
@@ -133,6 +134,10 @@
                     minified Javascript to standard output. A non-zero exit
                     status will be taken as indicating failure.
 
+  --brotli          The full path to the brotli executable generated by
+                    third_party/brotli/BUILD.gn, required if any entries use
+                    compress="brotli".
+
 Conditional inclusion of resources only affects the output of files which
 control which resources get linked into a binary, e.g. it affects .rc files
 meant for compilation but it does not affect resource header files (that define
@@ -158,16 +163,12 @@
     depend_on_stamp = False
     js_minifier = None
     replace_ellipsis = True
-    (own_opts, args) = getopt.getopt(args, 'a:p:o:D:E:f:w:t:',
-        ('depdir=','depfile=','assert-file-list=',
-         'help',
-         'output-all-resource-defines',
-         'no-output-all-resource-defines',
-         'no-replace-ellipsis',
-         'depend-on-stamp',
-         'js-minifier=',
-         'write-only-new=',
-         'whitelist-support'))
+    (own_opts, args) = getopt.getopt(
+        args, 'a:p:o:D:E:f:w:t:',
+        ('depdir=', 'depfile=', 'assert-file-list=', 'help',
+         'output-all-resource-defines', 'no-output-all-resource-defines',
+         'no-replace-ellipsis', 'depend-on-stamp', 'js-minifier=',
+         'write-only-new=', 'whitelist-support', 'brotli='))
     for (key, val) in own_opts:
       if key == '-a':
         assert_output_files.append(val)
@@ -207,6 +208,8 @@
         js_minifier = val
       elif key == '--whitelist-support':
         whitelist_support = True
+      elif key == '--brotli':
+        brotli_util.SetBrotliCommand([os.path.abspath(val)])
       elif key == '--help':
         self.ShowUsage()
         sys.exit(0)
diff --git a/tools/grit/grit_rule.gni b/tools/grit/grit_rule.gni
index 8a4f3f9..e4e3173e 100644
--- a/tools/grit/grit_rule.gni
+++ b/tools/grit/grit_rule.gni
@@ -95,6 +95,7 @@
 import("//build/config/compute_inputs_for_analyze.gni")
 import("//build/config/crypto.gni")
 import("//build/config/features.gni")
+import("//build/config/sanitizers/sanitizers.gni")
 import("//build/config/ui.gni")
 import("//build/toolchain/gcc_toolchain.gni")  # For enable_resource_whitelist_generation
 import("//third_party/closure_compiler/closure_args.gni")
@@ -348,6 +349,16 @@
     depfile = "$depfile_dir/${grit_output_name}_stamp.d"
     outputs = [ "${depfile}.stamp" ] + grit_outputs + pak_info_outputs
 
+    brotli_target = "//third_party/brotli:brotli($host_toolchain)"
+
+    brotli_executable = get_label_info(brotli_target, "root_out_dir") + "/" +
+                        get_label_info(brotli_target, "name")
+    if (host_os == "win") {
+      brotli_executable += ".exe"
+    }
+
+    inputs += [ brotli_executable ]
+
     args = [
              "-i",
              source_path,
@@ -360,6 +371,8 @@
              rebase_path(depfile, root_build_dir),
              "--write-only-new=1",
              "--depend-on-stamp",
+             "--brotli",
+             rebase_path(brotli_executable, root_build_dir),
            ] + grit_defines
 
     # Add extra defines with -D flags.
@@ -443,6 +456,11 @@
     deps = [
       "//tools/grit:grit_sources",
     ]
+    if (is_mac && is_asan) {
+      deps += [ "//tools/grit:brotli_mac_asan_workaround" ]
+    } else {
+      deps += [ brotli_target ]
+    }
     if (defined(invoker.deps)) {
       deps += invoker.deps
     }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index f86ac28..634e4d6 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -17349,7 +17349,7 @@
   <int value="515" label="PluginVmLicenseKey"/>
   <int value="516" label="ExtensionAllowInsecureUpdates"/>
   <int value="517" label="BrowserSwitcherEnabled"/>
-  <int value="518" label="CertificateManagementAllowed"/>
+  <int value="518" label="ClientCertificateManagementAllowed"/>
   <int value="519" label="BrowserSwitcherKeepLastChromeTab"/>
   <int value="520" label="DeviceRebootOnUserSignout"/>
   <int value="521" label="ForceNetworkInProcess"/>
@@ -33818,6 +33818,7 @@
   <int value="-1846471618"
       label="enable-experimental-accessibility-switch-access-text"/>
   <int value="-1844754731" label="Mash:disabled"/>
+  <int value="-1843677118" label="TwoPanesStartSurfaceAndroid:disabled"/>
   <int value="-1840608422" label="AdvancedPpdAttributes:disabled"/>
   <int value="-1839874877" label="WebXROrientationSensorDevice:enabled"/>
   <int value="-1839496458" label="disable-file-manager-touch-mode"/>
@@ -33869,6 +33870,7 @@
   <int value="-1755301960" label="ClearOldBrowsingData:enabled"/>
   <int value="-1753458842" label="OfflinePagesLivePageSharing:disabled"/>
   <int value="-1751928267" label="disable-icon-ntp"/>
+  <int value="-1750008152" label="UsernameFirstFlow:enabled"/>
   <int value="-1749176684" label="PauseBackgroundTabs:disabled"/>
   <int value="-1746767834" label="ssl-interstitial-v2-gray"/>
   <int value="-1746255521" label="NewOverviewUi:enabled"/>
@@ -34012,6 +34014,7 @@
   <int value="-1544248549" label="ArcUseAuthEndpoint:enabled"/>
   <int value="-1543316040"
       label="DisplayPersistenceToggleInPermissionPrompts:disabled"/>
+  <int value="-1541187160" label="UsernameFirstFlow:disabled"/>
   <int value="-1538492024" label="OmniboxReverseAnswers:enabled"/>
   <int value="-1537773844"
       label="ContextualSuggestionsAlternateCardLayout:disabled"/>
@@ -36352,6 +36355,7 @@
   <int value="1835523483" label="OmniboxUIExperimentSwapTitleAndUrl:enabled"/>
   <int value="1838990777" label="V8Future:enabled"/>
   <int value="1839740266" label="LocationHardReload:disabled"/>
+  <int value="1841793150" label="TwoPanesStartSurfaceAndroid:enabled"/>
   <int value="1842219851" label="enable-incognito-window-counter"/>
   <int value="1843088575" label="OutOfBlinkCors:enabled"/>
   <int value="1844110073" label="enable-app-view"/>
@@ -58406,6 +58410,7 @@
   <int value="0" label="Password"/>
   <int value="1" label="Pin"/>
   <int value="2" label="Fingerprint"/>
+  <int value="3" label="Challenge-response security token"/>
 </enum>
 
 <enum name="UnPackStatus">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 08bd8cd..9c524ec3 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -3244,6 +3244,9 @@
 
 <histogram name="Android.StrictMode.CheckGoogleSignedTime" units="ms"
     expires_after="M78">
+  <obsolete>
+    Deprecated July 2019 (http://crbug.com/984291).
+  </obsolete>
   <owner>estevenson@chromium.org</owner>
   <owner>wnwen@chromium.org</owner>
   <summary>
@@ -6414,7 +6417,7 @@
 </histogram>
 
 <histogram name="Ash.Login.Lock.UserClicks" enum="LockScreenUserClickTarget"
-    expires_after="M77">
+    expires_after="M82">
   <owner>jdufault@google.com</owner>
   <summary>
     The numbers of times that users click on the shelf buttons, trays and lock
@@ -6822,7 +6825,7 @@
   </summary>
 </histogram>
 
-<histogram name="Ash.SplitView.TimeInSplitView" units="ms" expires_after="M77">
+<histogram name="Ash.SplitView.TimeInSplitView" units="ms" expires_after="M92">
   <owner>xdai@chromium.org</owner>
   <summary>
     The amount of time that the user spent in split view mode. The time is
@@ -7164,7 +7167,7 @@
 </histogram>
 
 <histogram name="Ash.Wallpaper.CustomLayout" enum="WallpaperLayout"
-    expires_after="M77">
+    expires_after="M92">
   <owner>xdai@chromium.org</owner>
   <summary>
     The custom wallpaper layout type. Recorded when the user sets a new custom
@@ -7183,7 +7186,7 @@
   </summary>
 </histogram>
 
-<histogram name="Ash.Wallpaper.Source" enum="WallpaperType" expires_after="M77">
+<histogram name="Ash.Wallpaper.Source" enum="WallpaperType" expires_after="M92">
   <owner>xdai@chromium.org</owner>
   <summary>
     Recorded when a new wallpaper is set, either by the built-in Wallpaper
@@ -7220,7 +7223,7 @@
   </summary>
 </histogram>
 
-<histogram name="Ash.Wallpaper.Type" enum="WallpaperType" expires_after="M77">
+<histogram name="Ash.Wallpaper.Type" enum="WallpaperType" expires_after="M92">
   <owner>kuscher@google.com</owner>
   <summary>The wallpaper type. Recorded at user login.</summary>
 </histogram>
@@ -22564,7 +22567,7 @@
 </histogram>
 
 <histogram name="Cookie.TimeDatabaseMigrationToV11" units="ms"
-    expires_after="M78">
+    expires_after="2020-10-17">
   <owner>chlily@chromium.org</owner>
   <owner>morlovich@chromium.org</owner>
   <summary>
@@ -37267,6 +37270,9 @@
 
 <histogram name="Event.Touch.TargetAndDispatchResult2"
     enum="TouchTargetAndDispatchResultType2" expires_after="M77">
+  <obsolete>
+    Expired 2019-07
+  </obsolete>
   <owner>dtapuska@chromium.org</owner>
   <summary>
     An enumeration identifying 4 properties: 1) a classification of the current
@@ -53022,6 +53028,9 @@
 
 <histogram base="true" name="KioskNextHome.StateTransition.AnimationSmoothness"
     units="%" expires_after="2019-12-31">
+  <obsolete>
+    Removed on 2019-07.
+  </obsolete>
 <!-- Name completed by histogram_suffixes name="EnterOrExitOverview" -->
 
   <owner>agawronska@chromium.org</owner>
@@ -104506,7 +104515,7 @@
   </summary>
 </histogram>
 
-<histogram name="Printing.PrinterCapabilities" units="ms" expires_after="M77">
+<histogram name="Printing.PrinterCapabilities" units="ms" expires_after="M80">
   <owner>vkuzkokov@chromium.org</owner>
   <owner>skau@chromium.org</owner>
   <summary>
@@ -105737,8 +105746,8 @@
 </histogram>
 
 <histogram name="ProfileReset.ResetRequestOrigin"
-    enum="ProfileResetRequestOriginEnum" expires_after="M77">
-  <owner>alito@chromium.org</owner>
+    enum="ProfileResetRequestOriginEnum" expires_after="M90">
+  <owner>proberge@chromium.org</owner>
   <summary>
     Encodes from where the request for resetting the profile settings
     originated.
@@ -115313,8 +115322,12 @@
 </histogram>
 
 <histogram name="SBIRS.DiscardedIncident" enum="IncidentType"
-    expires_after="M77">
-  <owner>caitkp@google.com</owner>
+    expires_after="never">
+<!-- expires-never: This tracks health of the incident reporting feature and
+should be kept until we remove incident reporting. -->
+
+  <owner>vakh@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     The type of incident discarded by the safe browsing incident reporting
     service as a result of profile or service destruction.
@@ -115339,8 +115352,13 @@
   <summary>The result of writing a profile's download metadata file.</summary>
 </histogram>
 
-<histogram name="SBIRS.DroppedIncident" enum="IncidentType" expires_after="M77">
-  <owner>caitkp@google.com</owner>
+<histogram name="SBIRS.DroppedIncident" enum="IncidentType"
+    expires_after="never">
+<!-- expires-never: This tracks health of the incident reporting feature and
+should be kept until we remove incident reporting. -->
+
+  <owner>vakh@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     The type of incident given to the safe browsing incident reporting service
     but dropped as a result of not participating in safe browsing.
@@ -115364,8 +115382,12 @@
   </summary>
 </histogram>
 
-<histogram name="SBIRS.Incident" enum="IncidentType">
-  <owner>caitkp@google.com</owner>
+<histogram name="SBIRS.Incident" enum="IncidentType" expires_after="never">
+<!-- expires-never: This tracks health of the incident reporting feature and
+should be kept until we remove incident reporting. -->
+
+  <owner>vakh@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     The type of incident included in an incident report by the safe browsing
     incident reporting service.
@@ -115373,6 +115395,9 @@
 </histogram>
 
 <histogram name="SBIRS.IncidentCount" expires_after="M77">
+  <obsolete>
+    Deprecated 07/2019.
+  </obsolete>
   <owner>caitkp@google.com</owner>
   <summary>
     The number of incidents collated into a single safe browsing incident
@@ -115389,16 +115414,25 @@
 </histogram>
 
 <histogram name="SBIRS.NoDownloadIncident" enum="IncidentType"
-    expires_after="M77">
-  <owner>proberge@google.com</owner>
+    expires_after="never">
+<!-- expires-never: This tracks health of the incident reporting feature and
+should be kept until we remove incident reporting. -->
+
+  <owner>vakh@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     The type of incident pruned by the safe browsing incident reporting service
     as a result of not having a matching binary download.
   </summary>
 </histogram>
 
-<histogram name="SBIRS.PrunedIncident" enum="IncidentType" expires_after="M77">
-  <owner>proberge@google.com</owner>
+<histogram name="SBIRS.PrunedIncident" enum="IncidentType"
+    expires_after="never">
+<!-- expires-never: This tracks health of the incident reporting feature and
+should be kept until we remove incident reporting. -->
+
+  <owner>vakh@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     The type of incident pruned from a report in the safe browsing incident
     reporting service as a result of having previously been reported.
@@ -115430,26 +115464,40 @@
 </histogram>
 
 <histogram name="SBIRS.ReceivedIncident" enum="IncidentType"
-    expires_after="M77">
-  <owner>caitkp@google.com</owner>
+    expires_after="never">
+<!-- expires-never: This tracks health of the incident reporting feature and
+should be kept until we remove incident reporting. -->
+
+  <owner>vakh@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
     The type of incident received by the safe browsing incident reporting
     service.
   </summary>
 </histogram>
 
-<histogram name="SBIRS.ReportPayloadSize" units="bytes" expires_after="M77">
-  <owner>proberge@google.com</owner>
+<histogram name="SBIRS.ReportPayloadSize" units="bytes" expires_after="never">
+<!-- expires-never: This tracks health of the incident reporting feature and
+should be kept until we remove incident reporting. -->
+
+  <owner>vakh@chromium.org</owner>
+  <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>The size, in bytes, of a safe browsing incident report.</summary>
 </histogram>
 
 <histogram name="SBIRS.ReportUploadTime" units="ms" expires_after="M77">
+  <obsolete>
+    Deprecated 07/2019.
+  </obsolete>
   <owner>caitkp@google.com</owner>
   <summary>The elapsed time to upload a safe browsing incident report.</summary>
 </histogram>
 
 <histogram name="SBIRS.StateStoreInit" enum="StateStoreInitResult"
     expires_after="M77">
+  <obsolete>
+    Deprecated 07/2019.
+  </obsolete>
   <owner>proberge@google.com</owner>
   <summary>
     The result of initializing the state store and comparing the preferences to
@@ -121201,6 +121249,9 @@
 
 <histogram name="ServiceWorkerCache.Cache.AddResponseType"
     enum="FetchResponseType" expires_after="M77">
+  <obsolete>
+    This histogram was removed in M77.
+  </obsolete>
   <owner>nhiroki@chromium.org</owner>
   <summary>
     Records the response type to be added in the Cache by Cache.add()/addAll().
@@ -122264,6 +122315,9 @@
 
 <histogram name="Settings.InitializedFromMasterPrefs" enum="BooleanSuccess"
     expires_after="M77">
+  <obsolete>
+    Removed in July 2019.
+  </obsolete>
   <owner>csharp@chromium.org</owner>
   <owner>gab@chromium.org</owner>
   <summary>
@@ -122309,6 +122363,9 @@
 
 <histogram name="Settings.LegacyMachineIdGenerationSuccess"
     enum="BooleanSuccess" expires_after="M77">
+  <obsolete>
+    Deprecated 07/2019. LegacyMachineIdGeneration failed extremely rarely.
+  </obsolete>
   <owner>proberge@chromium.org</owner>
   <summary>
     Whether generation of the RLZ deterministic machine-specific device id was
@@ -122625,7 +122682,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceChanged" enum="TrackedPreference"
-    expires_after="M77">
+    expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference whose value has been changed since the last
@@ -122635,7 +122692,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceCleared" enum="TrackedPreference"
-    expires_after="M77">
+    expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference whose value has been cleared since the last
@@ -122645,7 +122702,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceInitialized"
-    enum="TrackedPreference" expires_after="M77">
+    enum="TrackedPreference" expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference whose last value isn't known. We may be just
@@ -122669,7 +122726,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceMigratedLegacyDeviceId"
-    enum="TrackedPreference" expires_after="M77">
+    enum="TrackedPreference" expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference whose value has not changed since the last
@@ -122681,7 +122738,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceNullInitialized"
-    enum="TrackedPreference" expires_after="M77">
+    enum="TrackedPreference" expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference which was initialized despite the absence of
@@ -122691,7 +122748,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceReset" enum="TrackedPreference"
-    expires_after="M77">
+    expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>The id of a tracked preference which was reset by Chrome.</summary>
 </histogram>
@@ -122747,7 +122804,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceTrustedInitialized"
-    enum="TrackedPreference" expires_after="M77">
+    enum="TrackedPreference" expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference which was initialized despite the absence of
@@ -122758,7 +122815,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceUnchanged" enum="TrackedPreference"
-    expires_after="M77">
+    expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference whose value has not changed since the last
@@ -122768,7 +122825,7 @@
 </histogram>
 
 <histogram name="Settings.TrackedPreferenceWantedReset"
-    enum="TrackedPreference" expires_after="M77">
+    enum="TrackedPreference" expires_after="M90">
   <owner>proberge@chromium.org</owner>
   <summary>
     The id of a tracked preference which Chrome would have reset had the config
@@ -122828,6 +122885,9 @@
 
 <histogram name="SettingsResetPrompt.DelayBeforePromptParam" units="seconds"
     expires_after="M77">
+  <obsolete>
+    Deprecated 07/2019.
+  </obsolete>
   <owner>alito@chromium.org</owner>
   <summary>
     The feature parameter determining the amount of time to wait after startup
@@ -123972,8 +124032,9 @@
 </histogram>
 
 <histogram name="Signin.InvestigatedScenario" enum="SigninInvestigatedScenario"
-    expires_after="M77">
-  <owner>skym@chromium.org</owner>
+    expires_after="M85">
+  <owner>treib@chromium.org</owner>
+  <owner>mmoskvitin@google.com</owner>
   <summary>
     Records the general type of signin that is occuring in relation to previous
     signin and local data.
@@ -130857,7 +130918,7 @@
 </histogram>
 
 <histogram name="SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Allowed"
-    units="microseconds" expires_after="M77">
+    units="microseconds" expires_after="M87">
   <owner>csharrison@chromium.org</owner>
   <summary>
     Records the total time a subframe navigation was delayed while calculating
@@ -130874,12 +130935,12 @@
 
 <histogram
     name="SubresourceFilter.DocumentLoad.SubframeFilteringDelay.Disallowed"
-    units="microseconds">
+    units="microseconds" expires_after="M87">
   <owner>csharrison@chromium.org</owner>
   <summary>
     Records the total time a subframe navigation was delayed while calculating
     whether it should be disallowed or not. Logged for all navigations that were
-    disallowed.
+    disallowed or would be disallowed.
   </summary>
 </histogram>
 
@@ -160485,7 +160546,11 @@
   <suffix name="popular_baked_in" label="Baked-in, popular suggestions."/>
   <suffix name="popular_fetched"
       label="Non-personalized, popular suggestions (fetched from the server)."/>
-  <suffix name="search_page" label="Google Search page"/>
+  <suffix name="search_page" label="Google Search page">
+    <obsolete>
+      Used for experiment but was never launched, as of 2019-07.
+    </obsolete>
+  </suffix>
   <suffix name="server" label="Suggestions coming from the server."/>
   <suffix name="server0">
     <obsolete>
diff --git a/tools/perf/contrib/leak_detection/page_sets.py b/tools/perf/contrib/leak_detection/page_sets.py
index a50bb7d..5abc8ec 100644
--- a/tools/perf/contrib/leak_detection/page_sets.py
+++ b/tools/perf/contrib/leak_detection/page_sets.py
@@ -8,9 +8,8 @@
 from telemetry.page import shared_page_state
 
 class LeakDetectionSharedState(shared_page_state.SharedDesktopPageState):
-  def ShouldStopBrowserAfterStoryRun(self, story):
-    del story # unused
-    return False  # Keep the same browser instance open across stories.
+  def ShouldReuseBrowserForAllStoryRuns(self):
+    return True
 
 
 class LeakDetectionPage(page_module.Page):
diff --git a/tools/traffic_annotation/summary/OWNERS b/tools/traffic_annotation/summary/OWNERS
index c73b0140..cea39be 100644
--- a/tools/traffic_annotation/summary/OWNERS
+++ b/tools/traffic_annotation/summary/OWNERS
@@ -3,4 +3,3 @@
 msramek@chromium.org
 nicolaso@chromium.org
 rhalavati@chromium.org
-tnagel@chromium.org
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 28b4a02..011c29d4 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -8,7 +8,6 @@
 -->
 
 <annotations>
- <item id="CRD_ice_config_request" hash_code="49825319" type="0" content_hash_code="8740825" os_list="linux,windows" file_path="remoting/protocol/http_ice_config_request.cc"/>
  <item id="CRD_relay_session_request" hash_code="24058523" type="0" content_hash_code="36997811" os_list="linux,windows" file_path="remoting/protocol/port_allocator.cc"/>
  <item id="accounts_image_fetcher" hash_code="98658519" type="0" content_hash_code="45432230" os_list="linux,windows" file_path="components/signin/internal/identity_manager/account_fetcher_service.cc"/>
  <item id="adb_client_socket" hash_code="87775794" type="0" content_hash_code="56654828" os_list="linux,windows" file_path="chrome/browser/devtools/device/adb/adb_client_socket.cc"/>
@@ -294,6 +293,5 @@
  <item id="webstore_installer" hash_code="18764319" type="0" content_hash_code="11030110" os_list="linux,windows" file_path="chrome/browser/extensions/webstore_installer.cc"/>
  <item id="webui_content_scripts_download" hash_code="100545943" type="0" content_hash_code="119898059" os_list="linux,windows" file_path="extensions/browser/guest_view/web_view/web_ui/web_ui_url_fetcher.cc"/>
  <item id="worker_script_load" hash_code="72087791" type="0" content_hash_code="24889169" os_list="linux,windows" file_path="content/browser/worker_host/worker_script_fetcher.cc"/>
- <item id="xmpp_signal_strategy" hash_code="88906454" type="0" content_hash_code="88958321" os_list="linux,windows" file_path="remoting/signaling/xmpp_signal_strategy.cc"/>
  <item id="web_push_message" hash_code="39886742" type="0" content_hash_code="110064650" os_list="linux,windows" file_path="components/gcm_driver/web_push_sender.cc"/>
 </annotations>
diff --git a/ui/android/java/res/values-v17/styles.xml b/ui/android/java/res/values-v17/styles.xml
index d3899ac..815ec29 100644
--- a/ui/android/java/res/values-v17/styles.xml
+++ b/ui/android/java/res/values-v17/styles.xml
@@ -192,6 +192,8 @@
         <item name="android:textSize">@dimen/text_size_medium</item>
         <item name="android:textStyle">bold</item>
     </style>
+
+    <!-- Text styles used on dark background on light theme, and light background on dark theme. -->
     <style name="TextAppearance.Headline.Inverse" parent="TextAppearance.WhiteHeadline" tools:ignore="UnusedResources">
         <item name="android:textColor">@color/default_text_color_inverse</item>
     </style>
diff --git a/ui/android/java/res/values/colors.xml b/ui/android/java/res/values/colors.xml
index 85c6bf746..216956c 100644
--- a/ui/android/java/res/values/colors.xml
+++ b/ui/android/java/res/values/colors.xml
@@ -8,6 +8,7 @@
     <!-- TODO(huayinz): remove tools:ignore once these colors are used in ui/android -->
     <!-- Common text colors -->
     <color name="default_text_color">@color/default_text_color_dark</color>
+    <!-- Text color used on dark background on light theme, and light background on dark theme. -->
     <color name="default_text_color_inverse">@color/default_text_color_light</color>
     <color name="default_text_color_secondary">@color/modern_grey_700</color>
     <color name="default_text_color_tertiary" tools:ignore="UnusedResources">@color/modern_grey_900_alpha_38</color>
diff --git a/ui/events/blink/prediction/linear_predictor.cc b/ui/events/blink/prediction/linear_predictor.cc
index 4c6682d8..9dd6911b 100644
--- a/ui/events/blink/prediction/linear_predictor.cc
+++ b/ui/events/blink/prediction/linear_predictor.cc
@@ -60,8 +60,13 @@
                                events_queue_.at(events_queue_.size() - 2).pos;
 
     // Get the velocity
-    cur_velocity_.set_x(ScaleVector2d(delta_pos, 1.0 / events_dt_).x());
-    cur_velocity_.set_y(ScaleVector2d(delta_pos, 1.0 / events_dt_).y());
+    if (events_dt_ > 0) {
+      cur_velocity_.set_x(ScaleVector2d(delta_pos, 1.0 / events_dt_).x());
+      cur_velocity_.set_y(ScaleVector2d(delta_pos, 1.0 / events_dt_).y());
+    } else {
+      cur_velocity_.set_x(0);
+      cur_velocity_.set_y(0);
+    }
   }
 }
 
@@ -90,7 +95,7 @@
   // Note : a first order prediction is computed when only 2 events are
   // available in the second order predictor
   GeneratePredictionFirstOrder(pred_dt, result);
-  if (equation_order_ == EquationOrder::kSecondOrder &&
+  if (equation_order_ == EquationOrder::kSecondOrder && events_dt_ > 0 &&
       events_queue_.size() == static_cast<size_t>(EquationOrder::kSecondOrder))
     // Add the acceleration term to the current result
     GeneratePredictionSecondOrder(pred_dt, result);
@@ -112,8 +117,7 @@
   gfx::Vector2dF acceleration =
       ScaleVector2d(cur_velocity_ - last_velocity_, 1.0 / events_dt_);
   // Update the prediction
-  result->pos =
-      result->pos + ScaleVector2d(acceleration, 0.5 * pred_dt * pred_dt);
+  result->pos += ScaleVector2d(acceleration, 0.5 * pred_dt * pred_dt);
 }
 
 }  // namespace ui
\ No newline at end of file
diff --git a/ui/native_theme/native_theme_aura.cc b/ui/native_theme/native_theme_aura.cc
index 5cf936b..1769b6d 100644
--- a/ui/native_theme/native_theme_aura.cc
+++ b/ui/native_theme/native_theme_aura.cc
@@ -63,6 +63,15 @@
 const SkColor kInputBorderHoveredColor = SkColorSetRGB(0x9D, 0x9D, 0x9D);
 const SkColor kInputBorderDisabledColor = SkColorSetRGB(0xC5, 0xC5, 0xC5);
 
+const SkScalar kButtonBorderRadius = 2.f;
+const SkScalar kButtonBorderWidth = 1.f;
+const SkColor kButtonBackgroundColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
+const SkColor kButtonBackgroundHoveredColor = SkColorSetRGB(0xF3, 0xF3, 0xF3);
+const SkColor kButtonBackgroundDisabledColor = SkColorSetRGB(0xEF, 0xEF, 0xEF);
+const SkColor kButtonBorderColor = SkColorSetRGB(0xCE, 0xCE, 0xCE);
+const SkColor kButtonBorderHoveredColor = SkColorSetRGB(0x9D, 0x9D, 0x9D);
+const SkColor kButtonBorderDisabledColor = SkColorSetRGB(0xC5, 0xC5, 0xC5);
+
 }  // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -484,6 +493,60 @@
                         SkIntToScalar(kInputBorderRadius), stroke_flags);
 }
 
+void NativeThemeAura::PaintButton(cc::PaintCanvas* canvas,
+                                  State state,
+                                  const gfx::Rect& rect,
+                                  const ButtonExtraParams& button) const {
+  if (!features::IsFormControlsRefreshEnabled()) {
+    return NativeThemeBase::PaintButton(canvas, state, rect, button);
+  }
+
+  cc::PaintFlags flags;
+  SkRect skrect = gfx::RectToSkRect(rect);
+
+  SkColor background_color;
+  if (state == kHovered) {
+    background_color = kButtonBackgroundHoveredColor;
+  } else if (state == kDisabled) {
+    background_color = kButtonBackgroundDisabledColor;
+  } else {
+    background_color = kButtonBackgroundColor;
+  }
+
+  flags.setAntiAlias(true);
+  flags.setStyle(cc::PaintFlags::kFill_Style);
+  flags.setColor(background_color);
+
+  // If the button is too small, fallback to drawing a single, solid color.
+  if (rect.width() < 5 || rect.height() < 5) {
+    canvas->drawRect(skrect, flags);
+    return;
+  }
+
+  // Paint the background (is not visible behind the rounded corners).
+  skrect.inset(kButtonBorderWidth / 2, kButtonBorderWidth / 2);
+  canvas->drawRoundRect(skrect, kButtonBorderRadius, kButtonBorderRadius,
+                        flags);
+
+  // Paint the border: 1px solid.
+  if (button.has_border) {
+    SkColor border_color;
+    if (state == kHovered) {
+      border_color = kButtonBorderHoveredColor;
+    } else if (state == kDisabled) {
+      border_color = kButtonBorderDisabledColor;
+    } else {
+      border_color = kButtonBorderColor;
+    }
+
+    flags.setStyle(cc::PaintFlags::kStroke_Style);
+    flags.setStrokeWidth(kButtonBorderWidth);
+    flags.setColor(border_color);
+    canvas->drawRoundRect(skrect, kButtonBorderRadius, kButtonBorderRadius,
+                          flags);
+  }
+}
+
 gfx::Size NativeThemeAura::GetPartSize(Part part,
                                        State state,
                                        const ExtraParams& extra) const {
diff --git a/ui/native_theme/native_theme_aura.h b/ui/native_theme/native_theme_aura.h
index e16358b..2683cd1c 100644
--- a/ui/native_theme/native_theme_aura.h
+++ b/ui/native_theme/native_theme_aura.h
@@ -64,6 +64,10 @@
                       State state,
                       const gfx::Rect& rect,
                       const TextFieldExtraParams& text) const override;
+  void PaintButton(cc::PaintCanvas* canvas,
+                   State state,
+                   const gfx::Rect& rect,
+                   const ButtonExtraParams& button) const override;
   gfx::Size GetPartSize(Part part,
                         State state,
                         const ExtraParams& extra) const override;
diff --git a/ui/ozone/platform/x11/x11_screen_ozone.cc b/ui/ozone/platform/x11/x11_screen_ozone.cc
index 13cedfb..ae098713 100644
--- a/ui/ozone/platform/x11/x11_screen_ozone.cc
+++ b/ui/ozone/platform/x11/x11_screen_ozone.cc
@@ -106,9 +106,10 @@
 
 display::Display X11ScreenOzone::GetDisplayNearestPoint(
     const gfx::Point& point) const {
-  // TODO(crbug.com/891175): Implement PlatformScreen for X11
-  NOTIMPLEMENTED_LOG_ONCE();
-  return GetPrimaryDisplay();
+  auto displays = GetAllDisplays();
+  if (displays.size() <= 1)
+    return GetPrimaryDisplay();
+  return *display::FindDisplayNearestPoint(displays, point);
 }
 
 display::Display X11ScreenOzone::GetDisplayMatching(
diff --git a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
index 15f191f7..f186b57 100644
--- a/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
+++ b/ui/ozone/platform/x11/x11_screen_ozone_unittest.cc
@@ -152,4 +152,19 @@
             screen()->GetDisplayForAcceleratedWidget(widget));
 }
 
+// This test case exercises GetDisplayNearestPoint function simulating 2
+// side-by-side displays setup.
+TEST_F(X11ScreenOzoneTest, GetDisplayNearestPointTwoDisplays) {
+  auto display_2 =
+      CreateDisplay(gfx::Rect(kPrimaryDisplayBounds.width(), 0, 1280, 720));
+  AddDisplayForTest(*display_2);
+
+  EXPECT_EQ(primary_display(),
+            screen()->GetDisplayNearestPoint(gfx::Point(10, 10)));
+  EXPECT_EQ(primary_display(),
+            screen()->GetDisplayNearestPoint(gfx::Point(790, 100)));
+  EXPECT_EQ(*display_2, screen()->GetDisplayNearestPoint(gfx::Point(1000, 10)));
+  EXPECT_EQ(*display_2,
+            screen()->GetDisplayNearestPoint(gfx::Point(10000, 10000)));
+}
 }  // namespace ui
diff --git a/ui/strings/OWNERS b/ui/strings/OWNERS
index 72e8ffc..18c7688b 100644
--- a/ui/strings/OWNERS
+++ b/ui/strings/OWNERS
@@ -1 +1,2 @@
 *
+# COMPONENT: UI>Internationalization 
diff --git a/ui/views/OWNERS b/ui/views/OWNERS
index 4ac3bc96..3da3cff 100644
--- a/ui/views/OWNERS
+++ b/ui/views/OWNERS
@@ -4,7 +4,6 @@
 msw@chromium.org
 pkasting@chromium.org
 robliao@chromium.org
-sadrul@chromium.org
 sky@chromium.org
 tapted@chromium.org
 weili@chromium.org
diff --git a/ui/views/animation/installable_ink_drop_animator_unittest.cc b/ui/views/animation/installable_ink_drop_animator_unittest.cc
index 19a81b1..9c0ebeb 100644
--- a/ui/views/animation/installable_ink_drop_animator_unittest.cc
+++ b/ui/views/animation/installable_ink_drop_animator_unittest.cc
@@ -19,7 +19,7 @@
  public:
   InstallableInkDropAnimatorTest()
       : scoped_task_environment_(
-            base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
+            base::test::ScopedTaskEnvironment::TimeSource::MOCK_TIME) {}
 
   base::test::ScopedTaskEnvironment* scoped_task_environment() {
     return &scoped_task_environment_;
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index d540002..52c0ed1 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1166,6 +1166,10 @@
     GetInputMethod()->CancelComposition(this);
 }
 
+void Textfield::OnTextChanged() {
+  OnPropertyChanged(&model_, kPropertyEffectsPaint);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Textfield, ContextMenuController overrides:
 
@@ -2030,6 +2034,11 @@
   return text().empty() && !GetPlaceholderText().empty();
 }
 
+views::PropertyChangedSubscription Textfield::AddModelChangedCallback(
+    views::PropertyChangedCallback callback) {
+  return AddPropertyChangedCallback(&model_, std::move(callback));
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Textfield, private:
 
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index d4be4a69..b7638eff 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -292,6 +292,7 @@
 
   // TextfieldModel::Delegate overrides:
   void OnCompositionTextConfirmedOrCleared() override;
+  void OnTextChanged() override;
 
   // ContextMenuController overrides:
   void ShowContextMenuForViewImpl(View* source,
@@ -383,6 +384,9 @@
       bool is_composition_committed) override;
 #endif
 
+  views::PropertyChangedSubscription AddModelChangedCallback(
+      views::PropertyChangedCallback callback);
+
  protected:
   // Inserts or appends a character in response to an IME operation.
   virtual void DoInsertChar(base::char16 ch);
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc
index abc945ad..4f9cfa40 100644
--- a/ui/views/controls/textfield/textfield_model.cc
+++ b/ui/views/controls/textfield/textfield_model.cc
@@ -641,7 +641,7 @@
 
   size_t cursor = GetCursorPosition();
   base::string16 new_text = text();
-  render_text_->SetText(new_text.insert(cursor, composition.text));
+  SetRenderTextText(new_text.insert(cursor, composition.text));
   composition_range_ = gfx::Range(cursor, cursor + composition.text.length());
   // Don't render IME spans with thickness "kNone".
   if (composition.ime_text_spans.size() > 0 &&
@@ -697,7 +697,7 @@
   gfx::Range range = composition_range_;
   ClearComposition();
   base::string16 new_text = text();
-  render_text_->SetText(new_text.erase(range.start(), range.length()));
+  SetRenderTextText(new_text.erase(range.start(), range.length()));
   render_text_->SetCursorPosition(range.start());
   if (delegate_)
     delegate_->OnCompositionTextConfirmedOrCleared();
@@ -843,9 +843,9 @@
   base::string16 old_text = text();
   ClearComposition();
   if (delete_from != delete_to)
-    render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from));
+    SetRenderTextText(old_text.erase(delete_from, delete_to - delete_from));
   if (!new_text.empty())
-    render_text_->SetText(old_text.insert(new_text_insert_at, new_text));
+    SetRenderTextText(old_text.insert(new_text_insert_at, new_text));
   if (selection.start() == selection.end()) {
     render_text_->SetCursorPosition(selection.start());
   } else {
@@ -853,6 +853,12 @@
   }
 }
 
+void TextfieldModel::SetRenderTextText(const base::string16& text) {
+  render_text_->SetText(text);
+  if (delegate_)
+    delegate_->OnTextChanged();
+}
+
 // static
 void TextfieldModel::ClearKillBuffer() {
   SetKillBuffer(base::string16());
diff --git a/ui/views/controls/textfield/textfield_model.h b/ui/views/controls/textfield/textfield_model.h
index c2391a35..19c77773 100644
--- a/ui/views/controls/textfield/textfield_model.h
+++ b/ui/views/controls/textfield/textfield_model.h
@@ -52,6 +52,9 @@
     // Called when the current composition text is confirmed or cleared.
     virtual void OnCompositionTextConfirmedOrCleared() = 0;
 
+    // Called any time that the text property is modified in TextfieldModel
+    virtual void OnTextChanged() {}
+
    protected:
     virtual ~Delegate();
   };
@@ -284,6 +287,9 @@
                   size_t new_text_insert_at,
                   gfx::Range selection);
 
+  // Calls render_text->SetText() and delegate's callback.
+  void SetRenderTextText(const base::string16& text);
+
   void ClearComposition();
 
   // Clears the kill buffer. Used to clear global state between tests.
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index 2358e37..f2d437a 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -3752,4 +3752,28 @@
             gfx::HorizontalAlignment::ALIGN_LEFT);
 }
 
+TEST_F(TextfieldTest, ModelChangedCallbackTest) {
+  InitTextfield();
+
+  bool model_changed = false;
+  auto subscription = textfield_->AddModelChangedCallback(base::BindRepeating(
+      [](bool* model_changed) { *model_changed = true; }, &model_changed));
+
+  textfield_->SetText(ASCIIToUTF16("abc"));
+  EXPECT_TRUE(model_changed);
+
+  model_changed = false;
+  textfield_->AppendText(ASCIIToUTF16("def"));
+  EXPECT_TRUE(model_changed);
+
+  // Undo should still cause callback.
+  model_changed = false;
+  SendKeyEvent(ui::VKEY_Z, false, true);
+  EXPECT_TRUE(model_changed);
+
+  model_changed = false;
+  SendKeyEvent(ui::VKEY_BACK);
+  EXPECT_TRUE(model_changed);
+}
+
 }  // namespace views
diff --git a/ui/views/examples/BUILD.gn b/ui/views/examples/BUILD.gn
index d184ac3f..90e1df27 100644
--- a/ui/views/examples/BUILD.gn
+++ b/ui/views/examples/BUILD.gn
@@ -123,6 +123,7 @@
     "//build/win:default_exe_manifest",
     "//components/viz/host",
     "//components/viz/service",
+    "//mojo/core/embedder",
     "//ui/base",
     "//ui/base/ime/init",
     "//ui/compositor",
diff --git a/ui/views/examples/DEPS b/ui/views/examples/DEPS
index 36a503a..7d637be 100644
--- a/ui/views/examples/DEPS
+++ b/ui/views/examples/DEPS
@@ -3,6 +3,7 @@
   "+components/viz/service",  # In-process viz service.
   "+content/public",
   "+content/shell",
+  "+mojo/core/embedder/embedder.h",  # TestGpuServiceHolder needs Mojo.
   "+sandbox",
   "+ui/gl/gl_switches.h",  # Disable Direct Composition Workaround.
   "+ui/gl/init/gl_factory.h",  # To initialize GL bindings.
diff --git a/ui/views/examples/examples_main.cc b/ui/views/examples/examples_main.cc
index 03abcb6..cb3e145a 100644
--- a/ui/views/examples/examples_main.cc
+++ b/ui/views/examples/examples_main.cc
@@ -20,6 +20,7 @@
 #include "components/viz/host/host_frame_sink_manager.h"
 #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "mojo/core/embedder/embedder.h"
 #include "ui/base/ime/init/input_method_initializer.h"
 #include "ui/base/material_design/material_design_controller.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -68,6 +69,8 @@
 
   base::AtExitManager at_exit;
 
+  mojo::core::Init();
+
 #if defined(USE_X11)
   // This demo uses InProcessContextFactory which uses X on a separate Gpu
   // thread.
diff --git a/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index df987800..69c9e73 100644
--- a/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -166,10 +166,6 @@
     const gfx::Point& point) const {
   if (displays_.size() <= 1)
     return GetPrimaryDisplay();
-  for (const auto& display : displays_) {
-    if (display.bounds().Contains(point))
-      return display;
-  }
   return *FindDisplayNearestPoint(displays_, point);
 }
 
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html b/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html
index 10ffddf..c7f8593 100644
--- a/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html
+++ b/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html
@@ -56,7 +56,7 @@
         <certificate-list id="personalCerts"
             certificates="[[personalCerts]]"
             certificate-type="[[certificateTypeEnum_.PERSONAL]]"
-            import-allowed="[[importAllowed]]">
+            import-allowed="[[clientImportAllowed]]">
         </certificate-list>
       </div>
       <div>
@@ -64,7 +64,7 @@
           <certificate-list id="serverCerts"
               certificates="[[serverCerts]]"
               certificate-type="[[certificateTypeEnum_.SERVER]]"
-              import-allowed="[[importAllowed]]">
+              import-allowed="true">
           </certificate-list>
         </template>
       </div>
@@ -73,7 +73,7 @@
           <certificate-list id="caCerts"
               certificates="[[caCerts]]"
               certificate-type="[[certificateTypeEnum_.CA]]"
-              import-allowed="[[importAllowed]]">
+              import-allowed="true">
           </certificate-list>
         </template>
       </div>
@@ -82,7 +82,7 @@
           <certificate-list id="otherCerts"
               certificates="[[otherCerts]]"
               certificate-type="[[certificateTypeEnum_.OTHER]]"
-              import-allowed="[[importAllowed]]">
+              import-allowed="false">
           </certificate-list>
         </template>
       </div>
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js b/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js
index 72d0ed9..b6ce82c 100644
--- a/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js
+++ b/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js
@@ -54,7 +54,7 @@
      * CertificateManagementAllowed.
      * Value exists only for Chrome OS.
      */
-    importAllowed: {
+    clientImportAllowed: {
       type: Boolean,
       value: true,
     },
@@ -127,14 +127,14 @@
   attached: function() {
     this.addWebUIListener('certificates-changed', this.set.bind(this));
     this.addWebUIListener(
-        'certificates-model-ready', this.setImportAllowed.bind(this));
+        'certificates-model-ready', this.setClientImportAllowed.bind(this));
     certificate_manager.CertificatesBrowserProxyImpl.getInstance()
         .refreshCertificates();
   },
 
   /** @private */
-  setImportAllowed: function(allowed) {
-    this.importAllowed = allowed;
+  setClientImportAllowed: function(allowed) {
+    this.clientImportAllowed = allowed;
   },
 
   /**