diff --git a/AUTHORS b/AUTHORS
index 90495c6..e6c97181 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1109,6 +1109,7 @@
 Zoltan Kuscsik <zoltan.kuscsik@linaro.org>
 Zsolt Borbely <zsborbely.u-szeged@partner.samsung.com>
 方觉 (Fang Jue) <fangjue23303@gmail.com>
+Julian Geppert <spctstr@gmail.com>
 # END individuals section.
 
 # BEGIN organizations section.
diff --git a/DEPS b/DEPS
index 3674b70..e086ccf 100644
--- a/DEPS
+++ b/DEPS
@@ -182,11 +182,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': 'f9ffdd6942f9b3ae2b6b3cfadbff314a96e376e5',
+  'skia_revision': 'cc23d95f5f8553aa0bf6905210bd652d0f0582bb',
   # 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': '926f4bf2884d84aab00450eadaf1ec138827a33d',
+  'v8_revision': '9912e35d594bf00cd78697889beff6b238ebe66d',
   # 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.
@@ -194,7 +194,7 @@
   # 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': '38e96a12f1830451c2330d76779571c7e17dae40',
+  'angle_revision': 'e9a0cb87f7a3486cc31e0a8ae4446fdf7d738281',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -245,7 +245,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': '03e7ff403592957f00e5af8c9ebe93d5939e335c',
+  'catapult_revision': '2ad47493f833c5191f56c74d3f1aac10e7c105e8',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -253,7 +253,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '12e579fd19256116a44e4ede0a5f66f9d781e7f3',
+  'devtools_frontend_revision': 'd3a1df10d3d7994da9f39984ee81660ec4905f5c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -305,11 +305,11 @@
   # 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': 'ee0516e3989ff6a7047083c7f317210245375b79',
+  'dawn_revision': '0a79bee135cd916e5d85495c47f4f77746e1c5f6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'quiche_revision': '1a5d09ce1b898b4a7a694f5ae99a9a9a31bd34f3',
+  'quiche_revision': '6cccce4f58708940e9a02462007ad6ed0fa019ff',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ios_webkit
   # and whatever else without interference from each other.
@@ -528,7 +528,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '86f5ae1f4a19e8f73af4cb30e2c9d3f10f53e875',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'dee8934c69d66b70b05a2cf2ccf02b5c805349f3',
       'condition': 'checkout_ios',
   },
 
@@ -875,7 +875,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'a85d58e50e33dc98e3faa2837a65a02ad288ae8b',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '37e562110fa58a913b13ed2258f18449f90c6ad7',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -931,7 +931,7 @@
     Var('chromium_git') + '/codecs/libgav1.git' + '@' + 'bf190c43e5c7cc81751867c917a81bc2920be079',
 
   'src/third_party/glslang/src':
-    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '8111268575a41753dfb6f9afc40b7c096af769aa',
+    Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '08328fea5ab97a9e354d46446a3547d89d1416da',
 
   'src/third_party/google_toolbox_for_mac/src': {
       'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'),
@@ -1207,7 +1207,7 @@
     Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + 'a5473711f3e20c6bd1c33d81b6c7b9a0618aa18f',
 
   'src/third_party/openscreen/src':
-    Var('chromium_git') + '/openscreen' + '@' + '1e53576f0a3fd0e420288959829d94b3de8785a5',
+    Var('chromium_git') + '/openscreen' + '@' + '778bf126ad386aee747e659aa977b7f055418eaf',
 
   'src/third_party/openxr/src': {
     'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '9e97b73e7dd2bfc07745489d728f6a36665c648f',
@@ -1224,7 +1224,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '080c1b433d370e62a2cdd9912f473391f7d40da9',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'f19675c75eab7f5f0ec5bd048fd6842896f146d0',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1302,7 +1302,7 @@
       'packages': [
           {
               'package': 'fuchsia/third_party/aemu/linux-amd64',
-              'version': 'pcue74MrtwdptQfnABqz12W-F6Br8-PlTN1pD5o_aQsC'
+              'version': 'GMB48BSk7tUABUOq1za-08Safc5r3VfS3614ZsTrWFQC'
           },
       ],
       'condition': 'host_os == "linux" and checkout_fuchsia',
@@ -1436,7 +1436,7 @@
     Var('chromium_git') + '/external/github.com/SeleniumHQ/selenium/py.git' + '@' + 'd0045ec570c1a77612db35d1e92f05e1d27b4d53',
 
   'src/third_party/webgl/src':
-    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '204abd22436837ddbe93816ec2ac52b7440daa6e',
+    Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '1b5de6a99a004ea1de500f7324a89dd4d3818cc5',
 
   'src/third_party/webgpu-cts/src':
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '550dfb76f2b4a363f46c02691c3d4480aae28ed1',
@@ -1452,7 +1452,7 @@
   },
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '10ef84728937fe73e7d8118c9c187601033450f3',
+    Var('webrtc_git') + '/src.git' + '@' + '09eb6e249d4e1f926dfa586bff9cc0de1c4cdefa',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1524,7 +1524,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c8d842d5c5c3b21bb0759e6f29c1c8d95432bc1b',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@91286aa462fad0d8e96a1d890116bda6784b07b9',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index 9a00817..67ca3a7 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1121,6 +1121,12 @@
                   'content/test/data/indexeddb|'\
                   'components/services/storage/indexed_db',
     },
+    'infobars_for_weblayer': {
+      'filepath': 'chrome/android/java/src/org/chromium/chrome/browser/banners/'\
+                  '|chrome/android/java/src/org/chromium/chrome/browser/infobar/'\
+                  '|chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/infobar/'\
+                  '|chrome/browser/ui/android/infobars/',
+    },
     'infra_docs': {
       'filepath': 'docs/infra',
     },
@@ -1812,8 +1818,7 @@
                   '|chromeos/components/tether/'
     },
     'textinput': {
-      'filepath': 'chrome/browser/ui/input_method'\
-                  '|content/browser/renderer_host/render_widget_host_view'\
+      'filepath': 'content/browser/renderer_host/render_widget_host_view'\
                   '|content/browser/renderer_host/text_input'\
                   '|ui/base/ime/'\
                   '|ui/views/controls/textfield/'\
@@ -2505,6 +2510,7 @@
     'incident_reporting': ['grt+watch@chromium.org'],
     'indexed_db': ['jsbell+idb@chromium.org',
                    'dmurph+watching-idb@chromium.org'],
+    'infobars_for_weblayer': ['blundell+infobars-watch@chromium.org'],
     'infra_docs': ['martiniss+watch@chromium.org'],
     'input': ['dtapuska+chromiumwatch@chromium.org'],
     'input_devices': ['spang+watch@chromium.org'],
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index fc1172d..e8784534 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -69,6 +69,19 @@
     min_sdk_version = 21
     compress_shared_libraries = true
   }
+
+  if (is_official_build) {
+    # Used for binary size monitoring.
+    create_app_bundle_minimal_apks("system_webview_minimal_apks") {
+      deps = [ ":system_webview_bundle" ]
+      bundle_path = "$root_build_dir/apks/SystemWebView.aab"
+    }
+
+    android_resource_sizes_test("resource_sizes_system_webview_bundle") {
+      file_path = "$root_build_dir/apks/SystemWebView.minimal.apks"
+      data_deps = [ ":system_webview_minimal_apks" ]
+    }
+  }
 }
 
 if (android_64bit_target_cpu) {
@@ -152,6 +165,19 @@
     min_sdk_version = 29
     static_library_provider = "//chrome/android:trichrome_library_apk"
   }
+
+  if (is_official_build) {
+    # Used for binary size monitoring.
+    create_app_bundle_minimal_apks("trichrome_webview_minimal_apks") {
+      deps = [ ":trichrome_webview_bundle" ]
+      bundle_path = "$root_build_dir/apks/TrichromeWebView.aab"
+    }
+
+    android_resource_sizes_test("resource_sizes_trichrome_webview_bundle") {
+      file_path = "$root_build_dir/apks/TrichromeWebView.minimal.apks"
+      data_deps = [ ":trichrome_webview_minimal_apks" ]
+    }
+  }
 }
 
 # Trichrome WebView APK for a 64-bit Chrome.
diff --git a/android_webview/browser/BUILD.gn b/android_webview/browser/BUILD.gn
index 52f78f7..d2da0a2 100644
--- a/android_webview/browser/BUILD.gn
+++ b/android_webview/browser/BUILD.gn
@@ -112,12 +112,19 @@
     "icon_helper.h",
     "input_stream.cc",
     "input_stream.h",
+    "js_java_interaction/aw_web_message_host_factory.cc",
+    "js_java_interaction/aw_web_message_host_factory.h",
     "js_java_interaction/js_java_configurator_host.cc",
     "js_java_interaction/js_java_configurator_host.h",
     "js_java_interaction/js_reply_proxy.cc",
     "js_java_interaction/js_reply_proxy.h",
     "js_java_interaction/js_to_java_messaging.cc",
     "js_java_interaction/js_to_java_messaging.h",
+    "js_java_interaction/web_message.cc",
+    "js_java_interaction/web_message.h",
+    "js_java_interaction/web_message_host.h",
+    "js_java_interaction/web_message_host_factory.h",
+    "js_java_interaction/web_message_reply_proxy.h",
     "network_service/android_stream_reader_url_loader.cc",
     "network_service/android_stream_reader_url_loader.h",
     "network_service/aw_network_change_notifier.cc",
diff --git a/android_webview/browser/aw_browser_policy_connector.cc b/android_webview/browser/aw_browser_policy_connector.cc
index 0e2feed..eadba8a 100644
--- a/android_webview/browser/aw_browser_policy_connector.cc
+++ b/android_webview/browser/aw_browser_policy_connector.cc
@@ -13,6 +13,8 @@
 #include "components/policy/core/browser/url_blacklist_policy_handler.h"
 #include "components/policy/core/common/policy_pref_names.h"
 #include "components/policy/policy_constants.h"
+#include "components/version_info/android/channel_getter.h"
+#include "components/version_info/channel.h"
 #include "net/url_request/url_request_context_getter.h"
 
 namespace android_webview {
@@ -32,10 +34,13 @@
 // to the associated preferences.
 std::unique_ptr<policy::ConfigurationPolicyHandlerList> BuildHandlerList(
     const policy::Schema& chrome_schema) {
+  version_info::Channel channel = version_info::android::GetChannel();
   std::unique_ptr<policy::ConfigurationPolicyHandlerList> handlers(
       new policy::ConfigurationPolicyHandlerList(
           base::BindRepeating(&PopulatePolicyHandlerParameters),
-          base::BindRepeating(&GetChromePolicyDetails)));
+          base::BindRepeating(&GetChromePolicyDetails),
+          channel != version_info::Channel::STABLE &&
+              channel != version_info::Channel::BETA));
 
   // URL Filtering
   handlers->AddHandler(std::make_unique<policy::SimplePolicyHandler>(
diff --git a/android_webview/browser/aw_browser_process.cc b/android_webview/browser/aw_browser_process.cc
index b1c4f895..0629678 100644
--- a/android_webview/browser/aw_browser_process.cc
+++ b/android_webview/browser/aw_browser_process.cc
@@ -5,6 +5,7 @@
 #include "android_webview/browser/aw_browser_process.h"
 
 #include "android_webview/browser/aw_browser_context.h"
+#include "android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h"
 #include "android_webview/browser/metrics/visibility_metrics_logger.h"
 #include "base/base_paths_posix.h"
 #include "base/path_service.h"
@@ -41,6 +42,9 @@
     AwFeatureListCreator* aw_feature_list_creator) {
   g_aw_browser_process = this;
   aw_feature_list_creator_ = aw_feature_list_creator;
+  aw_contents_lifecycle_notifier_ =
+      std::make_unique<AwContentsLifecycleNotifier>(base::BindRepeating(
+          &AwBrowserProcess::OnLoseForeground, base::Unretained(this)));
 }
 
 AwBrowserProcess::~AwBrowserProcess() {
@@ -71,6 +75,11 @@
   DCHECK(local_state_);
 }
 
+void AwBrowserProcess::OnLoseForeground() {
+  if (local_state_)
+    local_state_->CommitPendingWrite();
+}
+
 AwBrowserPolicyConnector* AwBrowserProcess::browser_policy_connector() {
   if (!browser_policy_connector_)
     CreateBrowserPolicyConnector();
diff --git a/android_webview/browser/aw_browser_process.h b/android_webview/browser/aw_browser_process.h
index 0fbe92e..b9a8c1b 100644
--- a/android_webview/browser/aw_browser_process.h
+++ b/android_webview/browser/aw_browser_process.h
@@ -9,6 +9,7 @@
 
 #include "android_webview/browser/aw_browser_context.h"
 #include "android_webview/browser/aw_feature_list_creator.h"
+#include "android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h"
 #include "android_webview/browser/safe_browsing/aw_safe_browsing_ui_manager.h"
 #include "android_webview/browser/safe_browsing/aw_safe_browsing_whitelist_manager.h"
 #include "base/feature_list.h"
@@ -30,6 +31,7 @@
 
 }  // namespace prefs
 
+class AwContentsLifecycleNotifier;
 class VisibilityMetricsLogger;
 
 class AwBrowserProcess {
@@ -75,6 +77,8 @@
 
   void OnAuthPrefsChanged();
 
+  void OnLoseForeground();
+
   // If non-null, this object holds a pref store that will be taken by
   // AwBrowserProcess to create the |local_state_|.
   // The AwFeatureListCreator is owned by AwMainDelegate.
@@ -103,6 +107,7 @@
       safe_browsing_whitelist_manager_;
 
   std::unique_ptr<VisibilityMetricsLogger> visibility_metrics_logger_;
+  std::unique_ptr<AwContentsLifecycleNotifier> aw_contents_lifecycle_notifier_;
 
   DISALLOW_COPY_AND_ASSIGN(AwBrowserProcess);
 };
diff --git a/android_webview/browser/aw_contents.cc b/android_webview/browser/aw_contents.cc
index 64254d3..3f59ee9 100644
--- a/android_webview/browser/aw_contents.cc
+++ b/android_webview/browser/aw_contents.cc
@@ -27,6 +27,7 @@
 #include "android_webview/browser/gfx/java_browser_view_renderer_helper.h"
 #include "android_webview/browser/gfx/render_thread_manager.h"
 #include "android_webview/browser/gfx/scoped_app_gl_state_restore.h"
+#include "android_webview/browser/js_java_interaction/aw_web_message_host_factory.h"
 #include "android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h"
 #include "android_webview/browser/page_load_metrics/page_load_metrics_initialize.h"
 #include "android_webview/browser/permission/aw_permission_request.h"
@@ -1326,15 +1327,26 @@
     const base::android::JavaParamRef<jobject>& obj,
     const base::android::JavaParamRef<jstring>& script,
     const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules) {
-  return GetJsJavaConfiguratorHost()->AddDocumentStartJavascript(
-      env, script, allowed_origin_rules);
+  std::vector<std::string> native_allowed_origin_rule_strings;
+  AppendJavaStringArrayToStringVector(env, allowed_origin_rules,
+                                      &native_allowed_origin_rule_strings);
+  auto result = GetJsJavaConfiguratorHost()->AddDocumentStartJavascript(
+      base::android::ConvertJavaStringToUTF16(env, script),
+      native_allowed_origin_rule_strings);
+  if (result.error_message) {
+    env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
+                  result.error_message->data());
+    return -1;
+  }
+  DCHECK(result.script_id);
+  return result.script_id.value();
 }
 
 void AwContents::RemoveDocumentStartJavascript(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj,
     jint script_id) {
-  GetJsJavaConfiguratorHost()->RemoveDocumentStartJavascript(env, script_id);
+  GetJsJavaConfiguratorHost()->RemoveDocumentStartJavascript(script_id);
 }
 
 base::android::ScopedJavaLocalRef<jstring> AwContents::AddWebMessageListener(
@@ -1343,15 +1355,26 @@
     const base::android::JavaParamRef<jobject>& listener,
     const base::android::JavaParamRef<jstring>& js_object_name,
     const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules) {
-  return GetJsJavaConfiguratorHost()->AddWebMessageListener(
-      env, listener, js_object_name, allowed_origin_rules);
+  base::string16 native_js_object_name =
+      base::android::ConvertJavaStringToUTF16(env, js_object_name);
+  std::vector<std::string> native_allowed_origin_rule_strings;
+  AppendJavaStringArrayToStringVector(env, allowed_origin_rules,
+                                      &native_allowed_origin_rule_strings);
+  const base::string16 error_message =
+      GetJsJavaConfiguratorHost()->AddWebMessageHostFactory(
+          std::make_unique<AwWebMessageHostFactory>(listener),
+          native_js_object_name, native_allowed_origin_rule_strings);
+  if (error_message.empty())
+    return nullptr;
+  return base::android::ConvertUTF16ToJavaString(env, error_message);
 }
 
 void AwContents::RemoveWebMessageListener(
     JNIEnv* env,
     const base::android::JavaParamRef<jobject>& obj,
     const base::android::JavaParamRef<jstring>& js_object_name) {
-  GetJsJavaConfiguratorHost()->RemoveWebMessageListener(env, js_object_name);
+  GetJsJavaConfiguratorHost()->RemoveWebMessageHostFactory(
+      ConvertJavaStringToUTF16(env, js_object_name));
 }
 
 base::android::ScopedJavaLocalRef<jobjectArray> AwContents::GetJsObjectsInfo(
@@ -1359,7 +1382,8 @@
     const base::android::JavaParamRef<jobject>& obj,
     const base::android::JavaParamRef<jclass>& clazz) {
   if (js_java_configurator_host_.get()) {
-    return GetJsJavaConfiguratorHost()->GetJsObjectsInfo(env, clazz);
+    return AwWebMessageHostFactory::GetWebMessageListenerInfo(
+        GetJsJavaConfiguratorHost(), env, clazz);
   }
   return nullptr;
 }
diff --git a/android_webview/browser/aw_pac_processor.cc b/android_webview/browser/aw_pac_processor.cc
index d37e2cd..7b8a93f 100644
--- a/android_webview/browser/aw_pac_processor.cc
+++ b/android_webview/browser/aw_pac_processor.cc
@@ -195,18 +195,53 @@
   return thread_holder.task_runner_;
 }
 
+proxy_resolver::ProxyResolverV8TracingFactory* GetProxyResolverFactory() {
+  static std::unique_ptr<proxy_resolver::ProxyResolverV8TracingFactory>
+      factory = proxy_resolver::ProxyResolverV8TracingFactory::Create();
+
+  return factory.get();
+}
+
 }  // namespace
 
+// Public methods of AwPacProcessor may be called on multiple threads.
+// ProxyResolverV8TracingFactory/ProxyResolverV8Tracing
+// expects its public interface to always be called on the same thread with
+// Chromium task runner so it can post it back to that thread
+// with the result of the queries.
+//
+// Job and its subclasses wrap queries from public methods of AwPacProcessor,
+// post them on a special thread and blocks on WaitableEvent
+// until the query is finished. |OnSignal| is passed to
+// ProxyResolverV8TracingFactory/ProxyResolverV8Tracing methods.
+// This callback is called once the request is processed and,
+// it signals WaitableEvent and returns result to the calling thread.
+//
+// ProxyResolverV8TracingFactory/ProxyResolverV8Tracing behaviour is the
+// following: if the corresponding request is destroyed,
+// the query is cancelled and the callback is never called.
+// That means that we need to signal WaitableEvent to unblock calling thread
+// when we cancel Job. We keep track of unfinished Jobs in |jobs_|. This field
+// is always accessed on the same thread.
+//
+// All Jobs must be cancelled prior to destruction of |proxy_resolver_| since
+// its destructor asserts there are no pending requests.
 class Job {
  public:
   virtual ~Job() = default;
 
   bool ExecSync() {
-    GetTaskRunner()->PostTask(FROM_HERE, std::move(task_));
+    GetTaskRunner()->PostTask(
+        FROM_HERE, base::BindOnce(&Job::Exec, base::Unretained(this)));
     event_.Wait();
     return net_error_ == net::OK;
   }
 
+  void Exec() {
+    processor_->jobs_.insert(this);
+    std::move(task_).Run();
+  }
+
   virtual void Cancel() = 0;
 
   void OnSignal(int net_error) {
@@ -218,24 +253,29 @@
     // Reset them here on the correct thread when the job is already finished
     // so no cancellation occurs.
     Cancel();
-    event_.Signal();
   }
 
   base::OnceClosure task_;
-  int net_error_;
+  int net_error_ = net::ERR_ABORTED;
   base::WaitableEvent event_;
+  AwPacProcessor* processor_;
 };
 
 class SetProxyScriptJob : public Job {
  public:
   SetProxyScriptJob(AwPacProcessor* processor, std::string script) {
+    processor_ = processor;
     task_ = base::BindOnce(
-        &AwPacProcessor::SetProxyScriptNative, base::Unretained(processor),
+        &AwPacProcessor::SetProxyScriptNative, base::Unretained(processor_),
         &request_, std::move(script),
         base::BindOnce(&SetProxyScriptJob::OnSignal, base::Unretained(this)));
   }
 
-  void Cancel() override { request_.reset(); }
+  void Cancel() override {
+    processor_->jobs_.erase(this);
+    request_.reset();
+    event_.Signal();
+  }
 
  private:
   std::unique_ptr<net::ProxyResolverFactory::Request> request_;
@@ -244,12 +284,19 @@
 class MakeProxyRequestJob : public Job {
  public:
   MakeProxyRequestJob(AwPacProcessor* processor, std::string url) {
+    processor_ = processor;
     task_ = base::BindOnce(
-        &AwPacProcessor::MakeProxyRequestNative, base::Unretained(processor),
+        &AwPacProcessor::MakeProxyRequestNative, base::Unretained(processor_),
         &request_, std::move(url), &proxy_info_,
         base::BindOnce(&MakeProxyRequestJob::OnSignal, base::Unretained(this)));
   }
-  void Cancel() override { request_.reset(); }
+
+  void Cancel() override {
+    processor_->jobs_.erase(this);
+    request_.reset();
+    event_.Signal();
+  }
+
   net::ProxyInfo proxy_info() { return proxy_info_; }
 
  private:
@@ -258,19 +305,41 @@
 };
 
 AwPacProcessor::AwPacProcessor() {
-  proxy_resolver_factory_ =
-      proxy_resolver::ProxyResolverV8TracingFactory::Create();
   host_resolver_ = std::make_unique<HostResolver>();
 }
 
-AwPacProcessor::~AwPacProcessor() = default;
+AwPacProcessor::~AwPacProcessor() {
+  base::WaitableEvent event;
+  // |proxy_resolver_| must be destroyed on the same thread it is created.
+  GetTaskRunner()->PostTask(
+      FROM_HERE,
+      base::BindOnce(&AwPacProcessor::Destroy, base::Unretained(this),
+                     base::Unretained(&event)));
+  event.Wait();
+}
+
+void AwPacProcessor::Destroy(base::WaitableEvent* event) {
+  // Cancel all unfinished jobs to unblock calling thread.
+  for (auto* job : jobs_) {
+    job->Cancel();
+  }
+
+  proxy_resolver_.reset();
+  event->Signal();
+}
+
+void AwPacProcessor::DestroyNative(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  delete this;
+}
 
 void AwPacProcessor::SetProxyScriptNative(
     std::unique_ptr<net::ProxyResolverFactory::Request>* request,
     const std::string& script,
     net::CompletionOnceCallback complete) {
   DCHECK(GetTaskRunner()->BelongsToCurrentThread());
-  proxy_resolver_factory_->CreateProxyResolverV8Tracing(
+  GetProxyResolverFactory()->CreateProxyResolverV8Tracing(
       net::PacFileData::FromUTF8(script), std::make_unique<Bindings>(this),
       &proxy_resolver_, std::move(complete), request);
 }
@@ -294,6 +363,7 @@
 bool AwPacProcessor::SetProxyScript(std::string script) {
   SetProxyScriptJob job(this, script);
   bool success = job.ExecSync();
+
   DCHECK(proxy_resolver_);
   return success;
 }
diff --git a/android_webview/browser/aw_pac_processor.h b/android_webview/browser/aw_pac_processor.h
index 64f16ca0..8c2c10b 100644
--- a/android_webview/browser/aw_pac_processor.h
+++ b/android_webview/browser/aw_pac_processor.h
@@ -15,12 +15,18 @@
 
 namespace android_webview {
 
+class Job;
+
 class AwPacProcessor {
  public:
   AwPacProcessor();
   AwPacProcessor(const AwPacProcessor&) = delete;
   AwPacProcessor& operator=(const AwPacProcessor&) = delete;
 
+  ~AwPacProcessor();
+  void DestroyNative(JNIEnv* env,
+                     const base::android::JavaParamRef<jobject>& obj);
+
   jboolean SetProxyScript(JNIEnv* env,
                           const base::android::JavaParamRef<jobject>& obj,
                           const base::android::JavaParamRef<jstring>& jscript);
@@ -34,7 +40,7 @@
     return host_resolver_.get();
   }
  private:
-  ~AwPacProcessor();
+  void Destroy(base::WaitableEvent* event);
   void SetProxyScriptNative(
       std::unique_ptr<net::ProxyResolverFactory::Request>* request,
       const std::string& script,
@@ -44,14 +50,14 @@
       const std::string& url,
       net::ProxyInfo* proxy_info,
       net::CompletionOnceCallback complete);
-  std::unique_ptr<proxy_resolver::ProxyResolverV8TracingFactory>
-      proxy_resolver_factory_;
   std::unique_ptr<proxy_resolver::ProxyResolverV8Tracing> proxy_resolver_;
   std::unique_ptr<proxy_resolver::ProxyHostResolver> host_resolver_;
 
   friend class Job;
   friend class SetProxyScriptJob;
   friend class MakeProxyRequestJob;
+
+  std::set<Job*> jobs_;
 };
 }  // namespace android_webview
 
diff --git a/android_webview/browser/aw_pac_processor_unittest.cc b/android_webview/browser/aw_pac_processor_unittest.cc
index 1a6aa83..97d61f0 100644
--- a/android_webview/browser/aw_pac_processor_unittest.cc
+++ b/android_webview/browser/aw_pac_processor_unittest.cc
@@ -27,6 +27,9 @@
 }  // namespace
 
 class AwPacProcessorTest : public testing::Test {
+ public:
+  void TearDown() override { delete pac_processor_; }
+
  protected:
   base::test::TaskEnvironment task_environment_{
            base::test::TaskEnvironment::TimeSource::MOCK_TIME};
@@ -55,6 +58,7 @@
 
   EXPECT_EQ("PROXY 127.0.0.1:80",
             other_pac_processor_->MakeProxyRequest(kRequestUrl));
+  delete other_pac_processor_;
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/cookie_manager.cc b/android_webview/browser/cookie_manager.cc
index 3ea18fbd..0b1cfb8 100644
--- a/android_webview/browser/cookie_manager.cc
+++ b/android_webview/browser/cookie_manager.cc
@@ -550,9 +550,9 @@
 void CookieManager::GetCookieListCompleted(
     base::OnceClosure complete,
     net::CookieList* result,
-    const net::CookieStatusList& value,
-    const net::CookieStatusList& excluded_cookies) {
-  *result = net::cookie_util::StripStatuses(value);
+    const net::CookieAccessResultList& value,
+    const net::CookieAccessResultList& excluded_cookies) {
+  *result = net::cookie_util::StripAccessResults(value);
   std::move(complete).Run();
 }
 
diff --git a/android_webview/browser/cookie_manager.h b/android_webview/browser/cookie_manager.h
index a6ac7db..0e87e20 100644
--- a/android_webview/browser/cookie_manager.h
+++ b/android_webview/browser/cookie_manager.h
@@ -198,10 +198,11 @@
   void GetCookieListAsyncHelper(const GURL& host,
                                 net::CookieList* result,
                                 base::OnceClosure complete);
-  void GetCookieListCompleted(base::OnceClosure complete,
-                              net::CookieList* result,
-                              const net::CookieStatusList& value,
-                              const net::CookieStatusList& excluded_cookies);
+  void GetCookieListCompleted(
+      base::OnceClosure complete,
+      net::CookieList* result,
+      const net::CookieAccessResultList& value,
+      const net::CookieAccessResultList& excluded_cookies);
 
   void RemoveSessionCookiesHelper(base::OnceCallback<void(bool)> callback);
   void RemoveAllCookiesHelper(base::OnceCallback<void(bool)> callback);
diff --git a/android_webview/browser/js_java_interaction/aw_web_message_host_factory.cc b/android_webview/browser/js_java_interaction/aw_web_message_host_factory.cc
new file mode 100644
index 0000000..6fe1aae
--- /dev/null
+++ b/android_webview/browser/js_java_interaction/aw_web_message_host_factory.cc
@@ -0,0 +1,97 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/js_java_interaction/aw_web_message_host_factory.h"
+
+#include "android_webview/browser/js_java_interaction/js_java_configurator_host.h"
+#include "android_webview/browser/js_java_interaction/js_reply_proxy.h"
+#include "android_webview/browser/js_java_interaction/web_message.h"
+#include "android_webview/browser/js_java_interaction/web_message_host.h"
+#include "android_webview/browser_jni_headers/WebMessageListenerHolder_jni.h"
+#include "android_webview/browser_jni_headers/WebMessageListenerInfo_jni.h"
+#include "android_webview/common/aw_origin_matcher.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "content/public/browser/android/app_web_message_port.h"
+
+namespace android_webview {
+namespace {
+
+// Calls through to WebMessageListenerInfo.
+class AwWebMessageHost : public WebMessageHost {
+ public:
+  AwWebMessageHost(WebMessageReplyProxy* reply_proxy,
+                   const base::android::ScopedJavaGlobalRef<jobject>& listener,
+                   const std::string& origin_string,
+                   bool is_main_frame)
+      : reply_proxy_(reply_proxy),
+        listener_(listener),
+        origin_string_(origin_string),
+        is_main_frame_(is_main_frame) {}
+
+  ~AwWebMessageHost() override = default;
+
+  // WebMessageHost:
+  void OnPostMessage(std::unique_ptr<WebMessage> message) override {
+    JNIEnv* env = base::android::AttachCurrentThread();
+    base::android::ScopedJavaGlobalRef<jobjectArray> jports =
+        content::AppWebMessagePort::WrapJavaArray(env,
+                                                  std::move(message->ports));
+    Java_WebMessageListenerHolder_onPostMessage(
+        env, listener_,
+        base::android::ConvertUTF16ToJavaString(env, message->message),
+        base::android::ConvertUTF8ToJavaString(env, origin_string_),
+        is_main_frame_, jports, reply_proxy_.GetJavaPeer());
+  }
+
+ private:
+  JsReplyProxy reply_proxy_;
+  base::android::ScopedJavaGlobalRef<jobject> listener_;
+  const std::string origin_string_;
+  const bool is_main_frame_;
+};
+
+}  // namespace
+
+AwWebMessageHostFactory::AwWebMessageHostFactory(
+    const base::android::JavaParamRef<jobject>& listener)
+    : listener_(listener) {}
+
+AwWebMessageHostFactory::~AwWebMessageHostFactory() = default;
+
+// static
+base::android::ScopedJavaLocalRef<jobjectArray>
+AwWebMessageHostFactory::GetWebMessageListenerInfo(
+    JsJavaConfiguratorHost* host,
+    JNIEnv* env,
+    const base::android::JavaParamRef<jclass>& clazz) {
+  auto factories = host->GetWebMessageHostFactories();
+  jobjectArray joa =
+      env->NewObjectArray(factories.size(), clazz.obj(), nullptr);
+  base::android::CheckException(env);
+
+  for (size_t i = 0; i < factories.size(); ++i) {
+    const auto& factory = factories[i];
+    const std::vector<std::string> rules =
+        factory.allowed_origin_rules.Serialize();
+    base::android::ScopedJavaLocalRef<jobject> object =
+        Java_WebMessageListenerInfo_create(
+            env, base::android::ConvertUTF16ToJavaString(env, factory.js_name),
+            base::android::ToJavaArrayOfStrings(env, rules),
+            static_cast<AwWebMessageHostFactory*>(factory.factory)->listener_);
+    env->SetObjectArrayElement(joa, i, object.obj());
+  }
+  return base::android::ScopedJavaLocalRef<jobjectArray>(env, joa);
+}
+
+std::unique_ptr<WebMessageHost> AwWebMessageHostFactory::CreateHost(
+    const std::string& origin_string,
+    bool is_main_frame,
+    WebMessageReplyProxy* proxy) {
+  return std::make_unique<AwWebMessageHost>(proxy, listener_, origin_string,
+                                            is_main_frame);
+}
+
+}  // namespace android_webview
diff --git a/android_webview/browser/js_java_interaction/aw_web_message_host_factory.h b/android_webview/browser/js_java_interaction/aw_web_message_host_factory.h
new file mode 100644
index 0000000..491abd71
--- /dev/null
+++ b/android_webview/browser/js_java_interaction/aw_web_message_host_factory.h
@@ -0,0 +1,47 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_AW_WEB_MESSAGE_HOST_FACTORY_H_
+#define ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_AW_WEB_MESSAGE_HOST_FACTORY_H_
+
+#include "android_webview/browser/js_java_interaction/web_message_host_factory.h"
+#include "base/android/scoped_java_ref.h"
+
+namespace android_webview {
+
+class JsJavaConfiguratorHost;
+
+// Adapts WebMessageHostFactory for use by WebView. An AwWebMessageHostFactory
+// is created per WebMessageListener. More specifically, every call to
+// AwContents::AddWebMessageListener() creates a new AwWebMessageHostFactory.
+class AwWebMessageHostFactory : public WebMessageHostFactory {
+ public:
+  explicit AwWebMessageHostFactory(
+      const base::android::JavaParamRef<jobject>& listener);
+  AwWebMessageHostFactory(const AwWebMessageHostFactory&) = delete;
+  AwWebMessageHostFactory& operator=(const AwWebMessageHostFactory&) = delete;
+  ~AwWebMessageHostFactory() override;
+
+  // Returns an array of WebMessageListenerInfos based on the registered
+  // factories.
+  static base::android::ScopedJavaLocalRef<jobjectArray>
+  GetWebMessageListenerInfo(JsJavaConfiguratorHost* host,
+                            JNIEnv* env,
+                            const base::android::JavaParamRef<jclass>& clazz);
+
+  // WebMessageConnection:
+  std::unique_ptr<WebMessageHost> CreateHost(
+      const std::string& origin_string,
+      bool is_main_frame,
+      WebMessageReplyProxy* proxy) override;
+
+ private:
+  // The WebMessageListenerHost that was supplied to
+  // AwContents::AddWebMessageListener().
+  base::android::ScopedJavaGlobalRef<jobject> listener_;
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_AW_WEB_MESSAGE_HOST_FACTORY_H_
diff --git a/android_webview/browser/js_java_interaction/js_java_configurator_host.cc b/android_webview/browser/js_java_interaction/js_java_configurator_host.cc
index fcc694ca..97d8fe7 100644
--- a/android_webview/browser/js_java_interaction/js_java_configurator_host.cc
+++ b/android_webview/browser/js_java_interaction/js_java_configurator_host.cc
@@ -5,12 +5,10 @@
 #include "android_webview/browser/js_java_interaction/js_java_configurator_host.h"
 
 #include "android_webview/browser/js_java_interaction/js_to_java_messaging.h"
-#include "android_webview/browser_jni_headers/WebMessageListenerInfo_jni.h"
+#include "android_webview/browser/js_java_interaction/web_message_host.h"
+#include "android_webview/browser/js_java_interaction/web_message_host_factory.h"
 #include "android_webview/common/aw_origin_matcher.h"
 #include "android_webview/common/aw_origin_matcher_mojom_traits.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/public/browser/web_contents.h"
@@ -18,34 +16,34 @@
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 
 namespace android_webview {
+namespace {
+
+std::string ConvertToNativeAllowedOriginRulesWithSanityCheck(
+    const std::vector<std::string>& allowed_origin_rules_strings,
+    AwOriginMatcher& allowed_origin_rules) {
+  for (auto& rule : allowed_origin_rules_strings) {
+    if (!allowed_origin_rules.AddRuleFromString(rule))
+      return "allowedOriginRules " + rule + " is invalid";
+  }
+  return std::string();
+}
+
+}  // namespace
 
 struct JsObject {
-  JsObject(base::string16 name,
+  JsObject(const base::string16& name,
            AwOriginMatcher allowed_origin_rules,
-           const base::android::JavaRef<jobject>& listener)
-      : name_(std::move(name)),
-        allowed_origin_rules_(std::move(allowed_origin_rules)),
-        listener_ref_(listener) {}
-
-  JsObject(JsObject&& other)
-      : name_(std::move(other.name_)),
-        allowed_origin_rules_(std::move(other.allowed_origin_rules_)),
-        listener_ref_(std::move(other.listener_ref_)) {}
-
-  JsObject& operator=(JsObject&& other) {
-    name_ = std::move(other.name_);
-    allowed_origin_rules_ = std::move(other.allowed_origin_rules_);
-    listener_ref_ = std::move(other.listener_ref_);
-    return *this;
-  }
-
+           std::unique_ptr<WebMessageHostFactory> factory)
+      : name(std::move(name)),
+        allowed_origin_rules(std::move(allowed_origin_rules)),
+        factory(std::move(factory)) {}
+  JsObject(JsObject&& other) = delete;
+  JsObject& operator=(JsObject&& other) = delete;
   ~JsObject() = default;
 
-  base::string16 name_;
-  AwOriginMatcher allowed_origin_rules_;
-  base::android::ScopedJavaGlobalRef<jobject> listener_ref_;
-
-  DISALLOW_COPY_AND_ASSIGN(JsObject);
+  base::string16 name;
+  AwOriginMatcher allowed_origin_rules;
+  std::unique_ptr<WebMessageHostFactory> factory;
 };
 
 struct DocumentStartJavascript {
@@ -66,91 +64,86 @@
   int32_t script_id_;
 };
 
+JsJavaConfiguratorHost::AddScriptResult::AddScriptResult() = default;
+JsJavaConfiguratorHost::AddScriptResult::AddScriptResult(
+    const JsJavaConfiguratorHost::AddScriptResult&) = default;
+JsJavaConfiguratorHost::AddScriptResult&
+JsJavaConfiguratorHost::AddScriptResult::operator=(
+    const JsJavaConfiguratorHost::AddScriptResult&) = default;
+JsJavaConfiguratorHost::AddScriptResult::~AddScriptResult() = default;
+
 JsJavaConfiguratorHost::JsJavaConfiguratorHost(
     content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents) {}
 
 JsJavaConfiguratorHost::~JsJavaConfiguratorHost() = default;
 
-jint JsJavaConfiguratorHost::AddDocumentStartJavascript(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jstring>& script,
-    const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules) {
-  base::string16 native_script =
-      base::android::ConvertJavaStringToUTF16(env, script);
+JsJavaConfiguratorHost::AddScriptResult
+JsJavaConfiguratorHost::AddDocumentStartJavascript(
+    const base::string16& script,
+    const std::vector<std::string>& allowed_origin_rules) {
   AwOriginMatcher origin_matcher;
   std::string error_message = ConvertToNativeAllowedOriginRulesWithSanityCheck(
-      env, allowed_origin_rules, origin_matcher);
+      allowed_origin_rules, origin_matcher);
+  AddScriptResult result;
   if (!error_message.empty()) {
-    env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
-                  error_message.data());
-    // Invalid script id.
-    return -1;
+    result.error_message = std::move(error_message);
+    return result;
   }
 
-  scripts_.emplace_back(native_script, origin_matcher, next_script_id_++);
+  scripts_.emplace_back(script, origin_matcher, next_script_id_++);
 
   web_contents()->ForEachFrame(base::BindRepeating(
       &JsJavaConfiguratorHost::NotifyFrameForAddDocumentStartJavascript,
       base::Unretained(this), &*scripts_.rbegin()));
-  return scripts_.rbegin()->script_id_;
+  result.script_id = scripts_.rbegin()->script_id_;
+  return result;
 }
 
-jboolean JsJavaConfiguratorHost::RemoveDocumentStartJavascript(
-    JNIEnv* env,
-    jint j_script_id) {
+bool JsJavaConfiguratorHost::RemoveDocumentStartJavascript(int script_id) {
   for (auto it = scripts_.begin(); it != scripts_.end(); ++it) {
-    if (it->script_id_ == j_script_id) {
+    if (it->script_id_ == script_id) {
       scripts_.erase(it);
       web_contents()->ForEachFrame(base::BindRepeating(
           &JsJavaConfiguratorHost::NotifyFrameForRemoveDocumentStartJavascript,
-          base::Unretained(this), j_script_id));
+          base::Unretained(this), script_id));
       return true;
     }
   }
   return false;
 }
 
-base::android::ScopedJavaLocalRef<jstring>
-JsJavaConfiguratorHost::AddWebMessageListener(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& listener,
-    const base::android::JavaParamRef<jstring>& js_object_name,
-    const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules) {
-  base::string16 native_js_object_name =
-      base::android::ConvertJavaStringToUTF16(env, js_object_name);
-
+base::string16 JsJavaConfiguratorHost::AddWebMessageHostFactory(
+    std::unique_ptr<WebMessageHostFactory> factory,
+    const base::string16& js_object_name,
+    const std::vector<std::string>& allowed_origin_rules) {
   AwOriginMatcher origin_matcher;
   std::string error_message = ConvertToNativeAllowedOriginRulesWithSanityCheck(
-      env, allowed_origin_rules, origin_matcher);
+      allowed_origin_rules, origin_matcher);
   if (!error_message.empty())
-    return base::android::ConvertUTF8ToJavaString(env, error_message);
+    return base::UTF8ToUTF16(error_message);
 
   for (const auto& js_object : js_objects_) {
-    if (js_object.name_ == native_js_object_name) {
-      return base::android::ConvertUTF16ToJavaString(
-          env, base::ASCIIToUTF16("jsObjectName ") + js_object.name_ +
-                   base::ASCIIToUTF16(" is already added."));
+    if (js_object->name == js_object_name) {
+      return base::ASCIIToUTF16("jsObjectName ") + js_object->name +
+             base::ASCIIToUTF16(" was already added.");
     }
   }
 
-  js_objects_.emplace_back(native_js_object_name, origin_matcher, listener);
+  js_objects_.push_back(std::make_unique<JsObject>(
+      js_object_name, origin_matcher, std::move(factory)));
 
   web_contents()->ForEachFrame(base::BindRepeating(
       &JsJavaConfiguratorHost::NotifyFrameForWebMessageListener,
       base::Unretained(this)));
-  return nullptr;
+  return base::string16();
 }
 
-void JsJavaConfiguratorHost::RemoveWebMessageListener(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jstring>& js_object_name) {
-  base::string16 native_js_object_name =
-      ConvertJavaStringToUTF16(env, js_object_name);
-
+void JsJavaConfiguratorHost::RemoveWebMessageHostFactory(
+    const base::string16& js_object_name) {
   for (auto iterator = js_objects_.begin(); iterator != js_objects_.end();
        ++iterator) {
-    if (iterator->name_ == native_js_object_name) {
+    if ((*iterator)->name == js_object_name) {
       js_objects_.erase(iterator);
       web_contents()->ForEachFrame(base::BindRepeating(
           &JsJavaConfiguratorHost::NotifyFrameForWebMessageListener,
@@ -160,28 +153,16 @@
   }
 }
 
-base::android::ScopedJavaLocalRef<jobjectArray>
-JsJavaConfiguratorHost::GetJsObjectsInfo(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jclass>& clazz) {
-  jobjectArray joa =
-      env->NewObjectArray(js_objects_.size(), clazz.obj(), nullptr);
-  base::android::CheckException(env);
-
-  for (size_t i = 0; i < js_objects_.size(); ++i) {
-    const JsObject& js_object = js_objects_[i];
-    std::vector<std::string> rules;
-    for (const auto& rule : js_object.allowed_origin_rules_.rules())
-      rules.push_back(rule->ToString());
-
-    base::android::ScopedJavaLocalRef<jobject> object =
-        Java_WebMessageListenerInfo_create(
-            env, base::android::ConvertUTF16ToJavaString(env, js_object.name_),
-            base::android::ToJavaArrayOfStrings(env, rules),
-            js_object.listener_ref_);
-    env->SetObjectArrayElement(joa, i, object.obj());
+std::vector<JsJavaConfiguratorHost::RegisteredFactory>
+JsJavaConfiguratorHost::GetWebMessageHostFactories() {
+  const size_t num_objects = js_objects_.size();
+  std::vector<RegisteredFactory> factories(num_objects);
+  for (size_t i = 0; i < num_objects; ++i) {
+    factories[i].js_name = js_objects_[i]->name;
+    factories[i].allowed_origin_rules = js_objects_[i]->allowed_origin_rules;
+    factories[i].factory = js_objects_[i]->factory.get();
   }
-  return base::android::ScopedJavaLocalRef<jobjectArray>(env, joa);
+  return factories;
 }
 
 void JsJavaConfiguratorHost::RenderFrameCreated(
@@ -215,10 +196,10 @@
         std::make_unique<JsToJavaMessaging>(
             render_frame_host,
             pending_remote.InitWithNewEndpointAndPassReceiver(),
-            js_object.listener_ref_, js_object.allowed_origin_rules_));
-    js_objects.push_back(mojom::JsObject::New(js_object.name_,
+            js_object->factory.get(), js_object->allowed_origin_rules));
+    js_objects.push_back(mojom::JsObject::New(js_object->name,
                                               std::move(pending_remote),
-                                              js_object.allowed_origin_rules_));
+                                              js_object->allowed_origin_rules));
   }
   configurator_remote->SetJsObjects(std::move(js_objects));
 }
@@ -244,20 +225,4 @@
   configurator_remote->RemoveDocumentStartScript(script_id);
 }
 
-std::string
-JsJavaConfiguratorHost::ConvertToNativeAllowedOriginRulesWithSanityCheck(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules,
-    AwOriginMatcher& native_allowed_origin_rules) {
-  std::vector<std::string> native_allowed_origin_rule_strings;
-  AppendJavaStringArrayToStringVector(env, allowed_origin_rules,
-                                      &native_allowed_origin_rule_strings);
-  for (auto& rule : native_allowed_origin_rule_strings) {
-    if (!native_allowed_origin_rules.AddRuleFromString(rule)) {
-      return "allowedOriginRules " + rule + " is invalid";
-    }
-  }
-  return std::string();
-}
-
 }  // namespace android_webview
diff --git a/android_webview/browser/js_java_interaction/js_java_configurator_host.h b/android_webview/browser/js_java_interaction/js_java_configurator_host.h
index 615180a..1f90fdf1 100644
--- a/android_webview/browser/js_java_interaction/js_java_configurator_host.h
+++ b/android_webview/browser/js_java_interaction/js_java_configurator_host.h
@@ -5,8 +5,11 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_JS_JAVA_CONFIGURATOR_HOST_H_
 #define ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_JS_JAVA_CONFIGURATOR_HOST_H_
 
+#include <memory>
+#include <vector>
+
 #include "android_webview/common/js_java_interaction/interfaces.mojom.h"
-#include "base/android/scoped_java_ref.h"
+#include "base/optional.h"
 #include "base/strings/string16.h"
 #include "content/public/browser/web_contents_observer.h"
 
@@ -19,8 +22,8 @@
 class AwOriginMatcher;
 struct DocumentStartJavascript;
 struct JsObject;
-
 class JsToJavaMessaging;
+class WebMessageHostFactory;
 
 // This class is 1:1 with WebContents, when AddWebMessageListener() is called,
 // it stores the information in this class and send them to renderer side
@@ -32,30 +35,48 @@
   explicit JsJavaConfiguratorHost(content::WebContents* web_contents);
   ~JsJavaConfiguratorHost() override;
 
+  // Captures the result of adding script. There are two possibilities when
+  // adding script: there was an error, in which case |error_message| is set,
+  // otherwise the add was successful and |script_id| is set.
+  struct AddScriptResult {
+    AddScriptResult();
+    AddScriptResult(const AddScriptResult&);
+    AddScriptResult& operator=(const AddScriptResult&);
+    ~AddScriptResult();
+
+    base::Optional<std::string> error_message;
+    base::Optional<int> script_id;
+  };
+
   // Native side AddDocumentStartJavascript, returns an error message if the
   // parameters didn't pass necessary checks.
-  jint AddDocumentStartJavascript(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jstring>& script,
-      const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules);
+  AddScriptResult AddDocumentStartJavascript(
+      const base::string16& script,
+      const std::vector<std::string>& allowed_origin_rules);
 
-  jboolean RemoveDocumentStartJavascript(JNIEnv* env, jint script_id);
+  bool RemoveDocumentStartJavascript(int script_id);
 
-  // Native side AddWebMessageListener, returns an error message if the
-  // parameters didn't pass necessary checks.
-  base::android::ScopedJavaLocalRef<jstring> AddWebMessageListener(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobject>& listener,
-      const base::android::JavaParamRef<jstring>& js_object_name,
-      const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules);
+  // Adds a new WebMessageHostFactory. For any urls that match
+  // |allowed_origin_rules|, |js_object_name| is registered as a JS object that
+  // can be used by script on the page to send and receive messages. Returns
+  // an empty string on success. On failure, the return string gives the error
+  // message.
+  base::string16 AddWebMessageHostFactory(
+      std::unique_ptr<WebMessageHostFactory> factory,
+      const base::string16& js_object_name,
+      const std::vector<std::string>& allowed_origin_rules);
 
-  void RemoveWebMessageListener(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jstring>& js_object_name);
+  // Returns the factory previously registered under the specified name.
+  void RemoveWebMessageHostFactory(const base::string16& js_object_name);
 
-  base::android::ScopedJavaLocalRef<jobjectArray> GetJsObjectsInfo(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jclass>& clazz);
+  struct RegisteredFactory {
+    base::string16 js_name;
+    AwOriginMatcher allowed_origin_rules;
+    WebMessageHostFactory* factory = nullptr;
+  };
+
+  // Returns the registered factories.
+  std::vector<RegisteredFactory> GetWebMessageHostFactories();
 
   // content::WebContentsObserver implementations
   void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
@@ -73,14 +94,10 @@
   void NotifyFrameForRemoveDocumentStartJavascript(
       int32_t script_id,
       content::RenderFrameHost* render_frame_host);
-  std::string ConvertToNativeAllowedOriginRulesWithSanityCheck(
-      JNIEnv* env,
-      const base::android::JavaParamRef<jobjectArray>& allowed_origin_rules,
-      AwOriginMatcher& native_allowed_origin_rules);
 
   int32_t next_script_id_ = 0;
   std::vector<DocumentStartJavascript> scripts_;
-  std::vector<JsObject> js_objects_;
+  std::vector<std::unique_ptr<JsObject>> js_objects_;
   std::map<content::RenderFrameHost*,
            std::vector<std::unique_ptr<JsToJavaMessaging>>>
       js_to_java_messagings_;
diff --git a/android_webview/browser/js_java_interaction/js_reply_proxy.cc b/android_webview/browser/js_java_interaction/js_reply_proxy.cc
index 70d67d07..381b0b8c 100644
--- a/android_webview/browser/js_java_interaction/js_reply_proxy.cc
+++ b/android_webview/browser/js_java_interaction/js_reply_proxy.cc
@@ -4,15 +4,15 @@
 
 #include "android_webview/browser/js_java_interaction/js_reply_proxy.h"
 
+#include "android_webview/browser/js_java_interaction/web_message.h"
+#include "android_webview/browser/js_java_interaction/web_message_reply_proxy.h"
 #include "android_webview/browser_jni_headers/JsReplyProxy_jni.h"
 #include "base/android/jni_string.h"
 
 namespace android_webview {
 
-JsReplyProxy::JsReplyProxy(
-    mojo::PendingAssociatedRemote<mojom::JavaToJsMessaging>
-        java_to_js_messaging)
-    : java_to_js_messaging_(std::move(java_to_js_messaging)) {
+JsReplyProxy::JsReplyProxy(WebMessageReplyProxy* reply_proxy)
+    : reply_proxy_(reply_proxy) {
   JNIEnv* env = base::android::AttachCurrentThread();
   java_ref_.Reset(
       Java_JsReplyProxy_create(env, reinterpret_cast<intptr_t>(this)));
@@ -33,9 +33,9 @@
 void JsReplyProxy::PostMessage(
     JNIEnv* env,
     const base::android::JavaParamRef<jstring>& message) {
-  DCHECK(java_to_js_messaging_);
-  java_to_js_messaging_->OnPostMessage(
-      base::android::ConvertJavaStringToUTF16(env, message));
+  std::unique_ptr<WebMessage> web_message = std::make_unique<WebMessage>();
+  web_message->message = base::android::ConvertJavaStringToUTF16(env, message);
+  reply_proxy_->PostMessage(std::move(web_message));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/js_java_interaction/js_reply_proxy.h b/android_webview/browser/js_java_interaction/js_reply_proxy.h
index c5df0b6c..1ea4a2a2 100644
--- a/android_webview/browser/js_java_interaction/js_reply_proxy.h
+++ b/android_webview/browser/js_java_interaction/js_reply_proxy.h
@@ -5,19 +5,16 @@
 #ifndef ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_JS_REPLY_PROXY_H_
 #define ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_JS_REPLY_PROXY_H_
 
-#include "android_webview/common/js_java_interaction/interfaces.mojom.h"
 #include "base/android/jni_weak_ref.h"
 #include "base/android/scoped_java_ref.h"
-#include "mojo/public/cpp/bindings/associated_remote.h"
-#include "mojo/public/cpp/bindings/pending_associated_remote.h"
 
 namespace android_webview {
 
+class WebMessageReplyProxy;
+
 class JsReplyProxy {
  public:
-  explicit JsReplyProxy(mojo::PendingAssociatedRemote<mojom::JavaToJsMessaging>
-                            java_to_js_messaging);
-
+  explicit JsReplyProxy(WebMessageReplyProxy* reply_proxy);
   ~JsReplyProxy();
 
   base::android::ScopedJavaLocalRef<jobject> GetJavaPeer();
@@ -26,8 +23,8 @@
                    const base::android::JavaParamRef<jstring>& message);
 
  private:
+  WebMessageReplyProxy* reply_proxy_;
   base::android::ScopedJavaGlobalRef<jobject> java_ref_;
-  mojo::AssociatedRemote<mojom::JavaToJsMessaging> java_to_js_messaging_;
 
   DISALLOW_COPY_AND_ASSIGN(JsReplyProxy);
 };
diff --git a/android_webview/browser/js_java_interaction/js_to_java_messaging.cc b/android_webview/browser/js_java_interaction/js_to_java_messaging.cc
index 549fa3aa..e3d7a49 100644
--- a/android_webview/browser/js_java_interaction/js_to_java_messaging.cc
+++ b/android_webview/browser/js_java_interaction/js_to_java_messaging.cc
@@ -4,32 +4,68 @@
 
 #include "android_webview/browser/js_java_interaction/js_to_java_messaging.h"
 
-#include "android_webview/browser_jni_headers/WebMessageListenerHolder_jni.h"
-#include "base/android/jni_android.h"
-#include "base/android/jni_array.h"
-#include "base/android/jni_string.h"
+#include "android_webview/browser/js_java_interaction/web_message.h"
+#include "android_webview/browser/js_java_interaction/web_message_host.h"
+#include "android_webview/browser/js_java_interaction/web_message_host_factory.h"
+#include "android_webview/browser/js_java_interaction/web_message_reply_proxy.h"
 #include "base/stl_util.h"
-#include "content/public/browser/android/app_web_message_port.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/web_contents.h"
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
+#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
 #include "url/origin.h"
 #include "url/url_util.h"
 
 namespace android_webview {
+namespace {
+
+// We want to pass a string "null" for local file schemes, to make it
+// consistent to the Blink side SecurityOrigin serialization. When both
+// setAllow{File,Universal}AccessFromFileURLs are false, Blink::SecurityOrigin
+// will be serialized as string "null" for local file schemes, but when
+// setAllowFileAccessFromFileURLs is true, Blink::SecurityOrigin will be
+// serialized as the scheme, which will be inconsistentt to this place. In
+// this case we want to let developer to know that local files are not safe,
+// so we still pass "null".
+std::string GetOriginString(const url::Origin& source_origin) {
+  return base::Contains(url::GetLocalSchemes(), source_origin.scheme())
+             ? "null"
+             : source_origin.Serialize();
+}
+
+}  // namespace
+
+class JsToJavaMessaging::ReplyProxyImpl : public WebMessageReplyProxy {
+ public:
+  explicit ReplyProxyImpl(
+      mojo::PendingAssociatedRemote<mojom::JavaToJsMessaging>
+          java_to_js_messaging)
+      : java_to_js_messaging_(std::move(java_to_js_messaging)) {}
+  ReplyProxyImpl(const ReplyProxyImpl&) = delete;
+  ReplyProxyImpl& operator=(const ReplyProxyImpl&) = delete;
+  ~ReplyProxyImpl() override = default;
+
+  // WebMessageReplyProxy:
+  void PostMessage(std::unique_ptr<WebMessage> message) override {
+    java_to_js_messaging_->OnPostMessage(message->message);
+  }
+
+ private:
+  mojo::AssociatedRemote<mojom::JavaToJsMessaging> java_to_js_messaging_;
+};
 
 JsToJavaMessaging::JsToJavaMessaging(
     content::RenderFrameHost* render_frame_host,
     mojo::PendingAssociatedReceiver<mojom::JsToJavaMessaging> receiver,
-    base::android::ScopedJavaGlobalRef<jobject> listener_ref,
+    WebMessageHostFactory* factory,
     const AwOriginMatcher& origin_matcher)
     : render_frame_host_(render_frame_host),
-      listener_ref_(listener_ref),
+      connection_factory_(factory),
       origin_matcher_(origin_matcher) {
   receiver_.Bind(std::move(receiver));
 }
 
-JsToJavaMessaging::~JsToJavaMessaging() {}
+JsToJavaMessaging::~JsToJavaMessaging() = default;
 
 void JsToJavaMessaging::PostMessage(
     const base::string16& message,
@@ -45,34 +81,39 @@
   // |source_origin| has no race with this PostMessage call, because of
   // associated mojo channel, the committed origin message and PostMessage are
   // in sequence.
-  url::Origin source_origin = render_frame_host_->GetLastCommittedOrigin();
+  const url::Origin source_origin =
+      render_frame_host_->GetLastCommittedOrigin();
 
   if (!origin_matcher_.Matches(source_origin))
     return;
 
-  // We want to pass a string "null" for local file schemes, to make it
-  // consistent to the Blink side SecurityOrigin serialization. When both
-  // setAllow{File,Universal}AccessFromFileURLs are false, Blink::SecurityOrigin
-  // will be serialized as string "null" for local file schemes, but when
-  // setAllowFileAccessFromFileURLs is true, Blink::SecurityOrigin will be
-  // serialized as the scheme, which will be inconsistentt to this place. In
-  // this case we want to let developer to know that local files are not safe,
-  // so we still pass "null".
-  std::string origin_string =
-      base::Contains(url::GetLocalSchemes(), source_origin.scheme())
-          ? "null"
-          : source_origin.Serialize();
-  JNIEnv* env = base::android::AttachCurrentThread();
+  // SetJavaToJsMessaging must be called before this.
+  DCHECK(reply_proxy_);
 
-  // Convert to an array of AppWebMessagePorts.
-  base::android::ScopedJavaGlobalRef<jobjectArray> jports =
-      content::AppWebMessagePort::WrapJavaArray(env, std::move(ports));
+  if (!host_) {
+    const std::string origin_string = GetOriginString(source_origin);
+    const bool is_main_frame =
+        web_contents->GetMainFrame() == render_frame_host_;
 
-  Java_WebMessageListenerHolder_onPostMessage(
-      env, listener_ref_, base::android::ConvertUTF16ToJavaString(env, message),
-      base::android::ConvertUTF8ToJavaString(env, origin_string),
-      web_contents->GetMainFrame() == render_frame_host_, jports,
-      reply_proxy_->GetJavaPeer());
+    host_ = connection_factory_->CreateHost(origin_string, is_main_frame,
+                                            reply_proxy_.get());
+#if DCHECK_IS_ON()
+    origin_string_ = origin_string;
+    is_main_frame_ = is_main_frame;
+#endif
+    if (!host_)
+      return;
+  }
+  // The origin and whether this is the main frame should not change once
+  // PostMessage() has been received.
+#if DCHECK_IS_ON()
+  DCHECK_EQ(GetOriginString(source_origin), origin_string_);
+  DCHECK_EQ(is_main_frame_, web_contents->GetMainFrame() == render_frame_host_);
+#endif
+  std::unique_ptr<WebMessage> web_message = std::make_unique<WebMessage>();
+  web_message->message = message;
+  web_message->ports = std::move(ports);
+  host_->OnPostMessage(std::move(web_message));
 }
 
 void JsToJavaMessaging::SetJavaToJsMessaging(
@@ -80,8 +121,9 @@
         java_to_js_messaging) {
   // A RenderFrame may inject JsToJavaMessaging in the JavaScript context more
   // than once because of reusing of RenderFrame.
+  host_.reset();
   reply_proxy_ =
-      std::make_unique<JsReplyProxy>(std::move(java_to_js_messaging));
+      std::make_unique<ReplyProxyImpl>(std::move(java_to_js_messaging));
 }
 
 }  // namespace android_webview
diff --git a/android_webview/browser/js_java_interaction/js_to_java_messaging.h b/android_webview/browser/js_java_interaction/js_to_java_messaging.h
index cdbf0e8..6691e788 100644
--- a/android_webview/browser/js_java_interaction/js_to_java_messaging.h
+++ b/android_webview/browser/js_java_interaction/js_to_java_messaging.h
@@ -7,10 +7,9 @@
 
 #include <vector>
 
-#include "android_webview/browser/js_java_interaction/js_reply_proxy.h"
 #include "android_webview/common/aw_origin_matcher.h"
 #include "android_webview/common/js_java_interaction/interfaces.mojom.h"
-#include "base/android/scoped_java_ref.h"
+#include "base/check.h"
 #include "base/strings/string16.h"
 #include "mojo/public/cpp/bindings/associated_receiver_set.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -24,6 +23,9 @@
 
 namespace android_webview {
 
+class WebMessageHost;
+class WebMessageHostFactory;
+
 // Implementation of mojo::JsToJavaMessaging interface. Receives PostMessage()
 // call from renderer JsBinding.
 class JsToJavaMessaging : public mojom::JsToJavaMessaging {
@@ -31,7 +33,7 @@
   JsToJavaMessaging(
       content::RenderFrameHost* rfh,
       mojo::PendingAssociatedReceiver<mojom::JsToJavaMessaging> receiver,
-      base::android::ScopedJavaGlobalRef<jobject> listener_ref,
+      WebMessageHostFactory* factory,
       const AwOriginMatcher& origin_matcher);
   ~JsToJavaMessaging() override;
 
@@ -43,11 +45,18 @@
           java_to_js_messaging) override;
 
  private:
+  class ReplyProxyImpl;
+
   content::RenderFrameHost* render_frame_host_;
-  std::unique_ptr<JsReplyProxy> reply_proxy_;
-  base::android::ScopedJavaGlobalRef<jobject> listener_ref_;
+  std::unique_ptr<ReplyProxyImpl> reply_proxy_;
+  WebMessageHostFactory* connection_factory_;
   AwOriginMatcher origin_matcher_;
   mojo::AssociatedReceiver<mojom::JsToJavaMessaging> receiver_{this};
+  std::unique_ptr<WebMessageHost> host_;
+#if DCHECK_IS_ON()
+  std::string origin_string_;
+  bool is_main_frame_;
+#endif
 
   DISALLOW_COPY_AND_ASSIGN(JsToJavaMessaging);
 };
diff --git a/android_webview/browser/js_java_interaction/web_message.cc b/android_webview/browser/js_java_interaction/web_message.cc
new file mode 100644
index 0000000..896063fc
--- /dev/null
+++ b/android_webview/browser/js_java_interaction/web_message.cc
@@ -0,0 +1,13 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/browser/js_java_interaction/web_message.h"
+
+namespace android_webview {
+
+WebMessage::WebMessage() = default;
+
+WebMessage::~WebMessage() = default;
+
+}  // namespace android_webview
diff --git a/android_webview/browser/js_java_interaction/web_message.h b/android_webview/browser/js_java_interaction/web_message.h
new file mode 100644
index 0000000..0ad02d6
--- /dev/null
+++ b/android_webview/browser/js_java_interaction/web_message.h
@@ -0,0 +1,26 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_H_
+#define ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_H_
+
+#include <vector>
+
+#include "base/strings/string16.h"
+#include "third_party/blink/public/common/messaging/message_port_descriptor.h"
+
+namespace android_webview {
+
+// Represents a message to or from the page.
+struct WebMessage {
+  WebMessage();
+  ~WebMessage();
+
+  base::string16 message;
+  std::vector<blink::MessagePortDescriptor> ports;
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_H_
diff --git a/android_webview/browser/js_java_interaction/web_message_host.h b/android_webview/browser/js_java_interaction/web_message_host.h
new file mode 100644
index 0000000..f5758f9
--- /dev/null
+++ b/android_webview/browser/js_java_interaction/web_message_host.h
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_HOST_H_
+#define ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_HOST_H_
+
+#include <memory>
+
+namespace android_webview {
+
+struct WebMessage;
+
+// Represents the browser side of a WebMessage channel.
+class WebMessageHost {
+ public:
+  virtual ~WebMessageHost() {}
+
+  virtual void OnPostMessage(std::unique_ptr<WebMessage> message) = 0;
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_HOST_H_
diff --git a/android_webview/browser/js_java_interaction/web_message_host_factory.h b/android_webview/browser/js_java_interaction/web_message_host_factory.h
new file mode 100644
index 0000000..e0b8945
--- /dev/null
+++ b/android_webview/browser/js_java_interaction/web_message_host_factory.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_HOST_FACTORY_H_
+#define ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_HOST_FACTORY_H_
+
+#include <memory>
+#include <string>
+
+namespace android_webview {
+
+class WebMessageHost;
+class WebMessageReplyProxy;
+
+// Creates a WebMessageHost in response to a page interacting with the object
+// registered by way of JsJavaConfiguratorHost::AddWebMessageHostFactory(). A
+// WebMessageHost is created for every page that matches the parameters of
+// AddWebMessageHostFactory().
+class WebMessageHostFactory {
+ public:
+  virtual ~WebMessageHostFactory() {}
+
+  // Creates a WebMessageHost for the specified page. |proxy| is valid for
+  // the life of the host and may be used to send messages back to the page.
+  virtual std::unique_ptr<WebMessageHost> CreateHost(
+      const std::string& origin_string,
+      bool is_main_frame,
+      WebMessageReplyProxy* proxy) = 0;
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_HOST_FACTORY_H_
diff --git a/android_webview/browser/js_java_interaction/web_message_reply_proxy.h b/android_webview/browser/js_java_interaction/web_message_reply_proxy.h
new file mode 100644
index 0000000..f3b45a8
--- /dev/null
+++ b/android_webview/browser/js_java_interaction/web_message_reply_proxy.h
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_REPLY_PROXY_H_
+#define ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_REPLY_PROXY_H_
+
+#include "base/strings/string16.h"
+
+namespace android_webview {
+
+struct WebMessage;
+
+// Used to send messages to the page.
+class WebMessageReplyProxy {
+ public:
+  virtual void PostMessage(std::unique_ptr<WebMessage> message) = 0;
+
+ protected:
+  virtual ~WebMessageReplyProxy() {}
+};
+
+}  // namespace android_webview
+
+#endif  // ANDROID_WEBVIEW_BROWSER_JS_JAVA_INTERACTION_WEB_MESSAGE_REPLY_PROXY_H_
diff --git a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.cc b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.cc
index 72ff998..2418853 100644
--- a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.cc
+++ b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.cc
@@ -16,12 +16,12 @@
 
 namespace {
 
-AwContentsLifecycleNotifier::AwContentsState CalcuateState(
-    bool is_atached_to_window,
+AwContentsLifecycleNotifier::AwContentsState CalculateState(
+    bool is_attached_to_window,
     bool is_window_visible) {
   // Can't assume the sequence of Attached, Detached, Visible, Invisible event
   // because the app could changed it; Calculate the state here.
-  if (is_atached_to_window) {
+  if (is_attached_to_window) {
     return is_window_visible
                ? AwContentsLifecycleNotifier::AwContentsState::kForeground
                : AwContentsLifecycleNotifier::AwContentsState::kBackground;
@@ -29,6 +29,8 @@
   return AwContentsLifecycleNotifier::AwContentsState::kDetached;
 }
 
+AwContentsLifecycleNotifier* g_instance = nullptr;
+
 }  // namespace
 
 AwContentsLifecycleNotifier::AwContentsData::AwContentsData() = default;
@@ -40,8 +42,23 @@
 
 // static
 AwContentsLifecycleNotifier& AwContentsLifecycleNotifier::GetInstance() {
-  static base::NoDestructor<AwContentsLifecycleNotifier> instance;
-  return *instance;
+  DCHECK(g_instance);
+  g_instance->EnsureOnValidSequence();
+  return *g_instance;
+}
+
+AwContentsLifecycleNotifier::AwContentsLifecycleNotifier(
+    OnLoseForegroundCallback on_lose_foreground_callback)
+    : on_lose_foreground_callback_(std::move(on_lose_foreground_callback)) {
+  EnsureOnValidSequence();
+  DCHECK(!g_instance);
+  g_instance = this;
+}
+
+AwContentsLifecycleNotifier::~AwContentsLifecycleNotifier() {
+  EnsureOnValidSequence();
+  DCHECK(g_instance);
+  g_instance = nullptr;
 }
 
 void AwContentsLifecycleNotifier::OnWebViewCreated(
@@ -133,10 +150,6 @@
   return result;
 }
 
-AwContentsLifecycleNotifier::AwContentsLifecycleNotifier() = default;
-
-AwContentsLifecycleNotifier::~AwContentsLifecycleNotifier() = default;
-
 size_t AwContentsLifecycleNotifier::ToIndex(AwContentsState state) const {
   size_t index = static_cast<size_t>(state);
   DCHECK(index < base::size(state_count_));
@@ -146,7 +159,7 @@
 void AwContentsLifecycleNotifier::OnAwContentsStateChanged(
     AwContentsLifecycleNotifier::AwContentsData* data) {
   AwContentsLifecycleNotifier::AwContentsState state =
-      CalcuateState(data->attached_to_window, data->window_visible);
+      CalculateState(data->attached_to_window, data->window_visible);
   if (data->aw_content_state == state)
     return;
   state_count_[ToIndex(data->aw_content_state)]--;
@@ -167,10 +180,16 @@
   else
     state = WebViewAppStateObserver::State::kDestroyed;
   if (state != app_state_) {
+    bool previous_in_foreground =
+        app_state_ == WebViewAppStateObserver::State::kForeground;
+
     app_state_ = state;
     for (auto& observer : observers_) {
       observer.OnAppStateChanged(app_state_);
     }
+    if (previous_in_foreground && on_lose_foreground_callback_) {
+      on_lose_foreground_callback_.Run();
+    }
   }
 }
 
diff --git a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
index 5e84a754..ec69d71 100644
--- a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
+++ b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier.h
@@ -9,9 +9,12 @@
 
 #include "android_webview/browser/lifecycle/webview_app_state_observer.h"
 #include "base/android/jni_android.h"
+#include "base/callback.h"
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/no_destructor.h"
 #include "base/observer_list.h"
+#include "base/sequence_checker.h"
 
 namespace android_webview {
 
@@ -19,6 +22,8 @@
 
 class AwContentsLifecycleNotifier {
  public:
+  using OnLoseForegroundCallback = base::RepeatingClosure;
+
   enum class AwContentsState {
     // AwContents isn't attached to a window.
     kDetached,
@@ -30,6 +35,12 @@
 
   static AwContentsLifecycleNotifier& GetInstance();
 
+  // The |onLoseForegroundCallback| will be invoked after all observers when app
+  // lose foreground.
+  explicit AwContentsLifecycleNotifier(
+      OnLoseForegroundCallback on_lose_foreground_callback);
+  virtual ~AwContentsLifecycleNotifier();
+
   void OnWebViewCreated(const AwContents* aw_contents);
   void OnWebViewDestroyed(const AwContents* aw_contents);
   void OnWebViewAttachedToWindow(const AwContents* aw_contents);
@@ -60,11 +71,11 @@
     DISALLOW_COPY(AwContentsData);
   };
 
-  friend base::NoDestructor<AwContentsLifecycleNotifier>;
   friend class TestAwContentsLifecycleNotifier;
 
-  AwContentsLifecycleNotifier();
-  virtual ~AwContentsLifecycleNotifier();
+  void EnsureOnValidSequence() const {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  }
 
   size_t ToIndex(AwContentsState state) const;
   void OnAwContentsStateChanged(
@@ -87,9 +98,14 @@
   bool has_aw_contents_ever_created_ = false;
 
   base::ObserverList<WebViewAppStateObserver>::Unchecked observers_;
+
+  OnLoseForegroundCallback on_lose_foreground_callback_;
+
   WebViewAppStateObserver::State app_state_ =
       WebViewAppStateObserver::State::kDestroyed;
 
+  SEQUENCE_CHECKER(sequence_checker_);
+
   DISALLOW_COPY_AND_ASSIGN(AwContentsLifecycleNotifier);
 };
 
diff --git a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier_unittest.cc b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier_unittest.cc
index 4022ae1..2dd8eab 100644
--- a/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier_unittest.cc
+++ b/android_webview/browser/lifecycle/aw_contents_lifecycle_notifier_unittest.cc
@@ -26,9 +26,28 @@
   WebViewAppStateObserver::State state_;
 };
 
+class TestOnLoseForegroundCallback {
+ public:
+  explicit TestOnLoseForegroundCallback(const TestWebViewAppObserver* other)
+      : other_(other) {}
+
+  ~TestOnLoseForegroundCallback() = default;
+
+  void OnLoseForeground() {
+    ASSERT_NE(other_->state(), WebViewAppStateObserver::State::kForeground);
+    called_ = true;
+  }
+  bool called() const { return called_; }
+
+ private:
+  bool called_ = false;
+  const TestWebViewAppObserver* other_;
+};
+
 class TestAwContentsLifecycleNotifier : public AwContentsLifecycleNotifier {
  public:
-  TestAwContentsLifecycleNotifier() = default;
+  explicit TestAwContentsLifecycleNotifier(OnLoseForegroundCallback callback)
+      : AwContentsLifecycleNotifier(callback) {}
   ~TestAwContentsLifecycleNotifier() override = default;
 
   size_t GetAwContentsStateCount(AwContentsState state) const {
@@ -72,11 +91,20 @@
               background_count);
   }
 
+  const TestWebViewAppObserver* observer() const { return observer_.get(); }
+  const TestOnLoseForegroundCallback* callback() const {
+    return callback_.get();
+  }
+
  protected:
   // testing::Test.
   void SetUp() override {
     observer_ = std::make_unique<TestWebViewAppObserver>();
-    notifier_ = std::make_unique<TestAwContentsLifecycleNotifier>();
+    callback_ = std::make_unique<TestOnLoseForegroundCallback>(observer_.get());
+    notifier_ = std::make_unique<TestAwContentsLifecycleNotifier>(
+        base::BindRepeating(&TestOnLoseForegroundCallback::OnLoseForeground,
+                            base::Unretained(callback_.get())));
+
     notifier_->AddObserver(observer_.get());
   }
 
@@ -85,6 +113,7 @@
  private:
   content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<TestWebViewAppObserver> observer_;
+  std::unique_ptr<TestOnLoseForegroundCallback> callback_;
   std::unique_ptr<TestAwContentsLifecycleNotifier> notifier_;
 };
 
@@ -282,4 +311,13 @@
   ASSERT_TRUE(all_aw_contents.empty());
 }
 
+TEST_F(AwContentsLifecycleNotifierTest, LoseForegroundCallback) {
+  const AwContents* fake_aw_contents = reinterpret_cast<const AwContents*>(1);
+  notifier()->OnWebViewCreated(fake_aw_contents);
+  notifier()->OnWebViewAttachedToWindow(fake_aw_contents);
+  notifier()->OnWebViewWindowBeVisible(fake_aw_contents);
+  notifier()->OnWebViewWindowBeInvisible(fake_aw_contents);
+  EXPECT_TRUE(callback()->called());
+}
+
 }  // namespace android_webview
diff --git a/android_webview/java/src/org/chromium/android_webview/AwPacProcessor.java b/android_webview/java/src/org/chromium/android_webview/AwPacProcessor.java
index 350b5c1..a7fb1c9 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwPacProcessor.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwPacProcessor.java
@@ -26,6 +26,11 @@
         mNativePacProcessor = AwPacProcessorJni.get().createNativePacProcessor();
     }
 
+    // The calling code must not call any methods after it called destroy().
+    public void destroy() {
+        AwPacProcessorJni.get().destroyNative(mNativePacProcessor, this);
+    }
+
     public boolean setProxyScript(String script) {
         return AwPacProcessorJni.get().setProxyScript(mNativePacProcessor, this, script);
     }
@@ -44,5 +49,6 @@
         long createNativePacProcessor();
         boolean setProxyScript(long nativeAwPacProcessor, AwPacProcessor caller, String script);
         String makeProxyRequest(long nativeAwPacProcessor, AwPacProcessor caller, String url);
+        void destroyNative(long nativeAwPacProcessor, AwPacProcessor caller);
     }
 }
diff --git a/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java b/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java
index b8560d5..1c8d1a0d7 100644
--- a/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java
+++ b/android_webview/test/shell/src/org/chromium/android_webview/test/AwJUnit4ClassRunner.java
@@ -6,7 +6,6 @@
 
 import androidx.annotation.CallSuper;
 
-import org.junit.runner.notification.RunNotifier;
 import org.junit.runners.model.FrameworkMethod;
 import org.junit.runners.model.InitializationError;
 
@@ -14,8 +13,6 @@
 import org.chromium.android_webview.test.OnlyRunIn.ProcessMode;
 import org.chromium.base.CommandLine;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
-import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.policy.test.annotations.Policies;
 
 import java.util.ArrayList;
@@ -32,6 +29,12 @@
  * which exercise code which cannot depend on single vs. multi process.
  */
 public final class AwJUnit4ClassRunner extends BaseJUnit4ClassRunner {
+    private final TestHook mWebViewMultiProcessHook = (targetContext, testMethod) -> {
+        if (testMethod instanceof WebViewMultiProcessFrameworkMethod) {
+            CommandLine.getInstance().appendSwitch(AwSwitches.WEBVIEW_SANDBOXED_RENDERER);
+        }
+    };
+
     /**
      * Create an AwJUnit4ClassRunner to run {@code klass} and initialize values
      *
@@ -44,8 +47,9 @@
 
     @CallSuper
     @Override
-    protected List<PreTestHook> getPreTestHooks() {
-        return addToList(super.getPreTestHooks(), Policies.getRegistrationHook());
+    protected List<TestHook> getPreTestHooks() {
+        return addToList(
+                super.getPreTestHooks(), Policies.getRegistrationHook(), mWebViewMultiProcessHook);
     }
 
     private ProcessMode processModeForMethod(FrameworkMethod method) {
@@ -88,15 +92,6 @@
         return result;
     }
 
-    @Override
-    protected void runChild(FrameworkMethod method, RunNotifier notifier) {
-        CommandLineFlags.setUp(method.getMethod());
-        if (method instanceof WebViewMultiProcessFrameworkMethod) {
-            CommandLine.getInstance().appendSwitch(AwSwitches.WEBVIEW_SANDBOXED_RENDERER);
-        }
-        super.runChild(method, notifier);
-    }
-
     /**
      * Custom FrameworkMethod class indicate this test method will run in multiprocess mode.
      *
diff --git a/apps/BUILD.gn b/apps/BUILD.gn
index bba3724c..4b21b4af 100644
--- a/apps/BUILD.gn
+++ b/apps/BUILD.gn
@@ -37,6 +37,7 @@
   configs += [ "//build/config/compiler:wexit_time_destructors" ]
 
   deps = [
+    "//base/util/values:values_util",
     "//components/keyed_service/content",
     "//content/public/browser",
     "//content/public/common",
diff --git a/apps/saved_files_service.cc b/apps/saved_files_service.cc
index 26bfb1c..fbb91ea 100644
--- a/apps/saved_files_service.cc
+++ b/apps/saved_files_service.cc
@@ -13,7 +13,7 @@
 #include <utility>
 
 #include "apps/saved_files_service_factory.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/notification_service.h"
 #include "extensions/browser/api/file_system/saved_file_entry.h"
@@ -67,7 +67,8 @@
 
   std::unique_ptr<base::DictionaryValue> file_entry_dict =
       std::make_unique<base::DictionaryValue>();
-  file_entry_dict->SetKey(kFileEntryPath, CreateFilePathValue(file_entry.path));
+  file_entry_dict->SetKey(kFileEntryPath,
+                          util::FilePathToValue(file_entry.path));
   file_entry_dict->SetBoolean(kFileEntryIsDirectory, file_entry.is_directory);
   file_entry_dict->SetInteger(kFileEntrySequenceNumber,
                               file_entry.sequence_number);
@@ -124,8 +125,9 @@
     const base::Value* path_value;
     if (!file_entry->Get(kFileEntryPath, &path_value))
       continue;
-    base::FilePath file_path;
-    if (!GetValueAsFilePath(*path_value, &file_path))
+    base::Optional<base::FilePath> file_path =
+        util::ValueToFilePath(*path_value);
+    if (!file_path)
       continue;
     bool is_directory = false;
     file_entry->GetBoolean(kFileEntryIsDirectory, &is_directory);
@@ -135,7 +137,7 @@
     if (!sequence_number)
       continue;
     result.push_back(
-        SavedFileEntry(it.key(), file_path, is_directory, sequence_number));
+        SavedFileEntry(it.key(), *file_path, is_directory, sequence_number));
   }
   return result;
 }
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc
index 3e04356..e8d6e57 100644
--- a/ash/app_list/app_list_controller_impl.cc
+++ b/ash/app_list/app_list_controller_impl.cc
@@ -1069,11 +1069,6 @@
       UMA_HISTOGRAM_COUNTS_100(kSearchQueryLengthInClamshell,
                                GetLastQueryLength());
     }
-
-    if (result->distance_from_origin() >= 0) {
-      UMA_HISTOGRAM_COUNTS_100(kSearchResultDistanceFromOrigin,
-                               result->distance_from_origin());
-    }
   }
 
   auto* notifier = GetNotifier();
diff --git a/ash/app_list/app_list_metrics.h b/ash/app_list/app_list_metrics.h
index db90659..0746a6be 100644
--- a/ash/app_list/app_list_metrics.h
+++ b/ash/app_list/app_list_metrics.h
@@ -125,11 +125,6 @@
 constexpr char kSearchQueryLengthInTablet[] =
     "Apps.AppListSearchQueryLength.TabletMode";
 
-// The UMA histogram that logs the Manhattan distance from the origin of the
-// search results to the selected result.
-constexpr char kSearchResultDistanceFromOrigin[] =
-    "Apps.AppListSearchResultDistanceFromOrigin";
-
 // The different ways to create a new page in the apps grid. These values are
 // written to logs. New enum values can be added, but existing enums must never
 // be renumbered or deleted and reused.
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index 7dce23c9..cb42e26 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -4266,16 +4266,25 @@
 
 // Tests that involve the virtual keyboard.
 class AppListPresenterDelegateVirtualKeyboardTest
-    : public AppListPresenterDelegateTest {
+    : public AppListPresenterDelegateZeroStateTest {
  public:
   AppListPresenterDelegateVirtualKeyboardTest() = default;
   ~AppListPresenterDelegateVirtualKeyboardTest() override = default;
 
-  // AppListPresenterDelegateTest:
+  // AppListPresenterDelegateZeroStateTest:
   void SetUp() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         keyboard::switches::kEnableVirtualKeyboard);
-    AppListPresenterDelegateTest::SetUp();
+    AppListPresenterDelegateZeroStateTest::SetUp();
+  }
+
+  // Performs mouse click or tap gesture on the provided point, depending on
+  // whether the test is parameterized to use mouse clicks or tap gestures.
+  void ClickOrTap(const gfx::Point& point) {
+    if (GetParam())
+      ClickMouseAt(point);
+    else
+      GetEventGenerator()->GestureTapAt(point);
   }
 };
 
@@ -4286,20 +4295,19 @@
                          testing::Bool());
 
 // Tests that tapping or clicking the body of the applist with an active virtual
-// keyboard results in the virtual keyboard closing with no side effects.
+// keyboard when there exists text in the searchbox results in the virtual
+// keyboard closing with no side effects.
 TEST_P(AppListPresenterDelegateVirtualKeyboardTest,
-       TapAppListWithVirtualKeyboardDismissesVirtualKeyboard) {
-  const bool test_click = GetParam();
+       TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithSearchText) {
   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
   EnableTabletMode(true);
 
   // Tap to activate the searchbox.
-  ui::test::EventGenerator* generator = GetEventGenerator();
-  generator->GestureTapAt(GetPointInsideSearchbox());
+  ClickOrTap(GetPointInsideSearchbox());
 
   // Enter some text in the searchbox, the applist should transition to
   // fullscreen search.
-  generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
+  GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_0, 0);
   GetAppListTestHelper()->WaitUntilIdle();
   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
 
@@ -4309,13 +4317,7 @@
   ASSERT_TRUE(keyboard::WaitUntilShown());
 
   // Tap or click outside the searchbox, the virtual keyboard should hide.
-  if (test_click) {
-    generator->MoveMouseTo(GetPointOutsideSearchbox());
-    generator->ClickLeftButton();
-    generator->ReleaseLeftButton();
-  } else {
-    generator->GestureTapAt(GetPointOutsideSearchbox());
-  }
+  ClickOrTap(GetPointOutsideSearchbox());
   EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
 
   // The searchbox should still be active and the AppListView should still be in
@@ -4326,17 +4328,38 @@
 
   // Tap or click the body of the AppList again, the searchbox should deactivate
   // and the applist should be in FULLSCREEN_ALL_APPS.
-  if (test_click) {
-    generator->MoveMouseTo(GetPointOutsideSearchbox());
-    generator->ClickLeftButton();
-    generator->ReleaseLeftButton();
-  } else {
-    generator->GestureTapAt(GetPointOutsideSearchbox());
-  }
+  ClickOrTap(GetPointOutsideSearchbox());
   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
   EXPECT_FALSE(GetAppListView()->search_box_view()->is_search_box_active());
 }
 
+// Tests that tapping or clicking the body of the applist with an active virtual
+// keyboard when there is no text in the searchbox results in both the virtual
+// keyboard and searchbox closing with no side effects.
+TEST_P(AppListPresenterDelegateVirtualKeyboardTest,
+       TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithoutSearchText) {
+  GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
+  EnableTabletMode(true);
+
+  // Tap to activate the searchbox.
+  ClickOrTap(GetPointInsideSearchbox());
+  GetAppListTestHelper()->WaitUntilIdle();
+  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
+
+  // Manually show the virtual keyboard.
+  auto* const keyboard_controller = keyboard::KeyboardUIController::Get();
+  keyboard_controller->ShowKeyboard(true);
+  ASSERT_TRUE(keyboard::WaitUntilShown());
+
+  // Tap or click outside the searchbox, the virtual keyboard should hide and
+  // the searchbox should be inactive when there is no text in the searchbox.
+  ClickOrTap(GetPointOutsideSearchbox());
+  GetAppListTestHelper()->WaitUntilIdle();
+  GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
+  EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
+  EXPECT_FALSE(GetAppListView()->search_box_view()->is_search_box_active());
+}
+
 TEST_P(AppListPresenterDelegateHomeLauncherTest,
        TapHomeButtonOnExternalDisplay) {
   UpdateDisplay("800x600,1000x768");
diff --git a/ash/app_list/model/search/search_result.h b/ash/app_list/model/search/search_result.h
index b6697dd..dc57d0e 100644
--- a/ash/app_list/model/search/search_result.h
+++ b/ash/app_list/model/search/search_result.h
@@ -122,11 +122,6 @@
     metadata_->result_subtype = result_subtype;
   }
 
-  int distance_from_origin() { return distance_from_origin_; }
-  void set_distance_from_origin(int distance) {
-    distance_from_origin_ = distance;
-  }
-
   const Actions& actions() const { return metadata_->actions; }
   void SetActions(const Actions& sets);
 
@@ -174,10 +169,6 @@
   // Opens the result. Clients should use AppListViewDelegate::OpenSearchResult.
   virtual void Open(int event_flags);
 
-  // The Manhattan distance from the origin of all search results to this
-  // result. This is logged for UMA.
-  int distance_from_origin_ = -1;
-
   bool is_visible_ = true;
 
   std::unique_ptr<SearchResultMetadata> metadata_;
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc
index 899821f..8e4d200 100644
--- a/ash/app_list/views/app_list_view.cc
+++ b/ash/app_list/views/app_list_view.cc
@@ -922,10 +922,13 @@
 }
 
 void AppListView::HandleClickOrTap(ui::LocatedEvent* event) {
-  // If the virtual keyboard is visible, dismiss the keyboard and return early.
+  // If the virtual keyboard is visible, dismiss the keyboard. If there is some
+  // text in the search box or the embedded assistant UI is shown, return early
+  // so they don't get closed.
   if (CloseKeyboardIfVisible()) {
     search_box_view_->NotifyGestureEvent();
-    return;
+    if (search_box_view_->HasSearch() || IsShowingEmbeddedAssistantUI())
+      return;
   }
 
   // Close embedded Assistant UI if it is shown.
diff --git a/ash/app_list/views/search_result_answer_card_view.h b/ash/app_list/views/search_result_answer_card_view.h
index 14ef4f4..55a4d7a 100644
--- a/ash/app_list/views/search_result_answer_card_view.h
+++ b/ash/app_list/views/search_result_answer_card_view.h
@@ -25,7 +25,6 @@
   const char* GetClassName() const override;
 
   // Overridden from SearchResultContainerView:
-  void NotifyFirstResultYIndex(int y_index) override {}
   int GetYSize() override;
   int DoUpdate() override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
diff --git a/ash/app_list/views/search_result_container_view.cc b/ash/app_list/views/search_result_container_view.cc
index 57d58fc..e625a16 100644
--- a/ash/app_list/views/search_result_container_view.cc
+++ b/ash/app_list/views/search_result_container_view.cc
@@ -34,10 +34,6 @@
   Update();
 }
 
-void SearchResultContainerView::NotifyFirstResultYIndex(int /*y_index*/) {
-  NOTREACHED();
-}
-
 int SearchResultContainerView::GetYSize() {
   NOTREACHED();
   return 0;
diff --git a/ash/app_list/views/search_result_container_view.h b/ash/app_list/views/search_result_container_view.h
index bb4b3af..6bc7f67 100644
--- a/ash/app_list/views/search_result_container_view.h
+++ b/ash/app_list/views/search_result_container_view.h
@@ -62,11 +62,6 @@
   void set_container_score(double score) { container_score_ = score; }
   double container_score() const { return container_score_; }
 
-  // Updates the distance_from_origin() properties of the results in this
-  // container. |y_index| is the absolute y-index of the first result of this
-  // container (counting from the top of the app list).
-  virtual void NotifyFirstResultYIndex(int y_index);
-
   // Gets the number of down keystrokes from the beginning to the end of this
   // container.
   virtual int GetYSize();
diff --git a/ash/app_list/views/search_result_list_view.cc b/ash/app_list/views/search_result_list_view.cc
index 3918b14..5c7c014 100644
--- a/ash/app_list/views/search_result_list_view.cc
+++ b/ash/app_list/views/search_result_list_view.cc
@@ -184,11 +184,6 @@
   return search_result_views_[index];
 }
 
-void SearchResultListView::NotifyFirstResultYIndex(int y_index) {
-  for (size_t i = 0; i < static_cast<size_t>(num_results()); ++i)
-    GetResultViewAt(i)->result()->set_distance_from_origin(i + y_index);
-}
-
 int SearchResultListView::GetYSize() {
   return num_results();
 }
diff --git a/ash/app_list/views/search_result_list_view.h b/ash/app_list/views/search_result_list_view.h
index d165d75..1a347ed 100644
--- a/ash/app_list/views/search_result_list_view.h
+++ b/ash/app_list/views/search_result_list_view.h
@@ -50,7 +50,6 @@
 
   // Overridden from SearchResultContainerView:
   SearchResultView* GetResultViewAt(size_t index) override;
-  void NotifyFirstResultYIndex(int y_index) override;
   int GetYSize() override;
   SearchResultBaseView* GetFirstResultView() override;
 
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc
index 4b78825..a92180e 100644
--- a/ash/app_list/views/search_result_page_view.cc
+++ b/ash/app_list/views/search_result_page_view.cc
@@ -303,29 +303,19 @@
               return a->container_score() > b->container_score();
             });
 
-  int result_y_index = 0;
   for (size_t i = 0; i < result_container_views_.size(); ++i) {
     SearchResultContainerView* view = result_container_views_[i];
 
     if (i > 0) {
       HorizontalSeparator* separator = separators_[i - 1];
       // Hides the separator above the container that has no results.
-      if (!view->num_results())
-        separator->SetVisible(false);
-      else
-        separator->SetVisible(true);
+      separator->SetVisible(view->num_results());
 
       contents_view_->ReorderChildView(separator, i * 2 - 1 + view_offset);
       contents_view_->ReorderChildView(view->parent(), i * 2 + view_offset);
-
-      result_y_index += kSeparatorThickness;
     } else {
       contents_view_->ReorderChildView(view->parent(), i + view_offset);
     }
-
-    view->NotifyFirstResultYIndex(result_y_index);
-
-    result_y_index += view->GetYSize();
   }
 
   Layout();
diff --git a/ash/app_list/views/search_result_tile_item_list_view.cc b/ash/app_list/views/search_result_tile_item_list_view.cc
index 27f3379..36e21509 100644
--- a/ash/app_list/views/search_result_tile_item_list_view.cc
+++ b/ash/app_list/views/search_result_tile_item_list_view.cc
@@ -122,11 +122,6 @@
   return tile_views_[index];
 }
 
-void SearchResultTileItemListView::NotifyFirstResultYIndex(int y_index) {
-  for (size_t i = 0; i < static_cast<size_t>(num_results()); ++i)
-    GetResultViewAt(i)->result()->set_distance_from_origin(i + y_index);
-}
-
 int SearchResultTileItemListView::GetYSize() {
   return num_results() ? 1 : 0;
 }
diff --git a/ash/app_list/views/search_result_tile_item_list_view.h b/ash/app_list/views/search_result_tile_item_list_view.h
index dce257e..2ecea17 100644
--- a/ash/app_list/views/search_result_tile_item_list_view.h
+++ b/ash/app_list/views/search_result_tile_item_list_view.h
@@ -32,7 +32,6 @@
 
   // Overridden from SearchResultContainerView:
   SearchResultTileItemView* GetResultViewAt(size_t index) override;
-  void NotifyFirstResultYIndex(int y_index) override;
   int GetYSize() override;
   SearchResultBaseView* GetFirstResultView() override;
 
diff --git a/ash/assistant/test/assistant_ash_test_base.cc b/ash/assistant/test/assistant_ash_test_base.cc
index 7980034..bbd71281a 100644
--- a/ash/assistant/test/assistant_ash_test_base.cc
+++ b/ash/assistant/test/assistant_ash_test_base.cc
@@ -128,7 +128,7 @@
   // At this point our Assistant service is ready for use.
   // Indicate this by changing status from NOT_READY to READY.
   test_api_->GetAssistantState()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   test_api_->DisableAnimations();
 
diff --git a/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc b/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
index 08d0782..16f19594 100644
--- a/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
+++ b/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
@@ -73,13 +73,9 @@
 // Tests -----------------------------------------------------------------------
 
 TEST_F(AssistantOnboardingViewTest, ShouldHaveExpectedGreeting) {
-  // Advance clock to midnight.
-  base::Time::Exploded now;
-  base::Time::Now().LocalExplode(&now);
-  AdvanceClock(base::TimeDelta::FromHours((24 - now.hour) % 24) -
-               base::TimeDelta::FromMinutes(now.minute) -
-               base::TimeDelta::FromSeconds(now.second) -
-               base::TimeDelta::FromMilliseconds(now.millisecond));
+  // Advance clock to midnight tomorrow.
+  AdvanceClock(base::Time::Now().LocalMidnight() +
+               base::TimeDelta::FromHours(24) - base::Time::Now());
 
   // Verify 4:59 AM.
   AdvanceClock(base::TimeDelta::FromHours(4) +
diff --git a/ash/quick_answers/ui/quick_answers_pre_target_handler.cc b/ash/quick_answers/ui/quick_answers_pre_target_handler.cc
index 122e2fc1..602247a 100644
--- a/ash/quick_answers/ui/quick_answers_pre_target_handler.cc
+++ b/ash/quick_answers/ui/quick_answers_pre_target_handler.cc
@@ -6,9 +6,12 @@
 
 #include "ash/quick_answers/ui/quick_answers_view.h"
 #include "ash/quick_answers/ui/user_consent_view.h"
-#include "ash/shell.h"
 #include "base/containers/adapters.h"
+#include "ui/aura/env.h"
 #include "ui/views/controls/menu/menu_controller.h"
+#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/controls/menu/submenu_view.h"
+#include "ui/views/focus/external_focus_tracker.h"
 #include "ui/views/widget/tooltip_manager.h"
 #include "ui/views/widget/widget.h"
 
@@ -27,19 +30,30 @@
 }
 
 QuickAnswersPreTargetHandler::~QuickAnswersPreTargetHandler() {
-  Shell::Get()->RemovePreTargetHandler(this);
+  aura::Env::GetInstance()->RemovePreTargetHandler(this);
 }
 
 void QuickAnswersPreTargetHandler::Init() {
   // QuickAnswersView is a companion view of a menu. Menu host widget sets
   // mouse capture as well as a pre-target handler, so we need to register one
   // here as well to intercept events for QuickAnswersView.
-  Shell::Get()->AddPreTargetHandler(this, ui::EventTarget::Priority::kSystem);
+  aura::Env::GetInstance()->AddPreTargetHandler(
+      this, ui::EventTarget::Priority::kSystem);
   view_observer_.Add(view_);
+  external_focus_tracker_ =
+      std::make_unique<views::ExternalFocusTracker>(view_, nullptr);
 }
 
 void QuickAnswersPreTargetHandler::OnEvent(ui::Event* event) {
-  if (!view_observer_.IsObservingSources() || !event->IsLocatedEvent())
+  if (!view_observer_.IsObservingSources())
+    return;
+
+  if (event->IsKeyEvent()) {
+    ProcessKeyEvent(static_cast<ui::KeyEvent*>(event));
+    return;
+  }
+
+  if (!event->IsLocatedEvent())
     return;
 
   // Clone event to forward down the view-hierarchy.
@@ -133,4 +147,89 @@
   return event->handled();
 }
 
+void QuickAnswersPreTargetHandler::ProcessKeyEvent(ui::KeyEvent* key_event) {
+  if (key_event->type() != ui::ET_KEY_PRESSED)
+    return;
+
+  auto* focus_manager = view_->GetFocusManager();
+  auto* currently_focused_view = focus_manager->GetFocusedView();
+  bool view_has_pane_focus = view_->Contains(currently_focused_view);
+
+  // |view_| will insert itself between the cyclic keyboard traversal order of
+  // the last and the first menu items of the active menu by commandeering the
+  // selection from these terminal items.
+
+  auto key_code = key_event->key_code();
+  switch (key_code) {
+    case ui::VKEY_UP:
+    case ui::VKEY_DOWN: {
+      if (view_has_pane_focus) {
+        // Allow key-events to pass on as-usual to the context menu and restore
+        // focus to wherever |view_| borrowed it from.
+        external_focus_tracker_->FocusLastFocusedExternalView();
+        external_focus_tracker_->SetFocusManager(nullptr);
+
+        // Explicitly lose focus if restoring to last focused did not work.
+        if (view_->Contains(focus_manager->GetFocusedView()))
+          focus_manager->SetFocusedView(nullptr);
+
+        return;
+      }
+
+      // Get the selected item, if any, in the currently active menu.
+      auto* const active_menu = views::MenuController::GetActiveInstance();
+      auto* const selected_item = active_menu->GetSelectedMenuItem();
+      if (!selected_item || !selected_item->GetParentMenuItem())
+        return;
+
+      // Check if the item is within the outer-most menu, since we do not want
+      // the selection to loop back to |view_| for submenus.
+      const auto* const parent = selected_item->GetParentMenuItem();
+      if (parent->GetParentMenuItem())
+        return;
+
+      // Check if the selected item is first or last within the menu.
+      bool is_first = selected_item == parent->GetSubmenu()->children().front();
+      bool is_last = selected_item == parent->GetSubmenu()->children().back();
+      if (!is_first && !is_last)
+        return;
+
+      // Focus |view_| if compatible key-event should transfer the selection to
+      // it from within the menu.
+      if (is_first == (key_code == ui::VKEY_UP)) {
+        // Track currently focused view to restore back to later and send focus
+        // to |view_|.
+        external_focus_tracker_->SetFocusManager(focus_manager);
+        view_->RequestFocus();
+        key_event->StopPropagation();
+
+        // Deselect the selected boundary menu-item.
+        selected_item->SetSelected(false);
+      }
+
+      return;
+    }
+    case ui::VKEY_RETURN: {
+      if (view_has_pane_focus) {
+        auto* button_in_focus = views::Button::AsButton(currently_focused_view);
+        if (button_in_focus)
+          button_in_focus->OnKeyPressed(*key_event);
+        key_event->StopPropagation();
+      }
+      return;
+    }
+    case ui::VKEY_LEFT:
+    case ui::VKEY_RIGHT: {
+      if (view_has_pane_focus) {
+        bool reverse = key_code == ui::VKEY_LEFT;
+        focus_manager->AdvanceFocus(reverse);
+        key_event->StopPropagation();
+      }
+      return;
+    }
+    default:
+      return;
+  }
+}
+
 }  // namespace ash
diff --git a/ash/quick_answers/ui/quick_answers_pre_target_handler.h b/ash/quick_answers/ui/quick_answers_pre_target_handler.h
index dd803060..e827fc6 100644
--- a/ash/quick_answers/ui/quick_answers_pre_target_handler.h
+++ b/ash/quick_answers/ui/quick_answers_pre_target_handler.h
@@ -14,6 +14,10 @@
 class LocatedEvent;
 }  // namespace ui
 
+namespace views {
+class ExternalFocusTracker;
+}  // namespace views
+
 namespace ash {
 
 class QuickAnswersView;
@@ -50,6 +54,7 @@
 
  private:
   void Init();
+  void ProcessKeyEvent(ui::KeyEvent* key_event);
 
   // Returns true if event was consumed by |view| or its children.
   bool DoDispatchEvent(views::View* view, ui::LocatedEvent* event);
@@ -61,6 +66,8 @@
   // Whether any active menus, |view_| is a companion Quick-Answers related view
   // of which, should be dismissed when it is deleted.
   bool dismiss_anchor_menu_on_view_closed_ = true;
+
+  std::unique_ptr<views::ExternalFocusTracker> external_focus_tracker_;
 };
 
 }  // namespace ash
diff --git a/ash/quick_answers/ui/quick_answers_view.cc b/ash/quick_answers/ui/quick_answers_view.cc
index c670ee3..8bcf2ef 100644
--- a/ash/quick_answers/ui/quick_answers_view.cc
+++ b/ash/quick_answers/ui/quick_answers_view.cc
@@ -23,6 +23,7 @@
 #include "ui/views/controls/label.h"
 #include "ui/views/controls/menu/menu_config.h"
 #include "ui/views/controls/menu/menu_controller.h"
+#include "ui/views/focus/focus_search.h"
 #include "ui/views/layout/box_layout.h"
 #include "ui/views/layout/fill_layout.h"
 #include "ui/views/painter.h"
@@ -114,6 +115,66 @@
 
 }  // namespace
 
+// QuickAnswersFocusSearch ----------------------------------------------------
+
+// This class manages the focus traversal order for elements inside
+// QuickAnswersView.
+// TODO(siabhijeet): QuickAnswersView is a menu-companion, so ideally should
+// avoid disturbing existing focus. Explore other ways for keyboard
+// accessibility.
+class QuickAnswersFocusSearch : public views::FocusSearch {
+ public:
+  explicit QuickAnswersFocusSearch(QuickAnswersView* view)
+      : FocusSearch(/*root=*/view, /*cycle=*/true, /*accessibility_mode=*/true),
+        view_(view) {}
+
+  ~QuickAnswersFocusSearch() override = default;
+
+  // views::FocusSearch:
+  views::View* FindNextFocusableView(
+      views::View* starting_view,
+      SearchDirection search_direction,
+      TraversalDirection traversal_direction,
+      StartingViewPolicy check_starting_view,
+      AnchoredDialogPolicy can_go_into_anchored_dialog,
+      views::FocusTraversable** focus_traversable,
+      views::View** focus_traversable_view) override {
+    DCHECK_EQ(root(), view_);
+
+    std::vector<views::View*> focusable_views;
+    // |view_| is not included in focus loop for retry-view.
+    if (!view_->retry_label_)
+      focusable_views.push_back(view_);
+    if (view_->retry_label_ && view_->retry_label_->GetVisible())
+      focusable_views.push_back(view_->retry_label_);
+    if (view_->dogfood_button_ && view_->dogfood_button_->GetVisible())
+      focusable_views.push_back(view_->dogfood_button_);
+    if (focusable_views.empty())
+      return nullptr;
+
+    int delta =
+        search_direction == FocusSearch::SearchDirection::kForwards ? 1 : -1;
+    int focusable_views_size = int{focusable_views.size()};
+    for (int i = 0; i < focusable_views_size; ++i) {
+      // If current view from the set is found to be focused, return the view
+      // next (or previous) to it as next focusable view.
+      if (focusable_views[i] == starting_view) {
+        int next_index =
+            (i + delta + focusable_views_size) % focusable_views_size;
+        return focusable_views[next_index];
+      }
+    }
+
+    // Case when none of the views are already focused.
+    return (search_direction == FocusSearch::SearchDirection::kForwards)
+               ? focusable_views.front()
+               : focusable_views.back();
+  }
+
+ private:
+  QuickAnswersView* const view_;
+};
+
 // QuickAnswersView -----------------------------------------------------------
 
 QuickAnswersView::QuickAnswersView(const gfx::Rect& anchor_view_bounds,
@@ -124,7 +185,8 @@
       controller_(controller),
       title_(title),
       quick_answers_view_handler_(
-          std::make_unique<QuickAnswersPreTargetHandler>(this)) {
+          std::make_unique<QuickAnswersPreTargetHandler>(this)),
+      focus_search_(std::make_unique<QuickAnswersFocusSearch>(this)) {
   InitLayout();
   InitWidget();
 
@@ -150,12 +212,24 @@
 
 void QuickAnswersView::OnFocus() {
   SetBackgroundState(true);
+  View* wants_focus = focus_search_->FindNextFocusableView(
+      nullptr, views::FocusSearch::SearchDirection::kForwards,
+      views::FocusSearch::TraversalDirection::kDown,
+      views::FocusSearch::StartingViewPolicy::kCheckStartingView,
+      views::FocusSearch::AnchoredDialogPolicy::kSkipAnchoredDialog, nullptr,
+      nullptr);
+  if (wants_focus != this)
+    wants_focus->RequestFocus();
 }
 
 void QuickAnswersView::OnBlur() {
   SetBackgroundState(false);
 }
 
+views::FocusTraversable* QuickAnswersView::GetPaneFocusTraversable() {
+  return this;
+}
+
 void QuickAnswersView::StateChanged(views::Button::ButtonState old_state) {
   switch (state()) {
     case Button::ButtonState::STATE_NORMAL: {
@@ -193,6 +267,18 @@
       views::ButtonController::NotifyAction::kOnPress);
 }
 
+views::FocusSearch* QuickAnswersView::GetFocusSearch() {
+  return focus_search_.get();
+}
+
+views::FocusTraversable* QuickAnswersView::GetFocusTraversableParent() {
+  return nullptr;
+}
+
+views::View* QuickAnswersView::GetFocusTraversableParentView() {
+  return nullptr;
+}
+
 void QuickAnswersView::SendQuickAnswersQuery() {
   controller_->OnQuickAnswersViewPressed();
 }
@@ -235,6 +321,7 @@
       description_container->AddChildView(std::make_unique<views::LabelButton>(
           /*listener=*/this, base::UTF8ToUTF16(kDefaultRetryStr)));
   retry_label_->SetEnabledTextColors(gfx::kGoogleBlue600);
+  retry_label_->SetFocusForPlatform();
   SetButtonNotifyActionToOnPress(retry_label_);
 }
 
diff --git a/ash/quick_answers/ui/quick_answers_view.h b/ash/quick_answers/ui/quick_answers_view.h
index a373190..5c956cd 100644
--- a/ash/quick_answers/ui/quick_answers_view.h
+++ b/ash/quick_answers/ui/quick_answers_view.h
@@ -10,6 +10,7 @@
 #include "ash/ash_export.h"
 #include "ui/events/event_handler.h"
 #include "ui/views/controls/button/button.h"
+#include "ui/views/focus/focus_manager.h"
 
 namespace chromeos {
 namespace quick_answers {
@@ -18,6 +19,7 @@
 }  // namespace chromeos
 
 namespace views {
+class FocusSearch;
 class ImageButton;
 class Label;
 class LabelButton;
@@ -30,7 +32,8 @@
 
 // A bubble style view to show QuickAnswer.
 class ASH_EXPORT QuickAnswersView : public views::Button,
-                                    public views::ButtonListener {
+                                    public views::ButtonListener,
+                                    public views::FocusTraversable {
  public:
   QuickAnswersView(const gfx::Rect& anchor_view_bounds,
                    const std::string& title,
@@ -44,6 +47,7 @@
   const char* GetClassName() const override;
   void OnFocus() override;
   void OnBlur() override;
+  views::FocusTraversable* GetPaneFocusTraversable() override;
 
   // views::Button:
   void StateChanged(views::Button::ButtonState old_state) override;
@@ -51,6 +55,11 @@
   // views::ButtonListener:
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
+  // views::FocusTraversable:
+  views::FocusSearch* GetFocusSearch() override;
+  views::FocusTraversable* GetFocusTraversableParent() override;
+  views::View* GetFocusTraversableParentView() override;
+
   // Called when a click happens to trigger Assistant Query.
   void SendQuickAnswersQuery();
 
@@ -63,6 +72,8 @@
   void ShowRetryView();
 
  private:
+  friend class QuickAnswersFocusSearch;
+
   void InitLayout();
   void InitWidget();
   void AddDogfoodButton();
@@ -81,12 +92,15 @@
   QuickAnswersUiController* const controller_;
   bool has_second_row_answer_ = false;
   std::string title_;
+
   views::View* main_view_ = nullptr;
   views::View* content_view_ = nullptr;
   views::Label* first_answer_label_ = nullptr;
   views::LabelButton* retry_label_ = nullptr;
   views::ImageButton* dogfood_button_ = nullptr;
+
   std::unique_ptr<QuickAnswersPreTargetHandler> quick_answers_view_handler_;
+  std::unique_ptr<views::FocusSearch> focus_search_;
   base::WeakPtrFactory<QuickAnswersView> weak_factory_{this};
 };
 }  // namespace ash
diff --git a/ash/shelf/home_button_unittest.cc b/ash/shelf/home_button_unittest.cc
index 5876e65d..a70725b 100644
--- a/ash/shelf/home_button_unittest.cc
+++ b/ash/shelf/home_button_unittest.cc
@@ -536,7 +536,7 @@
   assistant_state()->NotifyFeatureAllowed(
       chromeos::assistant::AssistantAllowedState::ALLOWED);
   assistant_state()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   ShelfNavigationWidget::TestApi test_api(
       GetPrimaryShelf()->navigation_widget());
@@ -568,7 +568,7 @@
   assistant_state()->NotifyFeatureAllowed(
       chromeos::assistant::AssistantAllowedState::ALLOWED);
   assistant_state()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(true);
 
diff --git a/ash/shelf/hotseat_widget.cc b/ash/shelf/hotseat_widget.cc
index 566e7d4..a60db4b 100644
--- a/ash/shelf/hotseat_widget.cc
+++ b/ash/shelf/hotseat_widget.cc
@@ -52,6 +52,39 @@
   }
 }
 
+// Calculates the state transition type for the given previous state and
+// the target state.
+HotseatWidget::StateTransition CalculateHotseatStateTransition(
+    HotseatState previous_state,
+    HotseatState target_state) {
+  if (previous_state == HotseatState::kNone ||
+      target_state == HotseatState::kNone) {
+    return HotseatWidget::StateTransition::kOther;
+  }
+
+  if (previous_state == target_state)
+    return HotseatWidget::StateTransition::kOther;
+
+  const bool related_to_homelauncher =
+      (previous_state == HotseatState::kShownHomeLauncher ||
+       target_state == HotseatState::kShownHomeLauncher);
+  const bool related_to_extended = (previous_state == HotseatState::kExtended ||
+                                    target_state == HotseatState::kExtended);
+  const bool related_to_hidden = (previous_state == HotseatState::kHidden ||
+                                  target_state == HotseatState::kHidden);
+
+  if (related_to_homelauncher && related_to_extended)
+    return HotseatWidget::StateTransition::kHomeLauncherAndExtended;
+
+  if (related_to_homelauncher && related_to_hidden)
+    return HotseatWidget::StateTransition::kHomeLauncherAndHidden;
+
+  if (related_to_extended && related_to_hidden)
+    return HotseatWidget::StateTransition::kHiddenAndExtended;
+
+  return HotseatWidget::StateTransition::kOther;
+}
+
 // Custom window targeter for the hotseat. Used so the hotseat only processes
 // events that land on the visible portion of the hotseat, and only while the
 // hotseat is not animating.
@@ -325,6 +358,25 @@
   ReorderLayers();
 }
 
+////////////////////////////////////////////////////////////////////////////////
+// ScopedInStateTransition
+
+HotseatWidget::ScopedInStateTransition::ScopedInStateTransition(
+    HotseatWidget* hotseat_widget,
+    HotseatState old_state,
+    HotseatState target_state)
+    : hotseat_widget_(hotseat_widget) {
+  hotseat_widget_->state_transition_in_progress_ =
+      CalculateHotseatStateTransition(old_state, target_state);
+}
+
+HotseatWidget::ScopedInStateTransition::~ScopedInStateTransition() {
+  hotseat_widget_->state_transition_in_progress_.reset();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// HotseatWidget
+
 HotseatWidget::HotseatWidget() : delegate_view_(new DelegateView()) {
   ShelfConfig::Get()->AddObserver(this);
 }
@@ -643,7 +695,6 @@
   if (state_ == state)
     return;
 
-  old_state_ = state_;
   state_ = state;
 
   // If the hotseat is not extended we can use the normal targeting as the
@@ -734,32 +785,4 @@
   SetBounds(target_bounds);
 }
 
-HotseatWidget::StateTransition HotseatWidget::CalculateHotseatStateTransition()
-    const {
-  if (old_state_ == HotseatState::kNone || state_ == HotseatState::kNone)
-    return StateTransition::kOther;
-
-  if (old_state_ == state_)
-    return StateTransition::kOther;
-
-  const bool related_to_homelauncher =
-      (old_state_ == HotseatState::kShownHomeLauncher ||
-       state_ == HotseatState::kShownHomeLauncher);
-  const bool related_to_extended = (old_state_ == HotseatState::kExtended ||
-                                    state_ == HotseatState::kExtended);
-  const bool related_to_hidden =
-      (old_state_ == HotseatState::kHidden || state_ == HotseatState::kHidden);
-
-  if (related_to_homelauncher && related_to_extended)
-    return StateTransition::kHomeLauncherAndExtended;
-
-  if (related_to_homelauncher && related_to_hidden)
-    return StateTransition::kHomeLauncherAndHidden;
-
-  if (related_to_extended && related_to_hidden)
-    return StateTransition::kHiddenAndExtended;
-
-  return StateTransition::kOther;
-}
-
 }  // namespace ash
diff --git a/ash/shelf/hotseat_widget.h b/ash/shelf/hotseat_widget.h
index 5ec272e..2133b25 100644
--- a/ash/shelf/hotseat_widget.h
+++ b/ash/shelf/hotseat_widget.h
@@ -29,6 +29,39 @@
                                  public ShelfConfig::Observer,
                                  public views::Widget {
  public:
+  // Defines the hotseat transition types.
+  enum class StateTransition {
+    // Hotseat state transits between kShownHomeLauncher and kExtended.
+    kHomeLauncherAndExtended,
+
+    // Hotseat state transits between kShownHomeLauncher and kHidden.
+    kHomeLauncherAndHidden,
+
+    // Hotseat state transits between kHidden and kExtended.
+    kHiddenAndExtended,
+
+    kOther
+  };
+
+  // Scoped class to notify HotseatWidget of hotseat state transition in
+  // progress. We should not calculate the state transition simply in
+  // HotseatWidget::SetState(). Otherwise it is hard to reset when the
+  // transition completes.
+  class ScopedInStateTransition {
+   public:
+    ScopedInStateTransition(HotseatWidget* hotseat_widget,
+                            HotseatState old_state,
+                            HotseatState target_state);
+    ~ScopedInStateTransition();
+
+    ScopedInStateTransition(const ScopedInStateTransition& rhs) = delete;
+    ScopedInStateTransition& operator=(const ScopedInStateTransition& rhs) =
+        delete;
+
+   private:
+    HotseatWidget* hotseat_widget_ = nullptr;
+  };
+
   HotseatWidget();
   ~HotseatWidget() override;
 
@@ -138,20 +171,6 @@
  private:
   class DelegateView;
 
-  // Defines the hotseat transition types.
-  enum class StateTransition {
-    // Hotseat state transits between kShownHomeLauncher and kExtended.
-    kHomeLauncherAndExtended,
-
-    // Hotseat state transits between kShownHomeLauncher and kHidden.
-    kHomeLauncherAndHidden,
-
-    // Hotseat state transits between kHidden and kExtended.
-    kHiddenAndExtended,
-
-    kOther
-  };
-
   struct LayoutInputs {
     gfx::Rect bounds;
     float shelf_view_opacity = 0.0f;
@@ -180,9 +199,6 @@
   void LayoutHotseatByAnimation(double target_opacity,
                                 const gfx::Rect& target_bounds);
 
-  // Calculates the state transition type before animating the hotseat.
-  StateTransition CalculateHotseatStateTransition() const;
-
   // The set of inputs that impact this widget's layout. The assumption is that
   // this widget needs a relayout if, and only if, one or more of these has
   // changed.
@@ -190,9 +206,11 @@
 
   gfx::Rect target_bounds_;
 
-  HotseatState old_state_ = HotseatState::kNone;
   HotseatState state_ = HotseatState::kNone;
 
+  // Indicates the type of the hotseat state transition in progress.
+  base::Optional<StateTransition> state_transition_in_progress_;
+
   Shelf* shelf_ = nullptr;
 
   // View containing the shelf items within an active user session. Owned by
diff --git a/ash/shelf/hotseat_widget_unittest.cc b/ash/shelf/hotseat_widget_unittest.cc
index 1bcc53e1..42e206f 100644
--- a/ash/shelf/hotseat_widget_unittest.cc
+++ b/ash/shelf/hotseat_widget_unittest.cc
@@ -101,7 +101,7 @@
       assistant_test_api_->GetAssistantState()->NotifyFeatureAllowed(
           chromeos::assistant::AssistantAllowedState::ALLOWED);
       assistant_test_api_->GetAssistantState()->NotifyStatusChanged(
-          chromeos::assistant::AssistantStatus::READY);
+          chromeos::assistant::AssistantStatus::NEW_READY);
 
       assistant_test_api_->WaitUntilIdle();
     }
diff --git a/ash/shelf/shelf_layout_manager.cc b/ash/shelf/shelf_layout_manager.cc
index da6a88f..cf8ac805 100644
--- a/ash/shelf/shelf_layout_manager.cc
+++ b/ash/shelf/shelf_layout_manager.cc
@@ -1295,7 +1295,15 @@
     MaybeUpdateShelfBackground(change_type);
 
   CalculateTargetBoundsAndUpdateWorkArea();
-  shelf_->hotseat_widget()->SetState(new_hotseat_state);
+  HotseatWidget* hotseat_widget = shelf_->hotseat_widget();
+  hotseat_widget->SetState(new_hotseat_state);
+
+  // Called before UpdateBoundsAndOpacity(). Because creation of the hotseat
+  // bounds animation which is triggered by hotseat state update requires the
+  // state transition type.
+  HotseatWidget::ScopedInStateTransition scoped_in_state_transition(
+      hotseat_widget, previous_hotseat_state, new_hotseat_state);
+
   UpdateBoundsAndOpacity(true /* animate */);
 
   // OnAutoHideStateChanged Should be emitted when:
diff --git a/ash/shortcut_viewer/ash_components_strings.grd b/ash/shortcut_viewer/ash_components_strings.grd
deleted file mode 100644
index b8dcb773..0000000
--- a/ash/shortcut_viewer/ash_components_strings.grd
+++ /dev/null
@@ -1,155 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-
-<grit base_dir="." latest_public_release="0" current_release="1"
-      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
-  <outputs>
-    <output filename="grit/ash_components_strings.h" type="rc_header">
-      <emit emit_type='prepend'></emit>
-    </output>
-    <output filename="ash_components_strings_am.pak" type="data_package" lang="am" />
-    <output filename="ash_components_strings_ar.pak" type="data_package" lang="ar" />
-    <output filename="ash_components_strings_bg.pak" type="data_package" lang="bg" />
-    <output filename="ash_components_strings_bn.pak" type="data_package" lang="bn" />
-    <output filename="ash_components_strings_ca.pak" type="data_package" lang="ca" />
-    <output filename="ash_components_strings_cs.pak" type="data_package" lang="cs" />
-    <output filename="ash_components_strings_da.pak" type="data_package" lang="da" />
-    <output filename="ash_components_strings_de.pak" type="data_package" lang="de" />
-    <output filename="ash_components_strings_el.pak" type="data_package" lang="el" />
-    <output filename="ash_components_strings_en-GB.pak" type="data_package" lang="en-GB" />
-    <output filename="ash_components_strings_en-US.pak" type="data_package" lang="en" />
-    <output filename="ash_components_strings_es.pak" type="data_package" lang="es" />
-    <output filename="ash_components_strings_es-419.pak" type="data_package" lang="es-419" />
-    <output filename="ash_components_strings_et.pak" type="data_package" lang="et" />
-    <output filename="ash_components_strings_fa.pak" type="data_package" lang="fa" />
-    <output filename="ash_components_strings_fake-bidi.pak" type="data_package" lang="fake-bidi" />
-    <output filename="ash_components_strings_fi.pak" type="data_package" lang="fi" />
-    <output filename="ash_components_strings_fil.pak" type="data_package" lang="fil" />
-    <output filename="ash_components_strings_fr.pak" type="data_package" lang="fr" />
-    <output filename="ash_components_strings_gu.pak" type="data_package" lang="gu" />
-    <output filename="ash_components_strings_he.pak" type="data_package" lang="he" />
-    <output filename="ash_components_strings_hi.pak" type="data_package" lang="hi" />
-    <output filename="ash_components_strings_hr.pak" type="data_package" lang="hr" />
-    <output filename="ash_components_strings_hu.pak" type="data_package" lang="hu" />
-    <output filename="ash_components_strings_id.pak" type="data_package" lang="id" />
-    <output filename="ash_components_strings_it.pak" type="data_package" lang="it" />
-    <output filename="ash_components_strings_ja.pak" type="data_package" lang="ja" />
-    <output filename="ash_components_strings_kn.pak" type="data_package" lang="kn" />
-    <output filename="ash_components_strings_ko.pak" type="data_package" lang="ko" />
-    <output filename="ash_components_strings_lt.pak" type="data_package" lang="lt" />
-    <output filename="ash_components_strings_lv.pak" type="data_package" lang="lv" />
-    <output filename="ash_components_strings_ml.pak" type="data_package" lang="ml" />
-    <output filename="ash_components_strings_mr.pak" type="data_package" lang="mr" />
-    <output filename="ash_components_strings_ms.pak" type="data_package" lang="ms" />
-    <output filename="ash_components_strings_nl.pak" type="data_package" lang="nl" />
-    <!-- The translation console uses 'no' for Norwegian Bokmål. It should
-         be 'nb'. -->
-    <output filename="ash_components_strings_nb.pak" type="data_package" lang="no" />
-    <output filename="ash_components_strings_pl.pak" type="data_package" lang="pl" />
-    <output filename="ash_components_strings_pt-BR.pak" type="data_package" lang="pt-BR" />
-    <output filename="ash_components_strings_pt-PT.pak" type="data_package" lang="pt-PT" />
-    <output filename="ash_components_strings_ro.pak" type="data_package" lang="ro" />
-    <output filename="ash_components_strings_ru.pak" type="data_package" lang="ru" />
-    <output filename="ash_components_strings_sk.pak" type="data_package" lang="sk" />
-    <output filename="ash_components_strings_sl.pak" type="data_package" lang="sl" />
-    <output filename="ash_components_strings_sr.pak" type="data_package" lang="sr" />
-    <output filename="ash_components_strings_sv.pak" type="data_package" lang="sv" />
-    <output filename="ash_components_strings_sw.pak" type="data_package" lang="sw" />
-    <output filename="ash_components_strings_ta.pak" type="data_package" lang="ta" />
-    <output filename="ash_components_strings_te.pak" type="data_package" lang="te" />
-    <output filename="ash_components_strings_th.pak" type="data_package" lang="th" />
-    <output filename="ash_components_strings_tr.pak" type="data_package" lang="tr" />
-    <output filename="ash_components_strings_uk.pak" type="data_package" lang="uk" />
-    <output filename="ash_components_strings_vi.pak" type="data_package" lang="vi" />
-    <output filename="ash_components_strings_zh-CN.pak" type="data_package" lang="zh-CN" />
-    <output filename="ash_components_strings_zh-TW.pak" type="data_package" lang="zh-TW" />
-  </outputs>
-  <translations>
-    <file path="strings/ash_components_strings_af.xtb" lang="af" />
-    <file path="strings/ash_components_strings_am.xtb" lang="am" />
-    <file path="strings/ash_components_strings_ar.xtb" lang="ar" />
-    <file path="strings/ash_components_strings_as.xtb" lang="as" />
-    <file path="strings/ash_components_strings_az.xtb" lang="az" />
-    <file path="strings/ash_components_strings_be.xtb" lang="be" />
-    <file path="strings/ash_components_strings_bg.xtb" lang="bg" />
-    <file path="strings/ash_components_strings_bn.xtb" lang="bn" />
-    <file path="strings/ash_components_strings_bs.xtb" lang="bs" />
-    <file path="strings/ash_components_strings_ca.xtb" lang="ca" />
-    <file path="strings/ash_components_strings_cs.xtb" lang="cs" />
-    <file path="strings/ash_components_strings_da.xtb" lang="da" />
-    <file path="strings/ash_components_strings_de.xtb" lang="de" />
-    <file path="strings/ash_components_strings_el.xtb" lang="el" />
-    <file path="strings/ash_components_strings_en-GB.xtb" lang="en-GB" />
-    <file path="strings/ash_components_strings_es.xtb" lang="es" />
-    <file path="strings/ash_components_strings_es-419.xtb" lang="es-419" />
-    <file path="strings/ash_components_strings_et.xtb" lang="et" />
-    <file path="strings/ash_components_strings_eu.xtb" lang="eu" />
-    <file path="strings/ash_components_strings_fa.xtb" lang="fa" />
-    <file path="strings/ash_components_strings_fi.xtb" lang="fi" />
-    <file path="strings/ash_components_strings_fil.xtb" lang="fil" />
-    <file path="strings/ash_components_strings_fr.xtb" lang="fr" />
-    <file path="strings/ash_components_strings_fr-CA.xtb" lang="fr-CA" />
-    <file path="strings/ash_components_strings_gl.xtb" lang="gl" />
-    <file path="strings/ash_components_strings_gu.xtb" lang="gu" />
-    <file path="strings/ash_components_strings_hi.xtb" lang="hi" />
-    <file path="strings/ash_components_strings_hr.xtb" lang="hr" />
-    <file path="strings/ash_components_strings_hu.xtb" lang="hu" />
-    <file path="strings/ash_components_strings_hy.xtb" lang="hy" />
-    <file path="strings/ash_components_strings_id.xtb" lang="id" />
-    <file path="strings/ash_components_strings_is.xtb" lang="is" />
-    <file path="strings/ash_components_strings_it.xtb" lang="it" />
-    <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
-    <file path="strings/ash_components_strings_iw.xtb" lang="he" />
-    <file path="strings/ash_components_strings_ja.xtb" lang="ja" />
-    <file path="strings/ash_components_strings_ka.xtb" lang="ka" />
-    <file path="strings/ash_components_strings_kk.xtb" lang="kk" />
-    <file path="strings/ash_components_strings_km.xtb" lang="km" />
-    <file path="strings/ash_components_strings_kn.xtb" lang="kn" />
-    <file path="strings/ash_components_strings_ko.xtb" lang="ko" />
-    <file path="strings/ash_components_strings_ky.xtb" lang="ky" />
-    <file path="strings/ash_components_strings_lo.xtb" lang="lo" />
-    <file path="strings/ash_components_strings_lt.xtb" lang="lt" />
-    <file path="strings/ash_components_strings_lv.xtb" lang="lv" />
-    <file path="strings/ash_components_strings_mk.xtb" lang="mk" />
-    <file path="strings/ash_components_strings_ml.xtb" lang="ml" />
-    <file path="strings/ash_components_strings_mn.xtb" lang="mn" />
-    <file path="strings/ash_components_strings_mr.xtb" lang="mr" />
-    <file path="strings/ash_components_strings_ms.xtb" lang="ms" />
-    <file path="strings/ash_components_strings_my.xtb" lang="my" />
-    <file path="strings/ash_components_strings_ne.xtb" lang="ne" />
-    <file path="strings/ash_components_strings_nl.xtb" lang="nl" />
-    <file path="strings/ash_components_strings_no.xtb" lang="no" />
-    <file path="strings/ash_components_strings_or.xtb" lang="or" />
-    <file path="strings/ash_components_strings_pa.xtb" lang="pa" />
-    <file path="strings/ash_components_strings_pl.xtb" lang="pl" />
-    <file path="strings/ash_components_strings_pt-BR.xtb" lang="pt-BR" />
-    <file path="strings/ash_components_strings_pt-PT.xtb" lang="pt-PT" />
-    <file path="strings/ash_components_strings_ro.xtb" lang="ro" />
-    <file path="strings/ash_components_strings_ru.xtb" lang="ru" />
-    <file path="strings/ash_components_strings_si.xtb" lang="si" />
-    <file path="strings/ash_components_strings_sk.xtb" lang="sk" />
-    <file path="strings/ash_components_strings_sl.xtb" lang="sl" />
-    <file path="strings/ash_components_strings_sq.xtb" lang="sq" />
-    <file path="strings/ash_components_strings_sr.xtb" lang="sr" />
-    <file path="strings/ash_components_strings_sr-Latn.xtb" lang="sr-Latn" />
-    <file path="strings/ash_components_strings_sv.xtb" lang="sv" />
-    <file path="strings/ash_components_strings_sw.xtb" lang="sw" />
-    <file path="strings/ash_components_strings_ta.xtb" lang="ta" />
-    <file path="strings/ash_components_strings_te.xtb" lang="te" />
-    <file path="strings/ash_components_strings_th.xtb" lang="th" />
-    <file path="strings/ash_components_strings_tr.xtb" lang="tr" />
-    <file path="strings/ash_components_strings_uk.xtb" lang="uk" />
-    <file path="strings/ash_components_strings_ur.xtb" lang="ur" />
-    <file path="strings/ash_components_strings_uz.xtb" lang="uz" />
-    <file path="strings/ash_components_strings_vi.xtb" lang="vi" />
-    <file path="strings/ash_components_strings_zh-CN.xtb" lang="zh-CN" />
-    <file path="strings/ash_components_strings_zh-HK.xtb" lang="zh-HK" />
-    <file path="strings/ash_components_strings_zh-TW.xtb" lang="zh-TW" />
-    <file path="strings/ash_components_strings_zu.xtb" lang="zu" />
-  </translations>
-  <release seq="1" allow_pseudo="false">
-    <messages fallback_to_english="true">
-      <part file="shortcut_viewer_strings.grdp" />
-
-    </messages>
-  </release>
-</grit>
diff --git a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
index 3d3c8bd..d5ee982 100644
--- a/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
+++ b/ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.cc
@@ -5,7 +5,7 @@
 #include "ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
 
 #include "ash/shortcut_viewer/keyboard_shortcut_item.h"
-#include "ash/shortcut_viewer/strings/grit/ash_components_strings.h"
+#include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "ash/shortcut_viewer/vector_icons/vector_icons.h"
 #include "base/check.h"
 #include "base/macros.h"
diff --git a/ash/shortcut_viewer/shortcut_viewer_strings.grdp b/ash/shortcut_viewer/shortcut_viewer_strings.grd
similarity index 78%
rename from ash/shortcut_viewer/shortcut_viewer_strings.grdp
rename to ash/shortcut_viewer/shortcut_viewer_strings.grd
index 358b72c..324a521a 100644
--- a/ash/shortcut_viewer/shortcut_viewer_strings.grdp
+++ b/ash/shortcut_viewer/shortcut_viewer_strings.grd
@@ -1,5 +1,153 @@
-<?xml version="1.0" encoding="utf-8"?>
-<grit-part>
+<?xml version="1.0" encoding="UTF-8"?>
+
+<grit base_dir="." latest_public_release="0" current_release="1"
+      output_all_resource_defines="false" source_lang_id="en" enc_check="möl">
+  <outputs>
+    <output filename="grit/shortcut_viewer_strings.h" type="rc_header">
+      <emit emit_type='prepend'></emit>
+    </output>
+    <output filename="shortcut_viewer_strings_am.pak" type="data_package" lang="am" />
+    <output filename="shortcut_viewer_strings_ar.pak" type="data_package" lang="ar" />
+    <output filename="shortcut_viewer_strings_bg.pak" type="data_package" lang="bg" />
+    <output filename="shortcut_viewer_strings_bn.pak" type="data_package" lang="bn" />
+    <output filename="shortcut_viewer_strings_ca.pak" type="data_package" lang="ca" />
+    <output filename="shortcut_viewer_strings_cs.pak" type="data_package" lang="cs" />
+    <output filename="shortcut_viewer_strings_da.pak" type="data_package" lang="da" />
+    <output filename="shortcut_viewer_strings_de.pak" type="data_package" lang="de" />
+    <output filename="shortcut_viewer_strings_el.pak" type="data_package" lang="el" />
+    <output filename="shortcut_viewer_strings_en-GB.pak" type="data_package" lang="en-GB" />
+    <output filename="shortcut_viewer_strings_en-US.pak" type="data_package" lang="en" />
+    <output filename="shortcut_viewer_strings_es.pak" type="data_package" lang="es" />
+    <output filename="shortcut_viewer_strings_es-419.pak" type="data_package" lang="es-419" />
+    <output filename="shortcut_viewer_strings_et.pak" type="data_package" lang="et" />
+    <output filename="shortcut_viewer_strings_fa.pak" type="data_package" lang="fa" />
+    <output filename="shortcut_viewer_strings_fake-bidi.pak" type="data_package" lang="fake-bidi" />
+    <output filename="shortcut_viewer_strings_fi.pak" type="data_package" lang="fi" />
+    <output filename="shortcut_viewer_strings_fil.pak" type="data_package" lang="fil" />
+    <output filename="shortcut_viewer_strings_fr.pak" type="data_package" lang="fr" />
+    <output filename="shortcut_viewer_strings_gu.pak" type="data_package" lang="gu" />
+    <output filename="shortcut_viewer_strings_he.pak" type="data_package" lang="he" />
+    <output filename="shortcut_viewer_strings_hi.pak" type="data_package" lang="hi" />
+    <output filename="shortcut_viewer_strings_hr.pak" type="data_package" lang="hr" />
+    <output filename="shortcut_viewer_strings_hu.pak" type="data_package" lang="hu" />
+    <output filename="shortcut_viewer_strings_id.pak" type="data_package" lang="id" />
+    <output filename="shortcut_viewer_strings_it.pak" type="data_package" lang="it" />
+    <output filename="shortcut_viewer_strings_ja.pak" type="data_package" lang="ja" />
+    <output filename="shortcut_viewer_strings_kn.pak" type="data_package" lang="kn" />
+    <output filename="shortcut_viewer_strings_ko.pak" type="data_package" lang="ko" />
+    <output filename="shortcut_viewer_strings_lt.pak" type="data_package" lang="lt" />
+    <output filename="shortcut_viewer_strings_lv.pak" type="data_package" lang="lv" />
+    <output filename="shortcut_viewer_strings_ml.pak" type="data_package" lang="ml" />
+    <output filename="shortcut_viewer_strings_mr.pak" type="data_package" lang="mr" />
+    <output filename="shortcut_viewer_strings_ms.pak" type="data_package" lang="ms" />
+    <output filename="shortcut_viewer_strings_nl.pak" type="data_package" lang="nl" />
+    <!-- The translation console uses 'no' for Norwegian Bokmål. It should
+         be 'nb'. -->
+    <output filename="shortcut_viewer_strings_nb.pak" type="data_package" lang="no" />
+    <output filename="shortcut_viewer_strings_pl.pak" type="data_package" lang="pl" />
+    <output filename="shortcut_viewer_strings_pt-BR.pak" type="data_package" lang="pt-BR" />
+    <output filename="shortcut_viewer_strings_pt-PT.pak" type="data_package" lang="pt-PT" />
+    <output filename="shortcut_viewer_strings_ro.pak" type="data_package" lang="ro" />
+    <output filename="shortcut_viewer_strings_ru.pak" type="data_package" lang="ru" />
+    <output filename="shortcut_viewer_strings_sk.pak" type="data_package" lang="sk" />
+    <output filename="shortcut_viewer_strings_sl.pak" type="data_package" lang="sl" />
+    <output filename="shortcut_viewer_strings_sr.pak" type="data_package" lang="sr" />
+    <output filename="shortcut_viewer_strings_sv.pak" type="data_package" lang="sv" />
+    <output filename="shortcut_viewer_strings_sw.pak" type="data_package" lang="sw" />
+    <output filename="shortcut_viewer_strings_ta.pak" type="data_package" lang="ta" />
+    <output filename="shortcut_viewer_strings_te.pak" type="data_package" lang="te" />
+    <output filename="shortcut_viewer_strings_th.pak" type="data_package" lang="th" />
+    <output filename="shortcut_viewer_strings_tr.pak" type="data_package" lang="tr" />
+    <output filename="shortcut_viewer_strings_uk.pak" type="data_package" lang="uk" />
+    <output filename="shortcut_viewer_strings_vi.pak" type="data_package" lang="vi" />
+    <output filename="shortcut_viewer_strings_zh-CN.pak" type="data_package" lang="zh-CN" />
+    <output filename="shortcut_viewer_strings_zh-TW.pak" type="data_package" lang="zh-TW" />
+  </outputs>
+  <translations>
+    <file path="strings/shortcut_viewer_strings_af.xtb" lang="af" />
+    <file path="strings/shortcut_viewer_strings_am.xtb" lang="am" />
+    <file path="strings/shortcut_viewer_strings_ar.xtb" lang="ar" />
+    <file path="strings/shortcut_viewer_strings_as.xtb" lang="as" />
+    <file path="strings/shortcut_viewer_strings_az.xtb" lang="az" />
+    <file path="strings/shortcut_viewer_strings_be.xtb" lang="be" />
+    <file path="strings/shortcut_viewer_strings_bg.xtb" lang="bg" />
+    <file path="strings/shortcut_viewer_strings_bn.xtb" lang="bn" />
+    <file path="strings/shortcut_viewer_strings_bs.xtb" lang="bs" />
+    <file path="strings/shortcut_viewer_strings_ca.xtb" lang="ca" />
+    <file path="strings/shortcut_viewer_strings_cs.xtb" lang="cs" />
+    <file path="strings/shortcut_viewer_strings_da.xtb" lang="da" />
+    <file path="strings/shortcut_viewer_strings_de.xtb" lang="de" />
+    <file path="strings/shortcut_viewer_strings_el.xtb" lang="el" />
+    <file path="strings/shortcut_viewer_strings_en-GB.xtb" lang="en-GB" />
+    <file path="strings/shortcut_viewer_strings_es.xtb" lang="es" />
+    <file path="strings/shortcut_viewer_strings_es-419.xtb" lang="es-419" />
+    <file path="strings/shortcut_viewer_strings_et.xtb" lang="et" />
+    <file path="strings/shortcut_viewer_strings_eu.xtb" lang="eu" />
+    <file path="strings/shortcut_viewer_strings_fa.xtb" lang="fa" />
+    <file path="strings/shortcut_viewer_strings_fi.xtb" lang="fi" />
+    <file path="strings/shortcut_viewer_strings_fil.xtb" lang="fil" />
+    <file path="strings/shortcut_viewer_strings_fr.xtb" lang="fr" />
+    <file path="strings/shortcut_viewer_strings_fr-CA.xtb" lang="fr-CA" />
+    <file path="strings/shortcut_viewer_strings_gl.xtb" lang="gl" />
+    <file path="strings/shortcut_viewer_strings_gu.xtb" lang="gu" />
+    <file path="strings/shortcut_viewer_strings_hi.xtb" lang="hi" />
+    <file path="strings/shortcut_viewer_strings_hr.xtb" lang="hr" />
+    <file path="strings/shortcut_viewer_strings_hu.xtb" lang="hu" />
+    <file path="strings/shortcut_viewer_strings_hy.xtb" lang="hy" />
+    <file path="strings/shortcut_viewer_strings_id.xtb" lang="id" />
+    <file path="strings/shortcut_viewer_strings_is.xtb" lang="is" />
+    <file path="strings/shortcut_viewer_strings_it.xtb" lang="it" />
+    <!-- The translation console uses 'iw' for Hebrew, but we use 'he'. -->
+    <file path="strings/shortcut_viewer_strings_iw.xtb" lang="he" />
+    <file path="strings/shortcut_viewer_strings_ja.xtb" lang="ja" />
+    <file path="strings/shortcut_viewer_strings_ka.xtb" lang="ka" />
+    <file path="strings/shortcut_viewer_strings_kk.xtb" lang="kk" />
+    <file path="strings/shortcut_viewer_strings_km.xtb" lang="km" />
+    <file path="strings/shortcut_viewer_strings_kn.xtb" lang="kn" />
+    <file path="strings/shortcut_viewer_strings_ko.xtb" lang="ko" />
+    <file path="strings/shortcut_viewer_strings_ky.xtb" lang="ky" />
+    <file path="strings/shortcut_viewer_strings_lo.xtb" lang="lo" />
+    <file path="strings/shortcut_viewer_strings_lt.xtb" lang="lt" />
+    <file path="strings/shortcut_viewer_strings_lv.xtb" lang="lv" />
+    <file path="strings/shortcut_viewer_strings_mk.xtb" lang="mk" />
+    <file path="strings/shortcut_viewer_strings_ml.xtb" lang="ml" />
+    <file path="strings/shortcut_viewer_strings_mn.xtb" lang="mn" />
+    <file path="strings/shortcut_viewer_strings_mr.xtb" lang="mr" />
+    <file path="strings/shortcut_viewer_strings_ms.xtb" lang="ms" />
+    <file path="strings/shortcut_viewer_strings_my.xtb" lang="my" />
+    <file path="strings/shortcut_viewer_strings_ne.xtb" lang="ne" />
+    <file path="strings/shortcut_viewer_strings_nl.xtb" lang="nl" />
+    <file path="strings/shortcut_viewer_strings_no.xtb" lang="no" />
+    <file path="strings/shortcut_viewer_strings_or.xtb" lang="or" />
+    <file path="strings/shortcut_viewer_strings_pa.xtb" lang="pa" />
+    <file path="strings/shortcut_viewer_strings_pl.xtb" lang="pl" />
+    <file path="strings/shortcut_viewer_strings_pt-BR.xtb" lang="pt-BR" />
+    <file path="strings/shortcut_viewer_strings_pt-PT.xtb" lang="pt-PT" />
+    <file path="strings/shortcut_viewer_strings_ro.xtb" lang="ro" />
+    <file path="strings/shortcut_viewer_strings_ru.xtb" lang="ru" />
+    <file path="strings/shortcut_viewer_strings_si.xtb" lang="si" />
+    <file path="strings/shortcut_viewer_strings_sk.xtb" lang="sk" />
+    <file path="strings/shortcut_viewer_strings_sl.xtb" lang="sl" />
+    <file path="strings/shortcut_viewer_strings_sq.xtb" lang="sq" />
+    <file path="strings/shortcut_viewer_strings_sr-Latn.xtb" lang="sr-Latn" />
+    <file path="strings/shortcut_viewer_strings_sr.xtb" lang="sr" />
+    <file path="strings/shortcut_viewer_strings_sv.xtb" lang="sv" />
+    <file path="strings/shortcut_viewer_strings_sw.xtb" lang="sw" />
+    <file path="strings/shortcut_viewer_strings_ta.xtb" lang="ta" />
+    <file path="strings/shortcut_viewer_strings_te.xtb" lang="te" />
+    <file path="strings/shortcut_viewer_strings_th.xtb" lang="th" />
+    <file path="strings/shortcut_viewer_strings_tr.xtb" lang="tr" />
+    <file path="strings/shortcut_viewer_strings_uk.xtb" lang="uk" />
+    <file path="strings/shortcut_viewer_strings_ur.xtb" lang="ur" />
+    <file path="strings/shortcut_viewer_strings_uz.xtb" lang="uz" />
+    <file path="strings/shortcut_viewer_strings_vi.xtb" lang="vi" />
+    <file path="strings/shortcut_viewer_strings_zh-CN.xtb" lang="zh-CN" />
+    <file path="strings/shortcut_viewer_strings_zh-HK.xtb" lang="zh-HK" />
+    <file path="strings/shortcut_viewer_strings_zh-TW.xtb" lang="zh-TW" />
+    <file path="strings/shortcut_viewer_strings_zu.xtb" lang="zu" />
+  </translations>
+  <release seq="1" allow_pseudo="false">
+    <messages fallback_to_english="true">
   <!-- Title -->
   <message name="IDS_KSV_TITLE" desc="The tooltip text of the keyboard shortcut viewer shelf icon.">
     Shortcuts
@@ -663,4 +811,6 @@
   <message name="IDS_KSV_DESCRIPTION_PRIVACY_SCREEN_TOGGLE" desc="Description of the command in keyboard shortcut viewer.">
     Turn privacy screen on or off
   </message>
-</grit-part>
+    </messages>
+  </release>
+</grit>
diff --git a/ash/shortcut_viewer/strings/BUILD.gn b/ash/shortcut_viewer/strings/BUILD.gn
index 1079117..04202153 100644
--- a/ash/shortcut_viewer/strings/BUILD.gn
+++ b/ash/shortcut_viewer/strings/BUILD.gn
@@ -5,62 +5,62 @@
 import("//tools/grit/grit_rule.gni")
 
 grit("strings") {
-  source = "../ash_components_strings.grd"
+  source = "../shortcut_viewer_strings.grd"
   outputs = [
-    "grit/ash_components_strings.h",
-    "ash_components_strings_am.pak",
-    "ash_components_strings_ar.pak",
-    "ash_components_strings_bg.pak",
-    "ash_components_strings_bn.pak",
-    "ash_components_strings_ca.pak",
-    "ash_components_strings_cs.pak",
-    "ash_components_strings_da.pak",
-    "ash_components_strings_de.pak",
-    "ash_components_strings_el.pak",
-    "ash_components_strings_en-GB.pak",
-    "ash_components_strings_en-US.pak",
-    "ash_components_strings_es-419.pak",
-    "ash_components_strings_es.pak",
-    "ash_components_strings_et.pak",
-    "ash_components_strings_fake-bidi.pak",
-    "ash_components_strings_fa.pak",
-    "ash_components_strings_fil.pak",
-    "ash_components_strings_fi.pak",
-    "ash_components_strings_fr.pak",
-    "ash_components_strings_gu.pak",
-    "ash_components_strings_he.pak",
-    "ash_components_strings_hi.pak",
-    "ash_components_strings_hr.pak",
-    "ash_components_strings_hu.pak",
-    "ash_components_strings_id.pak",
-    "ash_components_strings_it.pak",
-    "ash_components_strings_ja.pak",
-    "ash_components_strings_kn.pak",
-    "ash_components_strings_ko.pak",
-    "ash_components_strings_lt.pak",
-    "ash_components_strings_lv.pak",
-    "ash_components_strings_ml.pak",
-    "ash_components_strings_mr.pak",
-    "ash_components_strings_ms.pak",
-    "ash_components_strings_nb.pak",
-    "ash_components_strings_nl.pak",
-    "ash_components_strings_pl.pak",
-    "ash_components_strings_pt-BR.pak",
-    "ash_components_strings_pt-PT.pak",
-    "ash_components_strings_ro.pak",
-    "ash_components_strings_ru.pak",
-    "ash_components_strings_sk.pak",
-    "ash_components_strings_sl.pak",
-    "ash_components_strings_sr.pak",
-    "ash_components_strings_sv.pak",
-    "ash_components_strings_sw.pak",
-    "ash_components_strings_ta.pak",
-    "ash_components_strings_te.pak",
-    "ash_components_strings_th.pak",
-    "ash_components_strings_tr.pak",
-    "ash_components_strings_uk.pak",
-    "ash_components_strings_vi.pak",
-    "ash_components_strings_zh-CN.pak",
-    "ash_components_strings_zh-TW.pak",
+    "grit/shortcut_viewer_strings.h",
+    "shortcut_viewer_strings_am.pak",
+    "shortcut_viewer_strings_ar.pak",
+    "shortcut_viewer_strings_bg.pak",
+    "shortcut_viewer_strings_bn.pak",
+    "shortcut_viewer_strings_ca.pak",
+    "shortcut_viewer_strings_cs.pak",
+    "shortcut_viewer_strings_da.pak",
+    "shortcut_viewer_strings_de.pak",
+    "shortcut_viewer_strings_el.pak",
+    "shortcut_viewer_strings_en-GB.pak",
+    "shortcut_viewer_strings_en-US.pak",
+    "shortcut_viewer_strings_es-419.pak",
+    "shortcut_viewer_strings_es.pak",
+    "shortcut_viewer_strings_et.pak",
+    "shortcut_viewer_strings_fake-bidi.pak",
+    "shortcut_viewer_strings_fa.pak",
+    "shortcut_viewer_strings_fil.pak",
+    "shortcut_viewer_strings_fi.pak",
+    "shortcut_viewer_strings_fr.pak",
+    "shortcut_viewer_strings_gu.pak",
+    "shortcut_viewer_strings_he.pak",
+    "shortcut_viewer_strings_hi.pak",
+    "shortcut_viewer_strings_hr.pak",
+    "shortcut_viewer_strings_hu.pak",
+    "shortcut_viewer_strings_id.pak",
+    "shortcut_viewer_strings_it.pak",
+    "shortcut_viewer_strings_ja.pak",
+    "shortcut_viewer_strings_kn.pak",
+    "shortcut_viewer_strings_ko.pak",
+    "shortcut_viewer_strings_lt.pak",
+    "shortcut_viewer_strings_lv.pak",
+    "shortcut_viewer_strings_ml.pak",
+    "shortcut_viewer_strings_mr.pak",
+    "shortcut_viewer_strings_ms.pak",
+    "shortcut_viewer_strings_nb.pak",
+    "shortcut_viewer_strings_nl.pak",
+    "shortcut_viewer_strings_pl.pak",
+    "shortcut_viewer_strings_pt-BR.pak",
+    "shortcut_viewer_strings_pt-PT.pak",
+    "shortcut_viewer_strings_ro.pak",
+    "shortcut_viewer_strings_ru.pak",
+    "shortcut_viewer_strings_sk.pak",
+    "shortcut_viewer_strings_sl.pak",
+    "shortcut_viewer_strings_sr.pak",
+    "shortcut_viewer_strings_sv.pak",
+    "shortcut_viewer_strings_sw.pak",
+    "shortcut_viewer_strings_ta.pak",
+    "shortcut_viewer_strings_te.pak",
+    "shortcut_viewer_strings_th.pak",
+    "shortcut_viewer_strings_tr.pak",
+    "shortcut_viewer_strings_uk.pak",
+    "shortcut_viewer_strings_vi.pak",
+    "shortcut_viewer_strings_zh-CN.pak",
+    "shortcut_viewer_strings_zh-TW.pak",
   ]
 }
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_af.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_af.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_af.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_af.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_am.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_am.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_am.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_am.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ar.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ar.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ar.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ar.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_as.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_as.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_as.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_as.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_az.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_az.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_az.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_az.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_be.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_be.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_be.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_be.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_bg.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_bg.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_bg.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_bg.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_bn.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_bn.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_bn.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_bn.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_bs.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_bs.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_bs.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_bs.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ca.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ca.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ca.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ca.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_cs.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_cs.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_cs.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_cs.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_da.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_da.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_da.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_da.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_de.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_de.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_de.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_de.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_el.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_el.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_el.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_el.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_en-GB.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_en-GB.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_en-GB.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_en-GB.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_es-419.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_es-419.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_es-419.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_es-419.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_es.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_es.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_es.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_es.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_et.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_et.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_et.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_et.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_eu.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_eu.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_eu.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_eu.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_fa.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_fa.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_fa.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_fa.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_fi.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_fi.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_fi.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_fi.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_fil.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_fil.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_fil.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_fil.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_fr-CA.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_fr-CA.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_fr-CA.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_fr-CA.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_fr.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_fr.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_fr.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_fr.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_gl.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_gl.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_gl.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_gl.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_gu.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_gu.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_gu.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_gu.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_hi.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_hi.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_hi.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_hi.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_hr.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_hr.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_hr.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_hr.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_hu.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_hu.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_hu.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_hu.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_hy.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_hy.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_hy.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_hy.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_id.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_id.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_id.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_id.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_is.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_is.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_is.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_is.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_it.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_it.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_it.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_it.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_iw.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_iw.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_iw.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_iw.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ja.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ja.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ja.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ja.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ka.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ka.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ka.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ka.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_kk.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_kk.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_kk.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_kk.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_km.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_km.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_km.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_km.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_kn.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_kn.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_kn.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_kn.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ko.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ko.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ko.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ko.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ky.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ky.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ky.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ky.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_lo.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_lo.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_lo.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_lo.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_lt.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_lt.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_lt.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_lt.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_lv.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_lv.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_lv.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_lv.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_mk.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_mk.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_mk.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_mk.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ml.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ml.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ml.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ml.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_mn.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_mn.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_mn.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_mn.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_mr.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_mr.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_mr.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_mr.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ms.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ms.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ms.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ms.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_my.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_my.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_my.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_my.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ne.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ne.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ne.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ne.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_nl.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_nl.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_nl.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_nl.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_no.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_no.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_no.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_no.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_or.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_or.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_or.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_or.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_pa.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_pa.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_pa.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_pa.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_pl.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_pl.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_pl.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_pl.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_pt-BR.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_pt-BR.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_pt-BR.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_pt-BR.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_pt-PT.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_pt-PT.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_pt-PT.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_pt-PT.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ro.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ro.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ro.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ro.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ru.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ru.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ru.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ru.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_si.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_si.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_si.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_si.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_sk.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_sk.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_sk.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_sk.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_sl.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_sl.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_sl.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_sl.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_sq.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_sq.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_sq.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_sq.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_sr-Latn.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_sr-Latn.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_sr-Latn.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_sr-Latn.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_sr.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_sr.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_sr.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_sr.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_sv.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_sv.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_sv.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_sv.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_sw.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_sw.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_sw.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_sw.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ta.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ta.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ta.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ta.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_te.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_te.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_te.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_te.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_th.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_th.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_th.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_th.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_tr.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_tr.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_tr.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_tr.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_uk.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_uk.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_uk.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_uk.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_ur.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_ur.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_ur.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_ur.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_uz.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_uz.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_uz.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_uz.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_vi.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_vi.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_vi.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_vi.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_zh-CN.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_zh-CN.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_zh-CN.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_zh-CN.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_zh-HK.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_zh-HK.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_zh-HK.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_zh-HK.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_zh-TW.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_zh-TW.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_zh-TW.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_zh-TW.xtb
diff --git a/ash/shortcut_viewer/strings/ash_components_strings_zu.xtb b/ash/shortcut_viewer/strings/shortcut_viewer_strings_zu.xtb
similarity index 100%
rename from ash/shortcut_viewer/strings/ash_components_strings_zu.xtb
rename to ash/shortcut_viewer/strings/shortcut_viewer_strings_zu.xtb
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
index 57ca318..c9261d8 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_item_view.cc
@@ -9,7 +9,7 @@
 
 #include "ash/shortcut_viewer/keyboard_shortcut_item.h"
 #include "ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
-#include "ash/shortcut_viewer/strings/grit/ash_components_strings.h"
+#include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "ash/shortcut_viewer/vector_icons/vector_icons.h"
 #include "ash/shortcut_viewer/views/bubble_view.h"
 #include "base/i18n/rtl.h"
diff --git a/ash/shortcut_viewer/views/keyboard_shortcut_view.cc b/ash/shortcut_viewer/views/keyboard_shortcut_view.cc
index 1efc4e92..d63a4b4 100644
--- a/ash/shortcut_viewer/views/keyboard_shortcut_view.cc
+++ b/ash/shortcut_viewer/views/keyboard_shortcut_view.cc
@@ -18,7 +18,7 @@
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shell.h"
 #include "ash/shortcut_viewer/keyboard_shortcut_viewer_metadata.h"
-#include "ash/shortcut_viewer/strings/grit/ash_components_strings.h"
+#include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "ash/shortcut_viewer/vector_icons/vector_icons.h"
 #include "ash/shortcut_viewer/views/keyboard_shortcut_item_list_view.h"
 #include "ash/shortcut_viewer/views/keyboard_shortcut_item_view.h"
diff --git a/ash/shortcut_viewer/views/ksv_search_box_view.cc b/ash/shortcut_viewer/views/ksv_search_box_view.cc
index 8d6b74d..d876581f 100644
--- a/ash/shortcut_viewer/views/ksv_search_box_view.cc
+++ b/ash/shortcut_viewer/views/ksv_search_box_view.cc
@@ -4,7 +4,7 @@
 
 #include "ash/shortcut_viewer/views/ksv_search_box_view.h"
 
-#include "ash/shortcut_viewer/strings/grit/ash_components_strings.h"
+#include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "ash/shortcut_viewer/vector_icons/vector_icons.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ash/strings/BUILD.gn b/ash/strings/BUILD.gn
index c637fc4..f4a002f0 100644
--- a/ash/strings/BUILD.gn
+++ b/ash/strings/BUILD.gn
@@ -79,7 +79,7 @@
   repack(target_name) {
     # Each input pak file should also have a deps line for completeness.
     sources = [
-      "$root_gen_dir/ash/shortcut_viewer/strings/ash_components_strings_${locale}.pak",
+      "$root_gen_dir/ash/shortcut_viewer/strings/shortcut_viewer_strings_${locale}.pak",
       "$root_gen_dir/ash/strings/ash_strings_${locale}.pak",
       "$root_gen_dir/chromeos/strings/chromeos_strings_${locale}.pak",
       "$root_gen_dir/components/strings/components_strings_${locale}.pak",
diff --git a/ash/system/palette/palette_tray_unittest.cc b/ash/system/palette/palette_tray_unittest.cc
index 5d8ea73..4ac4b1f 100644
--- a/ash/system/palette/palette_tray_unittest.cc
+++ b/ash/system/palette/palette_tray_unittest.cc
@@ -342,7 +342,7 @@
   assistant_state()->NotifyFeatureAllowed(
       chromeos::assistant::AssistantAllowedState::ALLOWED);
   assistant_state()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
   prefs()->SetBoolean(chromeos::assistant::prefs::kAssistantEnabled, true);
   prefs()->SetBoolean(chromeos::assistant::prefs::kAssistantContextEnabled,
                       true);
@@ -459,7 +459,7 @@
 
   // Once the service is ready, the button should start working.
   assistant_state()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   // Press and drag with no button, still no highlighter.
   WaitDragAndAssertMetalayer("all enabled, no button ", origin, ui::EF_NONE,
diff --git a/ash/system/palette/tools/metalayer_unittest.cc b/ash/system/palette/tools/metalayer_unittest.cc
index 57cce029b..f87f87b4 100644
--- a/ash/system/palette/tools/metalayer_unittest.cc
+++ b/ash/system/palette/tools/metalayer_unittest.cc
@@ -72,7 +72,7 @@
 TEST_F(MetalayerToolTest, PaletteMenuState) {
   const chromeos::assistant::AssistantStatus kStates[] = {
       chromeos::assistant::AssistantStatus::NOT_READY,
-      chromeos::assistant::AssistantStatus::READY};
+      chromeos::assistant::AssistantStatus::NEW_READY};
   const chromeos::assistant::AssistantAllowedState kAllowedStates[] = {
       chromeos::assistant::AssistantAllowedState::ALLOWED,
       chromeos::assistant::AssistantAllowedState::DISALLOWED_BY_POLICY,
@@ -177,7 +177,7 @@
               DisableTool(PaletteToolId::METALAYER))
       .Times(0);
   assistant_state()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
   testing::Mock::VerifyAndClearExpectations(palette_tool_delegate_.get());
 
   // Changing the state to NOT_READY should disable the tool.
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 5e899daa..7dbd6ff 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -74,6 +74,7 @@
 #include "ui/events/gesture_detection/gesture_configuration.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/views/background.h"
+#include "ui/views/controls/button/button.h"
 #include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 #include "ui/views/window/client_view.h"
@@ -404,12 +405,13 @@
   // new desk button is enabled.
   DCHECK(desks_bar_view);
   EXPECT_TRUE(desks_bar_view->mini_views().empty());
-  EXPECT_TRUE(desks_bar_view->new_desk_button()->GetEnabled());
+  auto* new_desk_button = desks_bar_view->new_desk_button();
+  EXPECT_TRUE(new_desk_button->GetEnabled());
 
   // Click many times on the new desk button and expect only the max number of
   // desks will be created, and the button is no longer enabled.
   const gfx::Point button_center =
-      desks_bar_view->new_desk_button()->GetBoundsInScreen().CenterPoint();
+      new_desk_button->GetBoundsInScreen().CenterPoint();
 
   auto* event_generator = GetEventGenerator();
   event_generator->MoveMouseTo(button_center);
@@ -421,7 +423,8 @@
   EXPECT_EQ(controller->desks().size(), desks_bar_view->mini_views().size());
   EXPECT_FALSE(controller->CanCreateDesks());
   EXPECT_TRUE(controller->CanRemoveDesks());
-  EXPECT_FALSE(desks_bar_view->new_desk_button()->GetEnabled());
+  EXPECT_FALSE(new_desk_button->GetEnabled());
+  EXPECT_EQ(views::Button::STATE_DISABLED, new_desk_button->state());
 
   // Hover over one of the mini_views, and expect that the close button becomes
   // visible.
@@ -441,7 +444,8 @@
   EXPECT_EQ(desks_util::kMaxNumberOfDesks - 1, controller->desks().size());
   EXPECT_EQ(controller->desks().size(), desks_bar_view->mini_views().size());
   EXPECT_TRUE(controller->CanCreateDesks());
-  EXPECT_TRUE(desks_bar_view->new_desk_button()->GetEnabled());
+  EXPECT_TRUE(new_desk_button->GetEnabled());
+  EXPECT_EQ(views::Button::STATE_NORMAL, new_desk_button->state());
 
   // Exit overview mode and re-enter. Since we have more than one pre-existing
   // desks, their mini_views should be created upon construction of the desks
@@ -463,6 +467,31 @@
   EXPECT_TRUE(desks_bar_view->new_desk_button()->GetEnabled());
 }
 
+// Test that gesture taps do not reset the button state to normal when the
+// button is disabled. https://crbug.com/1084241.
+TEST_F(DesksTest, GestureTapOnNewDeskButton) {
+  auto* overview_controller = Shell::Get()->overview_controller();
+  overview_controller->StartOverview();
+  EXPECT_TRUE(overview_controller->InOverviewSession());
+
+  const auto* overview_grid =
+      GetOverviewGridForRoot(Shell::GetPrimaryRootWindow());
+
+  const auto* desks_bar_view = overview_grid->desks_bar_view();
+  DCHECK(desks_bar_view);
+  auto* new_desk_button = desks_bar_view->new_desk_button();
+  EXPECT_TRUE(new_desk_button->GetEnabled());
+
+  // Gesture tap multiple times on the new desk button until it's disabled, and
+  // verify the button state.
+  auto* event_generator = GetEventGenerator();
+  for (size_t i = 0; i < desks_util::kMaxNumberOfDesks + 2; ++i)
+    GestureTapOnView(new_desk_button, event_generator);
+
+  EXPECT_FALSE(new_desk_button->GetEnabled());
+  EXPECT_EQ(views::Button::STATE_DISABLED, new_desk_button->state());
+}
+
 TEST_F(DesksTest, DesksBarViewScreenLayoutTest) {
   UpdateDisplay("1600x1200");
   DesksController* controller = DesksController::Get();
diff --git a/ash/wm/overview/scoped_overview_hide_windows.cc b/ash/wm/overview/scoped_overview_hide_windows.cc
index b7dabf1..50b496c 100644
--- a/ash/wm/overview/scoped_overview_hide_windows.cc
+++ b/ash/wm/overview/scoped_overview_hide_windows.cc
@@ -13,11 +13,8 @@
     const std::vector<aura::Window*>& windows,
     bool force_hidden)
     : force_hidden_(force_hidden) {
-  for (auto* window : windows) {
-    window->AddObserver(this);
-    window_visibility_.emplace(window, window->IsVisible());
-    window->Hide();
-  }
+  for (auto* window : windows)
+    AddWindow(window);
 }
 
 ScopedOverviewHideWindows::~ScopedOverviewHideWindows() {
@@ -28,6 +25,20 @@
   }
 }
 
+void ScopedOverviewHideWindows::AddWindow(aura::Window* window) {
+  window->AddObserver(this);
+  window_visibility_.emplace(window, window->IsVisible());
+  window->Hide();
+}
+
+void ScopedOverviewHideWindows::RemoveWindow(aura::Window* window) {
+  DCHECK(base::Contains(window_visibility_, window));
+  window->RemoveObserver(this);
+  if (window_visibility_[window])
+    window->Show();
+  window_visibility_.erase(window);
+}
+
 void ScopedOverviewHideWindows::OnWindowDestroying(aura::Window* window) {
   window_visibility_.erase(window);
   window->RemoveObserver(this);
diff --git a/ash/wm/overview/scoped_overview_hide_windows.h b/ash/wm/overview/scoped_overview_hide_windows.h
index e7fd295b..12525c2 100644
--- a/ash/wm/overview/scoped_overview_hide_windows.h
+++ b/ash/wm/overview/scoped_overview_hide_windows.h
@@ -29,6 +29,9 @@
       delete;
   ~ScopedOverviewHideWindows() override;
 
+  void AddWindow(aura::Window* window);
+  void RemoveWindow(aura::Window* window);
+
   // aura::WindowObserver:
   void OnWindowDestroying(aura::Window* window) override;
   void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
diff --git a/ash/wm/overview/scoped_overview_transform_window.cc b/ash/wm/overview/scoped_overview_transform_window.cc
index a7b3978e..ae37682 100644
--- a/ash/wm/overview/scoped_overview_transform_window.cc
+++ b/ash/wm/overview/scoped_overview_transform_window.cc
@@ -98,16 +98,18 @@
 
     transient->SetProperty(kIsShowingInOverviewKey, true);
 
+    // Add this as |aura::WindowObserver| for observing |kHideInOverviewKey|
+    // property changes.
+    transient->AddObserver(this);
+
     // Hide transient children which have been specified to be hidden in
     // overview mode.
     if (transient != window && transient->GetProperty(kHideInOverviewKey))
       transient_children_to_hide.push_back(transient);
   }
 
-  if (!transient_children_to_hide.empty()) {
-    hidden_transient_children_ = std::make_unique<ScopedOverviewHideWindows>(
-        std::move(transient_children_to_hide), /*forced_hidden=*/true);
-  }
+  if (!transient_children_to_hide.empty())
+    AddHiddenTransientWindows(std::move(transient_children_to_hide));
 
   aura::client::GetTransientWindowClient()->AddObserver(this);
 
@@ -146,6 +148,7 @@
     transient->ClearProperty(kIsShowingInOverviewKey);
     DCHECK(event_targeting_blocker_map_.contains(transient));
     event_targeting_blocker_map_.erase(transient);
+    transient->RemoveObserver(this);
   }
 
   // Remove rounded corners and clipping.
@@ -454,6 +457,45 @@
       std::make_unique<aura::ScopedWindowEventTargetingBlocker>(
           transient_child);
   transient_child->SetProperty(kIsShowingInOverviewKey, true);
+
+  // Hide transient children which have been specified to be hidden in
+  // overview mode.
+  if (transient_child != window_ &&
+      transient_child->GetProperty(kHideInOverviewKey))
+    AddHiddenTransientWindows({transient_child});
+
+  // Add this as |aura::WindowObserver| for observing |kHideInOverviewKey|
+  // property changes.
+  transient_child->AddObserver(this);
+}
+
+void ScopedOverviewTransformWindow::OnWindowPropertyChanged(
+    aura::Window* window,
+    const void* key,
+    intptr_t old) {
+  if (key != kHideInOverviewKey)
+    return;
+
+  const auto current_value = window->GetProperty(kHideInOverviewKey);
+  if (current_value == old)
+    return;
+
+  if (current_value) {
+    AddHiddenTransientWindows({window});
+  } else {
+    hidden_transient_children_->RemoveWindow(window);
+  }
+}
+
+void ScopedOverviewTransformWindow::AddHiddenTransientWindows(
+    const std::vector<aura::Window*>& transient_windows) {
+  if (!hidden_transient_children_) {
+    hidden_transient_children_ = std::make_unique<ScopedOverviewHideWindows>(
+        std::move(transient_windows), /*forced_hidden=*/true);
+  } else {
+    for (auto* window : transient_windows)
+      hidden_transient_children_->AddWindow(window);
+  }
 }
 
 void ScopedOverviewTransformWindow::OnTransientChildWindowRemoved(
@@ -465,6 +507,7 @@
   transient_child->ClearProperty(kIsShowingInOverviewKey);
   DCHECK(event_targeting_blocker_map_.contains(transient_child));
   event_targeting_blocker_map_.erase(transient_child);
+  transient_child->RemoveObserver(this);
 }
 
 // static
diff --git a/ash/wm/overview/scoped_overview_transform_window.h b/ash/wm/overview/scoped_overview_transform_window.h
index 2eb5d21..7033671 100644
--- a/ash/wm/overview/scoped_overview_transform_window.h
+++ b/ash/wm/overview/scoped_overview_transform_window.h
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "ui/aura/client/transient_window_client_observer.h"
+#include "ui/aura/window_observer.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/geometry/size.h"
@@ -36,7 +37,8 @@
 // fit in certain bounds. The window's state is restored when this object is
 // destroyed.
 class ASH_EXPORT ScopedOverviewTransformWindow
-    : public aura::client::TransientWindowClientObserver {
+    : public aura::client::TransientWindowClientObserver,
+      public aura::WindowObserver {
  public:
   using ScopedAnimationSettings =
       std::vector<std::unique_ptr<ScopedOverviewAnimationSettings>>;
@@ -139,6 +141,11 @@
   void OnTransientChildWindowRemoved(aura::Window* parent,
                                      aura::Window* transient_child) override;
 
+  // aura::WindowObserver:
+  void OnWindowPropertyChanged(aura::Window* window,
+                               const void* key,
+                               intptr_t old) override;
+
   aura::Window* window() const { return window_; }
 
   OverviewGridWindowFillMode type() const { return type_; }
@@ -155,6 +162,12 @@
   // Closes the window managed by |this|.
   void CloseWidget();
 
+  // Adds transient windows that should be hidden to the hidden window list. The
+  // windows are hidden in overview mode and the visibility of the windows is
+  // recovered after overview mode.
+  void AddHiddenTransientWindows(
+      const std::vector<aura::Window*>& transient_windows);
+
   // A weak pointer to the overview item that owns |this|. Guaranteed to be not
   // null for the lifetime of |this|.
   OverviewItem* overview_item_;
diff --git a/ash/wm/overview/scoped_overview_transform_window_unittest.cc b/ash/wm/overview/scoped_overview_transform_window_unittest.cc
index 815b242..86d59b3a 100644
--- a/ash/wm/overview/scoped_overview_transform_window_unittest.cc
+++ b/ash/wm/overview/scoped_overview_transform_window_unittest.cc
@@ -268,6 +268,61 @@
   EXPECT_TRUE(child2->transform().IsIdentity());
 }
 
+// Tests that the transient window which should be invisible in overview is not
+// visible even if the window property is changed after initializing
+// ScopedOverviewTransformWindow.
+TEST_F(ScopedOverviewTransformWindowTest,
+       InvisibleTransientsPropertyChangeAfterInit) {
+  auto window = CreateTestWindow(gfx::Rect(200, 200));
+  auto child = CreateTestWindow(gfx::Rect(100, 190, 100, 10),
+                                aura::client::WINDOW_TYPE_POPUP);
+  ::wm::AddTransientChild(window.get(), child.get());
+
+  ScopedOverviewTransformWindow scoped_window(nullptr, window.get());
+  EXPECT_TRUE(window->IsVisible());
+  EXPECT_TRUE(child->IsVisible());
+
+  // Change property after construction of |scoped_window|.
+  child->SetProperty(kHideInOverviewKey, true);
+  EXPECT_TRUE(window->IsVisible());
+  EXPECT_FALSE(child->IsVisible());
+
+  // Clear property after construction of |scoped_window|.
+  child->ClearProperty(kHideInOverviewKey);
+  EXPECT_TRUE(window->IsVisible());
+  EXPECT_TRUE(child->IsVisible());
+
+  // Change to hide again.
+  child->SetProperty(kHideInOverviewKey, true);
+  EXPECT_TRUE(window->IsVisible());
+  EXPECT_FALSE(child->IsVisible());
+}
+
+// Tests that the transient window which should be invisible in overview is not
+// visible even if the window is added after initializing
+// ScopedOverviewTransformWindow.
+TEST_F(ScopedOverviewTransformWindowTest, InvisibleTransientsAddedAfterInit) {
+  auto window = CreateTestWindow(gfx::Rect(200, 200));
+  auto child = CreateTestWindow(gfx::Rect(100, 190, 100, 10),
+                                aura::client::WINDOW_TYPE_POPUP);
+  auto child2 = CreateTestWindow(gfx::Rect(0, 190, 100, 10),
+                                 aura::client::WINDOW_TYPE_POPUP);
+  child2->SetProperty(kHideInOverviewKey, true);
+
+  ScopedOverviewTransformWindow scoped_window(nullptr, window.get());
+
+  // Add visible transient after construction of |scoped_window|.
+  ::wm::AddTransientChild(window.get(), child.get());
+  EXPECT_TRUE(window->IsVisible());
+  EXPECT_TRUE(child->IsVisible());
+
+  // Add invisible transient after construction of |scoped_window|.
+  ::wm::AddTransientChild(window.get(), child2.get());
+  EXPECT_TRUE(window->IsVisible());
+  EXPECT_TRUE(child->IsVisible());
+  EXPECT_FALSE(child2->IsVisible());
+}
+
 // Tests that the event targeting policies of a given window and transient
 // descendants gets set as expected.
 TEST_F(ScopedOverviewTransformWindowTest, EventTargetingPolicy) {
diff --git a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
index daa618d..cde8a26 100644
--- a/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
+++ b/ash/wm/tablet_mode/tablet_mode_controller_unittest.cc
@@ -47,6 +47,7 @@
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/base/hit_test.h"
+#include "ui/compositor/layer_animator.h"
 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
 #include "ui/display/manager/display_manager.h"
 #include "ui/display/screen.h"
@@ -1774,10 +1775,39 @@
   EXPECT_TRUE(IsShelfOpaque());
 }
 
+namespace {
+
+class LayerStartAnimationWaiter : public ui::LayerAnimationObserver {
+ public:
+  explicit LayerStartAnimationWaiter(ui::LayerAnimator* animator)
+      : animator_(animator) {
+    animator_->AddObserver(this);
+    run_loop_.Run();
+  }
+  LayerStartAnimationWaiter(const LayerStartAnimationWaiter&) = delete;
+  LayerStartAnimationWaiter& operator=(const LayerStartAnimationWaiter&) =
+      delete;
+  ~LayerStartAnimationWaiter() override { animator_->RemoveObserver(this); }
+
+  // ui::LayerAnimationObserver:
+  void OnLayerAnimationStarted(ui::LayerAnimationSequence* sequence) override {
+    run_loop_.Quit();
+  }
+  void OnLayerAnimationEnded(ui::LayerAnimationSequence* sequence) override {}
+  void OnLayerAnimationAborted(ui::LayerAnimationSequence* sequence) override {}
+  void OnLayerAnimationScheduled(
+      ui::LayerAnimationSequence* sequence) override {}
+
+ private:
+  ui::LayerAnimator* animator_;
+  base::RunLoop run_loop_;
+};
+
+}  // namespace
+
 // Tests that the screenshot is visible when a window animation happens when
 // entering tablet mode.
-// Crashes on Linux Chrome OS.  http://crbug.com/1091085
-TEST_P(TabletModeControllerScreenshotTest, DISABLED_ScreenshotVisibility) {
+TEST_P(TabletModeControllerScreenshotTest, ScreenshotVisibility) {
   auto window = CreateTestWindow(gfx::Rect(200, 200));
   auto window2 = CreateTestWindow(gfx::Rect(300, 200));
 
@@ -1786,27 +1816,23 @@
   ASSERT_FALSE(IsScreenshotShown());
   EXPECT_TRUE(IsShelfOpaque());
 
-  TabletMode::Waiter waiter(/*enable=*/true);
   SetTabletMode(true);
   EXPECT_FALSE(IsScreenshotShown());
   EXPECT_FALSE(IsShelfOpaque());
 
-  EXPECT_FALSE(window2->layer()->GetAnimator()->is_animating());
-  // The layer we observer is actually the windows layer before starting the
+  // The layer we observe is actually the windows layer before starting the
   // animation. The animation performed is a cross-fade animation which
   // copies the window layer to another layer host. So cache them here for
-  // later use.
-  ui::Layer* old_layer = window2->layer();
-
-  // Tests that after waiting for the async tablet mode entry, the screenshot is
-  // shown.
-  waiter.Wait();
+  // later use. Wait until the animation has started, at this point the
+  // screenshot should be visible.
+  ui::LayerAnimator* old_animator = window2->layer()->GetAnimator();
+  ASSERT_FALSE(old_animator->is_animating());
+  { LayerStartAnimationWaiter waiter(old_animator); }
   EXPECT_TRUE(IsScreenshotShown());
-  EXPECT_TRUE(window2->layer()->GetAnimator()->is_animating());
   EXPECT_TRUE(IsShelfOpaque());
 
   // Tests that the screenshot is destroyed after the window is done animating.
-  old_layer->GetAnimator()->StopAnimating();
+  old_animator->StopAnimating();
   window2->layer()->GetAnimator()->StopAnimating();
   EXPECT_FALSE(IsScreenshotShown());
   EXPECT_TRUE(IsShelfOpaque());
diff --git a/base/BUILD.gn b/base/BUILD.gn
index feb30e90..a09c065ab 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -3585,6 +3585,7 @@
       "android/javatests/src/org/chromium/base/AdvancedMockContextTest.java",
       "android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java",
       "android/javatests/src/org/chromium/base/AssertsTest.java",
+      "android/javatests/src/org/chromium/base/CommandLineFlagsTest.java",
       "android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java",
       "android/javatests/src/org/chromium/base/CommandLineTest.java",
       "android/javatests/src/org/chromium/base/EarlyTraceEventTest.java",
@@ -3649,7 +3650,6 @@
       "test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java",
       "test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java",
       "test/android/javatests/src/org/chromium/base/test/BaseJUnit4TestRule.java",
-      "test/android/javatests/src/org/chromium/base/test/BaseTestResult.java",
       "test/android/javatests/src/org/chromium/base/test/BundleTestRule.java",
       "test/android/javatests/src/org/chromium/base/test/DestroyActivitiesRule.java",
       "test/android/javatests/src/org/chromium/base/test/LifetimeAssertRule.java",
diff --git a/base/allocator/partition_allocator/address_pool_manager.cc b/base/allocator/partition_allocator/address_pool_manager.cc
index 59767b1..2b656c1 100644
--- a/base/allocator/partition_allocator/address_pool_manager.cc
+++ b/base/allocator/partition_allocator/address_pool_manager.cc
@@ -24,18 +24,17 @@
   return instance.get();
 }
 
-pool_handle AddressPoolManager::Add(const void* ptr,
+pool_handle AddressPoolManager::Add(uintptr_t ptr,
                                     size_t length,
                                     size_t align) {
   DCHECK(base::bits::IsPowerOfTwo(align));
   const uintptr_t align_offset_mask = align - 1;
-  const uintptr_t ptr_as_uintptr = reinterpret_cast<uintptr_t>(ptr);
-  DCHECK(!(ptr_as_uintptr & align_offset_mask));
-  DCHECK(!((ptr_as_uintptr + length) & align_offset_mask));
+  DCHECK(!(ptr & align_offset_mask));
+  DCHECK(!((ptr + length) & align_offset_mask));
 
   for (pool_handle i = 0; i < base::size(pools_); ++i) {
     if (!pools_[i]) {
-      pools_[i] = std::make_unique<Pool>(ptr_as_uintptr, length, align);
+      pools_[i] = std::make_unique<Pool>(ptr, length, align);
       return i + 1;
     }
   }
@@ -53,11 +52,11 @@
   pools_[handle - 1].reset();
 }
 
-void* AddressPoolManager::Alloc(pool_handle handle, size_t length) {
+char* AddressPoolManager::Alloc(pool_handle handle, size_t length) {
   DCHECK(0 < handle && handle <= kNumPools);
   Pool* pool = pools_[handle - 1].get();
   DCHECK(pool);
-  return pool->FindChunk(length);
+  return reinterpret_cast<char*>(pool->FindChunk(length));
 }
 
 void AddressPoolManager::Free(pool_handle handle, void* ptr, size_t length) {
@@ -81,7 +80,7 @@
 #endif
 }
 
-void* AddressPoolManager::Pool::FindChunk(size_t requested_size) {
+uintptr_t AddressPoolManager::Pool::FindChunk(size_t requested_size) {
   base::AutoLock scoped_lock(lock_);
 
   const uintptr_t align_offset_mask = align_ - 1;
@@ -99,7 +98,7 @@
     }
   }
   if (!chosen_chunk)
-    return nullptr;
+    return 0;
 
   free_chunks_.erase(chosen_chunk);
   if (chosen_chunk_size > required_size) {
@@ -115,7 +114,7 @@
   DCHECK_LE(address_begin_, chosen_chunk);
   DCHECK_LE(chosen_chunk + required_size, address_end_);
 #endif
-  return reinterpret_cast<void*>(chosen_chunk);
+  return chosen_chunk;
 }
 
 void AddressPoolManager::Pool::FreeChunk(uintptr_t address, size_t free_size) {
diff --git a/base/allocator/partition_allocator/address_pool_manager.h b/base/allocator/partition_allocator/address_pool_manager.h
index 2c114bff..fba79a83 100644
--- a/base/allocator/partition_allocator/address_pool_manager.h
+++ b/base/allocator/partition_allocator/address_pool_manager.h
@@ -6,6 +6,7 @@
 #define BASE_ALLOCATOR_PARTITION_ALLOCATOR_ADDRESS_POOL_MANAGER_H_
 
 #include <map>
+#include <memory>
 
 #include "base/allocator/partition_allocator/partition_alloc_constants.h"
 #include "base/atomicops.h"
@@ -33,9 +34,9 @@
  public:
   static AddressPoolManager* GetInstance();
 
-  pool_handle Add(const void* address, size_t length, size_t align);
+  pool_handle Add(uintptr_t address, size_t length, size_t align);
   void Remove(pool_handle handle);
-  void* Alloc(pool_handle handle, size_t length);
+  char* Alloc(pool_handle handle, size_t length);
   void Free(pool_handle handle, void* ptr, size_t length);
   void ResetForTesting();
 
@@ -50,7 +51,7 @@
     Pool(uintptr_t ptr, size_t length, size_t align);
     ~Pool();
 
-    void* FindChunk(size_t size);
+    uintptr_t FindChunk(size_t size);
     void FreeChunk(uintptr_t address, size_t size);
 
    private:
diff --git a/base/allocator/partition_allocator/partition_address_space.cc b/base/allocator/partition_allocator/partition_address_space.cc
index 7d261a74..12d860d5 100644
--- a/base/allocator/partition_allocator/partition_address_space.cc
+++ b/base/allocator/partition_allocator/partition_address_space.cc
@@ -15,28 +15,51 @@
 
 #if defined(ARCH_CPU_64_BITS)
 
-constexpr size_t PartitionAddressSpace::kGigaBytes;
-constexpr size_t PartitionAddressSpace::kDirectMapPoolSize;
-constexpr size_t PartitionAddressSpace::kNormalBucketPoolSize;
-constexpr size_t PartitionAddressSpace::kReservedAddressSpaceSize;
+static_assert(sizeof(size_t) >= 8, "Need 64-bit address space");
+static_assert(
+    bits::IsPowerOfTwo(PartitionAddressSpace::kReservedAddressSpaceAlignment),
+    "kReservedAddressSpaceALignment should be a power of two.");
+static_assert(PartitionAddressSpace::kReservedAddressSpaceAlignment >=
+                  PartitionAddressSpace::kDesiredAddressSpaceSize,
+              "kReservedAddressSpaceAlignment should be larger or equal to "
+              "kDesiredAddressSpaceSize.");
+static_assert(PartitionAddressSpace::kReservedAddressSpaceAlignment / 2 <
+                  PartitionAddressSpace::kDesiredAddressSpaceSize,
+              "kReservedAddressSpaceAlignment should be the smallest power of "
+              "two greater or equal to kDesiredAddressSpaceSize. So a half of "
+              "the alignment should be smaller than the desired size.");
+static_assert(PartitionAddressSpace::kReservedAddressSpaceSize >
+                  PartitionAddressSpace::kReservedAddressSpaceAlignment,
+              "kReservedAddressSpaceSize should be larger than "
+              "kReservedAddressSpaceAlignment.");
 
-// static
-PartitionAddressSpace* PartitionAddressSpace::Instance() {
-  static NoDestructor<PartitionAddressSpace> instance;
-  return instance.get();
-}
+uintptr_t PartitionAddressSpace::reserved_address_start_ = 0;
+// Before PartitionAddressSpace::Init(), no allocation are allocated from a
+// reserved address space. So initially make reserved_base_address_ to
+// be kReservedAddressSpaceOffsetMask. So PartitionAddressSpace::Contains()
+// always returns false.
+uintptr_t PartitionAddressSpace::reserved_base_address_ =
+    kReservedAddressSpaceOffsetMask;
+
+pool_handle PartitionAddressSpace::direct_map_pool_ = 0;
+pool_handle PartitionAddressSpace::normal_bucket_pool_ = 0;
 
 void PartitionAddressSpace::Init() {
-  reserved_address_start_ = reinterpret_cast<char*>(SystemAllocPages(
+  DCHECK(!reserved_address_start_);
+  reserved_address_start_ = reinterpret_cast<uintptr_t>(SystemAllocPages(
       nullptr, kReservedAddressSpaceSize, base::PageInaccessible,
       PageTag::kPartitionAlloc, false));
-  DCHECK(reserved_address_start_);
-  reserved_address_end_ = reserved_address_start_ + kReservedAddressSpaceSize;
+  CHECK(reserved_address_start_);
 
-  char* current = reinterpret_cast<char*>(bits::Align(
-      reinterpret_cast<uintptr_t>(reserved_address_start_), kSuperPageSize));
-  DCHECK_GE(current, reserved_address_start_);
-  DCHECK(!(reinterpret_cast<uintptr_t>(current) & kSuperPageOffsetMask));
+  const uintptr_t reserved_address_end =
+      reserved_address_start_ + kReservedAddressSpaceSize;
+
+  reserved_base_address_ =
+      bits::Align(reserved_address_start_, kReservedAddressSpaceAlignment);
+  DCHECK_GE(reserved_base_address_, reserved_address_start_);
+  DCHECK(!(reserved_base_address_ & kReservedAddressSpaceOffsetMask));
+
+  uintptr_t current = reserved_base_address_;
 
   direct_map_pool_ = internal::AddressPoolManager::GetInstance()->Add(
       current, kDirectMapPoolSize, kSuperPageSize);
@@ -47,17 +70,18 @@
       current, kNormalBucketPoolSize, kSuperPageSize);
   DCHECK(normal_bucket_pool_);
   current += kNormalBucketPoolSize;
-  DCHECK_LE(current, reserved_address_end_);
+  DCHECK_LE(current, reserved_address_end);
+  DCHECK_EQ(current, reserved_base_address_ + kDesiredAddressSpaceSize);
 }
 
 void PartitionAddressSpace::UninitForTesting() {
   DCHECK(reserved_address_start_);
-  DCHECK(reserved_address_end_);
-  FreePages(reserved_address_start_,
-            reserved_address_end_ - reserved_address_start_);
-  reserved_address_start_ = nullptr;
-  reserved_address_end_ = nullptr;
+  FreePages(reinterpret_cast<void*>(reserved_address_start_),
+            kReservedAddressSpaceSize);
+  reserved_address_start_ = 0;
+  reserved_base_address_ = kReservedAddressSpaceOffsetMask;
   direct_map_pool_ = 0;
+  normal_bucket_pool_ = 0;
   internal::AddressPoolManager::GetInstance()->ResetForTesting();
 }
 
diff --git a/base/allocator/partition_allocator/partition_address_space.h b/base/allocator/partition_allocator/partition_address_space.h
index 153287f9..65181ec 100644
--- a/base/allocator/partition_allocator/partition_address_space.h
+++ b/base/allocator/partition_allocator/partition_address_space.h
@@ -9,6 +9,7 @@
 #include "base/allocator/partition_allocator/partition_alloc_constants.h"
 #include "base/allocator/partition_allocator/partition_alloc_features.h"
 #include "base/base_export.h"
+#include "base/bits.h"
 #include "base/feature_list.h"
 #include "base/notreached.h"
 #include "build/build_config.h"
@@ -20,35 +21,40 @@
 // The address space reservation is supported only on 64-bit architecture.
 #if defined(ARCH_CPU_64_BITS)
 
-static_assert(sizeof(size_t) >= 8, "Need 64-bit address space");
-
 // Reserves address space for PartitionAllocator.
 class BASE_EXPORT PartitionAddressSpace {
  public:
-  static PartitionAddressSpace* Instance();
-
-  internal::pool_handle GetDirectMapPool() { return direct_map_pool_; }
-  internal::pool_handle GetNormalBucketPool() { return normal_bucket_pool_; }
-
-  void Init();
-  void UninitForTesting();
-
-  // TODO(tasak): This method should be as cheap as possible. So we can make
-  // this cheaper since the range size is a power of two, but just checking that
-  // the high order bits of the address are the right ones.
-  bool Contains(const void* address) const {
-    return reserved_address_start_ <= address &&
-           address < reserved_address_end_;
+  static ALWAYS_INLINE internal::pool_handle GetDirectMapPool() {
+    return direct_map_pool_;
+  }
+  static ALWAYS_INLINE internal::pool_handle GetNormalBucketPool() {
+    return normal_bucket_pool_;
   }
 
- private:
+  static void Init();
+  static void UninitForTesting();
+
+  static ALWAYS_INLINE bool Contains(const void* address) {
+    return (reinterpret_cast<uintptr_t>(address) &
+            kReservedAddressSpaceBaseMask) == reserved_base_address_;
+  }
+
+  // PartitionAddressSpace is static_only class.
+  PartitionAddressSpace() = delete;
+  PartitionAddressSpace(const PartitionAddressSpace&) = delete;
+  void* operator new(size_t) = delete;
+  void* operator new(size_t, void*) = delete;
+
   // Partition Alloc Address Space
-  // Reserves 32Gbytes address space for 1 direct map space(16G) and 1 normal
-  // bucket space(16G).
+  // Reserves 64Gbytes address space for 1 direct map space(16G) and 1 normal
+  // bucket space(16G). The remaining 32G is for padding, so that we can
+  // guarantee a 32G alignment somewhere within the reserved region. Address
+  // space is cheap and abundant on 64-bit systems.
+  // TODO(tasak): release unused address space.
   //
   // +----------------+ reserved address start
   // |  (unused)      |
-  // +----------------+ kSuperPageSize-aligned reserved address: X
+  // +----------------+ 32G-aligned reserved address: X
   // |                |
   // |  direct map    |
   // |    space       |
@@ -59,30 +65,46 @@
   // +----------------+ X + 32G bytes
   // | (unused)       |
   // +----------------+ reserved address end
+  //
+  // The static member variables:
+  // - reserved_address_starts_ points the "reserved address start" address, and
+  // - reserved_base_address_ points the "32G-aligned reserved address: X".
 
   static constexpr size_t kGigaBytes = 1024 * 1024 * 1024;
   static constexpr size_t kDirectMapPoolSize = 16 * kGigaBytes;
   static constexpr size_t kNormalBucketPoolSize = 16 * kGigaBytes;
-  // kSuperPageSize padding is added to be able to align to kSuperPageSize
-  // boundary.
+  // Reserves 32GB aligned address space.
+  // Alignment should be the smallest power of two greater than or equal to the
+  // desired size, so that we can check containment with a single bitmask
+  // operation.
+  static constexpr size_t kDesiredAddressSpaceSize =
+      kDirectMapPoolSize + kNormalBucketPoolSize;
+  static constexpr size_t kReservedAddressSpaceAlignment =
+      kDesiredAddressSpaceSize;
   static constexpr size_t kReservedAddressSpaceSize =
-      kDirectMapPoolSize + kNormalBucketPoolSize + kSuperPageSize;
+      kReservedAddressSpaceAlignment * 2;
+  static constexpr uintptr_t kReservedAddressSpaceOffsetMask =
+      static_cast<uintptr_t>(kReservedAddressSpaceAlignment) - 1;
+  static constexpr uintptr_t kReservedAddressSpaceBaseMask =
+      ~kReservedAddressSpaceOffsetMask;
 
-  char* reserved_address_start_;
-  char* reserved_address_end_;
+ private:
+  // See the comment describing the address layout above.
+  static uintptr_t reserved_address_start_;
+  static uintptr_t reserved_base_address_;
 
-  internal::pool_handle direct_map_pool_;
-  internal::pool_handle normal_bucket_pool_;
+  static internal::pool_handle direct_map_pool_;
+  static internal::pool_handle normal_bucket_pool_;
 };
 
 ALWAYS_INLINE internal::pool_handle GetDirectMapPool() {
   DCHECK(IsPartitionAllocGigaCageEnabled());
-  return PartitionAddressSpace::Instance()->GetDirectMapPool();
+  return PartitionAddressSpace::GetDirectMapPool();
 }
 
 ALWAYS_INLINE internal::pool_handle GetNormalBucketPool() {
   DCHECK(IsPartitionAllocGigaCageEnabled());
-  return PartitionAddressSpace::Instance()->GetNormalBucketPool();
+  return PartitionAddressSpace::GetNormalBucketPool();
 }
 
 #else  // !defined(ARCH_CPU_64_BITS)
diff --git a/base/allocator/partition_allocator/partition_alloc.cc b/base/allocator/partition_allocator/partition_alloc.cc
index 6c3ffbd2..dfb47cd 100644
--- a/base/allocator/partition_allocator/partition_alloc.cc
+++ b/base/allocator/partition_allocator/partition_alloc.cc
@@ -10,7 +10,6 @@
 #include <type_traits>
 
 #include "base/allocator/partition_allocator/page_allocator_internal.h"
-#include "base/allocator/partition_allocator/partition_address_space.h"
 #include "base/allocator/partition_allocator/partition_alloc_features.h"
 #include "base/allocator/partition_allocator/partition_direct_map_extent.h"
 #include "base/allocator/partition_allocator/partition_oom.h"
@@ -206,14 +205,14 @@
 #if defined(ARCH_CPU_64_BITS)
   // Reserve address space for partition alloc.
   if (IsPartitionAllocGigaCageEnabled())
-    internal::PartitionAddressSpace::Instance()->Init();
+    internal::PartitionAddressSpace::Init();
 #endif
 }
 
 void PartitionAllocGlobalUninitForTesting() {
 #if defined(ARCH_CPU_64_BITS)
   if (IsPartitionAllocGigaCageEnabled())
-    internal::PartitionAddressSpace::Instance()->UninitForTesting();
+    internal::PartitionAddressSpace::UninitForTesting();
 #endif
   internal::g_oom_handling_function = nullptr;
 }
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index d777bee6..029ba1b 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -65,6 +65,7 @@
 
 #include "base/allocator/partition_allocator/memory_reclaimer.h"
 #include "base/allocator/partition_allocator/page_allocator.h"
+#include "base/allocator/partition_allocator/partition_address_space.h"
 #include "base/allocator/partition_allocator/partition_alloc_constants.h"
 #include "base/allocator/partition_allocator/partition_bucket.h"
 #include "base/allocator/partition_allocator/partition_cookie.h"
@@ -426,6 +427,14 @@
   PartitionRootGeneric partition_root_;
 };
 
+ALWAYS_INLINE bool IsManagedByPartitionAlloc(const void* address) {
+#if defined(ARCH_CPU_64_BITS)
+  return internal::PartitionAddressSpace::Contains(address);
+#else
+  return false;
+#endif
+}
+
 }  // namespace base
 
 #endif  // BASE_ALLOCATOR_PARTITION_ALLOCATOR_PARTITION_ALLOC_H_
diff --git a/base/allocator/partition_allocator/partition_alloc_constants.h b/base/allocator/partition_allocator/partition_alloc_constants.h
index 35348a71..4d3b7a5 100644
--- a/base/allocator/partition_allocator/partition_alloc_constants.h
+++ b/base/allocator/partition_allocator/partition_alloc_constants.h
@@ -64,9 +64,12 @@
 // We reserve virtual address space in 2 MiB chunks (aligned to 2 MiB as well).
 // These chunks are called *super pages*. We do this so that we can store
 // metadata in the first few pages of each 2 MiB-aligned section. This makes
-// freeing memory very fast. We specifically choose 2 MiB because this virtual
-// address block represents a full but single PTE allocation on ARM, ia32 and
-// x64.
+// freeing memory very fast. 2 MiB size & alignment were chosen, because this
+// virtual address block represents a full but single page table allocation on
+// ARM, ia32 and x64, which may be slightly more performance&memory efficient.
+// (Note, these super pages are backed by 4 KiB system pages and have nothing to
+// do with OS concept of "huge pages"/"large pages", even though the size
+// coincides.)
 //
 // The layout of the super page is as follows. The sizes below are the same for
 // 32- and 64-bit platforms.
@@ -79,16 +82,20 @@
 //     | Slot span             |
 //     | ...                   |
 //     | Slot span             |
-//     | Guard page (4 KiB)    |
+//     | Guard pages (16 KiB)  |
 //     +-----------------------+
 //
-// Each slot span is a contiguous range of one or more `PartitionPage`s.
+// Each slot span is a contiguous range of one or more `PartitionPage`s. Note
+// that slot spans of different sizes may co-exist with one super page. Even
+// slot spans of the same size may support different slot sizes. However, all
+// slots within a span have to be of the same size.
 //
 // The metadata page has the following format. Note that the `PartitionPage`
-// that is not at the head of a slot span is "unused". In other words, the
-// metadata for the slot span is stored only in the first `PartitionPage` of the
-// slot span. Metadata accesses to other `PartitionPage`s are redirected to the
-// first `PartitionPage`.
+// that is not at the head of a slot span is "unused" (by most part, it only
+// stores the offset from the head page). In other words, the metadata for the
+// slot span is stored only in the first `PartitionPage` of the slot span.
+// Metadata accesses to other `PartitionPage`s are redirected to the first
+// `PartitionPage`.
 //
 //     +---------------------------------------------+
 //     | SuperPageExtentEntry (32 B)                 |
@@ -98,28 +105,30 @@
 //     | PartitionPage of slot span 2 (32 B, used)   |
 //     | PartitionPage of slot span 3 (32 B, used)   |
 //     | ...                                         |
+//     | PartitionPage of slot span N (32 B, used)   |
+//     | PartitionPage of slot span N (32 B, unused) |
 //     | PartitionPage of slot span N (32 B, unused) |
 //     +---------------------------------------------+
 //
-// A direct-mapped page has a similar layout to fake it looking like a super
-// page:
+// A direct-mapped page has an identical layout at the beginning to fake it
+// looking like a super page:
 //
-//     +-----------------------+
-//     | Guard page (4 KiB)    |
-//     | Metadata page (4 KiB) |
-//     | Guard pages (8 KiB)   |
-//     | Direct mapped object  |
-//     | Guard page (4 KiB)    |
-//     +-----------------------+
+//     +---------------------------------+
+//     | Guard page (4 KiB)              |
+//     | Metadata page (4 KiB)           |
+//     | Guard pages (8 KiB)             |
+//     | Direct mapped object            |
+//     | Guard page (4 KiB, 32-bit only) |
+//     +---------------------------------+
 //
 // A direct-mapped page's metadata page has the following layout:
 //
-//     +--------------------------------+
-//     | SuperPageExtentEntry (32 B)    |
-//     | PartitionPage (32 B)           |
-//     | PartitionBucket (32 B)         |
-//     | PartitionDirectMapExtent (8 B) |
-//     +--------------------------------+
+//     +---------------------------------+
+//     | SuperPageExtentEntry (32 B)     |
+//     | PartitionPage (32 B)            |
+//     | PartitionBucket (32 B)          |
+//     | PartitionDirectMapExtent (32 B) |
+//     +---------------------------------+
 
 static const size_t kSuperPageShift = 21;  // 2 MiB
 static const size_t kSuperPageSize = 1 << kSuperPageShift;
diff --git a/base/allocator/partition_allocator/partition_bucket.cc b/base/allocator/partition_allocator/partition_bucket.cc
index fabcf8df..b569282 100644
--- a/base/allocator/partition_allocator/partition_bucket.cc
+++ b/base/allocator/partition_allocator/partition_bucket.cc
@@ -24,8 +24,8 @@
 
 char* CommitPages(internal::pool_handle pool, size_t map_size) {
 #if defined(ARCH_CPU_64_BITS)
-  char* ptr = reinterpret_cast<char*>(
-      internal::AddressPoolManager::GetInstance()->Alloc(pool, map_size));
+  char* ptr =
+      internal::AddressPoolManager::GetInstance()->Alloc(pool, map_size);
   if (UNLIKELY(!ptr))
     return nullptr;
   DCHECK(!(map_size & kSystemPageOffsetMask));
diff --git a/base/allocator/partition_allocator/partition_page.cc b/base/allocator/partition_allocator/partition_page.cc
index 1386015..52908faa 100644
--- a/base/allocator/partition_allocator/partition_page.cc
+++ b/base/allocator/partition_allocator/partition_page.cc
@@ -5,7 +5,7 @@
 #include "base/allocator/partition_allocator/partition_page.h"
 
 #include "base/allocator/partition_allocator/address_pool_manager.h"
-#include "base/allocator/partition_allocator/partition_address_space.h"
+#include "base/allocator/partition_allocator/partition_alloc.h"
 #include "base/allocator/partition_allocator/partition_alloc_features.h"
 #include "base/allocator/partition_allocator/partition_direct_map_extent.h"
 #include "base/allocator/partition_allocator/partition_root_base.h"
@@ -201,7 +201,7 @@
 
 void DeferredUnmap::Unmap() {
   DCHECK(ptr && size > 0);
-  if (IsPartitionAllocGigaCageEnabled()) {
+  if (IsManagedByPartitionAlloc(ptr)) {
     DecommitPages(ptr, size);
   } else {
     FreePages(ptr, size);
diff --git a/base/allocator/partition_allocator/partition_page.h b/base/allocator/partition_allocator/partition_page.h
index cc04e78f..b99d33f 100644
--- a/base/allocator/partition_allocator/partition_page.h
+++ b/base/allocator/partition_allocator/partition_page.h
@@ -140,6 +140,7 @@
   return reinterpret_cast<char*>(pointer_as_uint + kSystemPageSize);
 }
 
+// See the comment for |FromPointer|.
 template <bool thread_safe>
 ALWAYS_INLINE PartitionPage<thread_safe>*
 PartitionPage<thread_safe>::FromPointerNoAlignmentCheck(void* ptr) {
@@ -148,22 +149,25 @@
       reinterpret_cast<char*>(pointer_as_uint & kSuperPageBaseMask);
   uintptr_t partition_page_index =
       (pointer_as_uint & kSuperPageOffsetMask) >> kPartitionPageShift;
-  // Index 0 is invalid because it is the metadata and guard area and
-  // the last index is invalid because it is a guard page.
+  // Index 0 is invalid because it is the super page extent metadata and the
+  // last index is invalid because the whole PartitionPage is set as guard
+  // pages.
   DCHECK(partition_page_index);
   DCHECK(partition_page_index < kNumPartitionPagesPerSuperPage - 1);
   auto* page = reinterpret_cast<PartitionPage*>(
       PartitionSuperPageToMetadataArea(super_page_ptr) +
       (partition_page_index << kPageMetadataShift));
-  // Partition pages in the same slot span can share the same page object.
-  // Adjust for that.
+  // Partition pages in the same slot span share the same page object. Adjust
+  // for that.
   size_t delta = page->page_offset << kPageMetadataShift;
   page =
       reinterpret_cast<PartitionPage*>(reinterpret_cast<char*>(page) - delta);
   return page;
 }
 
-// Returns: start of the slot span for the PartitionPage.
+// Converts from a pointer to the PartitionPage object (within super pages's
+// metadata) into a pointer to the beginning of the partition page.
+// This doesn't have to be the first page in the slot span.
 template <bool thread_safe>
 ALWAYS_INLINE void* PartitionPage<thread_safe>::ToPointer(
     const PartitionPage<thread_safe>* page) {
@@ -179,9 +183,9 @@
                                                 kPageMetadataSize));
   uintptr_t partition_page_index =
       (super_page_offset - kSystemPageSize) >> kPageMetadataShift;
-  // Index 0 is invalid because it is the superpage extent metadata and the
+  // Index 0 is invalid because it is the super page extent metadata and the
   // last index is invalid because the whole PartitionPage is set as guard
-  // pages for the metadata region.
+  // pages.
   DCHECK(partition_page_index);
   DCHECK(partition_page_index < kNumPartitionPagesPerSuperPage - 1);
   uintptr_t super_page_base = (pointer_as_uint & kSuperPageBaseMask);
@@ -190,6 +194,10 @@
   return ret;
 }
 
+// Converts from a pointer inside a partition page into a pointer to the
+// PartitionPage object (within super pages's metadata).
+// The first PartitionPage of the slot span will be returned, regardless where
+// inside of the slot span |ptr| points to.
 template <bool thread_safe>
 ALWAYS_INLINE PartitionPage<thread_safe>*
 PartitionPage<thread_safe>::FromPointer(void* ptr) {
diff --git a/base/android/java/src/org/chromium/base/CommandLine.java b/base/android/java/src/org/chromium/base/CommandLine.java
index 646a4f6d..b66cfd4f 100644
--- a/base/android/java/src/org/chromium/base/CommandLine.java
+++ b/base/android/java/src/org/chromium/base/CommandLine.java
@@ -126,7 +126,6 @@
     }
 
     // Equivalent to CommandLine::ForCurrentProcess in C++.
-    @VisibleForTesting
     public static CommandLine getInstance() {
         CommandLine commandLine = sCommandLine.get();
         assert commandLine != null;
@@ -415,7 +414,7 @@
 
         @Override
         public void appendSwitchWithValue(String switchString, String value) {
-            CommandLineJni.get().appendSwitchWithValue(switchString, value);
+            CommandLineJni.get().appendSwitchWithValue(switchString, value == null ? "" : value);
         }
 
         @Override
diff --git a/base/android/javatests/src/org/chromium/base/CommandLineFlagsTest.java b/base/android/javatests/src/org/chromium/base/CommandLineFlagsTest.java
new file mode 100644
index 0000000..e0553c0
--- /dev/null
+++ b/base/android/javatests/src/org/chromium/base/CommandLineFlagsTest.java
@@ -0,0 +1,167 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.base;
+
+import android.support.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.Statement;
+
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Feature;
+
+import java.util.List;
+
+/**
+ * Test class for {@link CommandLineFlags}.
+ */
+@RunWith(CommandLineFlagsTest.ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
+@CommandLineFlags.
+Add({CommandLineFlagsTest.FLAG_1, "flagwithvalue=foo", "enable-features=feature1,feature2"})
+public class CommandLineFlagsTest {
+    public static class ClassRunner extends BaseJUnit4ClassRunner {
+        public ClassRunner(final Class<?> klass) throws InitializationError {
+            super(klass);
+        }
+
+        // Verify class-level modifications are reset after class finishes.
+        @Override
+        protected List<ClassHook> getPostClassHooks() {
+            return addToList(ClassRunner.super.getPostClassHooks(), (targetContext, testClass) -> {
+                verifyCommandLine(false, false, false, false, false, false, false);
+                Assert.assertFalse(CommandLine.getInstance().hasSwitch("flagwithvalue"));
+                String enabledFeatures =
+                        CommandLine.getInstance().getSwitchValue("enable-features");
+                if (enabledFeatures != null) {
+                    Assert.assertFalse(enabledFeatures.contains("feature1"));
+                    Assert.assertFalse(enabledFeatures.contains("feature2"));
+                }
+            });
+        }
+
+        // Verify that after each test, flags are reset to class-level state.
+        @Override
+        protected List<TestHook> getPostTestHooks() {
+            return addToList(ClassRunner.super.getPostTestHooks(),
+                    (targetContext, testMethod) -> { verifyClassLevelStateOnly(); });
+        }
+    }
+
+    static final String FLAG_1 = "flag1";
+    private static final String FLAG_2 = "flag2";
+    private static final String FLAG_3 = "flag3";
+    private static final String FLAG_4 = "flag4";
+    private static final String FLAG_5 = "flag5";
+    private static final String FLAG_6 = "flag6";
+    private static final String FLAG_7 = "flag7";
+
+    @CommandLineFlags.Add(FLAG_2)
+    private static class EmptyRule implements TestRule {
+        @Override
+        public Statement apply(Statement base, Description description) {
+            return base;
+        }
+    }
+
+    @CommandLineFlags.Add(FLAG_3)
+    private static class MyRule extends EmptyRule {
+        @CommandLineFlags.Add(FLAG_4)
+        private static class InnerRule extends EmptyRule {}
+
+        @SuppressWarnings("UnusedNestedClass")
+        @CommandLineFlags.Add(FLAG_5)
+        private static class UnusedRule extends EmptyRule {}
+
+        @Rule
+        public InnerRule mInnerRule = new InnerRule();
+    }
+
+    @Rule
+    public MyRule mRule = new MyRule();
+
+    @Before
+    public void setUp() {
+        LibraryLoader.getInstance().ensureInitialized();
+    }
+
+    private static void verifyCommandLine(boolean flag1, boolean flag2, boolean flag3,
+            boolean flag4, boolean flag5, boolean flag6, boolean flag7) {
+        CommandLine cmdLine = CommandLine.getInstance();
+        Assert.assertEquals(flag1, cmdLine.hasSwitch(FLAG_1));
+        Assert.assertEquals(flag2, cmdLine.hasSwitch(FLAG_2));
+        Assert.assertEquals(flag3, cmdLine.hasSwitch(FLAG_3));
+        Assert.assertEquals(flag4, cmdLine.hasSwitch(FLAG_4));
+        Assert.assertEquals(flag5, cmdLine.hasSwitch(FLAG_5));
+        Assert.assertEquals(flag6, cmdLine.hasSwitch(FLAG_6));
+        Assert.assertEquals(flag7, cmdLine.hasSwitch(FLAG_7));
+    }
+
+    private static void verifyClassLevelStateOnly() {
+        verifyCommandLine(true, true, true, true, false, false, false);
+        Assert.assertEquals("foo", CommandLine.getInstance().getSwitchValue("flagwithvalue"));
+        String enabledFeatures = CommandLine.getInstance().getSwitchValue("enable-features");
+        Assert.assertTrue(enabledFeatures.contains("feature1"));
+        Assert.assertTrue(enabledFeatures.contains("feature2"));
+        Assert.assertFalse(
+                CommandLine.getInstance().getSwitchValue("enable-features").contains("feature3"));
+        String disabledFeatures = CommandLine.getInstance().getSwitchValue("disable-features");
+        if (disabledFeatures != null) Assert.assertFalse(disabledFeatures.contains("feature2"));
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"CommandLine"})
+    public void testNoMethodModifications() {
+        verifyClassLevelStateOnly();
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"CommandLine"})
+    @CommandLineFlags.Add({FLAG_1, FLAG_6})
+    public void testMethodAdd() {
+        verifyCommandLine(true, true, true, true, false, true, false);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"CommandLine"})
+    @CommandLineFlags.Remove({FLAG_4, FLAG_7})
+    public void testMethodRemove() {
+        verifyCommandLine(true, true, true, false, false, false, false);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"CommandLine"})
+    @CommandLineFlags.Add({"flagwithvalue=bar"})
+    public void testOverrideFlagValue() {
+        Assert.assertEquals("bar", CommandLine.getInstance().getSwitchValue("flagwithvalue"));
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"CommandLine"})
+    @CommandLineFlags.Add({"enable-features=feature3", "disable-features=feature2"})
+    public void testFeatures() {
+        String enabledFeatures = CommandLine.getInstance().getSwitchValue("enable-features");
+        Assert.assertTrue(enabledFeatures.contains("feature1"));
+        Assert.assertTrue(enabledFeatures.contains("feature2"));
+        Assert.assertTrue(enabledFeatures.contains("feature3"));
+        Assert.assertTrue(
+                CommandLine.getInstance().getSwitchValue("disable-features").contains("feature2"));
+    }
+}
diff --git a/base/check_op.h b/base/check_op.h
index 28f4263a1..1acfa614 100644
--- a/base/check_op.h
+++ b/base/check_op.h
@@ -161,9 +161,13 @@
 
 #endif
 
-// The int-int overload avoids address-taking static int members.
+// The second overload avoids address-taking of static members for
+// fundamental types.
 #define DEFINE_CHECK_OP_IMPL(name, op)                                         \
-  template <typename T, typename U>                                            \
+  template <typename T, typename U,                                            \
+            std::enable_if_t<!std::is_fundamental<T>::value ||                 \
+                                 !std::is_fundamental<U>::value,               \
+                             int> = 0>                                         \
   constexpr ::logging::CheckOpResult Check##name##Impl(                        \
       const T& v1, const U& v2, const char* expr_str) {                        \
     if (ANALYZER_ASSUME_TRUE(v1 op v2))                                        \
@@ -171,7 +175,11 @@
     return ::logging::CheckOpResult(expr_str, CheckOpValueStr(v1),             \
                                     CheckOpValueStr(v2));                      \
   }                                                                            \
-  constexpr ::logging::CheckOpResult Check##name##Impl(int v1, int v2,         \
+  template <typename T, typename U,                                            \
+            std::enable_if_t<std::is_fundamental<T>::value &&                  \
+                                 std::is_fundamental<U>::value,                \
+                             int> = 0>                                         \
+  constexpr ::logging::CheckOpResult Check##name##Impl(T v1, U v2,             \
                                                        const char* expr_str) { \
     if (ANALYZER_ASSUME_TRUE(v1 op v2))                                        \
       return ::logging::CheckOpResult();                                       \
diff --git a/base/containers/stack_container.h b/base/containers/stack_container.h
index 46ced5b..b9fee2e 100644
--- a/base/containers/stack_container.h
+++ b/base/containers/stack_container.h
@@ -84,17 +84,15 @@
   // for Us.
   // TODO: If we were fancy pants, perhaps we could share storage
   // iff sizeof(T) == sizeof(U).
-  template<typename U, size_t other_capacity>
+  template <typename U, size_t other_capacity>
   StackAllocator(const StackAllocator<U, other_capacity>& other)
-      : source_(NULL) {
-  }
+      : source_(nullptr) {}
 
   // This constructor must exist. It creates a default allocator that doesn't
   // actually have a stack buffer. glibc's std::string() will compare the
   // current allocator against the default-constructed allocator, so this
   // should be fast.
-  StackAllocator() : source_(NULL) {
-  }
+  StackAllocator() : source_(nullptr) {}
 
   explicit StackAllocator(Source* source) : source_(source) {
   }
diff --git a/base/memory/singleton_unittest.cc b/base/memory/singleton_unittest.cc
index 06e53b2..815d6f2 100644
--- a/base/memory/singleton_unittest.cc
+++ b/base/memory/singleton_unittest.cc
@@ -156,10 +156,15 @@
 }
 
 CallbackFunc* GetStaticSingleton() {
-  return &CallbackSingletonWithStaticTrait::GetInstance()->callback_;
+  CallbackSingletonWithStaticTrait* instance =
+      CallbackSingletonWithStaticTrait::GetInstance();
+  if (instance == nullptr) {
+    return nullptr;
+  } else {
+    return &instance->callback_;
+  }
 }
 
-
 class SingletonTest : public testing::Test {
  public:
   SingletonTest() = default;
diff --git a/base/message_loop/message_pump_win.cc b/base/message_loop/message_pump_win.cc
index a2d45ef7..4c500064 100644
--- a/base/message_loop/message_pump_win.cc
+++ b/base/message_loop/message_pump_win.cc
@@ -255,8 +255,6 @@
     if (more_work_is_plausible)
       continue;
 
-    // WaitForWork() does some work itself, so notify the delegate of it.
-    state_->delegate->BeforeWait();
     WaitForWork(next_work_info);
   }
 }
@@ -270,6 +268,8 @@
   for (DWORD delay = GetSleepTimeoutMs(next_work_info.delayed_run_time,
                                        next_work_info.recent_now);
        delay != 0; delay = GetSleepTimeoutMs(next_work_info.delayed_run_time)) {
+    state_->delegate->BeforeWait();
+
     // Tell the optimizer to retain these values to simplify analyzing hangs.
     base::debug::Alias(&delay);
     base::debug::Alias(&wait_flags);
@@ -299,6 +299,11 @@
       }
 
       {
+        // ::GetQueueStatus() above may racily miss a sent-message and
+        // ::PeekMessage() below may thus process one and/or internal events per
+        // its doc.
+        state_->delegate->BeforeDoInternalWork();
+
         MSG msg;
         // Trace as in ProcessNextWindowsMessage().
         TRACE_EVENT0("base", "MessagePumpForUI::WaitForWork PeekMessage");
diff --git a/base/strings/string_piece.h b/base/strings/string_piece.h
index fc02389d..b185690d 100644
--- a/base/strings/string_piece.h
+++ b/base/strings/string_piece.h
@@ -163,7 +163,7 @@
   // We provide non-explicit singleton constructors so users can pass
   // in a "const char*" or a "string" wherever a "StringPiece" is
   // expected (likewise for char16, string16, StringPiece16).
-  constexpr BasicStringPiece() : ptr_(NULL), length_(0) {}
+  constexpr BasicStringPiece() : ptr_(nullptr), length_(0) {}
   // TODO(crbug.com/1049498): Construction from nullptr is not allowed for
   // std::basic_string_view, so remove the special handling for it.
   // Note: This doesn't just use STRING_TYPE::traits_type::length(), since that
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
index 728f6cde..16456472 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
@@ -25,15 +25,14 @@
 
 import org.chromium.base.CommandLine;
 import org.chromium.base.Log;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
 import org.chromium.base.test.params.MethodParamAnnotationRule;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisableIfSkipCheck;
 import org.chromium.base.test.util.MinAndroidSdkLevelSkipCheck;
 import org.chromium.base.test.util.RestrictionSkipCheck;
 import org.chromium.base.test.util.SkipCheck;
 
 import java.io.File;
-import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -59,35 +58,44 @@
     private static final String DURATION_BUNDLE_ID = "duration_ms";
 
     /**
+     * An interface for classes that have some code to run before (or after) the class is
+     * instantiated. They run after {@Link BeforeClass} (or before @AfterClass) methods are called.
+     * Provides access to the test class (and the annotations defined for it) and the
+     * instrumentation context.
+     *
+     * The only reason to use a ClassHook instead of a TestRule is because @BeforeClass/@AfterClass
+     * run during test listing, or multiple times for parameterized tests. See
+     * https://crbug.com/1090043.
+     *
+     * TODO(https://crbug.com/1092646): Migrate all Class/Test Hooks to TestRules.
+     */
+    public interface ClassHook {
+        /**
+         * @param targetContext the instrumentation context that will be used during the test.
+         * @param testMethod the test method to be run.
+         */
+        public void run(Context targetContext, Class<?> testClass);
+    }
+
+    /**
+     * An interface for classes that have some code to run before a test. They run after
+     * {@link SkipCheck}s and before {@Link Before} (or after @After). Provides access to the test
+     * method (and the annotations defined for it) and the instrumentation context.
+     *
+     * Do not use TestHooks unless you also require ClassHooks. Otherwise, you should use TestRules
+     * and {@link #getDefaultTestRules}.
+     */
+    public interface TestHook {
+        /**
+         * @param targetContext the instrumentation context that will be used during the test.
+         * @param testMethod the test method to be run.
+         */
+        public void run(Context targetContext, FrameworkMethod testMethod);
+    }
+
+    /**
      * Create a BaseJUnit4ClassRunner to run {@code klass} and initialize values.
      *
-     * To add more SkipCheck or PreTestHook in subclass, create Lists of checks and hooks,
-     * pass them into the super constructors. If you want make a subclass extendable by other
-     * class runners, you also have to create a constructor similar to the following one that
-     * merges default checks or hooks with this checks and hooks passed in by constructor.
-     *
-     * <pre>
-     * <code>
-     * e.g.
-     * public ChildRunner extends BaseJUnit4ClassRunner {
-     *     public ChildRunner(final Class<?> klass) {
-     *             throws InitializationError {
-     *         this(klass, Collections.emptyList(), Collections.emptyList(),
-     * Collections.emptyList());
-     *     }
-     *
-     *     public ChildRunner(
-     *             final Class<?> klass, List<SkipCheck> checks, List<PreTestHook> hook,
-     * List<TestRule> rules) { throws InitializationError { super(klass, mergeList( checks,
-     * getSkipChecks()), mergeList(hooks, getPreTestHooks()));
-     *     }
-     *
-     *     public List<SkipCheck> getSkipChecks() {...}
-     *
-     *     public List<PreTestHook> getPreTestHooks() {...}
-     * </code>
-     * </pre>
-     *
      * @throws InitializationError if the test class malformed
      */
     public BaseJUnit4ClassRunner(final Class<?> klass) throws InitializationError {
@@ -160,15 +168,51 @@
     }
 
     /**
-     * Override this method to return a list of {@link PreTestHook}s.
+     * See {@link ClassHook}. Prefer to use TestRules over this.
      *
-     * Additional hooks can be added to the list using {@link #addToList}:
-     * {@code return addToList(super.getPreTestHooks(), hook1, hook2);}
-     * TODO(bauerb): Migrate PreTestHook to TestRule.
+     * Additional hooks can be added to the list by overriding this method and using {@link
+     * #addToList}:
+     * {@code return addToList(super.getPreClassHooks(), hook1, hook2);}
      */
     @CallSuper
-    protected List<PreTestHook> getPreTestHooks() {
-        return Collections.emptyList();
+    protected List<ClassHook> getPreClassHooks() {
+        return Arrays.asList(CommandLineFlags.getPreClassHook());
+    }
+
+    /**
+     * See {@link ClassHook}. Prefer to use TestRules over this.
+     *
+     * Additional hooks can be added to the list by overriding this method and using {@link
+     * #addToList}:
+     * {@code return addToList(super.getPostClassHooks(), hook1, hook2);}
+     */
+    @CallSuper
+    protected List<ClassHook> getPostClassHooks() {
+        return Arrays.asList(CommandLineFlags.getPostClassHook());
+    }
+
+    /**
+     * See {@link TestHook}. Prefer to use TestRules over this.
+     *
+     * Additional hooks can be added to the list by overriding this method and using {@link
+     * #addToList}:
+     * {@code return addToList(super.getPreTestHooks(), hook1, hook2);}
+     */
+    @CallSuper
+    protected List<TestHook> getPreTestHooks() {
+        return Arrays.asList(CommandLineFlags.getPreTestHook());
+    }
+
+    /**
+     * See {@link TestHook}. Prefer to use TestRules over this.
+     *
+     * Additional hooks can be added to the list by overriding this method and using {@link
+     * #addToList}:
+     * {@code return addToList(super.getPostTestHooks(), hook1, hook2);}
+     */
+    @CallSuper
+    protected List<TestHook> getPostTestHooks() {
+        return Arrays.asList(CommandLineFlags.getPostTestHook());
     }
 
     /**
@@ -237,17 +281,12 @@
             return;
         }
 
-        if (!CommandLine.isInitialized()) {
-            initCommandLineForTest();
-        }
-        super.run(notifier);
-    }
+        runPreClassHooks(getDescription().getTestClass());
+        assert CommandLine.isInitialized();
 
-    /**
-     * Override this method to change how test class runner initiate commandline flags
-     */
-    protected void initCommandLineForTest() {
-        CommandLine.init(null);
+        super.run(notifier);
+
+        runPostClassHooks(getDescription().getTestClass());
     }
 
     @Override
@@ -255,12 +294,14 @@
         String testName = method.getName();
         TestTraceEvent.begin(testName);
 
-        runPreTestHooks(method);
-
         long start = SystemClock.uptimeMillis();
 
+        runPreTestHooks(method);
+
         super.runChild(method, notifier);
 
+        runPostTestHooks(method);
+
         Bundle b = new Bundle();
         b.putLong(DURATION_BUNDLE_ID, SystemClock.uptimeMillis() - start);
         InstrumentationRegistry.getInstrumentation().sendStatus(STATUS_CODE_TEST_DURATION, b);
@@ -277,10 +318,30 @@
      * Loop through all the {@code PreTestHook}s to run them
      */
     private void runPreTestHooks(FrameworkMethod frameworkMethod) {
-        Method testMethod = frameworkMethod.getMethod();
         Context targetContext = InstrumentationRegistry.getTargetContext();
-        for (PreTestHook hook : getPreTestHooks()) {
-            hook.run(targetContext, testMethod);
+        for (TestHook hook : getPreTestHooks()) {
+            hook.run(targetContext, frameworkMethod);
+        }
+    }
+
+    private void runPreClassHooks(Class<?> klass) {
+        Context targetContext = InstrumentationRegistry.getTargetContext();
+        for (ClassHook hook : getPreClassHooks()) {
+            hook.run(targetContext, klass);
+        }
+    }
+
+    private void runPostTestHooks(FrameworkMethod frameworkMethod) {
+        Context targetContext = InstrumentationRegistry.getTargetContext();
+        for (TestHook hook : getPostTestHooks()) {
+            hook.run(targetContext, frameworkMethod);
+        }
+    }
+
+    private void runPostClassHooks(Class<?> klass) {
+        Context targetContext = InstrumentationRegistry.getTargetContext();
+        for (ClassHook hook : getPostClassHooks()) {
+            hook.run(targetContext, klass);
         }
     }
 
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java b/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
deleted file mode 100644
index a80e0cc..0000000
--- a/base/test/android/javatests/src/org/chromium/base/test/BaseTestResult.java
+++ /dev/null
@@ -1,137 +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.
-
-package org.chromium.base.test;
-
-import android.app.Instrumentation;
-import android.content.Context;
-import android.os.Bundle;
-import android.os.SystemClock;
-
-import junit.framework.TestCase;
-import junit.framework.TestResult;
-
-import org.chromium.base.Log;
-import org.chromium.base.test.util.SkipCheck;
-
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A test result that can skip tests.
- */
-public class BaseTestResult extends TestResult {
-    private static final String TAG = "base_test";
-
-    private static final int SLEEP_INTERVAL_MS = 50;
-    private static final int WAIT_DURATION_MS = 5000;
-
-    private final Instrumentation mInstrumentation;
-    private final List<SkipCheck> mSkipChecks;
-    private final List<PreTestHook> mPreTestHooks;
-
-    /**
-     * Creates an instance of BaseTestResult.
-     */
-    public BaseTestResult(Instrumentation instrumentation) {
-        mSkipChecks = new ArrayList<>();
-        mPreTestHooks = new ArrayList<>();
-        mInstrumentation = instrumentation;
-    }
-
-    /**
-     * An interface for classes that have some code to run before a test. They run after
-     * {@link SkipCheck}s. Provides access to the test method (and the annotations defined for it)
-     * and the instrumentation context.
-     */
-    public interface PreTestHook {
-        /**
-         * @param targetContext the instrumentation context that will be used during the test.
-         * @param testMethod the test method to be run.
-         */
-        public void run(Context targetContext, Method testMethod);
-    }
-
-    /**
-     * Adds a check for whether a test should run.
-     *
-     * @param skipCheck The check to add.
-     */
-    public void addSkipCheck(SkipCheck skipCheck) {
-        mSkipChecks.add(skipCheck);
-    }
-
-    /**
-     * Adds hooks that will be executed before each test that runs.
-     *
-     * @param preTestHook The hook to add.
-     */
-    public void addPreTestHook(PreTestHook preTestHook) {
-        mPreTestHooks.add(preTestHook);
-    }
-
-    protected boolean shouldSkip(TestCase test) {
-        for (SkipCheck s : mSkipChecks) {
-            if (s.shouldSkip(test)) return true;
-        }
-        return false;
-    }
-
-    private void runPreTestHooks(TestCase test) {
-        try {
-            Method testMethod = test.getClass().getMethod(test.getName());
-            Context targetContext = getTargetContext();
-
-            for (PreTestHook hook : mPreTestHooks) {
-                hook.run(targetContext, testMethod);
-            }
-        } catch (NoSuchMethodException e) {
-            Log.e(TAG, "Unable to run pre test hooks.", e);
-        }
-    }
-
-    @Override
-    protected void run(TestCase test) {
-        runPreTestHooks(test);
-
-        if (shouldSkip(test)) {
-            startTest(test);
-
-            Bundle skipResult = new Bundle();
-            skipResult.putString("class", test.getClass().getName());
-            skipResult.putString("test", test.getName());
-            skipResult.putBoolean("test_skipped", true);
-            mInstrumentation.sendStatus(0, skipResult);
-
-            endTest(test);
-        } else {
-            super.run(test);
-        }
-    }
-
-    /**
-     * Gets the target context.
-     *
-     * On older versions of Android, getTargetContext() may initially return null, so we have to
-     * wait for it to become available.
-     *
-     * @return The target {@link Context} if available; null otherwise.
-     */
-    public Context getTargetContext() {
-        Context targetContext = mInstrumentation.getTargetContext();
-        try {
-            long startTime = SystemClock.uptimeMillis();
-            // TODO(jbudorick): Convert this to CriteriaHelper once that moves to base/.
-            while (targetContext == null
-                    && SystemClock.uptimeMillis() - startTime < WAIT_DURATION_MS) {
-                Thread.sleep(SLEEP_INTERVAL_MS);
-                targetContext = mInstrumentation.getTargetContext();
-            }
-        } catch (InterruptedException e) {
-            Log.e(TAG, "Interrupted while attempting to initialize the command line.");
-        }
-        return targetContext;
-    }
-}
diff --git a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
index 43014d71..572ce22 100644
--- a/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
+++ b/base/test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java
@@ -11,21 +11,24 @@
 
 import org.chromium.base.CommandLine;
 import org.chromium.base.CommandLineInitUtil;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
+import org.chromium.base.test.BaseJUnit4ClassRunner.ClassHook;
+import org.chromium.base.test.BaseJUnit4ClassRunner.TestHook;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Inherited;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import java.lang.reflect.AnnotatedElement;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 
 /**
@@ -59,6 +62,15 @@
     private static final String DISABLE_FEATURES = "disable-features";
     private static final String ENABLE_FEATURES = "enable-features";
 
+    private static boolean sInitializedForTest = false;
+
+    // These members are used to track CommandLine state modifications made by the class/test method
+    // currently being run, to be undone when the class/test method finishes.
+    private static Set<String> sClassFlagsToRemove;
+    private static Map<String, String> sClassFlagsToAdd;
+    private static Set<String> sMethodFlagsToRemove;
+    private static Map<String, String> sMethodFlagsToAdd;
+
     /**
      * Adds command-line flags to the {@link org.chromium.base.CommandLine} for this test.
      */
@@ -91,18 +103,63 @@
      * and {@link CommandLineFlags.Remove} to the {@link org.chromium.base.CommandLine}. Note that
      * trying to remove a flag set externally, i.e. by the command-line flags file, will not work.
      */
-    public static void setUp(AnnotatedElement element) {
-        CommandLine.reset();
-        CommandLineInitUtil.initCommandLine(getTestCmdLineFile());
-        Set<String> enableFeatures = new HashSet<String>(getFeatureValues(ENABLE_FEATURES));
-        Set<String> disableFeatures = new HashSet<String>(getFeatureValues(DISABLE_FEATURES));
+    private static void setUpClass(Class<?> clazz) {
+        // The command line may already have been initialized by Application-level init. We need to
+        // re-initialize it with test flags.
+        if (!sInitializedForTest) {
+            CommandLine.reset();
+            CommandLineInitUtil.initCommandLine(getTestCmdLineFile());
+            sInitializedForTest = true;
+        }
 
         Set<String> flags = new HashSet<>();
-        updateFlagsForElement(element, flags);
-        for (String flag : flags) {
+        updateFlagsForClass(clazz, flags);
+        sClassFlagsToRemove = new HashSet<>();
+        sClassFlagsToAdd = new HashMap<>();
+        applyFlags(flags, null, sClassFlagsToRemove, sClassFlagsToAdd);
+    }
+
+    private static void tearDownClass() {
+        restoreFlags(sClassFlagsToRemove, sClassFlagsToAdd);
+        sClassFlagsToRemove = null;
+        sClassFlagsToAdd = null;
+    }
+
+    private static void setUpMethod(Method method) {
+        Set<String> flagsToAdd = new HashSet<>();
+        Set<String> flagsToRemove = new HashSet<>();
+        updateFlagsForMethod(method, flagsToAdd, flagsToRemove);
+        sMethodFlagsToRemove = new HashSet<>();
+        sMethodFlagsToAdd = new HashMap<>();
+        applyFlags(flagsToAdd, flagsToRemove, sMethodFlagsToRemove, sMethodFlagsToAdd);
+    }
+
+    private static void tearDownMethod() {
+        restoreFlags(sMethodFlagsToRemove, sMethodFlagsToAdd);
+        sMethodFlagsToRemove = null;
+        sMethodFlagsToAdd = null;
+    }
+
+    private static void restoreFlags(Set<String> flagsToRemove, Map<String, String> flagsToAdd) {
+        for (String flag : flagsToRemove) {
+            CommandLine.getInstance().removeSwitch(flag);
+        }
+        for (Entry<String, String> flag : flagsToAdd.entrySet()) {
+            CommandLine.getInstance().appendSwitchWithValue(flag.getKey(), flag.getValue());
+        }
+    }
+
+    private static void applyFlags(Set<String> flagsToAdd, Set<String> flagsToRemove,
+            Set<String> flagsToRemoveForRestore, Map<String, String> flagsToAddForRestore) {
+        Set<String> enableFeatures = new HashSet<String>(getFeatureValues(ENABLE_FEATURES));
+        Set<String> disableFeatures = new HashSet<String>(getFeatureValues(DISABLE_FEATURES));
+        for (String flag : flagsToAdd) {
             String[] parsedFlags = flag.split("=", 2);
             if (parsedFlags.length == 1) {
-                CommandLine.getInstance().appendSwitch(flag);
+                if (!CommandLine.getInstance().hasSwitch(flag)) {
+                    CommandLine.getInstance().appendSwitch(flag);
+                    flagsToRemoveForRestore.add(flag);
+                }
             } else if (ENABLE_FEATURES.equals(parsedFlags[0])) {
                 // We collect enable/disable features flags separately and aggregate them because
                 // they may be specified multiple times, in which case the values will trample each
@@ -111,60 +168,74 @@
             } else if (DISABLE_FEATURES.equals(parsedFlags[0])) {
                 Collections.addAll(disableFeatures, parsedFlags[1].split(","));
             } else {
+                String existingValue = CommandLine.getInstance().getSwitchValue(parsedFlags[0]);
+                if (parsedFlags[1].equals(existingValue)) continue;
+                if (existingValue != null) {
+                    flagsToAddForRestore.put(parsedFlags[0], existingValue);
+                    CommandLine.getInstance().removeSwitch(parsedFlags[0]);
+                }
                 CommandLine.getInstance().appendSwitchWithValue(parsedFlags[0], parsedFlags[1]);
+                flagsToRemoveForRestore.add(parsedFlags[0]);
             }
         }
 
         if (enableFeatures.size() > 0) {
+            String existingValue = CommandLine.getInstance().getSwitchValue(ENABLE_FEATURES);
+            flagsToAddForRestore.put(ENABLE_FEATURES, existingValue);
             CommandLine.getInstance().appendSwitchWithValue(
                     ENABLE_FEATURES, TextUtils.join(",", enableFeatures));
+            flagsToRemoveForRestore.add(ENABLE_FEATURES);
         }
         if (disableFeatures.size() > 0) {
+            String existingValue = CommandLine.getInstance().getSwitchValue(DISABLE_FEATURES);
+            flagsToAddForRestore.put(DISABLE_FEATURES, existingValue);
             CommandLine.getInstance().appendSwitchWithValue(
                     DISABLE_FEATURES, TextUtils.join(",", disableFeatures));
+            flagsToRemoveForRestore.add(DISABLE_FEATURES);
+        }
+        if (flagsToRemove == null) return;
+        for (String flag : flagsToRemove) {
+            if (CommandLine.getInstance().hasSwitch(flag)) {
+                CommandLine.getInstance().removeSwitch(flag);
+                flagsToAddForRestore.put(flag, null);
+            }
         }
     }
 
-    private static void updateFlagsForElement(AnnotatedElement element, Set<String> flags) {
-        if (element instanceof Class<?>) {
-            // Get flags from rules within the class.
-            for (Field field : ((Class<?>) element).getFields()) {
-                if (field.isAnnotationPresent(Rule.class)) {
-                    // The order in which fields are returned is undefined, so, for consistency,
-                    // a rule must only ever add flags.
-                    updateFlagsForElement(field.getType(), flags);
-                }
+    private static void updateFlagsForClass(Class<?> clazz, Set<String> flags) {
+        // Get flags from rules within the class.
+        for (Field field : clazz.getFields()) {
+            if (field.isAnnotationPresent(Rule.class)) {
+                // The order in which fields are returned is undefined, so, for consistency,
+                // a rule must only ever add flags.
+                updateFlagsForClass(field.getType(), flags);
             }
-            for (Method method : ((Class<?>) element).getMethods()) {
-                Assert.assertFalse("@Rule annotations on methods are unsupported. Cause: "
-                                + method.toGenericString(),
-                        method.isAnnotationPresent(Rule.class));
-            }
+        }
+        for (Method method : clazz.getMethods()) {
+            Assert.assertFalse("@Rule annotations on methods are unsupported. Cause: "
+                            + method.toGenericString(),
+                    method.isAnnotationPresent(Rule.class));
         }
 
         // Add the flags from the parent. Override any flags defined by the rules.
-        AnnotatedElement parent = (element instanceof Method)
-                ? ((Method) element).getDeclaringClass()
-                : ((Class<?>) element).getSuperclass();
-        if (parent != null) updateFlagsForElement(parent, flags);
+        Class<?> parent = clazz.getSuperclass();
+        if (parent != null) updateFlagsForClass(parent, flags);
 
         // Flags on the element itself override all other flag sources.
-        if (element.isAnnotationPresent(CommandLineFlags.Add.class)) {
-            flags.addAll(
-                    Arrays.asList(element.getAnnotation(CommandLineFlags.Add.class).value()));
+        if (clazz.isAnnotationPresent(CommandLineFlags.Add.class)) {
+            flags.addAll(Arrays.asList(clazz.getAnnotation(CommandLineFlags.Add.class).value()));
         }
+    }
 
-        if (element.isAnnotationPresent(CommandLineFlags.Remove.class)) {
-            List<String> flagsToRemove =
-                    Arrays.asList(element.getAnnotation(CommandLineFlags.Remove.class).value());
-            for (String flagToRemove : flagsToRemove) {
-                // If your test fails here, you have tried to remove a command-line flag via
-                // CommandLineFlags.Remove that was loaded into CommandLine via something other
-                // than CommandLineFlags.Add (probably the command-line flag file).
-                Assert.assertFalse("Unable to remove command-line flag \"" + flagToRemove + "\".",
-                        CommandLine.getInstance().hasSwitch(flagToRemove));
-            }
-            flags.removeAll(flagsToRemove);
+    private static void updateFlagsForMethod(
+            Method method, Set<String> flagsToAdd, Set<String> flagsToRemove) {
+        if (method.isAnnotationPresent(CommandLineFlags.Add.class)) {
+            flagsToAdd.addAll(
+                    Arrays.asList(method.getAnnotation(CommandLineFlags.Add.class).value()));
+        }
+        if (method.isAnnotationPresent(CommandLineFlags.Remove.class)) {
+            flagsToRemove.addAll(
+                    Arrays.asList(method.getAnnotation(CommandLineFlags.Remove.class).value()));
         }
     }
 
@@ -178,8 +249,20 @@
         throw new AssertionError("CommandLineFlags is a non-instantiable class");
     }
 
-    public static PreTestHook getRegistrationHook() {
-        return (targetContext, testMethod) -> CommandLineFlags.setUp(testMethod);
+    public static TestHook getPreTestHook() {
+        return (targetContext, testMethod) -> CommandLineFlags.setUpMethod(testMethod.getMethod());
+    }
+
+    public static ClassHook getPreClassHook() {
+        return (targetContext, testClass) -> CommandLineFlags.setUpClass(testClass);
+    }
+
+    public static TestHook getPostTestHook() {
+        return (targetContext, testMethod) -> CommandLineFlags.tearDownMethod();
+    }
+
+    public static ClassHook getPostClassHook() {
+        return (targetContext, testClass) -> CommandLineFlags.tearDownClass();
     }
 
     public static String getTestCmdLineFile() {
diff --git a/build/android/gyp/aar.py b/build/android/gyp/aar.py
index c375e22..bd5c7b6 100755
--- a/build/android/gyp/aar.py
+++ b/build/android/gyp/aar.py
@@ -149,12 +149,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-""" + gn_helpers.ToGNString(aar_info)
+""" + gn_helpers.ToGNString(aar_info, pretty=True)
 
   if args.command == 'extract':
     if args.assert_info_file:
       cached_info = args.assert_info_file.read()
-      if formatted_info != cached_info:
+      # Relax comparisons by indiscriminately removing whitespaces. This reduces
+      # noise during migration to pretty-print.
+      # TODO(huangs): Return to direct comparison once migration is complete.
+      if ''.join(formatted_info.split()) != ''.join(cached_info.split()):
         raise Exception('android_aar_prebuilt() cached .info file is '
                         'out-of-date. Run gn gen with '
                         'update_android_aar_prebuilts=true to update it.')
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 073a2b9..4b5490f 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -935,13 +935,16 @@
         }
       }
 
-      _suppressions_file = "//build/android/lint/suppressions.xml"
       if (defined(invoker.lint_suppressions_file)) {
         _suppressions_file = invoker.lint_suppressions_file
-      } else if (defined(lint_suppressions_file)) {
-        # WebRTC defines its own lint_suppressions_file:
-        # //tools_webrtc/android/suppressions.xml
-        _suppressions_file = lint_suppressions_file
+
+        # The custom suppressions file might be a generated file needing a dep.
+        # e.g. generating it by appending to the default suppressions.xml file.
+        if (defined(invoker.lint_suppressions_dep)) {
+          deps += [ invoker.lint_suppressions_dep ]
+        }
+      } else {
+        _suppressions_file = "//build/android/lint/suppressions.xml"
       }
 
       _min_sdk_version = default_min_sdk_version
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni
index adf8f64..4ebf8819 100644
--- a/build/config/android/rules.gni
+++ b/build/config/android/rules.gni
@@ -3363,6 +3363,8 @@
       android_lint(_android_lint_target) {
         forward_variables_from(invoker,
                                [
+                                 "lint_suppressions_dep",
+                                 "lint_suppressions_file",
                                  "manifest_package",
                                  "min_sdk_version",
                                ])
@@ -3371,7 +3373,12 @@
         deps = [ ":$_java_target" ]
       }
     } else {
-      not_needed(invoker, [ "manifest_package" ])
+      not_needed(invoker,
+                 [
+                   "manifest_package",
+                   "lint_suppressions_dep",
+                   "lint_suppressions_file",
+                 ])
     }
 
     group(target_name) {
@@ -3473,6 +3480,8 @@
                                "keystore_name",
                                "keystore_password",
                                "keystore_path",
+                               "lint_suppressions_dep",
+                               "lint_suppressions_file",
                                "load_library_from_apk",
                                "loadable_modules",
                                "manifest_package",
@@ -4290,37 +4299,37 @@
       not_needed(invoker, [ "strip_drawables" ])
     }
 
-    _java_library_vars = [
-      "enable_bytecode_checks",
-      "enable_jetify",
-      "jar_excluded_patterns",
-      "jar_included_patterns",
-      "missing_classes_allowlist",
-      "requires_android",
-      "testonly",
-    ]
-
-    # Create android_java_prebuilt target for extra jars within jars/.
-    _subjar_targets = []
-    foreach(_tuple, _scanned_files.subjar_tuples) {
-      _current_target = "${target_name}__subjar_${_tuple[0]}"
-      _subjar_targets += [ ":$_current_target" ]
-      java_prebuilt(_current_target) {
-        forward_variables_from(invoker, _java_library_vars)
-        deps = [ ":$_unpack_target_name" ]
-        if (!defined(requires_android)) {
-          requires_android = true
-        }
-        supports_android = true
-        jar_path = "$_output_path/${_tuple[1]}"
-        _base_output_name = get_path_info(jar_path, "name")
-        output_name = "${invoker.target_name}-$_base_output_name"
-        public_target_label = invoker.target_name
-      }
-    }
-
     # Create android_java_prebuilt target for classes.jar.
     if (_scanned_files.has_classes_jar) {
+      _java_library_vars = [
+        "enable_bytecode_checks",
+        "enable_jetify",
+        "jar_excluded_patterns",
+        "jar_included_patterns",
+        "missing_classes_allowlist",
+        "requires_android",
+        "testonly",
+      ]
+
+      # Create android_java_prebuilt target for extra jars within jars/.
+      _subjar_targets = []
+      foreach(_tuple, _scanned_files.subjar_tuples) {
+        _current_target = "${target_name}__subjar_${_tuple[0]}"
+        _subjar_targets += [ ":$_current_target" ]
+        java_prebuilt(_current_target) {
+          forward_variables_from(invoker, _java_library_vars)
+          deps = [ ":$_unpack_target_name" ]
+          if (!defined(requires_android)) {
+            requires_android = true
+          }
+          supports_android = true
+          jar_path = "$_output_path/${_tuple[1]}"
+          _base_output_name = get_path_info(jar_path, "name")
+          output_name = "${invoker.target_name}-$_base_output_name"
+          public_target_label = invoker.target_name
+        }
+      }
+
       _jar_target_name = "${target_name}__classes"
       java_prebuilt(_jar_target_name) {
         forward_variables_from(invoker, _java_library_vars)
@@ -4964,16 +4973,22 @@
       android_lint(_android_lint_target) {
         forward_variables_from(invoker,
                                [
+                                 "lint_suppressions_dep",
+                                 "lint_suppressions_file",
                                  "manifest_package",
                                  "min_sdk_version",
-                                 "lint_suppressions_file",
                                ])
         build_config = _build_config
         build_config_dep = ":$_build_config_target"
         deps = _module_java_targets
       }
     } else {
-      not_needed(invoker, [ "manifest_package" ])
+      not_needed(invoker,
+                 [
+                   "manifest_package",
+                   "lint_suppressions_dep",
+                   "lint_suppressions_file",
+                 ])
     }
 
     group(_target_name) {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 538bee5..d567def8 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -121,9 +121,6 @@
   thin_lto_enable_optimizations =
       (is_chromeos || is_android || is_win) && is_official_build
 
-  # By default only the binaries in official builds get build IDs.
-  force_local_build_id = false
-
   # Initialize all local variables with a pattern. This flag will fill
   # uninitialized floating-point types (and 32-bit pointers) with 0xFF and the
   # rest with 0xAA. This makes behavior of uninitialized memory bugs consistent,
@@ -332,14 +329,16 @@
       }
     }
 
-    if (is_official_build || force_local_build_id) {
-      # Explicitly pass --build-id to ld. Compilers used to always pass this
-      # implicitly but don't any more (in particular clang when built without
-      # ENABLE_LINKER_BUILD_ID=ON). The crash infrastructure does need a build
-      # id, so explicitly enable it in official builds. It's not needed in
-      # unofficial builds and computing it does slow down the link, so go with
-      # faster links in unofficial builds.
+    # Explicitly pass --build-id to ld. Compilers used to always pass this
+    # implicitly but don't any more (in particular clang when built without
+    # ENABLE_LINKER_BUILD_ID=ON).
+    if (is_official_build) {
+      # The sha1 build id has lower risk of collision but is more expensive to
+      # compute, so only use it in the official build to avoid slowing down
+      # links.
       ldflags += [ "-Wl,--build-id=sha1" ]
+    } else {
+      ldflags += [ "-Wl,--build-id" ]
     }
 
     if (!is_android) {
@@ -2023,6 +2022,12 @@
     } else {
       cflags = [ "-Os" ] + common_optimize_on_cflags
     }
+
+    if (!is_component_build) {
+      # Required for library partitions. Without this all symbols just end up
+      # in the base partition.
+      ldflags = [ "-Wl,--gc-sections" ]
+    }
   } else if (is_fuchsia) {
     # On Fuchsia, we optimize for size here to reduce the size of debug build
     # packages so they can be run in a KVM. See crbug.com/910243 for details.
@@ -2274,7 +2279,8 @@
       cflags += [ "-g2" ]
     }
 
-    if (is_clang && !is_nacl && !use_xcode_clang) {
+    # TODO(https://crbug.com/1050118): Investigate missing debug info on mac.
+    if (is_clang && !is_nacl && !use_xcode_clang && !is_mac && !is_ios) {
       cflags += [
         "-Xclang",
         "-debug-info-kind=constructor",
diff --git a/build/config/mac/prepare_framework_version.py b/build/config/mac/prepare_framework_version.py
index 5e8a53f..db921506 100644
--- a/build/config/mac/prepare_framework_version.py
+++ b/build/config/mac/prepare_framework_version.py
@@ -31,7 +31,7 @@
   # directory exists.
   dirname = os.path.dirname(version_file)
   if not os.path.isdir(dirname):
-    os.makedirs(dirname, 0700)
+    os.makedirs(dirname, 0o700)
 
   with open(version_file, 'w+') as f:
     f.write(version)
diff --git a/build/fuchsia/emu_target.py b/build/fuchsia/emu_target.py
index 4e2f0b9..f5e7c1f 100644
--- a/build/fuchsia/emu_target.py
+++ b/build/fuchsia/emu_target.py
@@ -74,7 +74,7 @@
                                          env=emu_env)
 
     try:
-      self._WaitUntilReady();
+      self._WaitUntilReady(ssh_diagnostic_log_file=stdout)
     except target.FuchsiaTargetException:
       if temporary_system_log_file:
         logging.info('Kernel logs:\n' +
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 2854eb4f..e81cc5603 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20200608.1.1
+0.20200604.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 2854eb4f..e81cc5603 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20200608.1.1
+0.20200604.3.1
diff --git a/build/fuchsia/target.py b/build/fuchsia/target.py
index d8c1741f..7290a7d6 100644
--- a/build/fuchsia/target.py
+++ b/build/fuchsia/target.py
@@ -211,20 +211,25 @@
   def _AssertIsStarted(self):
     assert self.IsStarted()
 
-  def _WaitUntilReady(self):
+  def _WaitUntilReady(self, ssh_diagnostic_log_file=open(os.devnull, 'w')):
     logging.info('Connecting to Fuchsia using SSH.')
 
     host, port = self._GetEndpoint()
     end_time = time.time() + _ATTACH_RETRY_SECONDS
     while time.time() < end_time:
       runner = remote_cmd.CommandRunner(self._GetSshConfigPath(), host, port)
-      if runner.RunCommand(['true'], True) == 0:
+      ssh_proc = runner.RunCommandPiped(['true'],
+                                        ssh_args=['-v'],
+                                        stdout=ssh_diagnostic_log_file,
+                                        stderr=subprocess.STDOUT)
+      if ssh_proc.wait() == 0:
         logging.info('Connected!')
         self._started = True
         return True
       time.sleep(_ATTACH_RETRY_INTERVAL)
 
     logging.error('Timeout limit reached.')
+    ssh_diagnostic_log_file.flush()
 
     raise FuchsiaTargetException('Couldn\'t connect using SSH.')
 
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py
index 78314e0..51ffc14 100755
--- a/build/mac/find_sdk.py
+++ b/build/mac/find_sdk.py
@@ -39,7 +39,7 @@
 
 def parse_version(version_str):
   """'10.6' => [10, 6]"""
-  return map(int, re.findall(r'(\d+)', version_str))
+  return [int(s) for s in re.findall(r'(\d+)', version_str)]
 
 
 def main():
diff --git a/build_overrides/build.gni b/build_overrides/build.gni
index 050e6719..ced95dc033 100644
--- a/build_overrides/build.gni
+++ b/build_overrides/build.gni
@@ -27,9 +27,6 @@
 # ubsan_security_blacklist_path = "path/to/ubsan/security_blacklist.txt"
 # cfi_blacklist_path = "path/to/cfi/blacklist.txt"
 
-# Uncomment these to specify a different lint suppressions file for android
-# lint_suppressions_file = path/to/your/suppressions/file/suppressions.xml
-
 declare_args() {
   # Android 32-bit non-component, non-clang builds cannot have symbol_level=2
   # due to 4GiB file size limit, see https://crbug.com/648948.
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc
index 86deeddd..7fda3764 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -113,6 +113,10 @@
   return cached_sk_image_;
 }
 
+const sk_sp<SkImage>& PaintImage::GetRasterSkImage() const {
+  return cached_sk_image_;
+}
+
 PaintImage PaintImage::MakeSubset(const gfx::Rect& subset) const {
   DCHECK(!subset.IsEmpty());
 
@@ -133,7 +137,7 @@
   // PaintImage is an optimization to allow re-use of the original decode for
   // image subsets in skia, for cases that rely on skia's image decode cache.
   result.cached_sk_image_ =
-      GetSkImage()->makeSubset(gfx::RectToSkIRect(subset));
+      GetRasterSkImage()->makeSubset(gfx::RectToSkIRect(subset));
   return result;
 }
 
@@ -361,18 +365,19 @@
     size_t index,
     GeneratorClientId client_id) const {
   DCHECK_LT(index, FrameCount());
+  DCHECK(!IsTextureBacked());
 
   // |client_id| and |index| are only relevant for generator backed images which
   // perform lazy decoding and can be multi-frame.
   if (!paint_image_generator_) {
     DCHECK_EQ(index, kDefaultFrameIndex);
-    return GetSkImage();
+    return GetRasterSkImage();
   }
 
   // The internally cached SkImage is constructed using the default frame index
   // and GeneratorClientId. Avoid creating a new SkImage.
   if (index == kDefaultFrameIndex && client_id == kDefaultGeneratorClientId)
-    return GetSkImage();
+    return GetRasterSkImage();
 
   sk_sp<SkImage> image =
       SkImage::MakeFromGenerator(std::make_unique<SkiaPaintImageGenerator>(
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h
index 9588120..c7e0f46f 100644
--- a/cc/paint/paint_image.h
+++ b/cc/paint/paint_image.h
@@ -229,6 +229,13 @@
                  const SkYUVASizeInfo& yuva_size_info,
                  SkYUVAIndex* plane_indices) const;
 
+  // Returns the SkImage associated with this PaintImage. If PaintImage is
+  // texture backed, this API may do a readback from GPU to CPU memory.
+  // Avoid using this API unless actual pixels are needed.
+  // For other cases, prefer using PaintImage APIs directly or use
+  // GetSkImageInfo() for metadata about the SkImage.
+  const sk_sp<SkImage>& GetRasterSkImage() const;
+
   Id stable_id() const { return id_; }
   const sk_sp<SkImage>& GetSkImage() const;
   AnimationType animation_type() const { return animation_type_; }
diff --git a/cc/paint/paint_op_buffer.cc b/cc/paint/paint_op_buffer.cc
index f955b93..04963e4 100644
--- a/cc/paint/paint_op_buffer.cc
+++ b/cc/paint/paint_op_buffer.cc
@@ -1272,7 +1272,8 @@
       canvas->scale(1.f / op->scale_adjustment.width(),
                     1.f / op->scale_adjustment.height());
     }
-    canvas->drawImage(op->image.GetSkImage().get(), op->left, op->top, &paint);
+    canvas->drawImage(op->image.GetRasterSkImage().get(), op->left, op->top,
+                      &paint);
     return;
   }
 
@@ -1342,8 +1343,8 @@
   if (!params.image_provider) {
     SkRect adjusted_src = AdjustSrcRectForScale(op->src, op->scale_adjustment);
     flags->DrawToSk(canvas, [op, adjusted_src](SkCanvas* c, const SkPaint& p) {
-      c->drawImageRect(op->image.GetSkImage().get(), adjusted_src, op->dst, &p,
-                       op->constraint);
+      c->drawImageRect(op->image.GetRasterSkImage().get(), adjusted_src,
+                       op->dst, &p, op->constraint);
     });
     return;
   }
diff --git a/cc/paint/paint_op_writer.cc b/cc/paint/paint_op_writer.cc
index 962d075..bb59e6f 100644
--- a/cc/paint/paint_op_writer.cc
+++ b/cc/paint/paint_op_writer.cc
@@ -243,7 +243,7 @@
   // Security constrained serialization inlines the image bitmap.
   if (enable_security_constraints_) {
     SkBitmap bm;
-    if (!draw_image.paint_image().GetSkImage()->asLegacyBitmap(&bm)) {
+    if (!draw_image.paint_image().GetRasterSkImage()->asLegacyBitmap(&bm)) {
       Write(static_cast<uint8_t>(PaintOp::SerializedImageType::kNoImage));
       return;
     }
diff --git a/cc/raster/playback_image_provider.cc b/cc/raster/playback_image_provider.cc
index cbda15c..da15a727 100644
--- a/cc/raster/playback_image_provider.cc
+++ b/cc/raster/playback_image_provider.cc
@@ -57,9 +57,10 @@
 
   DrawImage adjusted_image(draw_image, 1.f, frame_index, target_color_space_);
   if (!cache_->UseCacheForDrawImage(adjusted_image)) {
-    return ScopedResult(DecodedDrawImage(
-        paint_image.GetSkImage(), SkSize::Make(0, 0), SkSize::Make(1.f, 1.f),
-        draw_image.filter_quality(), true /* is_budgeted */));
+    return ScopedResult(
+        DecodedDrawImage(paint_image.GetRasterSkImage(), SkSize::Make(0, 0),
+                         SkSize::Make(1.f, 1.f), draw_image.filter_quality(),
+                         true /* is_budgeted */));
   }
 
   auto decoded_draw_image = cache_->GetDecodedImageForDraw(adjusted_image);
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
index b745256..a19fa2a1e 100644
--- a/cc/tiles/gpu_image_decode_cache.cc
+++ b/cc/tiles/gpu_image_decode_cache.cc
@@ -1922,7 +1922,8 @@
       DLOG(ERROR) << "YUV + Bitmap is unknown and unimplemented!";
       NOTREACHED();
     } else {
-      image_data->decode.SetBitmapImage(draw_image.paint_image().GetSkImage());
+      image_data->decode.SetBitmapImage(
+          draw_image.paint_image().GetRasterSkImage());
     }
     return;
   }
@@ -2086,7 +2087,7 @@
 
       // Get the encoded data in a contiguous form.
       sk_sp<SkData> encoded_data =
-          draw_image.paint_image().GetSkImage()->refEncodedData();
+          draw_image.paint_image().GetRasterSkImage()->refEncodedData();
       DCHECK(encoded_data);
       const uint32_t transfer_cache_id =
           ClientImageTransferCacheEntry::GetNextId();
diff --git a/cc/tiles/software_image_decode_cache.cc b/cc/tiles/software_image_decode_cache.cc
index c674a44..412c1b0 100644
--- a/cc/tiles/software_image_decode_cache.cc
+++ b/cc/tiles/software_image_decode_cache.cc
@@ -82,7 +82,7 @@
     const ImageType image_type =
         image_metadata ? image_metadata->image_type : ImageType::kInvalid;
     devtools_instrumentation::ScopedImageDecodeTask image_decode_task(
-        paint_image_.GetSkImage().get(),
+        paint_image_.GetRasterSkImage().get(),
         devtools_instrumentation::ScopedImageDecodeTask::kSoftware,
         ImageDecodeCache::ToScopedTaskType(tracing_info_.task_type),
         ImageDecodeCache::ToScopedImageType(image_type));
@@ -134,24 +134,6 @@
                                    : kLow_SkFilterQuality;
 }
 
-void RecordLockExistingCachedImageHistogram(TilePriority::PriorityBin bin,
-                                            bool success) {
-  switch (bin) {
-    case TilePriority::NOW:
-      UMA_HISTOGRAM_BOOLEAN("Renderer4.LockExistingCachedImage.Software.NOW",
-                            success);
-      break;
-    case TilePriority::SOON:
-      UMA_HISTOGRAM_BOOLEAN("Renderer4.LockExistingCachedImage.Software.SOON",
-                            success);
-      break;
-    case TilePriority::EVENTUALLY:
-      UMA_HISTOGRAM_BOOLEAN(
-          "Renderer4.LockExistingCachedImage.Software.EVENTUALLY", success);
-      break;
-  }
-}
-
 }  // namespace
 
 SoftwareImageDecodeCache::SoftwareImageDecodeCache(
@@ -357,9 +339,6 @@
       return TaskProcessingResult::kLockOnly;
 
     bool lock_succeeded = entry->Lock();
-    // TODO(vmpstr): Deprecate the prepaint split, since it doesn't matter.
-    RecordLockExistingCachedImageHistogram(TilePriority::NOW, lock_succeeded);
-
     if (lock_succeeded)
       return TaskProcessingResult::kLockOnly;
   }
diff --git a/cc/tiles/tile_priority.cc b/cc/tiles/tile_priority.cc
index 606a8c6..1bfe552 100644
--- a/cc/tiles/tile_priority.cc
+++ b/cc/tiles/tile_priority.cc
@@ -11,18 +11,6 @@
 
 namespace cc {
 
-std::string WhichTreeToString(WhichTree tree) {
-  switch (tree) {
-  case ACTIVE_TREE:
-    return "ACTIVE_TREE";
-  case PENDING_TREE:
-    return "PENDING_TREE";
-  default:
-      DCHECK(false) << "Unrecognized WhichTree value " << tree;
-      return "<unknown WhichTree value>";
-  }
-}
-
 std::string TileResolutionToString(TileResolution resolution) {
   switch (resolution) {
   case LOW_RESOLUTION:
diff --git a/cc/tiles/tile_priority.h b/cc/tiles/tile_priority.h
index 34cd3bc..bffd8d8 100644
--- a/cc/tiles/tile_priority.h
+++ b/cc/tiles/tile_priority.h
@@ -16,10 +16,6 @@
 #include "cc/cc_export.h"
 #include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_compositor_scheduler_state.pbzero.h"
 
-namespace base {
-class Value;
-}
-
 namespace cc {
 
 enum WhichTree {
@@ -28,9 +24,7 @@
   ACTIVE_TREE = 0,
   PENDING_TREE = 1,
   LAST_TREE = 1
-  // Be sure to update WhichTreeAsValue when adding new fields.
 };
-std::unique_ptr<base::Value> WhichTreeAsValue(WhichTree tree);
 
 enum TileResolution {
   LOW_RESOLUTION = 0 ,
diff --git a/cc/trees/occlusion_tracker.h b/cc/trees/occlusion_tracker.h
index d249867..c734bef 100644
--- a/cc/trees/occlusion_tracker.h
+++ b/cc/trees/occlusion_tracker.h
@@ -59,7 +59,7 @@
 
  protected:
   struct StackObject {
-    StackObject() : target(0) {}
+    StackObject() : target(nullptr) {}
     explicit StackObject(const RenderSurfaceImpl* target) : target(target) {}
     const RenderSurfaceImpl* target;
     SimpleEnclosedRegion occlusion_from_outside_target;
diff --git a/chrome/VERSION b/chrome/VERSION
index 4a282494..e9d4af3 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=85
 MINOR=0
-BUILD=4167
+BUILD=4168
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index f2d40f99..c8501fb1 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -229,15 +229,6 @@
   }
 }
 
-# TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-if (enable_password_change_in_leaked_dialog) {
-  android_resources("password_change_resources") {
-    sources = [ "//chrome/android/java/res_password_change/layout/password_manager_dialog_with_help_button_password_change.xml" ]
-    deps = [ ":chrome_app_java_resources" ]
-    custom_package = "org.chromium.chrome.password_change"
-  }
-}
-
 # TODO(chouinard): Remove this wrapper target after downstream dependencies on it are replaced.
 android_resources("chrome_download_java_resources") {
   sources = []
@@ -535,9 +526,6 @@
     deps += [ ":chrome_vr_java_resources" ]
   }
 
-  if (enable_password_change_in_leaked_dialog) {
-    deps += [ ":password_change_resources" ]
-  }
   srcjar_deps += [ ":chrome_vr_android_java_enums_srcjar" ]
   if (enable_feed_in_chrome) {
     deps += [ "//chrome/android/feed:chrome_feed_java_resources" ]
@@ -1827,6 +1815,8 @@
                              "is_modern",
                              "target_type",
                              "enable_multidex",
+                             "lint_suppressions_dep",
+                             "lint_suppressions_file",
 
                              # TODO(crbug.com/1076896): remove
                              # "disable_library_rename" when we remove chrome
@@ -2722,6 +2712,28 @@
     verify_native_libs_and_assets = _enable_libs_and_assets_verification
   }
 
+  if (is_official_build) {
+    # Used for binary size monitoring.
+    create_app_bundle_minimal_apks("trichrome_chrome_minimal_apks") {
+      deps = [ ":trichrome_chrome_bundle" ]
+      bundle_path = "$root_build_dir/apks/TrichromeChrome.aab"
+    }
+
+    android_resource_sizes_test("resource_sizes_trichrome") {
+      apk_name = "Trichrome"
+      trichrome_chrome_path =
+          "$root_build_dir/apks/TrichromeChrome.minimal.apks"
+      trichrome_webview_path =
+          "$root_build_dir/apks/TrichromeWebView.minimal.apks"
+      trichrome_library_path = "$root_build_dir/apks/TrichromeLibrary.apk"
+      data_deps = [
+        ":trichrome_chrome_minimal_apks",
+        ":trichrome_library_apk",
+        "//android_webview:trichrome_webview_minimal_apks",
+      ]
+    }
+  }
+
   if (android_64bit_target_cpu) {
     monochrome_or_trichrome_public_bundle_tmpl("monochrome_32_public_bundle") {
       bundle_suffix = "32"
@@ -3075,10 +3087,6 @@
   if (enable_vr) {
     sources += [ "java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java" ]
   }
-
-  if (enable_password_change_in_leaked_dialog) {
-    sources += [ "java/src/org/chromium/chrome/browser/password_manager/CredentialLeakDialogPasswordChangeBridge.java" ]
-  }
 }
 
 native_java_unittests_tests = [
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index f20c887f..1bf4513 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -1191,7 +1191,7 @@
   "java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java",
   "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewDemoManager.java",
   "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewExperiments.java",
-  "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewInitializer.java",
+  "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java",
   "java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewTabHelper.java",
   "java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java",
   "java/src/org/chromium/chrome/browser/paint_preview/services/PaintPreviewDemoService.java",
@@ -1390,7 +1390,6 @@
   "java/src/org/chromium/chrome/browser/settings/MainSettings.java",
   "java/src/org/chromium/chrome/browser/settings/SettingsActivity.java",
   "java/src/org/chromium/chrome/browser/settings/SettingsLauncherImpl.java",
-  "java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProvider.java",
   "java/src/org/chromium/chrome/browser/share/ChromeShareExtras.java",
   "java/src/org/chromium/chrome/browser/share/LensUtils.java",
   "java/src/org/chromium/chrome/browser/share/OptionalShareTargetsManager.java",
@@ -1399,10 +1398,6 @@
   "java/src/org/chromium/chrome/browser/share/ShareDelegate.java",
   "java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java",
   "java/src/org/chromium/chrome/browser/share/ShareHelper.java",
-  "java/src/org/chromium/chrome/browser/share/ShareSheetBottomSheetContent.java",
-  "java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java",
-  "java/src/org/chromium/chrome/browser/share/ShareSheetItemViewProperties.java",
-  "java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java",
   "java/src/org/chromium/chrome/browser/share/ShareUtils.java",
   "java/src/org/chromium/chrome/browser/sharing/SharingAdapter.java",
   "java/src/org/chromium/chrome/browser/sharing/SharingJNIBridge.java",
@@ -1561,13 +1556,11 @@
   "java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParams.java",
   "java/src/org/chromium/chrome/browser/tabmodel/AsyncTabParamsManager.java",
   "java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java",
-  "java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelFilter.java",
   "java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelSelectorObserver.java",
   "java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java",
   "java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelImplCreator.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabCreatorManager.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelDelegate.java",
-  "java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelFilterProvider.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java",
   "java/src/org/chromium/chrome/browser/tabmodel/TabModelJniBridge.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 2763bde..68c0e78 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -413,6 +413,7 @@
   "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestUseStatsTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/SkipToGPayHelperTest.java",
   "javatests/src/org/chromium/chrome/browser/payments/WebPaymentIntentHelperTest.java",
+  "javatests/src/org/chromium/chrome/browser/permissions/AutomaticEmbargoTest.java",
   "javatests/src/org/chromium/chrome/browser/permissions/GeolocationTest.java",
   "javatests/src/org/chromium/chrome/browser/permissions/MIDITest.java",
   "javatests/src/org/chromium/chrome/browser/permissions/MediaTest.java",
@@ -451,13 +452,10 @@
   "javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java",
   "javatests/src/org/chromium/chrome/browser/settings/language/LanguageSettingsTest.java",
   "javatests/src/org/chromium/chrome/browser/shape_detection/ShapeDetectionTest.java",
-  "javatests/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderTest.java",
   "javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java",
   "javatests/src/org/chromium/chrome/browser/share/ShareButtonControllerTest.java",
   "javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplTest.java",
-  "javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java",
-  "javatests/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilderTest.java",
   "javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java",
   "javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java",
   "javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
index b7b2f930..dbc8e53 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantClient.java
@@ -18,6 +18,7 @@
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.chrome.browser.signin.IdentityServicesProvider;
+import org.chromium.components.signin.AccessTokenData;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.content_public.browser.WebContents;
@@ -285,10 +286,10 @@
         IdentityServicesProvider.get().getIdentityManager().getAccessToken(
                 mAccount, AUTH_TOKEN_TYPE, new IdentityManager.GetAccessTokenCallback() {
                     @Override
-                    public void onGetTokenSuccess(String token) {
+                    public void onGetTokenSuccess(AccessTokenData token) {
                         if (mNativeClientAndroid != 0) {
                             AutofillAssistantClientJni.get().onAccessToken(mNativeClientAndroid,
-                                    AutofillAssistantClient.this, true, token);
+                                    AutofillAssistantClient.this, true, token.getToken());
                         }
                     }
 
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
index 727edd6..6280bb97 100644
--- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
+++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java
@@ -815,8 +815,11 @@
     @MediumTest
     @Feature("TabSuggestion")
     @EnableFeatures(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study")
-    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true"})
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
     public void testTabSuggestionMessageCard_dismiss() throws InterruptedException {
+        // clang-format on
         prepareTabs(3, 0, null);
 
         // TODO(meiliang): Avoid using static variable for tracking state,
@@ -841,8 +844,11 @@
     @MediumTest
     @Feature("TabSuggestion")
     @EnableFeatures(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study")
-    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true"})
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
     public void testTabSuggestionMessageCard_review() throws InterruptedException {
+        // clang-format on
         prepareTabs(3, 0, null);
 
         CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
@@ -867,9 +873,12 @@
     @MediumTest
     @Feature("TabSuggestion")
     @EnableFeatures({ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study"})
-    @CommandLineFlags.Add({BASE_PARAMS + "/cleanup-delay/10000/baseline_tab_suggestions/true"})
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
     public void testShowOnlyOneTabSuggestionMessageCard_withSoftCleanup()
             throws InterruptedException {
+        // clang-format on
         verifyOnlyOneTabSuggestionMessageCardIsShowing();
     }
 
@@ -877,9 +886,12 @@
     @MediumTest
     @Feature("TabSuggestion")
     @EnableFeatures({ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study"})
-    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true"})
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
     public void testShowOnlyOneTabSuggestionMessageCard_withHardCleanup()
             throws InterruptedException {
+        // clang-format on
         verifyOnlyOneTabSuggestionMessageCardIsShowing();
     }
 
@@ -887,8 +899,11 @@
     @MediumTest
     @Feature("TabSuggestion")
     @EnableFeatures({ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study"})
-    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true"})
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
     public void testTabSuggestionMessageCardDismissAfterTabClosing() throws InterruptedException {
+        // clang-format on
         prepareTabs(3, 0, mUrl);
         CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
         CriteriaHelper.pollUiThread(Criteria.equals(3, this::getTabCountInCurrentTabModel));
@@ -968,8 +983,11 @@
     @MediumTest
     @Feature("TabSuggestion")
     @EnableFeatures(ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study")
-    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true"})
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
     public void testTabSuggestionMessageCard_orientation() throws InterruptedException {
+        // clang-format on
         ChromeTabbedActivity cta = mActivityTestRule.getActivity();
         prepareTabs(3, 0, null);
 
@@ -1646,7 +1664,8 @@
     @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID,
             ChromeFeatureList.CLOSE_TAB_SUGGESTIONS + "<Study"})
     @DisableFeatures(ChromeFeatureList.TAB_TO_GTS_ANIMATION + "<Study")
-    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true"})
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
     public void testTabGroupManualSelection_AfterReviewTabSuggestion() throws InterruptedException {
         // clang-format on
         ChromeTabbedActivity cta = mActivityTestRule.getActivity();
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn
index 3caa3c9..a978f94 100644
--- a/chrome/android/features/tab_ui/BUILD.gn
+++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -159,7 +159,7 @@
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiColorProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java",
-    "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineStaleTabSuggestionProvider.java",
+    "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineTabSuggestionProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/StaleTabSuggestionProvider.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserver.java",
     "java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionProvider.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
index f8c8007..96659a4 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
@@ -9,6 +9,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.annotation.Nullable;
+
 /**
  * This is the coordinator for MessageCardProvider component. This component is used to build a
  * TabGridMessageCardView for each {@link MessageService.MessageType}. This coordinator manages the
@@ -36,14 +38,24 @@
 
     /**
      * Get all messages.
-     * @return a list of {@link
-     *         MessageCardProviderMediator.Message}.
+     * @return a list of {@link MessageCardProviderMediator.Message}.
      */
     public List<MessageCardProviderMediator.Message> getMessageItems() {
         return mMediator.getMessageItems();
     }
 
     /**
+     * @param messageType The {@link MessageService#mMessageType} associates with the message.
+     * @return The next {@link MessageCardProviderMediator.Message} for the given messageType, if
+     *         there is any. Otherwise returns null.
+     */
+    @Nullable
+    public MessageCardProviderMediator.Message getNextMessageItemForType(
+            @MessageService.MessageType int messageType) {
+        return mMediator.getNextMessageItemForType(messageType);
+    }
+
+    /**
      * Clean up all member fields.
      */
     public void destroy() {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
index 430f7fc4..520f78b 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
@@ -67,6 +67,21 @@
         return new ArrayList<>(mShownMessageItems.values());
     }
 
+    Message getNextMessageItemForType(@MessageService.MessageType int messageType) {
+        if (mShownMessageItems.containsKey(messageType)) return mShownMessageItems.get(messageType);
+
+        if (!mMessageItems.containsKey(messageType)) return null;
+
+        List<Message> messages = mMessageItems.get(messageType);
+
+        assert messages.size() > 0;
+        mShownMessageItems.put(messageType, messages.remove(0));
+
+        if (messages.size() == 0) mMessageItems.remove(messageType);
+
+        return mShownMessageItems.get(messageType);
+    }
+
     private PropertyModel buildModel(int messageType, MessageService.MessageData data) {
         switch (messageType) {
             case TAB_SUGGESTION:
@@ -109,8 +124,8 @@
 
     @VisibleForTesting
     void invalidateShownMessage(@MessageService.MessageType int type) {
-        mUiDismissActionProvider.dismiss(type);
         mShownMessageItems.remove(type);
+        mUiDismissActionProvider.dismiss(type);
     }
 
     @VisibleForTesting
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
index 63ebb299..86a628d 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -255,6 +255,10 @@
         mTabModelSelectorTabObserver = new TabModelSelectorTabObserver(mTabModelSelector) {
             @Override
             public void onPageLoadStarted(Tab tab, String url) {
+                // TODO(crbug.com/1087826) This is a band-aid fix for M84. The root cause is
+                // probably a leaked observer. Remove this when the TabObservers are removed during
+                // tab reparenting.
+                if (mTabModelSelector.getTabById(tab.getId()) == null) return;
                 List<Tab> listOfTabs = getTabsToShowForId(tab.getId());
                 int numTabs = listOfTabs.size();
                 // This is set to zero because the UI is hidden.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index e3ecc13..f7c4fcd 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -1073,11 +1073,8 @@
      */
     void updateSpanCountForOrientation(GridLayoutManager manager, int orientation) {
         // When in multi-window mode, the span count is fixed to 2 to keep tab card size reasonable.
-        if (MultiWindowUtils.getInstance().isInMultiWindowMode((Activity) mContext)) {
-            manager.setSpanCount(TabListCoordinator.GRID_LAYOUT_SPAN_COUNT_PORTRAIT);
-            return;
-        }
         int spanCount = orientation == Configuration.ORIENTATION_PORTRAIT
+                        || MultiWindowUtils.getInstance().isInMultiWindowMode((Activity) mContext)
                 ? TabListCoordinator.GRID_LAYOUT_SPAN_COUNT_PORTRAIT
                 : TabListCoordinator.GRID_LAYOUT_SPAN_COUNT_LANDSCAPE;
         manager.setSpanCount(spanCount);
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 15be38f..6f3b49a 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
@@ -53,7 +53,7 @@
                 activity.getTabModelSelector(), activity.getTabContentManager(),
                 activity.getFullscreenManager(), activity,
                 activity.getMenuOrKeyboardActionController(), containerView,
-                activity.getShareDelegateSupplier(),
+                activity.getShareDelegateSupplier(), activity.getMultiWindowModeStateDispatcher(),
                 TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled()
                                 && SysUtils.isLowEndDevice()
                         ? TabListCoordinator.TabListMode.LIST
@@ -66,7 +66,8 @@
                 activity.getTabModelSelector(), activity.getTabContentManager(),
                 activity.getFullscreenManager(), activity,
                 activity.getMenuOrKeyboardActionController(), containerView,
-                activity.getShareDelegateSupplier(), TabListCoordinator.TabListMode.CAROUSEL);
+                activity.getShareDelegateSupplier(), activity.getMultiWindowModeStateDispatcher(),
+                TabListCoordinator.TabListMode.CAROUSEL);
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
index ad837ed..1f34aab 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -26,6 +26,7 @@
 import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.Destroyable;
+import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
 import org.chromium.chrome.browser.share.ShareDelegate;
 import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
 import org.chromium.chrome.browser.tabmodel.TabList;
@@ -94,6 +95,7 @@
     private final TabModelSelector mTabModelSelector;
     private final @TabListCoordinator.TabListMode int mMode;
     private final MessageCardProviderCoordinator mMessageCardProviderCoordinator;
+    private final MultiWindowModeStateDispatcher mMultiWindowModeStateDispatcher;
 
     private TabSelectionEditorCoordinator mTabSelectionEditorCoordinator;
     private TabGroupManualSelectionMode mTabGroupManualSelectionMode;
@@ -136,16 +138,19 @@
             ChromeFullscreenManager fullscreenManager, TabCreatorManager tabCreatorManager,
             MenuOrKeyboardActionController menuOrKeyboardActionController, ViewGroup container,
             ObservableSupplier<ShareDelegate> shareDelegateSupplier,
+            MultiWindowModeStateDispatcher multiWindowModeStateDispatcher,
             @TabListCoordinator.TabListMode int mode) {
         mMode = mode;
         mTabModelSelector = tabModelSelector;
         mContainer = container;
         mTabCreatorManager = tabCreatorManager;
+        mMultiWindowModeStateDispatcher = multiWindowModeStateDispatcher;
 
         PropertyModel containerViewModel = new PropertyModel(TabListContainerProperties.ALL_KEYS);
 
         mMediator = new TabSwitcherMediator(this, containerViewModel, tabModelSelector,
-                fullscreenManager, container, tabContentManager, this, mode);
+                fullscreenManager, container, tabContentManager, this,
+                multiWindowModeStateDispatcher, mode);
 
         mMultiThumbnailCardProvider =
                 new MultiThumbnailCardProvider(context, tabContentManager, tabModelSelector);
@@ -163,10 +168,12 @@
         mContainerViewChangeProcessor = PropertyModelChangeProcessor.create(containerViewModel,
                 mTabListCoordinator.getContainerView(), TabListContainerViewBinder::bind);
 
-        mMessageCardProviderCoordinator = new MessageCardProviderCoordinator(context,
-                (identifier)
-                        -> mTabListCoordinator.removeSpecialListItem(
-                                TabProperties.UiType.MESSAGE, identifier));
+        mMessageCardProviderCoordinator =
+                new MessageCardProviderCoordinator(context, (identifier) -> {
+                    mTabListCoordinator.removeSpecialListItem(
+                            TabProperties.UiType.MESSAGE, identifier);
+                    appendNextMessage(identifier);
+                });
 
         if (TabUiFeatureUtilities.isTabGroupsAndroidEnabled()) {
             mTabGridDialogCoordinator = new TabGridDialogCoordinator(context, tabModelSelector,
@@ -431,6 +438,7 @@
     }
 
     private void appendMessagesTo(int index) {
+        if (mMultiWindowModeStateDispatcher.isInMultiWindowMode()) return;
         sAppendedMessagesForTesting = false;
         List<MessageCardProviderMediator.Message> messages =
                 mMessageCardProviderCoordinator.getMessageItems();
@@ -441,6 +449,16 @@
         if (messages.size() > 0) sAppendedMessagesForTesting = true;
     }
 
+    private void appendNextMessage(@MessageService.MessageType int messageType) {
+        assert mMessageCardProviderCoordinator != null;
+
+        MessageCardProviderMediator.Message nextMessage =
+                mMessageCardProviderCoordinator.getNextMessageItemForType(messageType);
+        if (nextMessage == null) return;
+        mTabListCoordinator.addSpecialListItemToEnd(
+                TabProperties.UiType.MESSAGE, nextMessage.model);
+    }
+
     private View getTabGridDialogAnimationSourceView(int tabId) {
         int index = mTabListCoordinator.indexOfTab(tabId);
         // TODO(crbug.com/999372): This is band-aid fix that will show basic fade-in/fade-out
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
index 8f4f2ec..ad4cb6c 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -35,6 +35,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.fullscreen.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.init.FirstDrawDetector;
+import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabCreationState;
 import org.chromium.chrome.browser.tab.TabHidingType;
@@ -94,6 +95,8 @@
     private final BrowserControlsStateProvider.Observer mBrowserControlsObserver;
     private final ViewGroup mContainerView;
     private final TabContentManager mTabContentManager;
+    private final MultiWindowModeStateDispatcher mMultiWindowModeStateDispatcher;
+    private final MultiWindowModeStateDispatcher.MultiWindowModeObserver mMultiWindowModeObserver;
 
     private Integer mSoftCleanupDelayMsForTesting;
     private Integer mCleanupDelayMsForTesting;
@@ -189,17 +192,21 @@
      * @param browserControlsStateProvider {@link BrowserControlsStateProvider} to use.
      * @param containerView The container {@link ViewGroup} to use.
      * @param tabContentManager The {@link TabContentManager} for first meaningful paint event.
+     * @param multiWindowModeStateDispatcher The {@link MultiWindowModeStateDispatcher} to observe
+     *         for multi-window related changes.
      * @param mode One of the {@link TabListCoordinator.TabListMode}.
      */
     TabSwitcherMediator(ResetHandler resetHandler, PropertyModel containerViewModel,
             TabModelSelector tabModelSelector,
             BrowserControlsStateProvider browserControlsStateProvider, ViewGroup containerView,
             TabContentManager tabContentManager, MessageItemsController messageItemsController,
+            MultiWindowModeStateDispatcher multiWindowModeStateDispatcher,
             @TabListCoordinator.TabListMode int mode) {
         mResetHandler = resetHandler;
         mContainerViewModel = containerViewModel;
         mTabModelSelector = tabModelSelector;
         mBrowserControlsStateProvider = browserControlsStateProvider;
+        mMultiWindowModeStateDispatcher = multiWindowModeStateDispatcher;
         mMode = mode;
 
         mTabModelSelectorObserver = new EmptyTabModelSelectorObserver() {
@@ -364,6 +371,15 @@
         // TODO(crbug.com/982018): Let the start surface pass in the parameter and add unit test for
         // it. This is a temporary solution to keep this change minimum.
         mShowTabsInMruOrder = isShowingTabsInMRUOrder();
+
+        mMultiWindowModeObserver = isInMultiWindowMode -> {
+            if (isInMultiWindowMode) {
+                messageItemsController.removeAllAppendedMessage();
+            } else {
+                messageItemsController.restoreAllAppendedMessage();
+            }
+        };
+        mMultiWindowModeStateDispatcher.addObserver(mMultiWindowModeObserver);
     }
 
     /**
@@ -724,6 +740,7 @@
         mBrowserControlsStateProvider.removeObserver(mBrowserControlsObserver);
         mTabModelSelector.getTabModelFilterProvider().removeTabModelFilterObserver(
                 mTabModelObserver);
+        mMultiWindowModeStateDispatcher.removeObserver(mMultiWindowModeObserver);
     }
 
     void setOnTabSelectingListener(TabSwitcher.OnTabSelectingListener listener) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineStaleTabSuggestionProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineStaleTabSuggestionProvider.java
deleted file mode 100644
index 147c9dd..0000000
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineStaleTabSuggestionProvider.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.tasks.tab_management.suggestions;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * Baseline method for identifying Tab candidates which the user may want
- * to close due to lack of engagement. It returns all Tabs. This is
- * used for testing code upstream from the provider - not the provider
- * itself. This provider is very deterministic and creates very stable
- * instrumentation tests and tests for {@link TabSuggestionsOrchestrator}
- * and {@link TabSuggestionsClientFetcher}
- */
-public class BaselineStaleTabSuggestionProvider implements TabSuggestionProvider {
-    @Override
-    public List<TabSuggestion> suggest(TabContext tabContext) {
-        if (tabContext == null || tabContext.getUngroupedTabs() == null
-                || tabContext.getUngroupedTabs().size() < 1) {
-            return null;
-        }
-        List<TabContext.TabInfo> staleTabs = new ArrayList<>();
-        staleTabs.addAll(tabContext.getUngroupedTabs());
-        return Arrays.asList(new TabSuggestion(staleTabs, TabSuggestion.TabSuggestionAction.CLOSE,
-                TabSuggestionsRanker.SuggestionProviders.STALE_TABS_SUGGESTION_PROVIDER));
-    }
-}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineTabSuggestionProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineTabSuggestionProvider.java
new file mode 100644
index 0000000..b826ea5
--- /dev/null
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/BaselineTabSuggestionProvider.java
@@ -0,0 +1,49 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tasks.tab_management.suggestions;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Baseline method for identifying Tab candidates which the user may want
+ * to close or group due to lack of engagement. It returns all Tabs. This is
+ * used for testing code upstream from the provider - not the provider
+ * itself. This provider is very deterministic and creates very stable
+ * instrumentation tests and tests for {@link TabSuggestionsOrchestrator}
+ * and {@link TabSuggestionsClientFetcher}
+ */
+public class BaselineTabSuggestionProvider implements TabSuggestionProvider {
+    // Default action is TabSuggestion.TabSuggestionAction.CLOSE;
+    private final @TabSuggestion.TabSuggestionAction int mAction;
+
+    BaselineTabSuggestionProvider() {
+        this(TabSuggestion.TabSuggestionAction.CLOSE);
+    }
+
+    BaselineTabSuggestionProvider(@TabSuggestion.TabSuggestionAction int action) {
+        mAction = action;
+    }
+
+    @Override
+    public List<TabSuggestion> suggest(TabContext tabContext) {
+        if (tabContext == null || tabContext.getUngroupedTabs() == null
+                || tabContext.getUngroupedTabs().size() < 1) {
+            return null;
+        }
+        List<TabContext.TabInfo> tabs = new ArrayList<>();
+        tabs.addAll(tabContext.getUngroupedTabs());
+        return Arrays.asList(new TabSuggestion(tabs, mAction, getSuggestionProvider()));
+    }
+
+    private String getSuggestionProvider() {
+        switch (mAction) {
+            case TabSuggestion.TabSuggestionAction.CLOSE:
+                return TabSuggestionsRanker.SuggestionProviders.STALE_TABS_SUGGESTION_PROVIDER;
+        }
+        return "";
+    }
+}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsClientFetcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsClientFetcher.java
index f13d377..1404251 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsClientFetcher.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsClientFetcher.java
@@ -23,10 +23,22 @@
      * heuristics.
      */
     public TabSuggestionsClientFetcher() {
+        // TODO(crbug.com/1085251): Move the if block to some testing relevant file instead.
         if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
                     ChromeFeatureList.CLOSE_TAB_SUGGESTIONS, "baseline_tab_suggestions", false)) {
-            mClientSuggestionProviders =
-                    new ArrayList<>(Arrays.asList(new BaselineStaleTabSuggestionProvider()));
+            mClientSuggestionProviders = new ArrayList<>();
+            if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                        ChromeFeatureList.CLOSE_TAB_SUGGESTIONS, "baseline_group_tab_suggestions",
+                        false)) {
+                mClientSuggestionProviders.add(
+                        new BaselineTabSuggestionProvider(TabSuggestion.TabSuggestionAction.GROUP));
+            }
+            if (ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                        ChromeFeatureList.CLOSE_TAB_SUGGESTIONS, "baseline_close_tab_suggestions",
+                        false)) {
+                mClientSuggestionProviders.add(
+                        new BaselineTabSuggestionProvider(TabSuggestion.TabSuggestionAction.CLOSE));
+            }
         } else {
             mClientSuggestionProviders =
                     new ArrayList<>(Arrays.asList(new StaleTabSuggestionProvider()));
@@ -35,7 +47,7 @@
 
     protected void setUseBaselineTabSuggestionsForTesting() {
         mClientSuggestionProviders =
-                new ArrayList<>(Arrays.asList(new BaselineStaleTabSuggestionProvider()));
+                new ArrayList<>(Arrays.asList(new BaselineTabSuggestionProvider()));
     }
 
     @Override
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
index 946d9f56..aabc935 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestrator.java
@@ -117,6 +117,7 @@
                     break;
             }
         }
+        // TODO(crbug.com/1085452): Sort the suggestion based on priority.
         Collections.shuffle(aggregated);
         return aggregated;
     }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
index 34bad17..c98a6a5 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGridIphTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
+import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.clickFirstCardFromTabSwitcher;
 import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.closeFirstTabInTabSwitcher;
 import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.enterTabSwitcher;
 import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.getSwipeToDismissAction;
@@ -56,6 +57,7 @@
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
 import org.chromium.chrome.features.start_surface.StartSurfaceLayout;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -327,6 +329,27 @@
         onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
     }
 
+    @Test
+    @MediumTest
+    public void testNotShowIPHInMultiWindowMode() {
+        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        enterTabSwitcher(cta);
+        onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
+
+        // Mock that user enters multi-window mode, and the IPH message should not show in tab
+        // switcher.
+        clickFirstCardFromTabSwitcher(cta);
+        MultiWindowUtils.getInstance().setIsInMultiWindowModeForTesting(true);
+        enterTabSwitcher(cta);
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
+
+        // Mock that user exits multi-window mode, and the IPH message should show in tab switcher.
+        clickFirstCardFromTabSwitcher(cta);
+        MultiWindowUtils.getInstance().setIsInMultiWindowModeForTesting(false);
+        enterTabSwitcher(cta);
+        onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
+    }
+
     private void verifyIphDialogShowing(ChromeTabbedActivity cta) {
         // Verify IPH dialog view.
         onView(withId(R.id.iph_dialog))
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java
index c186c25..a7947c3 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java
@@ -6,13 +6,17 @@
 
 import static android.support.test.espresso.Espresso.onView;
 import static android.support.test.espresso.action.ViewActions.click;
+import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static android.support.test.espresso.assertion.ViewAssertions.matches;
 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
 import static android.support.test.espresso.matcher.ViewMatchers.withId;
 import static android.support.test.espresso.matcher.ViewMatchers.withParent;
+import static android.support.test.espresso.matcher.ViewMatchers.withText;
 
 import static org.hamcrest.core.AllOf.allOf;
 
+import static org.chromium.chrome.test.util.ViewUtils.onViewWaiting;
+
 import android.support.test.filters.MediumTest;
 
 import org.junit.Before;
@@ -22,16 +26,15 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.ui.test.util.UiRestriction;
 
@@ -42,67 +45,195 @@
 // clang-format off
 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
 @Features.EnableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
+        ChromeFeatureList.TAB_GROUPS_ANDROID,
         ChromeFeatureList.CLOSE_TAB_SUGGESTIONS+"<Study"})
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "force-fieldtrials=Study/Group",
-        "force-fieldtrial-params=Study.Group:baseline_tab_suggestions/true"})
+// Disable TAB_TO_GTS_ANIMATION to make it less flaky. When animation is enabled, the suggestion
+// cards will be removed temporarily, then append again.
+@Features.DisableFeatures({ChromeFeatureList.TAB_TO_GTS_ANIMATION})
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+        "force-fieldtrials=Study/Group"})
 public class TabSuggestionMessageCardTest {
     // clang-format on
+    private static final String BASE_PARAMS = "force-fieldtrial-params="
+            + "Study.Group:baseline_tab_suggestions/true";
     @Rule
     public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
 
     @Rule
     public TestRule mProcessor = new Features.InstrumentationProcessor();
 
+    private final TabSelectionEditorTestingRobot mTabSelectionEditorTestingRobot =
+            new TabSelectionEditorTestingRobot();
+    private final String mClosingSuggestionMessage =
+            "3 of your tabs haven't been used lately. Close them?";
+    private final String mGroupingSuggestionMessage = "3 tabs seem related. Group them?";
+
     @Before
     public void setUp() {
         mActivityTestRule.startMainActivityOnBlankPage();
         TabUiTestHelper.prepareTabsWithThumbnail(mActivityTestRule, 3, 0, "about:blank");
     }
 
-    @Test
-    @MediumTest
-    @FlakyTest(message = "crbug.com/1075650")
-    public void closeTabSuggestionReviewedAndAccepted() {
-        TabModel currentTabModel =
-                mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel();
-        CriteriaHelper.pollUiThread(Criteria.equals(3, currentTabModel::getCount));
-        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
-
+    private void enteringTabSwitcherAndVerifySuggestionIsShown(String suggestionText) {
         TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity());
         CriteriaHelper.pollUiThread(TabSwitcherCoordinator::hasAppendedMessagesForTesting);
-        onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
+        onView(allOf(withParent(withId(R.id.tab_grid_message_item)), withText(suggestionText)))
+                .check(matches(isDisplayed()));
+    }
 
+    private void reviewSuggestion() {
         onView(allOf(withId(R.id.action_button), withParent(withId(R.id.tab_grid_message_item))))
                 .perform(click());
-        TabSelectionEditorTestingRobot tabSelectionEditorTestingRobot =
-                new TabSelectionEditorTestingRobot();
-        tabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsVisible();
+        mTabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsVisible();
+    }
 
-        tabSelectionEditorTestingRobot.actionRobot.clickToolbarActionButton();
-        tabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsHidden();
-        CriteriaHelper.pollUiThread(Criteria.equals(0, currentTabModel::getCount));
+    private void acceptSuggestion() {
+        mTabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsVisible();
+        mTabSelectionEditorTestingRobot.actionRobot.clickToolbarActionButton();
+        mTabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsHidden();
+    }
+
+    private void dismissSuggestion(boolean isReviewed) {
+        if (isReviewed) {
+            mTabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsVisible();
+            mTabSelectionEditorTestingRobot.actionRobot.clickToolbarNavigationButton();
+            mTabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsHidden();
+        } else {
+            onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
+            onView(allOf(withId(R.id.close_button), withParent(withId(R.id.tab_grid_message_item))))
+                    .perform(click());
+        }
     }
 
     @Test
     @MediumTest
+    @FlakyTest(message = "crbug.com/1075650")
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_close_tab_suggestions/true"})
+    public void closeTabSuggestionReviewedAndAccepted() {
+        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
+
+        enteringTabSwitcherAndVerifySuggestionIsShown(mClosingSuggestionMessage);
+        reviewSuggestion();
+        acceptSuggestion();
+
+        onViewWaiting(allOf(withParent(withId(R.id.snackbar)), withText("3 tabs closed")));
+    }
+
+    @Test
+    @MediumTest
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_close_tab_suggestions/true"})
     public void closeTabSuggestionReviewedAndDismissed() {
-        TabModel currentTabModel =
-                mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel();
-        CriteriaHelper.pollUiThread(Criteria.equals(3, currentTabModel::getCount));
+        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
+
+        enteringTabSwitcherAndVerifySuggestionIsShown(mClosingSuggestionMessage);
+        reviewSuggestion();
+        dismissSuggestion(true);
+
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
+    }
+
+    @Test
+    @MediumTest
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_group_tab_suggestions/true"})
+    public void groupTabSuggestionReviewedAndAccepted() {
+        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
+
+        enteringTabSwitcherAndVerifySuggestionIsShown(mGroupingSuggestionMessage);
+        reviewSuggestion();
+        acceptSuggestion();
+
+        onViewWaiting(allOf(withParent(withId(R.id.snackbar)), withText("3 tabs grouped")));
+    }
+
+    @Test
+    @MediumTest
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_group_tab_suggestions/true"})
+    public void groupTabSuggestionReviewedAndDismissed() {
+        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
+
+        enteringTabSwitcherAndVerifySuggestionIsShown(mGroupingSuggestionMessage);
+        reviewSuggestion();
+        dismissSuggestion(true);
+
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
+    }
+
+    @Test
+    @MediumTest
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_group_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
+    @DisabledTest(message = "crbug.com/1085452 Enable this test and remove the one below if the" +
+            "bug is resolved")
+    public void groupAndCloseTabSuggestionDismissedAndShowNext() {
+        // clang-format on
+        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
+
+        enteringTabSwitcherAndVerifySuggestionIsShown(mGroupingSuggestionMessage);
+        dismissSuggestion(false);
+        onView(allOf(withParent(withId(R.id.tab_grid_message_item)),
+                       withText(mClosingSuggestionMessage)))
+                .check(matches(isDisplayed()));
+        dismissSuggestion(false);
+
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
+    }
+
+    @Test
+    @MediumTest
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_group_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
+    public void groupAndCloseTabSuggestionDismissedAndShowNext_temp() {
+        // clang-format on
         CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
 
         TabUiTestHelper.enterTabSwitcher(mActivityTestRule.getActivity());
         CriteriaHelper.pollUiThread(TabSwitcherCoordinator::hasAppendedMessagesForTesting);
         onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
 
-        onView(allOf(withId(R.id.action_button), withParent(withId(R.id.tab_grid_message_item))))
-                .perform(click());
-        TabSelectionEditorTestingRobot tabSelectionEditorTestingRobot =
-                new TabSelectionEditorTestingRobot();
-        tabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsVisible();
+        dismissSuggestion(false);
+        onView(withId(R.id.tab_grid_message_item)).check(matches(isDisplayed()));
+        dismissSuggestion(false);
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
+    }
 
-        tabSelectionEditorTestingRobot.actionRobot.clickToolbarNavigationButton();
-        tabSelectionEditorTestingRobot.resultRobot.verifyTabSelectionEditorIsHidden();
-        CriteriaHelper.pollUiThread(Criteria.equals(3, currentTabModel::getCount));
+    @Test
+    @MediumTest
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_group_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
+    @DisabledTest(message = "crbug.com/1085452 Enable this test if the bug is resolved")
+    public void groupAndCloseTabSuggestionReviewDismissedAndShowNext() {
+        // clang-format on
+        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
+
+        enteringTabSwitcherAndVerifySuggestionIsShown(mGroupingSuggestionMessage);
+        reviewSuggestion();
+        dismissSuggestion(true);
+        onView(allOf(withParent(withId(R.id.tab_grid_message_item)),
+                       withText(mClosingSuggestionMessage)))
+                .check(matches(isDisplayed()));
+        reviewSuggestion();
+        dismissSuggestion(true);
+
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
+    }
+
+    @Test
+    @MediumTest
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS + "/baseline_group_tab_suggestions/true" +
+            "/baseline_close_tab_suggestions/true"})
+    @DisabledTest(message = "crbug.com/1085452 Enable this test if the bug is resolved")
+    public void groupAndCloseTabSuggestionAccepted() {
+        // clang-format on
+        CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
+
+        enteringTabSwitcherAndVerifySuggestionIsShown(mGroupingSuggestionMessage);
+        reviewSuggestion();
+        acceptSuggestion();
+
+        onView(withId(R.id.tab_grid_message_item)).check(doesNotExist());
     }
 }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
index e11a319..fe241377 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediatorUnitTest.java
@@ -47,6 +47,7 @@
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.fullscreen.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabHidingType;
 import org.chromium.chrome.browser.tab.TabSelectionType;
@@ -123,6 +124,8 @@
     TabGridDialogMediator.DialogController mTabGridDialogController;
     @Mock
     TabSwitcherMediator.MessageItemsController mMessageItemsController;
+    @Mock
+    MultiWindowModeStateDispatcher mMultiWindowModeStateDispatcher;
 
     @Captor
     ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor;
@@ -131,6 +134,9 @@
     @Captor
     private ArgumentCaptor<BrowserControlsStateProvider.Observer>
             mBrowserControlsStateProviderObserverCaptor;
+    @Captor
+    ArgumentCaptor<MultiWindowModeStateDispatcher.MultiWindowModeObserver>
+            mMultiWindowModeObserverCaptor;
 
     private Tab mTab1;
     private Tab mTab2;
@@ -185,12 +191,15 @@
         doNothing()
                 .when(mBrowserControlsStateProvider)
                 .addObserver(mBrowserControlsStateProviderObserverCaptor.capture());
+        doReturn(true)
+                .when(mMultiWindowModeStateDispatcher)
+                .addObserver(mMultiWindowModeObserverCaptor.capture());
 
         mModel = new PropertyModel(TabListContainerProperties.ALL_KEYS);
         mModel.addObserver(mPropertyObserver);
         mMediator = new TabSwitcherMediator(mResetHandler, mModel, mTabModelSelector,
                 mBrowserControlsStateProvider, mCompositorViewHolder, null, mMessageItemsController,
-                TabListCoordinator.TabListMode.GRID);
+                mMultiWindowModeStateDispatcher, TabListCoordinator.TabListMode.GRID);
         mMediator.initWithNative(null);
         mMediator.addOverviewModeObserver(mOverviewModeObserver);
         mMediator.setOnTabSelectingListener(mLayout::onTabSelecting);
@@ -677,6 +686,24 @@
         assertEquals(0, mModel.get(TabListContainerProperties.SHADOW_TOP_MARGIN));
     }
 
+    @Test
+    public void enterMultiWindowMode() {
+        initAndAssertAllProperties();
+
+        mMultiWindowModeObserverCaptor.getValue().onMultiWindowModeChanged(true);
+
+        verify(mMessageItemsController).removeAllAppendedMessage();
+    }
+
+    @Test
+    public void exitMultiWindowMode() {
+        initAndAssertAllProperties();
+
+        mMultiWindowModeObserverCaptor.getValue().onMultiWindowModeChanged(false);
+
+        verify(mMessageItemsController).restoreAllAppendedMessage();
+    }
+
     private void initAndAssertAllProperties() {
         assertThat(mModel.get(TabListContainerProperties.VISIBILITY_LISTENER),
                 instanceOf(TabSwitcherMediator.class));
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
index eb2cb53..d76448e 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -39,8 +39,6 @@
 import org.chromium.chrome.browser.feed.shared.stream.NonDismissibleHeader;
 import org.chromium.chrome.browser.feed.shared.stream.Stream;
 import org.chromium.chrome.browser.feed.tooltip.BasicTooltipApi;
-import org.chromium.chrome.browser.feed.v2.FeedServiceBridge;
-import org.chromium.chrome.browser.feed.v2.FeedStreamSurface;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.native_page.ContextMenuManager;
 import org.chromium.chrome.browser.native_page.NativePageNavigationDelegate;
@@ -81,7 +79,6 @@
     private final int mDefaultMargin;
     private final int mWideMargin;
     private final FeedSurfaceMediator mMediator;
-    private FeedStreamSurface mFeedStreamSurface;
 
     private UiConfig mUiConfig;
     private FrameLayout mRootView;
@@ -345,15 +342,6 @@
             mMediator.onHomepagePromoStateChange();
         }
 
-        // Native should already have been loaded because of FeedSurfaceMediator.
-        if (FeedServiceBridge.isEnabled()) {
-            // TODO(jianli): Temporary: simulate opening the feed V2 surface. This should probably
-            // move to FeedSurfaceMediator.
-            mFeedStreamSurface = new FeedStreamSurface(
-                    tabModelSelector, tabProvider, mActivity, mSnackbarManager);
-            mFeedStreamSurface.surfaceOpened();
-        }
-
         mUserEducationHelper = new UserEducationHelper(mActivity);
     }
 
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java
index 757af8ca..f02759c 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStream.java
@@ -471,15 +471,9 @@
         new ItemTouchHelper(new StreamItemTouchCallbacks()).attachToRecyclerView(mRecyclerView);
         mRecyclerView.setAdapter(mAdapter);
         mRecyclerView.setClipToPadding(false);
-        if (VERSION.SDK_INT > VERSION_CODES.JELLY_BEAN) {
-            mRecyclerView.setPaddingRelative(mStreamConfiguration.getPaddingStart(),
-                    mStreamConfiguration.getPaddingTop(), mStreamConfiguration.getPaddingEnd(),
-                    mStreamConfiguration.getPaddingBottom());
-        } else {
-            mRecyclerView.setPadding(mStreamConfiguration.getPaddingStart(),
-                    mStreamConfiguration.getPaddingTop(), mStreamConfiguration.getPaddingEnd(),
-                    mStreamConfiguration.getPaddingBottom());
-        }
+        mRecyclerView.setPaddingRelative(mStreamConfiguration.getPaddingStart(),
+                mStreamConfiguration.getPaddingTop(), mStreamConfiguration.getPaddingEnd(),
+                mStreamConfiguration.getPaddingBottom());
 
         mItemAnimator = new StreamItemAnimator(
                 mStreamContentChangedListener, mActionManager, mRecyclerView);
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtils.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtils.java
index ab6ad82a..ec33406d 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtils.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtils.java
@@ -7,10 +7,6 @@
 import android.annotation.TargetApi;
 import android.content.Context;
 import android.os.Build;
-import android.os.Build.VERSION;
-import android.text.TextUtils;
-
-import androidx.annotation.VisibleForTesting;
 
 import java.util.Locale;
 
@@ -29,33 +25,6 @@
 
     /** Returns a string which represents the top locale and region of the device. */
     public static String getLanguageTag(Context context) {
-        return getLanguageTag(getLocale(context));
-    }
-
-    /** Returns a string representation of a specified locale and region. */
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    @VisibleForTesting
-    static String getLanguageTag(Locale locale) {
-        return (VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
-                ? locale.toLanguageTag()
-                : getLanguageTagPreLollipop(locale);
-    }
-
-    private static String getLanguageTagPreLollipop(Locale locale) {
-        StringBuilder sb = new StringBuilder();
-        String language = locale.getLanguage();
-        if (TextUtils.isEmpty(language)) {
-            language = "und";
-        }
-        sb.append(language);
-        String variant = locale.getVariant();
-        if (!TextUtils.isEmpty(variant)) {
-            sb.append("-").append(variant);
-        }
-        String country = locale.getCountry();
-        if (!TextUtils.isEmpty(country)) {
-            sb.append("-").append(country);
-        }
-        return sb.toString();
+        return getLocale(context).toLanguageTag();
     }
 }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/StyleProvider.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/StyleProvider.java
index d6bc231a..9bd4331b 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/StyleProvider.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/StyleProvider.java
@@ -7,8 +7,6 @@
 import android.content.Context;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
@@ -387,20 +385,16 @@
         marginLayoutParams.setMargins(startMargin,
                 (int) LayoutUtils.dpToPx(margins.getTop(), context), endMargin,
                 (int) LayoutUtils.dpToPx(margins.getBottom(), context));
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            marginLayoutParams.setMarginStart(startMargin);
-            marginLayoutParams.setMarginEnd(endMargin);
-        }
+        marginLayoutParams.setMarginStart(startMargin);
+        marginLayoutParams.setMarginEnd(endMargin);
     }
 
     FrameLayout createWrapperView(Context context, RoundedCornerMaskCache maskCache,
             boolean allowClipPathRounding, boolean allowOutlineRounding) {
         if (!hasRoundedCorners()) {
             FrameLayout view = new FrameLayout(context);
-            if (Build.VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
-                // The wrapper view gets elevation; set an outline so it can cast a shadow.
-                view.setOutlineProvider(ViewOutlineProvider.BOUNDS);
-            }
+            // The wrapper view gets elevation; set an outline so it can cast a shadow.
+            view.setOutlineProvider(ViewOutlineProvider.BOUNDS);
             return view;
         }
         int radiusOverride = getRoundedCorners().getUseHostRadiusOverride()
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapter.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapter.java
index e4353f4..d2805610 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapter.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapter.java
@@ -7,8 +7,6 @@
 import android.content.Context;
 import android.graphics.Typeface;
 import android.os.Build;
-import android.os.Build.VERSION;
-import android.os.Build.VERSION_CODES;
 import android.text.Layout;
 import android.text.TextUtils;
 import android.view.View;
@@ -99,21 +97,7 @@
         }
         float letterSpacingDp = textStyle.getFont().getLetterSpacingDp();
         float letterSpacingEm = letterSpacingDp / textSize;
-        if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
-            textView.setLetterSpacing(letterSpacingEm);
-        } else {
-            // Letter spacing wasn't supported before L. We substitute SetTextScaleX, which actually
-            // stretches the letters, rather than just adding space between them. It won't look
-            // exactly the same, but we can use it to get close to the same width for a set of
-            // characters.
-            float extraLetterSpaceDp = letterSpacingEm * textSize;
-            // It can vary by font and character, but typically letter width is about half of
-            // height.
-            float approximateLetterwidth = textSize / 2;
-            float textScale =
-                    (approximateLetterwidth + extraLetterSpaceDp) / approximateLetterwidth;
-            textView.setTextScaleX(textScale);
-        }
+        textView.setLetterSpacing(letterSpacingEm);
     }
 
     @Override
@@ -135,10 +119,7 @@
     @Override
     void onUnbindModel() {
         TextView textView = getBaseView();
-
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
-            textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
-        }
+        textView.setTextAlignment(View.TEXT_ALIGNMENT_GRAVITY);
         textView.setText("");
     }
 
@@ -183,14 +164,6 @@
         }
         int extraPaddingForLineHeightTop = totalExtraPadding / 2;
         int extraPaddingForLineHeightBottom = totalExtraPadding - extraPaddingForLineHeightTop;
-        // In API version 21 (Lollipop), the implementation of lineSpacingMultiplier() changed to
-        // add no extra space beneath a block of text. Before API 21, we need to subtract the extra
-        // padding (so that only half the padding is on the bottom). That means
-        // extraPaddingForLineHeightBottom needs to be negative.
-        if (VERSION.SDK_INT < VERSION_CODES.LOLLIPOP) {
-            extraPaddingForLineHeightBottom =
-                    -(extraLineHeightBetweenLines - extraPaddingForLineHeightBottom);
-        }
 
         mExtraLineHeight = ExtraLineHeight.builder()
                                    .setTopPaddingPx(extraPaddingForLineHeightTop)
@@ -330,7 +303,7 @@
 
     private static TextView createView(Context context) {
         TextView view = new TextView(context);
-        if (Build.VERSION.SDK_INT >= VERSION_CODES.M) {
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
             view.setBreakStrategy(Layout.BREAK_STRATEGY_SIMPLE);
         }
         return view;
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperView.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperView.java
index 2db04a5..69048fe21 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperView.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperView.java
@@ -6,14 +6,11 @@
 
 import static org.chromium.chrome.browser.feed.library.common.Validators.checkState;
 
-import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.graphics.drawable.shapes.RoundRectShape;
-import android.os.Build;
-import android.os.Build.VERSION;
 import android.view.View;
 import android.view.ViewOutlineProvider;
 import android.view.ViewParent;
@@ -95,23 +92,14 @@
 
         setRoundingStrategy();
 
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            // Even when not using the outline provider strategy, the outline needs to be set for
-            // shadows to render properly.
-            setupOutlineProvider();
-        }
+        // Even when not using the outline provider strategy, the outline needs to be set for
+        // shadows to render properly.
+        setupOutlineProvider();
         setWillNotDraw(false);
     }
 
     private void setRoundingStrategy() {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && mAllowClipPath) {
-            setRoundingDelegate(RoundingStrategy.CLIP_PATH);
-            if (VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
-                // clipPath doesn't work with hardware rendering on < 18.
-                setLayerType(LAYER_TYPE_SOFTWARE, null);
-            }
-        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && mAllFourCornersRounded
-                && mAllowOutlineRounding) {
+        if (mAllFourCornersRounded && mAllowOutlineRounding) {
             setRoundingDelegate(RoundingStrategy.OUTLINE_PROVIDER);
         } else {
             setRoundingDelegate(RoundingStrategy.BITMAP_MASKING);
@@ -138,7 +126,6 @@
         mRoundingDelegate.initializeForView(this);
     }
 
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
     private void setupOutlineProvider() {
         if (mHasRoundedCorners) {
             super.setOutlineProvider(new ViewOutlineProvider() {
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTracker.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTracker.java
new file mode 100644
index 0000000..130bfab
--- /dev/null
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTracker.java
@@ -0,0 +1,92 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.feed.v2;
+
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import java.util.HashSet;
+
+/**
+ * Tracks position of slice views. When a slice's view is first 2/3rds visible in the viewport,
+ * the observer is notified.
+ */
+class FeedSliceViewTracker implements ViewTreeObserver.OnPreDrawListener {
+    private static final String TAG = "FeedSliceViewTracker";
+    private static final double DEFAULT_VIEW_LOG_THRESHOLD = .66;
+
+    @Nullable
+    private RecyclerView mRootView;
+    @Nullable
+    private FeedListContentManager mContentManager;
+    // The set of content keys already reported as visible.
+    private HashSet<String> mContentKeysVisible = new HashSet<String>();
+    @Nullable
+    private Observer mObserver;
+
+    /** Notified the first time slices are visible */
+    public interface Observer {
+        void sliceVisible(String sliceId);
+    }
+
+    FeedSliceViewTracker(@NonNull RecyclerView rootView,
+            @NonNull FeedListContentManager contentManager, @NonNull Observer observer) {
+        mRootView = (RecyclerView) rootView;
+        mContentManager = contentManager;
+        mObserver = observer;
+        mRootView.getViewTreeObserver().addOnPreDrawListener(this);
+    }
+
+    /** Stop observing rootView. Prevents further calls to observer. */
+    public void destroy() {
+        if (mRootView != null && mRootView.getViewTreeObserver().isAlive()) {
+            mRootView.getViewTreeObserver().removeOnPreDrawListener(this);
+        }
+        mRootView = null;
+        mObserver = null;
+        mContentManager = null;
+    }
+
+    // ViewTreeObserver.OnPreDrawListener.
+    @Override
+    public boolean onPreDraw() {
+        // Not sure why, but this method can be called just after destroy().
+        if (mRootView == null) return false;
+        if (!(mRootView.getLayoutManager() instanceof LinearLayoutManager)) return true;
+
+        LinearLayoutManager layoutManager = (LinearLayoutManager) mRootView.getLayoutManager();
+        int firstPosition = layoutManager.findFirstVisibleItemPosition();
+        int lastPosition = layoutManager.findLastVisibleItemPosition();
+        for (int i = firstPosition;
+                i <= lastPosition && i < mContentManager.getItemCount() && i >= 0; ++i) {
+            String contentKey = mContentManager.getContent(i).getKey();
+            View childView = layoutManager.findViewByPosition(i);
+            if (mContentKeysVisible.contains(contentKey) || childView == null
+                    || !isViewVisible(childView)) {
+                continue;
+            }
+            mContentKeysVisible.add(contentKey);
+            mObserver.sliceVisible(contentKey);
+        }
+        return true;
+    }
+
+    @VisibleForTesting
+    boolean isViewVisible(View childView) {
+        Rect rect = new Rect(0, 0, childView.getWidth(), childView.getHeight());
+        int viewArea = rect.width() * rect.height();
+        if (viewArea <= 0) return false;
+        if (!mRootView.getChildVisibleRect(childView, rect, null)) return false;
+        int visibleArea = rect.width() * rect.height();
+        return (float) visibleArea / viewArea >= DEFAULT_VIEW_LOG_THRESHOLD;
+    }
+}
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
index 5965433..c97b5ac 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java
@@ -32,8 +32,10 @@
     private final ObserverList<ScrollListener> mScrollListeners;
 
     private RecyclerView mRecyclerView;
-    // TODO(jianli): To be used.
-    private boolean mIsStreamContentVisible = true;
+    // setStreamContentVisibility() is always called once after onCreate(). So we can assume the
+    // stream content is hidden initially and it can be made visible later when
+    // setStreamContentVisibility() is called.
+    private boolean mIsStreamContentVisible = false;
 
     public FeedStream(
             Activity activity, boolean isBackgroundDark, SnackbarManager snackbarManager) {
@@ -87,6 +89,12 @@
             return;
         }
         mIsStreamContentVisible = visible;
+
+        if (visible) {
+            mFeedStreamSurface.surfaceOpened();
+        } else {
+            mFeedStreamSurface.surfaceClosed();
+        }
     }
 
     @Override
@@ -159,6 +167,8 @@
     public void triggerRefresh() {}
 
     private void setupRecyclerView() {
+        assert (!mIsStreamContentVisible);
+
         mRecyclerView = (RecyclerView) mFeedStreamSurface.getView();
         mRecyclerView.setId(R.id.feed_stream_recycler_view);
         mRecyclerView.setClipToPadding(false);
@@ -170,7 +180,5 @@
                 }
             }
         });
-
-        mFeedStreamSurface.surfaceOpened();
     }
 }
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
index 136d2eb..31023b9 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java
@@ -9,7 +9,9 @@
 import android.view.View;
 import android.widget.TextView;
 
+import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
+import androidx.recyclerview.widget.RecyclerView;
 
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
@@ -63,6 +65,8 @@
     private final HybridListRenderer mHybridListRenderer;
     private final SnackbarManager mSnackbarManager;
     private final Activity mActivity;
+    @Nullable
+    private FeedSliceViewTracker mSliceViewTracker;
 
     private int mHeaderCount;
 
@@ -146,6 +150,14 @@
 
         if (mHybridListRenderer != null) {
             mRootView = mHybridListRenderer.bind(mContentManager);
+            // XSurface returns a View, but it should be a RecyclerView.
+            assert (mRootView instanceof RecyclerView);
+
+            mSliceViewTracker = new FeedSliceViewTracker(
+                    (RecyclerView) mRootView, mContentManager, (String sliceId) -> {
+                        FeedStreamSurfaceJni.get().reportSliceViewed(
+                                mNativeFeedStreamSurface, FeedStreamSurface.this, sliceId);
+                    });
         } else {
             mRootView = null;
         }
@@ -155,8 +167,12 @@
      * Performs all necessary cleanups.
      */
     public void destroy() {
+        if (mSliceViewTracker != null) {
+            mSliceViewTracker.destroy();
+            mSliceViewTracker = null;
+        }
         mHybridListRenderer.unbind();
-        FeedStreamSurfaceJni.get().surfaceClosed(mNativeFeedStreamSurface, FeedStreamSurface.this);
+        surfaceClosed();
     }
 
     /**
@@ -374,6 +390,17 @@
         FeedStreamSurfaceJni.get().surfaceOpened(mNativeFeedStreamSurface, FeedStreamSurface.this);
     }
 
+    /**
+     * Informs that the surface is closed.
+     */
+    public void surfaceClosed() {
+        int feedCount = mContentManager.getItemCount() - mHeaderCount;
+        if (feedCount > 0) {
+            mContentManager.removeContents(mHeaderCount, feedCount);
+        }
+        FeedStreamSurfaceJni.get().surfaceClosed(mNativeFeedStreamSurface, FeedStreamSurface.this);
+    }
+
     @NativeMethods
     interface Natives {
         long init(FeedStreamSurface caller);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageCardRenderTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageCardRenderTest.java
index b43be34..d8df9a2d2 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageCardRenderTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageCardRenderTest.java
@@ -57,7 +57,7 @@
         "disable-features=IPH_FeedHeaderMenu"})
 @Features.EnableFeatures({ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS,
     ChromeFeatureList.OMNIBOX_SEARCH_ENGINE_LOGO})
-@Features.DisableFeatures(ChromeFeatureList.REPORT_FEED_USER_ACTIONS)
+@Features.DisableFeatures({ChromeFeatureList.REPORT_FEED_USER_ACTIONS, ChromeFeatureList.QUERY_TILES})
 public class FeedNewTabPageCardRenderTest {
     //clang-format on
     private static final String TEST_FEED_DATA_BASE_PATH = "/chrome/test/data/android/feed/";
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
index 0f485a95..e5e9ec6 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/FeedNewTabPageTest.java
@@ -42,6 +42,7 @@
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.RuleChain;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.params.ParameterAnnotations;
@@ -74,6 +75,7 @@
 import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
 import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites;
 import org.chromium.components.embedder_support.util.UrlConstants;
+import org.chromium.components.signin.test.util.FakeAccountManagerFacade;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.net.test.EmbeddedTestServer;
 
@@ -90,7 +92,8 @@
 @CommandLineFlags.
 Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "disable-features=IPH_FeedHeaderMenu"})
 @Features.EnableFeatures(ChromeFeatureList.INTEREST_FEED_CONTENT_SUGGESTIONS)
-@Features.DisableFeatures(ChromeFeatureList.REPORT_FEED_USER_ACTIONS)
+@Features.
+DisableFeatures({ChromeFeatureList.REPORT_FEED_USER_ACTIONS, ChromeFeatureList.QUERY_TILES})
 public class FeedNewTabPageTest {
     private static final int ARTICLE_SECTION_HEADER_POSITION = 1;
     private static final int SIGNIN_PROMO_POSITION = 2;
@@ -101,14 +104,30 @@
     private static final ViewAction SWIPE_LEFT = new GeneralSwipeAction(
             Swipe.FAST, GeneralLocation.CENTER, GeneralLocation.CENTER_LEFT, Press.FINGER);
 
-    @Rule
-    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+    private boolean mIsCachePopulatedInAccountManagerFacade = true;
 
     @Rule
-    public SuggestionsDependenciesRule mSuggestionsDeps = new SuggestionsDependenciesRule();
+    public final SuggestionsDependenciesRule mSuggestionsDeps = new SuggestionsDependenciesRule();
 
+    private final ChromeTabbedActivityTestRule mActivityTestRule =
+            new ChromeTabbedActivityTestRule();
+
+    private final AccountManagerTestRule mAccountManagerTestRule =
+            new AccountManagerTestRule(new FakeAccountManagerFacade(null) {
+                @Override
+                public boolean isCachePopulated() {
+                    // Attention. When isCachePopulated() returns false,
+                    // runAfterCacheIsPopulated(...) shouldn't run. If this becomes a problem,
+                    // we can override runAfterCacheIsPopulated(...) as well.
+                    return mIsCachePopulatedInAccountManagerFacade;
+                }
+            });
+
+    // Mock sign-in environment needs to be destroyed after ChromeActivity in case there are
+    // observers registered in the AccountManagerFacade mock.
     @Rule
-    public AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
+    public final RuleChain mRuleChain =
+            RuleChain.outerRule(mAccountManagerTestRule).around(mActivityTestRule);
 
     /** Parameter provider for enabling/disabling the signin promo card. */
     public static class SigninPromoParams implements ParameterProvider {
@@ -261,14 +280,14 @@
     @MediumTest
     @Feature({"FeedNewTabPage"})
     public void testSignInPromo_AccountsNotReady() {
-        mAccountManagerTestRule.setIsCachePopulated(false);
+        mIsCachePopulatedInAccountManagerFacade = false;
         openNewTabPage();
         // Check that the sign-in promo is not shown if accounts are not ready.
         onView(instanceOf(RecyclerView.class))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
 
-        mAccountManagerTestRule.setIsCachePopulated(true);
+        mIsCachePopulatedInAccountManagerFacade = true;
         TestThreadUtils.runOnUiThreadBlocking(mTab::reload);
         ChromeTabUtils.waitForTabPageLoaded(mTab, mTab.getUrlString());
 
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java
index b3d0e6e3..2a755da 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/basicstream/BasicStreamTest.java
@@ -24,7 +24,6 @@
 
 import android.app.Activity;
 import android.content.Context;
-import android.os.Build.VERSION_CODES;
 import android.util.Base64;
 import android.view.View;
 import android.widget.FrameLayout;
@@ -761,18 +760,6 @@
     }
 
     @Test
-    @Config(sdk = VERSION_CODES.KITKAT)
-    public void testPadding_kitKat() {
-        // Padding is setup in constructor.
-        View view = mBasicStream.getView();
-
-        assertThat(view.getPaddingStart()).isEqualTo(START_PADDING);
-        assertThat(view.getPaddingEnd()).isEqualTo(END_PADDING);
-        assertThat(view.getPaddingTop()).isEqualTo(TOP_PADDING);
-        assertThat(view.getPaddingBottom()).isEqualTo(BOTTOM_PADDING);
-    }
-
-    @Test
     public void testTrim() {
         ShadowRecycledViewPool viewPool =
                 Shadow.extract(getStreamRecyclerView().getRecycledViewPool());
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtilsTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtilsTest.java
index cf49dc8f8..c6b04c2 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtilsTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/common/locale/LocaleUtilsTest.java
@@ -44,32 +44,8 @@
     }
 
     @Test
-    @Config(qualifiers = "fr-rCA", sdk = VERSION_CODES.LOLLIPOP)
-    public void getLanguageTag_byContext_postLollipop() {
+    @Config(qualifiers = "fr-rCA")
+    public void getLanguageTag() {
         assertThat(LocaleUtils.getLanguageTag(mContext)).isEqualTo("fr-CA");
     }
-
-    @Test
-    @Config(qualifiers = "fr-rCA", sdk = VERSION_CODES.KITKAT)
-    public void getLanguageTag_byContext_preLollipop() {
-        assertThat(LocaleUtils.getLanguageTag(mContext)).isEqualTo("fr-CA");
-    }
-
-    @Test
-    @Config(sdk = VERSION_CODES.LOLLIPOP)
-    public void getLanguageTag_byLocale_postLollipop() {
-        assertThat(LocaleUtils.getLanguageTag(Locale.CANADA_FRENCH)).isEqualTo("fr-CA");
-    }
-
-    @Test
-    @Config(sdk = VERSION_CODES.KITKAT)
-    public void getLanguageTag_byLocale_preLollipop() {
-        assertThat(LocaleUtils.getLanguageTag(Locale.CANADA_FRENCH)).isEqualTo("fr-CA");
-    }
-
-    @Test
-    @Config(sdk = VERSION_CODES.KITKAT)
-    public void getLanguageTag_byLocale_preLollipop_badLanguage() {
-        assertThat(LocaleUtils.getLanguageTag(new Locale("", "CA"))).isEqualTo("und-CA");
-    }
 }
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/StyleProviderTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/StyleProviderTest.java
index cc8fb1b..fcd4289 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/StyleProviderTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/StyleProviderTest.java
@@ -18,7 +18,6 @@
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.ShapeDrawable;
-import android.os.Build.VERSION_CODES;
 import android.view.Gravity;
 import android.view.View;
 import android.view.ViewGroup.LayoutParams;
@@ -588,22 +587,6 @@
     }
 
     @Test
-    @Config(sdk = VERSION_CODES.KITKAT)
-    public void testElementStyles_shadowDoesNotError_KK() {
-        Style shadowStyle = Style.newBuilder()
-                                    .setShadow(Shadow.newBuilder().setElevationShadow(
-                                            ElevationShadow.newBuilder().setElevation(5280)))
-                                    .build();
-        Style noShadowStyle = Style.getDefaultInstance();
-
-        new StyleProvider(shadowStyle, mMockAssetProvider).applyElementStyles(mAdapter);
-
-        new StyleProvider(noShadowStyle, mMockAssetProvider).applyElementStyles(mAdapter);
-
-        // Assert nothing failed.
-    }
-
-    @Test
     public void testElementStyles_opacity() {
         new StyleProvider(Style.newBuilder().setOpacity(0.5f).build(), mMockAssetProvider)
                 .applyElementStyles(mAdapter);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapterTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapterTest.java
index 472101cd..0863c60 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapterTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/TextElementAdapterTest.java
@@ -24,7 +24,6 @@
 import android.content.Context;
 import android.graphics.Color;
 import android.graphics.Typeface;
-import android.os.Build.VERSION_CODES;
 import android.text.Layout;
 import android.text.TextUtils.TruncateAt;
 import android.view.Gravity;
@@ -312,21 +311,6 @@
         assertThat(extraLineHeight.topPaddingPx()).isEqualTo(20);
     }
 
-    @Config(sdk = VERSION_CODES.KITKAT)
-    @Test
-    public void testGetExtraLineHeight_roundDown_kitkat() {
-        // Extra height is 40.2px. In KitKat and lower, 40 pixels (the amount added between lines)
-        // will have already been added to the bottom. To get to our desired value of 21 bottom
-        // pixels, the actual bottom padding must be -19 (40 - 19 = 21).
-        initializeAdapterWithExtraLineHeightPx(40.2f);
-
-        TextElementAdapter.ExtraLineHeight extraLineHeight = mAdapter.getExtraLineHeight();
-
-        assertThat(extraLineHeight.betweenLinesExtraPx()).isEqualTo(40);
-        assertThat(extraLineHeight.bottomPaddingPx()).isEqualTo(-19);
-        assertThat(extraLineHeight.topPaddingPx()).isEqualTo(20);
-    }
-
     @Test
     public void testGetExtraLineHeight_noRound() {
         // Extra height is 40px. 40 pixels will be added between each line, and that amount is split
@@ -340,21 +324,6 @@
         assertThat(extraLineHeight.topPaddingPx()).isEqualTo(20);
     }
 
-    @Config(sdk = VERSION_CODES.KITKAT)
-    @Test
-    public void testGetExtraLineHeight_noRound_kitkat() {
-        // Extra height is 40px. In KitKat and lower, 40 pixels (the amount added between lines)
-        // will have already been added to the bottom. To get to our desired value of 20 bottom
-        // pixels, the actual bottom padding must be -20 (40 - 20 = 20).
-        initializeAdapterWithExtraLineHeightPx(40.0f);
-
-        TextElementAdapter.ExtraLineHeight extraLineHeight = mAdapter.getExtraLineHeight();
-
-        assertThat(extraLineHeight.betweenLinesExtraPx()).isEqualTo(40);
-        assertThat(extraLineHeight.bottomPaddingPx()).isEqualTo(-20);
-        assertThat(extraLineHeight.topPaddingPx()).isEqualTo(20);
-    }
-
     @Test
     public void testGetExtraLineHeight_roundUp() {
         // Extra height is 40.8px. This gets rounded up between the lines (to 41) and rounded down
@@ -368,21 +337,6 @@
         assertThat(extraLineHeight.topPaddingPx()).isEqualTo(20);
     }
 
-    @Config(sdk = VERSION_CODES.KITKAT)
-    @Test
-    public void testGetExtraLineHeight_roundUp_kitkat() {
-        // Extra height is 40.8px. In KitKat and lower, 41 pixels (the amount added between lines)
-        // will have already been added to the bottom. To get to our desired value of 20 bottom
-        // pixels, the actual bottom padding must be -21 (41 - 21 = 20).
-        initializeAdapterWithExtraLineHeightPx(40.8f);
-
-        TextElementAdapter.ExtraLineHeight extraLineHeight = mAdapter.getExtraLineHeight();
-
-        assertThat(extraLineHeight.betweenLinesExtraPx()).isEqualTo(41);
-        assertThat(extraLineHeight.bottomPaddingPx()).isEqualTo(-21);
-        assertThat(extraLineHeight.topPaddingPx()).isEqualTo(20);
-    }
-
     private void initializeAdapterWithExtraLineHeightPx(float lineHeightPx) {
         // Line height is specified in sp, so line height px = scaledDensity  x line height sp
         // These tests set display density because, in order to test the rounding behavior of
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperViewTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperViewTest.java
index ad6913d..73a3a03 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperViewTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/library/piet/ui/RoundedCornerWrapperViewTest.java
@@ -10,7 +10,6 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.os.Build.VERSION_CODES;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -419,36 +418,6 @@
         assertThat(view.getRoundingStrategy()).isEqualTo(RoundingStrategy.OUTLINE_PROVIDER);
     }
 
-    @Config(sdk = VERSION_CODES.KITKAT)
-    @Test
-    public void useClipPathStrategy_kitkat() {
-        int radius = 16;
-        RoundedCorners roundedCorners = RoundedCorners.newBuilder()
-                                                .setBitmask(ALL_CORNERS_BITMASK)
-                                                .setRadiusDp(radius)
-                                                .build();
-        CommonRoundedCornerWrapperView view =
-                CommonRoundedCornerWrapperView.builder().setRoundedCorners(roundedCorners).build();
-
-        assertThat(view.getRoundingStrategy()).isEqualTo(RoundingStrategy.CLIP_PATH);
-    }
-
-    @Config(sdk = VERSION_CODES.KITKAT)
-    @Test
-    public void useMaskingStrategy_kitkat_noClipPathAllowed() {
-        int radius = 16;
-        RoundedCorners roundedCorners = RoundedCorners.newBuilder()
-                                                .setBitmask(ALL_CORNERS_BITMASK)
-                                                .setRadiusDp(radius)
-                                                .build();
-        CommonRoundedCornerWrapperView view = CommonRoundedCornerWrapperView.builder()
-                                                      .setRoundedCorners(roundedCorners)
-                                                      .setAllowClipPath(false)
-                                                      .build();
-
-        assertThat(view.getRoundingStrategy()).isEqualTo(RoundingStrategy.BITMAP_MASKING);
-    }
-
     @Test
     public void useClipPathStrategy_noHardwareAcceleration() {
         int width = 100;
diff --git a/chrome/android/feed/feed_java_sources.gni b/chrome/android/feed/feed_java_sources.gni
index 06421ab..6e2c8495 100644
--- a/chrome/android/feed/feed_java_sources.gni
+++ b/chrome/android/feed/feed_java_sources.gni
@@ -384,6 +384,7 @@
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/tooltip/FeedTooltipUtils.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedListContentManager.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedServiceBridge.java",
+    "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTracker.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStream.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurface.java",
     "//chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/v2/NativeViewListRenderer.java",
@@ -646,6 +647,7 @@
     "junit/src/org/chromium/chrome/browser/feed/NtpStreamLifecycleManagerTest.java",
     "junit/src/org/chromium/chrome/browser/feed/action/FeedActionHandlerTest.java",
     "junit/src/org/chromium/chrome/browser/feed/v2/FeedListContentManagerTest.java",
+    "junit/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTrackerTest.java",
     "junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java",
     "junit/src/org/chromium/chrome/browser/feed/v2/NativeViewListRendererTest.java",
   ]
diff --git a/chrome/android/java/res_password_change/layout/password_manager_dialog_with_help_button_password_change.xml b/chrome/android/java/res_password_change/layout/password_manager_dialog_with_help_button_password_change.xml
deleted file mode 100644
index 2116918..0000000
--- a/chrome/android/java/res_password_change/layout/password_manager_dialog_with_help_button_password_change.xml
+++ /dev/null
@@ -1,82 +0,0 @@
-<?xml version="1.0" encoding="utf-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. -->
-
-<org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    android:id="@+id/password_manager_dialog"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:gravity="center">
-
-    <!-- PasswordManagerDialogPasswordChangeView extends ScrollView, which can only have one child.
-         Thus an additional layout to wrap everything is needed. -->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:paddingBottom="22dp"
-        android:orientation="vertical">
-
-        <org.chromium.ui.widget.ChromeImageButton
-            android:id="@+id/password_dialog_help_button"
-            android:layout_height="48dp"
-            android:layout_width="48dp"
-            android:layout_marginTop="4dp"
-            android:layout_marginEnd="4dp"
-            android:layout_gravity="end"
-            android:background="?attr/selectableItemBackground"
-            app:srcCompat="@drawable/ic_help_and_feedback"
-            android:contentDescription="@string/help"
-            android:visibility="gone"/>
-
-        <ImageView
-            android:id="@+id/password_manager_dialog_illustration"
-            android:layout_width="match_parent"
-            android:layout_height="140dp"
-            android:layout_marginStart="@dimen/password_manager_dialog_illustration_margin"
-            android:layout_marginEnd="@dimen/password_manager_dialog_illustration_margin"
-            android:adjustViewBounds="true"
-            android:scaleType="fitCenter"
-            tools:ignore="ContentDescription" />
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-            <TextView
-                android:id="@+id/password_manager_dialog_title"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_weight="1"
-                android:layout_marginStart="@dimen/password_manager_dialog_text_margin"
-                android:layout_marginEnd="@dimen/password_manager_dialog_text_margin"
-                android:paddingTop="@dimen/password_manager_dialog_title_padding_top"
-                android:textAppearance="@style/TextAppearance.Headline.Primary" />
-
-            <org.chromium.ui.widget.ChromeImageButton
-                android:id="@+id/password_dialog_inline_help_button"
-                android:layout_height="48dp"
-                android:layout_width="48dp"
-                android:layout_weight="0"
-                android:layout_marginTop="4dp"
-                android:layout_marginEnd="4dp"
-                android:background="?attr/selectableItemBackground"
-                app:srcCompat ="@drawable/ic_help_and_feedback"
-                android:visibility="gone"/>
-        </LinearLayout>
-
-        <org.chromium.ui.widget.TextViewWithLeading
-            android:id="@+id/password_manager_dialog_details"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_marginStart="@dimen/password_manager_dialog_text_margin"
-            android:layout_marginEnd="@dimen/password_manager_dialog_text_margin"
-            android:layout_marginTop="@dimen/password_manager_dialog_details_padding_top"
-            android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
-            app:leading="@dimen/text_size_medium_leading" />
-    </LinearLayout>
-</org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeView>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 1940e508..7c2a946 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -112,7 +112,7 @@
 import org.chromium.chrome.browser.omaha.notification.UpdateNotificationControllerFactory;
 import org.chromium.chrome.browser.page_info.ChromePageInfoControllerDelegate;
 import org.chromium.chrome.browser.page_info.ChromePermissionParamsListBuilderDelegate;
-import org.chromium.chrome.browser.paint_preview.PaintPreviewInitializer;
+import org.chromium.chrome.browser.paint_preview.PaintPreviewHelper;
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
@@ -440,8 +440,7 @@
             if (!isFinishing() && getFullscreenManager() != null) {
                 getFullscreenManager().initialize(
                         (ControlContainer) findViewById(R.id.control_container),
-                        getActivityTabProvider(), getTabModelSelector(),
-                        getControlContainerHeightResource());
+                        getTabModelSelector(), getControlContainerHeightResource());
             }
 
             BottomContainer bottomContainer = (BottomContainer) findViewById(R.id.bottom_container);
@@ -613,7 +612,7 @@
         mIncognitoTabCreator = tabCreators.second;
 
         OfflinePageUtils.observeTabModelSelector(this, mTabModelSelector);
-        PaintPreviewInitializer.observeTabModelSelector(this, mTabModelSelector);
+        PaintPreviewHelper.observeTabModelSelector(this, mTabModelSelector);
 
         if (mTabModelSelectorTabObserver != null) mTabModelSelectorTabObserver.destroy();
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index 9c96cdd..bf81d90b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -41,6 +41,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinatorFactory;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabLaunchType;
@@ -658,7 +659,7 @@
         OfflinePageUtils.getLoadUrlParamsForOpeningMhtmlFileOrContent(url, (loadUrlParams) -> {
             processUrlViewIntent(loadUrlParams.getUrl(), null, loadUrlParams.getVerbatimHeaders(),
                     TabOpenType.OPEN_NEW_TAB, null, 0, false, intent);
-        });
+        }, Profile.getLastUsedRegularProfile());
     }
 
     private static PendingIntent getAuthenticationToken() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
index df02b9d..e7ce99e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -635,7 +635,7 @@
 
         boolean itemVisible = canShowRequestDesktopSite
                 && (!isChromeScheme || currentTab.isNativePage())
-                && !shouldShowReaderModePrefs(currentTab);
+                && !shouldShowReaderModePrefs(currentTab) && currentTab.getWebContents() != null;
         requestMenuRow.setVisible(itemVisible);
         if (!itemVisible) return;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
index cf1e3a5..e82d190 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchTabHelper.java
@@ -106,7 +106,7 @@
     public void onContentChanged(Tab tab) {
         // Native initialization happens after a page loads or content is changed to ensure profile
         // is initialized.
-        if (mNativeHelper == 0) {
+        if (mNativeHelper == 0 && tab.getWebContents() != null) {
             mNativeHelper = ContextualSearchTabHelperJni.get().init(
                     ContextualSearchTabHelper.this, Profile.fromWebContents(tab.getWebContents()));
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
index c9c257e..7fa9578f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
@@ -20,6 +20,7 @@
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.profiles.ProfileManager;
 import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.components.feature_engagement.EventConstants;
@@ -69,6 +70,18 @@
             itemText.setText(
                     getContext().getString(R.string.data_reduction_saved_label, dataSaved));
             itemSummary.setText(getContext().getString(R.string.data_reduction_date_label, date));
+            // TODO (https://crbug.com/1048632): Use the TabModel-specific profile instead of
+            // calling Profile.getLastUsedRegularProfile().
+            Profile profile =
+                    ProfileManager.isInitialized() ? Profile.getLastUsedRegularProfile() : null;
+            if (profile != null) {
+                Tracker tracker = TrackerFactory.getTrackerForProfile(profile);
+                tracker.addOnInitializedCallback((success) -> {
+                    if (success) {
+                        tracker.notifyEvent(EventConstants.OVERFLOW_OPENED_WITH_DATA_SAVER_SHOWN);
+                    }
+                });
+            }
         } else {
             DataReductionProxyUma.dataReductionProxyUIAction(
                     DataReductionProxyUma.ACTION_MAIN_MENU_DISPLAYED_OFF);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
index 0166a6f5..407029c3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -202,8 +202,9 @@
         }
 
         // Make sure there is a WebContentsObserver on this tab's WebContents.
-        if (mWebContentsObserver == null) mWebContentsObserver = createWebContentsObserver();
-
+        if (mWebContentsObserver == null && mTab.getWebContents() != null) {
+            mWebContentsObserver = createWebContentsObserver();
+        }
         tryShowingInfoBar();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java
index 4e41b5b..701649d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadInfoBarController.java
@@ -169,6 +169,21 @@
             return idEquality && TextUtils.equals(message, other.message)
                     && TextUtils.equals(link, other.link) && icon == other.icon;
         }
+
+        /** Called to update the value of this object from a given object. */
+        public void update(DownloadProgressInfoBarData other) {
+            id = other.id;
+            message = other.message;
+            accessibilityMessage = other.accessibilityMessage;
+            link = other.link;
+            icon = other.icon;
+            hasVectorDrawable = other.hasVectorDrawable;
+            hasAnimation = other.hasAnimation;
+            dontRepeat = other.dontRepeat;
+            forceReparent = other.forceReparent;
+            downloadCount = other.downloadCount;
+            resultState = other.resultState;
+        }
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
index 298fe57..11ea247 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/fullscreen/ChromeFullscreenManager.java
@@ -27,8 +27,6 @@
 import org.chromium.base.TraceEvent;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.ActivityTabProvider;
-import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.fullscreen.FullscreenHtmlApiHandler.FullscreenHtmlApiDelegate;
 import org.chromium.chrome.browser.tab.SadTab;
@@ -38,8 +36,10 @@
 import org.chromium.chrome.browser.tab.TabBrowserControlsConstraintsHelper;
 import org.chromium.chrome.browser.tab.TabBrowserControlsOffsetHelper;
 import org.chromium.chrome.browser.tab.TabHidingType;
+import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.chrome.browser.tabmodel.TabModelImpl;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
 import org.chromium.chrome.browser.toolbar.ControlContainer;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
@@ -90,6 +90,7 @@
     private int mBottomControlsMinHeight;
     private boolean mAnimateBrowserControlsHeightChanges;
     private boolean mControlsResizeView;
+    private TabModelSelectorTabModelObserver mTabModelObserver;
 
     private int mRendererTopControlOffset;
     private int mRendererBottomControlOffset;
@@ -101,7 +102,6 @@
     private boolean mIsEnteringPersistentModeState;
     private FullscreenOptions mPendingFullscreenOptions;
     private boolean mOffsetsChanged;
-    private ActivityTabTabObserver mActiveTabObserver;
 
     private boolean mInGesture;
     private boolean mContentViewScrolling;
@@ -206,25 +206,39 @@
      * Initializes the fullscreen manager with the required dependencies.
      *
      * @param controlContainer Container holding the controls (Toolbar).
-     * @param activityTabProvider Provider of the current activity tab.
      * @param modelSelector The tab model selector that will be monitored for tab changes.
      * @param resControlContainerHeight The dimension resource ID for the control container height.
      */
-    public void initialize(ControlContainer controlContainer,
-            ActivityTabProvider activityTabProvider, final TabModelSelector modelSelector,
+    public void initialize(ControlContainer controlContainer, final TabModelSelector modelSelector,
             int resControlContainerHeight) {
         ApplicationStatus.registerStateListenerForActivity(this, mActivity);
         ApplicationStatus.registerWindowFocusChangedListener(this);
-        mActiveTabObserver = new ActivityTabTabObserver(activityTabProvider) {
+
+        // TODO(crbug.com/978941): Consider switching to ActivityTabTabProvider.
+        mTabModelObserver = new TabModelSelectorTabModelObserver(modelSelector) {
             @Override
-            protected void onObservingDifferentTab(Tab tab) {
-                setTab(tab);
+            public void tabClosureCommitted(Tab tab) {
+                setTab(modelSelector.getCurrentTab());
             }
 
             @Override
-            public void onContentViewScrollingStateChanged(boolean scrolling) {
-                mContentViewScrolling = scrolling;
-                if (!scrolling) updateVisuals();
+            public void allTabsClosureCommitted() {
+                setTab(modelSelector.getCurrentTab());
+            }
+
+            @Override
+            public void tabRemoved(Tab tab) {
+                setTab(modelSelector.getCurrentTab());
+            }
+
+            @Override
+            public void didSelectTab(Tab tab, @TabSelectionType int type, int lastId) {
+                setTab(modelSelector.getCurrentTab());
+            }
+
+            @Override
+            public void didCloseTab(int tabId, boolean incognito) {
+                setTab(modelSelector.getCurrentTab());
             }
         };
 
@@ -283,6 +297,14 @@
                             topControlsMinHeightOffset, bottomControlsMinHeightOffset);
                 }
             }
+
+            @Override
+            public void onContentViewScrollingStateChanged(Tab tab, boolean scrolling) {
+                if (tab == getTab()) {
+                    mContentViewScrolling = scrolling;
+                    if (!scrolling) updateVisuals();
+                }
+            }
         };
         assert controlContainer != null || mControlsPosition == ControlsPosition.NONE;
         mControlContainer = controlContainer;
@@ -466,6 +488,8 @@
         } else if (newState == ActivityState.DESTROYED) {
             ApplicationStatus.unregisterActivityStateListener(this);
             ApplicationStatus.unregisterWindowFocusChangedListener(this);
+
+            mTabModelObserver.destroy();
         }
     }
 
@@ -1183,7 +1207,6 @@
      */
     public void destroy() {
         mTab = null;
-        if (mActiveTabObserver != null) mActiveTabObserver.destroy();
         mBrowserVisibilityDelegate.destroy();
         if (mTabFullscreenObserver != null) mTabFullscreenObserver.destroy();
         if (mContentView != null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java
index 4a04f382b..3b411eb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.gsa;
 
-import android.accounts.Account;
 import android.annotation.SuppressLint;
 import android.content.ComponentName;
 import android.content.Context;
@@ -22,7 +21,10 @@
 import org.chromium.base.PackageManagerUtils;
 import org.chromium.base.PackageUtils;
 import org.chromium.chrome.browser.IntentHandler;
-import org.chromium.components.signin.ChromeSigninController;
+import org.chromium.chrome.browser.profiles.ProfileManager;
+import org.chromium.chrome.browser.signin.IdentityServicesProvider;
+import org.chromium.components.signin.base.CoreAccountInfo;
+import org.chromium.components.signin.identitymanager.ConsentLevel;
 
 import java.util.List;
 
@@ -99,9 +101,12 @@
      * both are logged out is not considered a match.
      */
     public boolean doesGsaAccountMatchChrome() {
-        Account chromeUser = ChromeSigninController.get().getSignedInUser();
-        return chromeUser != null && !TextUtils.isEmpty(mGsaAccount) && TextUtils.equals(
-                chromeUser.name, mGsaAccount);
+        if (!ProfileManager.isInitialized()) return false;
+        CoreAccountInfo chromeAccountInfo =
+                IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo(
+                        ConsentLevel.SYNC);
+        return chromeAccountInfo != null && !TextUtils.isEmpty(mGsaAccount)
+                && TextUtils.equals(chromeAccountInfo.getEmail(), mGsaAccount);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java
index 4a8d0a0..da4b446 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/DownloadProgressInfoBar.java
@@ -172,8 +172,8 @@
     public void updateInfoBar(DownloadInfoBarController.DownloadProgressInfoBarData info) {
         if (getView() == null) return;
 
-        mInfo = info;
-        setLayoutProperties((InfoBarLayout) getView(), info);
+        mInfo.update(info);
+        setLayoutProperties((InfoBarLayout) getView(), mInfo);
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java
index e4b9d4c..7617f4e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/media/PictureInPictureController.java
@@ -345,6 +345,11 @@
         public void onCrash(Tab tab) {
             dismissActivity(mActivity, METRICS_END_REASON_CRASH);
         }
+
+        @Override
+        public void webContentsWillSwap(Tab tab) {
+            dismissActivity(mActivity, METRICS_END_REASON_WEB_CONTENTS_LEFT_FULLSCREEN);
+        }
     }
 
     /** A class to dismiss the Activity when a new tab is created. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java
index ce5b2111..083a8b3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/AutoFetchNotifier.java
@@ -267,11 +267,13 @@
     @CalledByNative
     private static void showCompleteNotification(
             String pageTitle, String originalUrl, String finalUrl, int tabId, long offlineId) {
+        // Since offline pages are only available in regular mode, any downloaded content should be
+        // triggered by regular mode. Hence, it is correct to pass always regular profile.
         OfflinePageUtils.getLoadUrlParamsForOpeningOfflineVersion(
                 finalUrl, offlineId, LaunchLocation.NOTIFICATION, (params) -> {
                     showCompleteNotificationWithParams(
                             pageTitle, tabId, offlineId, originalUrl, finalUrl, params);
-                });
+                }, Profile.getLastUsedRegularProfile());
     }
 
     private static void showCompleteNotificationWithParams(String pageTitle, int tabId,
@@ -361,9 +363,7 @@
     }
 
     private static void cancelInProgress() {
-        // TODO(https://crbug.com/1067314): Use the current profile (i.e., regular profile or
-        // incognito profile) instead of always using regular profile. It is wrong and need to be
-        // fixed.
+        // Using regular profile here, since this function is only called in regular mode.
         AutoFetchNotifierJni.get().cancelInProgress(Profile.getLastUsedRegularProfile());
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
index 43ce991..a44a55b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -635,14 +635,11 @@
      * @param offlineId The ID of the offline page to open.
      * @param location  Indicates where the offline page is launched.
      * @param callback  The callback to pass back the LoadUrlParams for launching an URL.
+     * @param profile   The profile to get an instance of OfflinePageBridge.
      */
     public static void getLoadUrlParamsForOpeningOfflineVersion(final String url, long offlineId,
-            final @LaunchLocation int location, Callback<LoadUrlParams> callback) {
-        // TODO(https://crbug.com/1067314): Use the current profile (i.e., regular profile or
-        // incognito profile) instead of always using regular profile. It is wrong and need to be
-        // fixed.
-        OfflinePageBridge offlinePageBridge =
-                getInstance().getOfflinePageBridge(Profile.getLastUsedRegularProfile());
+            final @LaunchLocation int location, Callback<LoadUrlParams> callback, Profile profile) {
+        OfflinePageBridge offlinePageBridge = getInstance().getOfflinePageBridge(profile);
         if (offlinePageBridge == null) {
             callback.onResult(null);
             return;
@@ -658,14 +655,11 @@
      * Otherwise, the file or content URL from the intent will be launched.
      * @param intentUrl URL from the intent.
      * @param callback  The callback to pass back the launching URL and extra headers.
+     * @param profile   The profile to get an instance of OfflinePageBridge.
      */
     public static void getLoadUrlParamsForOpeningMhtmlFileOrContent(
-            final String intentUrl, Callback<LoadUrlParams> callback) {
-        // TODO(https://crbug.com/1067314): Use the current profile (i.e., regular profile or
-        // incognito profile) instead of always using regular profile. It is wrong and need to be
-        // fixed.
-        OfflinePageBridge offlinePageBridge =
-                getInstance().getOfflinePageBridge(Profile.getLastUsedRegularProfile());
+            final String intentUrl, Callback<LoadUrlParams> callback, Profile profile) {
+        OfflinePageBridge offlinePageBridge = getInstance().getOfflinePageBridge(profile);
         if (offlinePageBridge == null) {
             callback.onResult(new LoadUrlParams(intentUrl));
             return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java
index 858a233b..51c95c9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/downloads/OfflinePageDownloadBridge.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.offlinepages.OfflinePageOrigin;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
+import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.document.AsyncTabCreationParams;
@@ -88,6 +89,8 @@
     @CalledByNative
     private static void openItem(final String url, final long offlineId, final int location,
             final boolean isIncognito, final boolean openInCct) {
+        Profile profile = isIncognito ? Profile.getLastUsedRegularProfile().getPrimaryOTRProfile()
+                                      : Profile.getLastUsedRegularProfile();
         OfflinePageUtils.getLoadUrlParamsForOpeningOfflineVersion(
                 url, offlineId, location, (params) -> {
                     if (params == null) return;
@@ -101,7 +104,7 @@
                     } else {
                         openItemInNewTab(offlineId, params, isIncognito);
                     }
-                });
+                }, profile);
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTask.java
index 11e1a08..77c0a77f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/OfflineNotificationBackgroundTask.java
@@ -270,9 +270,7 @@
         if (sOfflinePageBridgeForTesting != null) {
             return sOfflinePageBridgeForTesting;
         }
-        // TODO(https://crbug.com/1067314): Use the current profile (i.e., regular profile or
-        // incognito profile) instead of always using regular profile. It is wrong and need to be
-        // fixed.
+        // Using regular profile here, since this function is only called in regular mode.
         return OfflinePageBridge.getForProfile(Profile.getLastUsedRegularProfile());
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java
similarity index 70%
rename from chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewInitializer.java
rename to chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java
index 9b632ef..78cfb738 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewInitializer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java
@@ -8,13 +8,14 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
 import org.chromium.chrome.browser.paint_preview.services.PaintPreviewTabServiceFactory;
+import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 
 /**
  * Handles initialization of the Paint Preview tab observers.
  */
-public class PaintPreviewInitializer {
+public class PaintPreviewHelper {
     /**
      * Observes a {@link TabModelSelector} to monitor for initialization completion.
      * @param activity The ChromeActivity that corresponds to the tabModelSelector.
@@ -39,4 +40,20 @@
             }
         });
     }
+
+    /**
+     * Attemps to display the Paint Preview representation of for the given Tab.
+     * @param onShown The callback for when the Paint Preview is shown.
+     * @param onDismissed The callback for when the Paint Preview is dismissed.
+     * @return Whether the Paint Preview started to initialize or is already initializating.
+     * Note that if the Paint Preview is already showing, this will return false.
+     */
+    public static boolean showPaintPreviewOnRestore(
+            Tab tab, Runnable onShown, Runnable onDismissed) {
+        if (!ChromeFeatureList.isEnabled(ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP)) {
+            return false;
+        }
+
+        return TabbedPaintPreviewPlayer.get(tab).maybeShow(onShown, onDismissed);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java
index 3a3feab..fa58731 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/paint_preview/TabbedPaintPreviewPlayer.java
@@ -32,6 +32,7 @@
     private PlayerManager mPlayerManager;
     private Runnable mOnShown;
     private Runnable mOnDismissed;
+    private Boolean mInitializing;
 
     public static TabbedPaintPreviewPlayer get(Tab tab) {
         if (tab.getUserDataHost().getUserData(USER_DATA_KEY) == null) {
@@ -46,24 +47,27 @@
     }
 
     /**
-     * Shows a Paint Preview for the provided tab if it exists.
+     * Shows a Paint Preview for the provided tab if it exists and has not been displayed for this
+     * Tab before.
      * @param onShown The callback for when the Paint Preview is shown.
      * @param onDismissed The callback for when the Paint Preview is dismissed.
-     * @return a boolean indicating whether a Paint Preview exists for the tab.
+     * @return Whether the Paint Preview started to initialize or is already initializating.
+     * Note that if the Paint Preview is already showing, this will return false.
      */
-    public boolean showIfExists(@Nullable Runnable onShown, @Nullable Runnable onDismissed) {
-        if (isShowing()) return true;
+    public boolean maybeShow(@Nullable Runnable onShown, @Nullable Runnable onDismissed) {
+        if (mInitializing != null) return mInitializing;
 
         // Check if a capture exists. This is a quick check using a cache.
         boolean hasCapture = mPaintPreviewTabService.hasCaptureForTab(mTab.getId());
-        mOnShown = onShown;
-        mOnDismissed = onDismissed;
+        mInitializing = hasCapture;
         if (hasCapture) {
             mPlayerManager = new PlayerManager(mTab.getUrl(), mTab.getContext(),
                     mPaintPreviewTabService, String.valueOf(mTab.getId()), this::onLinkClicked,
                     this::removePaintPreview,
                     () -> TabViewManager.get(mTab).addTabViewProvider(this),
                     TabThemeColorHelper.getBackgroundColor(mTab), this::removePaintPreview);
+            mOnShown = onShown;
+            mOnDismissed = onDismissed;
         }
 
         return hasCapture;
@@ -74,13 +78,14 @@
      * nothing if there is no view showing.
      */
     private void removePaintPreview() {
+        mOnShown = null;
+        mOnDismissed = null;
+        mInitializing = false;
         if (mTab == null || mPlayerManager == null) return;
 
         TabViewManager.get(mTab).removeTabViewProvider(this);
         mPlayerManager.destroy();
         mPlayerManager = null;
-        mOnShown = null;
-        mOnDismissed = null;
     }
 
     public boolean isShowing() {
@@ -106,6 +111,7 @@
 
     @Override
     public void onShown() {
+        mInitializing = false;
         if (mOnShown != null) mOnShown.run();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/CredentialLeakDialogPasswordChangeBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/CredentialLeakDialogPasswordChangeBridge.java
deleted file mode 100644
index c58b0f3a..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/CredentialLeakDialogPasswordChangeBridge.java
+++ /dev/null
@@ -1,107 +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.
-package org.chromium.chrome.browser.password_manager;
-
-import org.chromium.base.annotations.CalledByNative;
-import org.chromium.base.annotations.NativeMethods;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeActivity;
-import org.chromium.chrome.browser.help.HelpAndFeedback;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.ui.base.WindowAndroid;
-import org.chromium.ui.modaldialog.DialogDismissalCause;
-
-import java.lang.ref.WeakReference;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-/**
- * JNI call glue between the native password manager CredentialLeak class and
- * Java objects.
- */
-public class CredentialLeakDialogPasswordChangeBridge {
-    private long mNativeCredentialLeakDialogPasswordChangeViewAndroid;
-    private final PasswordManagerDialogPasswordChangeCoordinator mCredentialLeakDialog;
-    private final WeakReference<ChromeActivity> mActivity;
-
-    private CredentialLeakDialogPasswordChangeBridge(
-            WindowAndroid windowAndroid, long nativeCredentialLeakDialogPasswordChangeViewAndroid) {
-        mNativeCredentialLeakDialogPasswordChangeViewAndroid =
-                nativeCredentialLeakDialogPasswordChangeViewAndroid;
-        ChromeActivity activity = (ChromeActivity) windowAndroid.getActivity().get();
-        mActivity = new WeakReference<>(activity);
-        mCredentialLeakDialog = new PasswordManagerDialogPasswordChangeCoordinator(
-                activity.getModalDialogManager(), activity.findViewById(android.R.id.content),
-                activity.getFullscreenManager(), activity.getControlContainerHeightResource());
-    }
-
-    @CalledByNative
-    public static CredentialLeakDialogPasswordChangeBridge create(
-            WindowAndroid windowAndroid, long nativeDialog) {
-        return new CredentialLeakDialogPasswordChangeBridge(windowAndroid, nativeDialog);
-    }
-
-    @CalledByNative
-    public void showDialog(String credentialLeakTitle, String credentialLeakDetails,
-            String positiveButton, String negativeButton) {
-        if (mActivity.get() == null) return;
-
-        PasswordManagerDialogPasswordChangeContents contents =
-                new PasswordManagerDialogPasswordChangeContents(credentialLeakTitle,
-                        credentialLeakDetails, R.drawable.password_check_warning, positiveButton,
-                        negativeButton, this::onClick);
-        contents.setPrimaryButtonFilled(negativeButton != null);
-        contents.setHelpButtonCallback(this::showHelpArticle);
-
-        mCredentialLeakDialog.initialize(mActivity.get(), contents);
-        mCredentialLeakDialog.showDialog();
-    }
-
-    @CalledByNative
-    private void destroy() {
-        mNativeCredentialLeakDialogPasswordChangeViewAndroid = 0;
-        mCredentialLeakDialog.dismissDialog(DialogDismissalCause.DISMISSED_BY_NATIVE);
-    }
-
-    private void onClick(@DialogDismissalCause int dismissalCause) {
-        if (mNativeCredentialLeakDialogPasswordChangeViewAndroid == 0) return;
-        switch (dismissalCause) {
-            case DialogDismissalCause.POSITIVE_BUTTON_CLICKED:
-                CredentialLeakDialogPasswordChangeBridgeJni.get().accepted(
-                        mNativeCredentialLeakDialogPasswordChangeViewAndroid,
-                        CredentialLeakDialogPasswordChangeBridge.this);
-                return;
-            case DialogDismissalCause.NEGATIVE_BUTTON_CLICKED:
-                CredentialLeakDialogPasswordChangeBridgeJni.get().cancelled(
-                        mNativeCredentialLeakDialogPasswordChangeViewAndroid,
-                        CredentialLeakDialogPasswordChangeBridge.this);
-                return;
-            default:
-                CredentialLeakDialogPasswordChangeBridgeJni.get().closed(
-                        mNativeCredentialLeakDialogPasswordChangeViewAndroid,
-                        CredentialLeakDialogPasswordChangeBridge.this);
-        }
-    }
-
-    private void showHelpArticle() {
-        if (mActivity.get() == null) return;
-
-        Profile profile = Profile.fromWebContents(
-                mActivity.get().getActivityTabProvider().get().getWebContents());
-        HelpAndFeedback.getInstance().show(mActivity.get(),
-                mActivity.get().getString(R.string.help_context_password_leak_detection), profile,
-                null);
-    }
-
-    @NativeMethods
-    interface Natives {
-        void accepted(long nativeCredentialLeakDialogPasswordChangeViewAndroid,
-                CredentialLeakDialogPasswordChangeBridge caller);
-
-        void cancelled(long nativeCredentialLeakDialogPasswordChangeViewAndroid,
-                CredentialLeakDialogPasswordChangeBridge caller);
-
-        void closed(long nativeCredentialLeakDialogPasswordChangeViewAndroid,
-                CredentialLeakDialogPasswordChangeBridge caller);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeContents.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeContents.java
deleted file mode 100644
index f4efeea..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeContents.java
+++ /dev/null
@@ -1,189 +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.
-package org.chromium.chrome.browser.password_manager;
-
-import androidx.annotation.IdRes;
-import androidx.annotation.Nullable;
-
-import org.chromium.base.Callback;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-
-/**
- * Class containing all data that customizes the contents displayed in the
- * dialog.
- */
-public class PasswordManagerDialogPasswordChangeContents {
-    /**
-     * Helper class for range. TODO(crbug.com/1041591): Replace it with
-     * android.util.Range once the minimum API level is 21.
-     */
-    public static class BoldRange {
-        public final int start;
-        public final int end;
-
-        BoldRange(int start, int end) {
-            assert (start <= end);
-            this.start = start;
-            this.end = end;
-        }
-    }
-
-    private final String mTitle;
-    private final String mDetails;
-    private final String mPrimaryButtonText;
-    private final @Nullable String mSecondaryButtonText;
-    private final @IdRes int mIllustrationId;
-    private final Callback<Integer> mButtonClickCallback;
-
-    private boolean mPrimaryButtonFilled;
-    private @Nullable Runnable mHelpButtonCallback;
-    private @ModalDialogManager.ModalDialogType int mDialogType;
-    private BoldRange[] mBoldRanges;
-
-    /**
-     * Constructor for the dialog contents.
-     *
-     * @param title               The title of the dialog, to be displayed below the
-     *                            image.
-     * @param details             The details text to be displayed under the title.
-     * @param illustrationId      The resource id of the image displayed above the
-     *                            title.
-     * @param primaryButtonText   The text of the primary button.
-     * @param secondaryButtonText The text of the secondary button or null if there
-     *                            shouldn't be a secondary button.
-     * @param buttonClickCallback The callback handling the click on the buttons. It
-     *                            takes the type of the button as a parameter.
-     */
-    public PasswordManagerDialogPasswordChangeContents(String title, String details,
-            int illustrationId, String primaryButtonText, @Nullable String secondaryButtonText,
-            Callback<Integer> buttonClickCallback) {
-        mTitle = title;
-        mDetails = details;
-        mPrimaryButtonText = primaryButtonText;
-        mSecondaryButtonText = secondaryButtonText;
-        mIllustrationId = illustrationId;
-        mButtonClickCallback = buttonClickCallback;
-        mPrimaryButtonFilled = false;
-        mHelpButtonCallback = null;
-        mDialogType = ModalDialogManager.ModalDialogType.APP;
-        mBoldRanges = new BoldRange[] {};
-    }
-
-    /**
-     * Sets whether or not the primary button should be displayed as filled.
-     */
-    public void setPrimaryButtonFilled(boolean primaryButtonFilled) {
-        mPrimaryButtonFilled = primaryButtonFilled;
-    }
-
-    /**
-     * Sets a callback to be invoked when the help button is clicked. If left null,
-     * no help button will be displayed.
-     */
-    public void setHelpButtonCallback(Runnable helpButtonCallback) {
-        mHelpButtonCallback = helpButtonCallback;
-    }
-
-    /**
-     * Sets type of the modal dialog to be displayed: app or tab modal.
-     */
-    public void setDialogType(@ModalDialogManager.ModalDialogType int type) {
-        mDialogType = type;
-    }
-
-    /**
-     * Sets the bold ranges in the dialog details.
-     *
-     * @param boldStartRanges The start positions of bold spans in dialog details,
-     *                        inclusive.
-     * @param boldEndRanges   The end positions of bold spans in dialog details,
-     *                        exclusive.
-     */
-    public void setBoldRanges(int[] boldStartRanges, int[] boldEndRanges) {
-        assert (boldStartRanges.length == boldEndRanges.length);
-        mBoldRanges = new BoldRange[boldStartRanges.length];
-        for (int i = 0; i < boldStartRanges.length; i++) {
-            mBoldRanges[i] = new BoldRange(boldStartRanges[i], boldEndRanges[i]);
-        }
-    }
-
-    /**
-     * Returns the title of the dialog. It is also used as content description.
-     */
-    public String getTitle() {
-        return mTitle;
-    }
-
-    /**
-     * Returns the details to be displayed in the dialog under the title.
-     */
-    public String getDetails() {
-        return mDetails;
-    }
-
-    /**
-     * Returns the text displayed in the primary button.
-     */
-    public String getPrimaryButtonText() {
-        return mPrimaryButtonText;
-    }
-
-    /**
-     * Returns the text displayed in the secondary button or null if the dialog has
-     * only one button.
-     */
-    @Nullable
-    public String getSecondaryButtonText() {
-        return mSecondaryButtonText;
-    }
-
-    /**
-     * The resource id of the image displayed above the title.
-     */
-    public @IdRes int getIllustrationId() {
-        return mIllustrationId;
-    }
-
-    /**
-     * The callback invoked when either of the two dialog buttons is clicked.
-     *
-     * @return A {@link Callback} taking an {@link Integer} as a parameter which
-     *         represents which button was clicked.
-     */
-    public Callback getButtonClickCallback() {
-        return mButtonClickCallback;
-    }
-
-    /**
-     * Whether the primary button should be displayed as filled or not.
-     */
-    public boolean isPrimaryButtonFilled() {
-        return mPrimaryButtonFilled;
-    }
-
-    /**
-     * Returns the callback handling the click on the help icon or null if no help
-     * icon should be displayed.
-     */
-    @Nullable
-    public Runnable getHelpButtonCallback() {
-        return mHelpButtonCallback;
-    }
-
-    /**
-     * The type of the dialog: app modal or tab modal.
-     */
-    public @ModalDialogManager.ModalDialogType int getDialogType() {
-        return mDialogType;
-    }
-
-    /**
-     * Returns the bold ranges in the details text.
-     */
-    public BoldRange[] getBoldRanges() {
-        return mBoldRanges;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeCoordinator.java
deleted file mode 100644
index 6b73bb1..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeCoordinator.java
+++ /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.
-
-package org.chromium.chrome.browser.password_manager;
-
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.DETAILS;
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.HELP_BUTTON_CALLBACK;
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.ILLUSTRATION;
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.TITLE;
-
-import android.content.Context;
-import android.graphics.Typeface;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.style.StyleSpan;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
-import org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeContents.BoldRange;
-import org.chromium.chrome.password_change.R;
-import org.chromium.ui.modaldialog.DialogDismissalCause;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
-
-/**
- * The coordinator for the password manager illustration modal dialog. Manages
- * the sub-component objects.
- */
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-
-public class PasswordManagerDialogPasswordChangeCoordinator {
-    private final PasswordManagerDialogPasswordChangeMediator mMediator;
-    private PropertyModel mModel;
-
-    public PasswordManagerDialogPasswordChangeCoordinator(ModalDialogManager modalDialogManager,
-            View androidContentView, ChromeFullscreenManager fullscreenManager,
-            int containerHeightResource) {
-        mMediator = new PasswordManagerDialogPasswordChangeMediator(
-                new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS), modalDialogManager,
-                androidContentView, fullscreenManager, containerHeightResource);
-    }
-
-    public void initialize(Context context, PasswordManagerDialogPasswordChangeContents contents) {
-        View customView = LayoutInflater.from(context).inflate(
-                R.layout.password_manager_dialog_with_help_button_password_change, null);
-        mModel = buildModel(contents);
-        mMediator.initialize(mModel, customView, contents);
-        PropertyModelChangeProcessor.create(
-                mModel, customView, PasswordManagerDialogPasswordChangeViewBinder::bind);
-    }
-
-    public void showDialog() {
-        mMediator.showDialog();
-    }
-
-    public void dismissDialog(@DialogDismissalCause int dismissalCause) {
-        mMediator.dismissDialog(dismissalCause);
-    }
-
-    private PropertyModel buildModel(PasswordManagerDialogPasswordChangeContents contents) {
-        return PasswordManagerDialogPasswordChangeProperties.defaultModelBuilder()
-                .with(TITLE, contents.getTitle())
-                .with(DETAILS,
-                        addBoldSpanToDetails(contents.getDetails(), contents.getBoldRanges()))
-                .with(ILLUSTRATION, contents.getIllustrationId())
-                .with(HELP_BUTTON_CALLBACK, contents.getHelpButtonCallback())
-                .build();
-    }
-
-    private SpannableString addBoldSpanToDetails(String details, BoldRange[] boldRanges) {
-        SpannableString spannableDetails = new SpannableString(details);
-        for (BoldRange boldRange : boldRanges) {
-            StyleSpan boldSpan = new StyleSpan(Typeface.BOLD);
-            spannableDetails.setSpan(
-                    boldSpan, boldRange.start, boldRange.end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
-        }
-        return spannableDetails;
-    }
-
-    @VisibleForTesting
-    public PasswordManagerDialogPasswordChangeMediator getMediatorForTesting() {
-        return mMediator;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeMediator.java
deleted file mode 100644
index 5b03e07..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeMediator.java
+++ /dev/null
@@ -1,138 +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.
-
-package org.chromium.chrome.browser.password_manager;
-
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.ILLUSTRATION_VISIBLE;
-
-import android.content.res.Resources;
-import android.view.View;
-
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.Callback;
-import org.chromium.base.task.PostTask;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
-import org.chromium.chrome.browser.modaldialog.ChromeTabModalPresenter;
-import org.chromium.content_public.browser.UiThreadTaskTraits;
-import org.chromium.ui.modaldialog.DialogDismissalCause;
-import org.chromium.ui.modaldialog.ModalDialogManager;
-import org.chromium.ui.modaldialog.ModalDialogProperties;
-import org.chromium.ui.modelutil.PropertyModel;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-
-/**
- * Mediator class responsible for the logic of showing the password manager
- * dialog (e.g. onboarding dialog).
- */
-class PasswordManagerDialogPasswordChangeMediator implements View.OnLayoutChangeListener {
-    private final ModalDialogManager mDialogManager;
-    private final View mAndroidContentView;
-    private final ChromeFullscreenManager mFullscreenManager;
-    private final int mContainerHeightResource;
-
-    private PropertyModel.Builder mHostDialogModelBuilder;
-    private PropertyModel mHostDialogModel;
-    private PropertyModel mModel;
-    private Resources mResources;
-    private @ModalDialogManager.ModalDialogType int mDialogType;
-
-    private static class DialogClickHandler implements ModalDialogProperties.Controller {
-        private Callback<Integer> mCallback;
-
-        DialogClickHandler(Callback<Integer> onClick) {
-            mCallback = onClick;
-        }
-
-        @Override
-        public void onClick(PropertyModel model, int buttonType) {
-            switch (buttonType) {
-                case ModalDialogProperties.ButtonType.POSITIVE:
-                    mCallback.onResult(DialogDismissalCause.POSITIVE_BUTTON_CLICKED);
-                    break;
-                case ModalDialogProperties.ButtonType.NEGATIVE:
-                    mCallback.onResult(DialogDismissalCause.NEGATIVE_BUTTON_CLICKED);
-                    break;
-                default:
-                    assert false : "Unexpected button pressed in dialog: " + buttonType;
-            }
-        }
-
-        @Override
-        public void onDismiss(PropertyModel model, @DialogDismissalCause int dismissalCause) {
-            mCallback.onResult(dismissalCause);
-        }
-    }
-
-    PasswordManagerDialogPasswordChangeMediator(PropertyModel.Builder hostDialogModelBuilder,
-            ModalDialogManager manager, View androidContentView,
-            ChromeFullscreenManager fullscreenManager, int containerHeightResource) {
-        mDialogManager = manager;
-        mHostDialogModelBuilder = hostDialogModelBuilder;
-        mAndroidContentView = androidContentView;
-        mFullscreenManager = fullscreenManager;
-        mContainerHeightResource = containerHeightResource;
-        mAndroidContentView.addOnLayoutChangeListener(this);
-    }
-
-    void initialize(
-            PropertyModel model, View view, PasswordManagerDialogPasswordChangeContents contents) {
-        mResources = view.getResources();
-        mModel = model;
-        mHostDialogModel =
-                mHostDialogModelBuilder.with(ModalDialogProperties.CUSTOM_VIEW, view)
-                        .with(ModalDialogProperties.CONTROLLER,
-                                new DialogClickHandler(contents.getButtonClickCallback()))
-                        .with(ModalDialogProperties.CONTENT_DESCRIPTION, contents.getTitle())
-                        .with(ModalDialogProperties.POSITIVE_BUTTON_TEXT,
-                                contents.getPrimaryButtonText())
-                        .with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT,
-                                contents.getSecondaryButtonText())
-                        .with(ModalDialogProperties.PRIMARY_BUTTON_FILLED,
-                                contents.isPrimaryButtonFilled())
-                        .build();
-        mDialogType = contents.getDialogType();
-    }
-
-    private boolean hasSufficientSpaceForIllustration(int heightPx) {
-        // If |mResources| is null, it means that the dialog was not initialized yet.
-        if (mResources == null) return false;
-        heightPx -= ChromeTabModalPresenter.getContainerTopMargin(mResources, mFullscreenManager);
-        heightPx -= ChromeTabModalPresenter.getContainerBottomMargin(mFullscreenManager);
-        return heightPx >= mResources.getDimensionPixelSize(
-                       R.dimen.password_manager_dialog_min_vertical_space_to_show_illustration);
-    }
-
-    @Override
-    public void onLayoutChange(View view, int left, int top, int right, int bottom, int oldLeft,
-            int oldTop, int oldRight, int oldBottom) {
-        // Return if the dialog wasn't initialized
-        if (mModel == null) return;
-        int oldHeight = oldBottom - oldTop;
-        int newHeight = bottom - top;
-        if (newHeight == oldHeight) return;
-        PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> {
-            mModel.set(ILLUSTRATION_VISIBLE, hasSufficientSpaceForIllustration(newHeight));
-        });
-    }
-
-    void showDialog() {
-        mModel.set(ILLUSTRATION_VISIBLE,
-                hasSufficientSpaceForIllustration(mAndroidContentView.getHeight()));
-        mHostDialogModel = mHostDialogModelBuilder.build();
-        mDialogManager.showDialog(mHostDialogModel, mDialogType);
-    }
-
-    void dismissDialog(int dismissalCause) {
-        mDialogManager.dismissDialog(mHostDialogModel, dismissalCause);
-        mAndroidContentView.removeOnLayoutChangeListener(this);
-    }
-
-    @VisibleForTesting
-    public PropertyModel getModelForTesting() {
-        return mModel;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeProperties.java
deleted file mode 100644
index 8f5b209..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeProperties.java
+++ /dev/null
@@ -1,43 +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.
-
-package org.chromium.chrome.browser.password_manager;
-
-import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModel.ReadableIntPropertyKey;
-import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey;
-import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-
-/**
- * Data properties for the password manager illustration modal dialog.
- */
-class PasswordManagerDialogPasswordChangeProperties {
-    // Callback handling clicks on the help button. If present, the button will be
-    // shown.
-    static final ReadableObjectPropertyKey<Runnable> HELP_BUTTON_CALLBACK =
-            new ReadableObjectPropertyKey<>();
-
-    // Illustration drawable resource id for the password manager.
-    static final ReadableIntPropertyKey ILLUSTRATION = new ReadableIntPropertyKey();
-
-    // Boolean indicating whether there is enough space for the illustration to be
-    // shown.
-    static final WritableBooleanPropertyKey ILLUSTRATION_VISIBLE = new WritableBooleanPropertyKey();
-
-    // Title that appears below the illustration.
-    static final ReadableObjectPropertyKey<String> TITLE = new ReadableObjectPropertyKey<>();
-
-    // Multiline explanation text displayed under the illustration.
-    static final ReadableObjectPropertyKey<CharSequence> DETAILS =
-            new ReadableObjectPropertyKey<>();
-
-    private PasswordManagerDialogPasswordChangeProperties() {}
-
-    static PropertyModel.Builder defaultModelBuilder() {
-        return new PropertyModel.Builder(
-                HELP_BUTTON_CALLBACK, ILLUSTRATION, ILLUSTRATION_VISIBLE, TITLE, DETAILS);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeView.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeView.java
deleted file mode 100644
index 87eeb4fc..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeView.java
+++ /dev/null
@@ -1,89 +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.
-
-package org.chromium.chrome.browser.password_manager;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.chrome.R;
-import org.chromium.ui.widget.ChromeImageButton;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-/**
- * The dialog content view for illustration dialogs used by the password manager
- * (e.g. onboarding, leak warning).
- */
-public class PasswordManagerDialogPasswordChangeView extends ScrollView {
-    private @Nullable ChromeImageButton mHelpButtonView;
-    private @Nullable ChromeImageButton mInlineHelpButtonView;
-    private ImageView mIllustrationView;
-    private TextView mTitleView;
-    private TextView mDetailsView;
-
-    public PasswordManagerDialogPasswordChangeView(Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-        mHelpButtonView = findViewById(R.id.password_dialog_help_button);
-        mInlineHelpButtonView = findViewById(R.id.password_dialog_inline_help_button);
-        mIllustrationView = findViewById(R.id.password_manager_dialog_illustration);
-        mTitleView = findViewById(R.id.password_manager_dialog_title);
-        mDetailsView = findViewById(R.id.password_manager_dialog_details);
-    }
-
-    void addHelpButton(Runnable callback) {
-        if (mHelpButtonView == null) return;
-        mHelpButtonView.setOnClickListener(view -> callback.run());
-        mInlineHelpButtonView.setOnClickListener(view -> callback.run());
-        mHelpButtonView.setVisibility(VISIBLE);
-    }
-
-    void setIllustration(int illustration) {
-        mIllustrationView.setImageResource(illustration);
-    }
-
-    public void updateIllustrationVisibility(boolean illustrationVisible) {
-        if (illustrationVisible) {
-            mIllustrationView.setVisibility(VISIBLE);
-        } else {
-            mIllustrationView.setVisibility(GONE);
-        }
-    }
-
-    public void updateHelpIcon(boolean usesInlineIcon) {
-        // There is no help button to update.
-        if (mHelpButtonView == null) return;
-
-        // The inline help icon is displayed on the same line as the title and requires
-        // a different
-        // margin.
-        LinearLayout.LayoutParams layoutParams =
-                (LinearLayout.LayoutParams) mTitleView.getLayoutParams();
-        layoutParams.setMarginEnd(getResources().getDimensionPixelSize(usesInlineIcon
-                        ? R.dimen.password_manager_dialog_title_compact_margin
-                        : R.dimen.password_manager_dialog_text_margin));
-        mTitleView.setLayoutParams(layoutParams);
-
-        mHelpButtonView.setVisibility(usesInlineIcon ? GONE : VISIBLE);
-        mInlineHelpButtonView.setVisibility(usesInlineIcon ? VISIBLE : GONE);
-    }
-
-    void setTitle(String title) {
-        mTitleView.setText(title);
-    }
-
-    void setDetails(CharSequence details) {
-        mDetailsView.setText(details);
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeViewBinder.java
deleted file mode 100644
index d2b7e2e..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeViewBinder.java
+++ /dev/null
@@ -1,39 +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.
-
-package org.chromium.chrome.browser.password_manager;
-
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.DETAILS;
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.HELP_BUTTON_CALLBACK;
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.ILLUSTRATION;
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.ILLUSTRATION_VISIBLE;
-import static org.chromium.chrome.browser.password_manager.PasswordManagerDialogPasswordChangeProperties.TITLE;
-
-import android.view.View;
-
-import org.chromium.ui.modelutil.PropertyKey;
-import org.chromium.ui.modelutil.PropertyModel;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when prototype is done.
-/**
- * Class responsible for binding the model and the view.
- */
-class PasswordManagerDialogPasswordChangeViewBinder {
-    static void bind(PropertyModel model, View view, PropertyKey propertyKey) {
-        PasswordManagerDialogPasswordChangeView dialogView =
-                (PasswordManagerDialogPasswordChangeView) view;
-        if (HELP_BUTTON_CALLBACK == propertyKey) {
-            dialogView.addHelpButton(model.get(HELP_BUTTON_CALLBACK));
-        } else if (ILLUSTRATION == propertyKey) {
-            dialogView.setIllustration(model.get(ILLUSTRATION));
-        } else if (ILLUSTRATION_VISIBLE == propertyKey) {
-            dialogView.updateIllustrationVisibility(model.get(ILLUSTRATION_VISIBLE));
-            dialogView.updateHelpIcon(!model.get(ILLUSTRATION_VISIBLE));
-        } else if (TITLE == propertyKey) {
-            dialogView.setTitle(model.get(TITLE));
-        } else if (DETAILS == propertyKey) {
-            dialogView.setDetails(model.get(DETAILS));
-        }
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportFlow.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportFlow.java
index 9129802..31ae44a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportFlow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/ExportFlow.java
@@ -19,6 +19,7 @@
 
 import org.chromium.base.ContentUriUtils;
 import org.chromium.base.ContextUtils;
+import org.chromium.base.StrictModeContext;
 import org.chromium.chrome.R;
 import org.chromium.ui.widget.Toast;
 
@@ -267,7 +268,9 @@
      */
     @VisibleForTesting
     public static String getTargetDirectory() {
-        return ContextUtils.getApplicationContext().getCacheDir() + PASSWORDS_CACHE_DIR;
+        try (StrictModeContext ignored = StrictModeContext.allowDiskWrites()) {
+            return ContextUtils.getApplicationContext().getCacheDir() + PASSWORDS_CACHE_DIR;
+        }
     }
 
     /**
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 470b474..990513fe 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
@@ -903,7 +903,8 @@
                 SecurityStateModel.getSecurityLevelForWebContents(mWebContents),
                 new ShippingStrings(mShippingType), mPaymentUisShowStateReconciler,
                 Profile.fromWebContents(mWebContents));
-        activity.getLifecycleDispatcher().register(mUI);
+        activity.getLifecycleDispatcher().register(
+                mUI); // registered as a PauseResumeWithNativeObserver
 
         final FaviconHelper faviconHelper = new FaviconHelper();
         faviconHelper.getLocalFaviconImageForURL(Profile.fromWebContents(mWebContents),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java
index 384d6cf..52599d62 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerCoordinator.java
@@ -90,7 +90,8 @@
         PaymentHandlerMediator mediator = new PaymentHandlerMediator(model, this::hide,
                 mWebContents, uiObserver, activity.getActivityTab().getView(),
                 mToolbarCoordinator.getToolbarHeightPx(),
-                calculateBottomSheetToolbarContainerTopPadding(activity));
+                calculateBottomSheetToolbarContainerTopPadding(activity),
+                activity.getLifecycleDispatcher());
         activity.getWindow().getDecorView().addOnLayoutChangeListener(mediator);
         BottomSheetController bottomSheetController = activity.getBottomSheetController();
         bottomSheetController.addObserver(mediator);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java
index 78626d6c..a2c46a3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/PaymentHandlerMediator.java
@@ -7,8 +7,12 @@
 import android.os.Handler;
 import android.view.View;
 
+import androidx.annotation.IntDef;
+
 import org.chromium.chrome.browser.ChromeActivity;
 import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
+import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
+import org.chromium.chrome.browser.lifecycle.Destroyable;
 import org.chromium.chrome.browser.payments.ServiceWorkerPaymentAppBridge;
 import org.chromium.chrome.browser.payments.SslValidityChecker;
 import org.chromium.chrome.browser.payments.handler.PaymentHandlerCoordinator.PaymentHandlerUiObserver;
@@ -26,6 +30,9 @@
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.util.TokenHolder;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * PaymentHandler mediator, which is responsible for receiving events from the view and notifies the
  * backend (the coordinator).
@@ -40,7 +47,7 @@
     private final PropertyModel mModel;
     // Whenever invoked, invoked outside of the WebContentsObserver callbacks.
     private final Runnable mHider;
-    // Postfixed with "Ref" to distinguish from mWebContent in WebContentsObserver. Although
+    // Postfixes with "Ref" to distinguish from mWebContent in WebContentsObserver. Although
     // referencing the same object, mWebContentsRef is preferable to WebContents here because
     // mWebContents (a weak ref) requires null checks, while mWebContentsRef is guaranteed to be not
     // null.
@@ -49,12 +56,26 @@
     // Used to postpone execution of a callback to avoid destroy objects (e.g., WebContents) in
     // their own methods.
     private final Handler mHandler = new Handler();
+    private final Destroyable mActivityDestroyListener;
+    private final ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
     private final View mTabView;
     private final int mToolbarViewHeightPx;
     private final int mContainerTopPaddingPx;
+    private @CloseReason int mCloseReason = CloseReason.OTHERS;
 
     /** A token held while the payment sheet is obscuring all visible tabs. */
-    private int mTabObscuringToken;
+    private int mTabObscuringToken = TokenHolder.INVALID_TOKEN;
+
+    @IntDef({CloseReason.OTHERS, CloseReason.USER, CloseReason.ACTIVITY_DIED,
+            CloseReason.INSECURE_NAVIGATION, CloseReason.FAIL_LOAD})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface CloseReason {
+        int OTHERS = 0;
+        int USER = 1;
+        int ACTIVITY_DIED = 2;
+        int INSECURE_NAVIGATION = 3;
+        int FAIL_LOAD = 4;
+    }
 
     /**
      * Build a new mediator that handle events from outside the payment handler component.
@@ -67,10 +88,13 @@
      * @param tabView The view of the main tab.
      * @param toolbarViewHeightPx The height of the toolbar view in px.
      * @param containerTopPaddingPx The padding top of bottom_sheet_toolbar_container in px
+     * @param activityLifeCycleDispatcher The lifecycle dispatcher of the activity where this UI
+     *         lives.
      */
     /* package */ PaymentHandlerMediator(PropertyModel model, Runnable hider,
             WebContents webContents, PaymentHandlerUiObserver observer, View tabView,
-            int toolbarViewHeightPx, int containerTopPaddingPx) {
+            int toolbarViewHeightPx, int containerTopPaddingPx,
+            ActivityLifecycleDispatcher activityLifeCycleDispatcher) {
         super(webContents);
         assert webContents != null;
         mTabView = tabView;
@@ -82,7 +106,15 @@
         mContainerTopPaddingPx = containerTopPaddingPx;
         mModel.set(PaymentHandlerProperties.CONTENT_VISIBLE_HEIGHT_PX, contentVisibleHeight());
 
-        mTabObscuringToken = TokenHolder.INVALID_TOKEN;
+        mActivityLifecycleDispatcher = activityLifeCycleDispatcher;
+        mActivityDestroyListener = new Destroyable() {
+            @Override
+            public void destroy() {
+                mCloseReason = CloseReason.ACTIVITY_DIED;
+                mHandler.post(mHider);
+            }
+        };
+        mActivityLifecycleDispatcher.register(mActivityDestroyListener);
     }
 
     // Implement View.OnLayoutChangeListener:
@@ -100,7 +132,7 @@
     public void onSheetStateChanged(@SheetState int newState) {
         switch (newState) {
             case BottomSheetController.SheetState.HIDDEN:
-                ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContentsRef);
+                mCloseReason = CloseReason.USER;
                 mHandler.post(mHider);
                 break;
         }
@@ -112,6 +144,7 @@
                 - mContainerTopPaddingPx;
     }
 
+    // Implement BottomSheetObserver:
     @Override
     public void onSheetOffsetChanged(float heightFraction, float offsetPx) {}
 
@@ -145,48 +178,79 @@
         setIsObscuringAllTabs(activity, true);
     }
 
+    // Implement BottomSheetObserver:
     @Override
     public void onSheetOpened(@StateChangeReason int reason) {
         mPaymentHandlerUiObserver.onPaymentHandlerUiShown();
         showScrim();
     }
 
+    // Implement BottomSheetObserver:
     @Override
     public void onSheetClosed(@StateChangeReason int reason) {
         // This is invoked when the sheet returns to the peek state, but Payment Handler doesn't
         // have a peek state.
     }
 
+    // Implement BottomSheetObserver:
     @Override
     public void onSheetFullyPeeked() {}
 
+    // Implement BottomSheetObserver:
     @Override
     public void onSheetContentChanged(BottomSheetContent newContent) {}
 
     // Implement WebContentsObserver:
     @Override
     public void destroy() {
-        super.destroy(); // Stops observing the web contents and cleans up associated references.
+        mActivityLifecycleDispatcher.unregister(mActivityDestroyListener);
+
+        switch (mCloseReason) {
+            case CloseReason.INSECURE_NAVIGATION:
+                ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindowForInsecureNavigation(
+                        mWebContentsRef);
+                break;
+            case CloseReason.USER:
+                // Intentional fallthrough.
+            case CloseReason.FAIL_LOAD:
+                // Intentional fallthrough.
+                // TODO(crbug.com/1017926): Respond to service worker with the net error.
+            case CloseReason.ACTIVITY_DIED:
+                ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContentsRef);
+                break;
+            case CloseReason.OTHERS:
+                // No need to notify ServiceWorkerPaymentAppBridge when merchant aborts the
+                // payment request (and thus {@link PaymentRequestImpl} closes
+                // PaymentHandlerMediator). "OTHERS" category includes this cases.
+                // TODO(crbug.com/1091957): we should explicitly list merchant aborting payment
+                // request as a {@link CloseReason}, renames "OTHERS" as "UNKNOWN" and asserts
+                // that PaymentHandler wouldn't be closed for unknown reason.
+        }
         mHandler.removeCallbacksAndMessages(null);
         hideScrim();
+        super.destroy(); // Stops observing the web contents and cleans up associated references.
     }
 
     private void hideScrim() {
         ChromeActivity activity = ChromeActivity.fromWebContents(mWebContentsRef);
-        assert activity != null;
-
-        ScrimCoordinator coordinator = activity.getBottomSheetController().getScrimCoordinator();
-        coordinator.hideScrim(true);
+        // activity would be null when this method is triggered by activity being destroyed.
+        if (activity == null) return;
 
         setIsObscuringAllTabs(activity, false);
+
+        ScrimCoordinator coordinator = activity.getBottomSheetController().getScrimCoordinator();
+        if (coordinator == null) return;
+        coordinator.hideScrim(/*animate=*/true);
     }
 
+    // Implement WebContentsObserver:
     @Override
     public void didFinishNavigation(NavigationHandle navigationHandle) {
         if (navigationHandle.isSameDocument()) return;
         closeIfInsecure();
     }
 
+    // Implement WebContentsObserver:
     @Override
     public void didChangeVisibleSecurityState() {
         closeIfInsecure();
@@ -200,17 +264,16 @@
 
     private void closeUIForInsecureNavigation() {
         mHandler.post(() -> {
-            ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindowForInsecureNavigation(
-                    mWebContentsRef);
+            mCloseReason = CloseReason.INSECURE_NAVIGATION;
             mHider.run();
         });
     }
 
+    // Implement WebContentsObserver:
     @Override
     public void didFailLoad(boolean isMainFrame, int errorCode, String failingUrl) {
         mHandler.post(() -> {
-            // TODO(crbug.com/1017926): Respond to service worker with the net error.
-            ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContentsRef);
+            mCloseReason = CloseReason.FAIL_LOAD;
             mHider.run();
         });
     }
@@ -218,10 +281,11 @@
     // Implement PaymentHandlerToolbarObserver:
     @Override
     public void onToolbarCloseButtonClicked() {
-        ServiceWorkerPaymentAppBridge.onClosingPaymentAppWindow(mWebContentsRef);
+        mCloseReason = CloseReason.USER;
         mHandler.post(mHider);
     }
 
+    // Implement PaymentHandlerView.PaymentHandlerViewObserver
     @Override
     public void onSystemBackButtonClicked() {
         NavigationController navigation = mWebContentsRef.getNavigationController();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarCoordinator.java
index b993af84..77e5ea7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/handler/toolbar/PaymentHandlerToolbarCoordinator.java
@@ -60,14 +60,18 @@
         assert url != null;
         mWebContents = webContents;
         mActivity = context;
-        PropertyModel model = new PropertyModel.Builder(PaymentHandlerToolbarProperties.ALL_KEYS)
-                                      .with(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, true)
-                                      .with(PaymentHandlerToolbarProperties.LOAD_PROGRESS,
-                                              PaymentHandlerToolbarMediator.MINIMUM_LOAD_PROGRESS)
-                                      .with(PaymentHandlerToolbarProperties.SECURITY_ICON,
-                                              ConnectionSecurityLevel.NONE)
-                                      .with(PaymentHandlerToolbarProperties.URL, url)
-                                      .build();
+        int defaultSecurityLevel = ConnectionSecurityLevel.NONE;
+        PropertyModel model =
+                new PropertyModel.Builder(PaymentHandlerToolbarProperties.ALL_KEYS)
+                        .with(PaymentHandlerToolbarProperties.PROGRESS_VISIBLE, true)
+                        .with(PaymentHandlerToolbarProperties.LOAD_PROGRESS,
+                                PaymentHandlerToolbarMediator.MINIMUM_LOAD_PROGRESS)
+                        .with(PaymentHandlerToolbarProperties.SECURITY_ICON,
+                                getSecurityIconResource(defaultSecurityLevel))
+                        .with(PaymentHandlerToolbarProperties.SECURITY_ICON_CONTENT_DESCRIPTION,
+                                getSecurityIconContentDescription(defaultSecurityLevel))
+                        .with(PaymentHandlerToolbarProperties.URL, url)
+                        .build();
         mIsSmallDevice = !DeviceFormFactor.isNonMultiDisplayContextOnTablet(context);
         mMediator = new PaymentHandlerToolbarMediator(model, webContents, /*delegate=*/this);
         mToolbarView =
@@ -116,7 +120,7 @@
     public int getSecurityIconResource(@ConnectionSecurityLevel int securityLevel) {
         return SecurityStatusIcon.getSecurityIconResource(securityLevel,
                 SecurityStateModel.shouldShowDangerTriangleForWarningLevel(), mIsSmallDevice,
-                /*skipIconForNeutralState=*/true);
+                /*skipIconForNeutralState=*/false);
     }
 
     // Implement PaymentHandlerToolbarMediatorDelegate.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java
index 4c4fab38..ac85e9b6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareDelegateImpl.java
@@ -20,8 +20,11 @@
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
 import org.chromium.chrome.browser.printing.PrintShareActivity;
+import org.chromium.chrome.browser.printing.TabPrinter;
 import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfShareActivity;
 import org.chromium.chrome.browser.share.qrcode.QrCodeShareActivity;
+import org.chromium.chrome.browser.share.share_sheet.ShareSheetCoordinator;
+import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder;
 import org.chromium.chrome.browser.tab.SadTab;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.util.ChromeFileProvider;
@@ -32,6 +35,9 @@
 import org.chromium.components.ui_metrics.CanonicalURLResult;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.net.GURLUtils;
+import org.chromium.printing.PrintManagerDelegateImpl;
+import org.chromium.printing.PrintingController;
+import org.chromium.printing.PrintingControllerImpl;
 import org.chromium.ui.base.WindowAndroid;
 
 import java.util.ArrayList;
@@ -70,8 +76,8 @@
         if (mShareStartTime == 0L) {
             mShareStartTime = System.currentTimeMillis();
         }
-        mDelegate.share(
-                params, chromeShareExtras, mBottomSheetController, mTabProvider, mShareStartTime);
+        mDelegate.share(params, chromeShareExtras, mBottomSheetController, mTabProvider,
+                this::printTab, mShareStartTime);
         mShareStartTime = 0;
     }
 
@@ -255,6 +261,15 @@
         }
     }
 
+    private void printTab(Tab tab) {
+        Activity activity = mTabProvider.get().getWindowAndroid().getActivity().get();
+        PrintingController printingController = PrintingControllerImpl.getInstance();
+        if (printingController != null && !printingController.isBusy()) {
+            printingController.startPrint(
+                    new TabPrinter(mTabProvider.get()), new PrintManagerDelegateImpl(activity));
+        }
+    }
+
     /**
      * Delegate for share handling.
      */
@@ -263,7 +278,8 @@
          * Trigger the share action for the specified params.
          */
         void share(ShareParams params, ChromeShareExtras chromeShareExtras,
-                BottomSheetController controller, Supplier<Tab> tabProvider, long shareStartTime) {
+                BottomSheetController controller, Supplier<Tab> tabProvider,
+                Callback<Tab> printCallback, long shareStartTime) {
             if (chromeShareExtras.shareDirectly()) {
                 ShareHelper.shareWithLastUsedComponent(params);
             } else if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARING_HUB)) {
@@ -271,7 +287,7 @@
                         new ShareSheetCoordinator(controller, tabProvider,
                                 new ShareSheetPropertyModelBuilder(controller,
                                         ContextUtils.getApplicationContext().getPackageManager()),
-                                PrefServiceBridge.getInstance());
+                                PrefServiceBridge.getInstance(), printCallback);
                 // TODO(crbug/1009124): open custom share sheet.
                 coordinator.showShareSheet(params, chromeShareExtras, shareStartTime);
             } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
index deaa80a9..539f10c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareHelper.java
@@ -85,7 +85,8 @@
      * @param params The share parameters.
      * @param saveLastUsed True if the chosen share component should be saved for future reuse.
      */
-    static void showDefaultShareUi(ShareParams params, boolean saveLastUsed) {
+    // TODO(crbug/1022172): Should be package-protected once modularization is complete.
+    public static void showDefaultShareUi(ShareParams params, boolean saveLastUsed) {
         if (saveLastUsed) {
             params.setCallback(new SaveComponentCallback(params.getCallback()));
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
index 9ae97df..ebf618e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/DEPS
@@ -51,6 +51,7 @@
     "+chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePage.java",
     "+chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageAssassin.java",
     "+chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java",
+    "+chrome/android/java/src/org/chromium/chrome/browser/paint_preview/PaintPreviewHelper.java",
     "+chrome/android/java/src/org/chromium/chrome/browser/prerender/ExternalPrerenderHandler.java",
     "+chrome/android/java/src/org/chromium/chrome/browser/rlz/RevenueStats.java",
     "+chrome/android/java/src/org/chromium/chrome/browser/night_mode",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java
index 4ad747c6..1e4bcf8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabGestureStateListener.java
@@ -67,7 +67,7 @@
                 boolean scrolling = manager != null ? manager.isScrollInProgress() : false;
                 RewindableIterator<TabObserver> observers = ((TabImpl) mTab).getTabObservers();
                 while (observers.hasNext()) {
-                    observers.next().onContentViewScrollingStateChanged(scrolling);
+                    observers.next().onContentViewScrollingStateChanged(mTab, scrolling);
                 }
             }
         };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
index 1ec43bb..c28887e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabImpl.java
@@ -34,6 +34,7 @@
 import org.chromium.chrome.browser.native_page.NativePageAssassin;
 import org.chromium.chrome.browser.night_mode.NightModeUtils;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
+import org.chromium.chrome.browser.paint_preview.PaintPreviewHelper;
 import org.chromium.chrome.browser.prerender.ExternalPrerenderHandler;
 import org.chromium.chrome.browser.rlz.RevenueStats;
 import org.chromium.chrome.browser.tab.TabState.WebContentsState;
@@ -618,7 +619,6 @@
             updateInteractableState();
 
             loadIfNeeded();
-            assert !isFrozen();
 
             if (getWebContents() != null) getWebContents().onShow();
 
@@ -1175,6 +1175,7 @@
         Rect original = hasWebContents
                 ? new Rect(0, 0, mContentView.getWidth(), mContentView.getHeight())
                 : new Rect();
+        for (TabObserver observer : mObservers) observer.webContentsWillSwap(this);
         if (hasWebContents) mWebContents.onHide();
         Context appContext = ContextUtils.getApplicationContext();
         Rect bounds = original.isEmpty()
@@ -1394,6 +1395,14 @@
      * history load are used.
      */
     private final void restoreIfNeeded() {
+        // Attempts to display the Paint Preview representation of this Tab instead of fully
+        // restoring. Please note that this is behind an experimental flag.
+        if (isFrozen()
+                && PaintPreviewHelper.showPaintPreviewOnRestore(
+                        this, () -> restoreIfNeeded(), () -> restoreIfNeeded())) {
+            return;
+        }
+
         try {
             TraceEvent.begin("Tab.restoreIfNeeded");
             // Restore is needed for a tab that is loaded for the first time. WebContents will
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManager.java
index 38230aa..5c276c07 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManager.java
@@ -14,20 +14,15 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate;
-import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
 import org.chromium.chrome.browser.omnibox.LocationBar;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinator;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuObserver;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuPropertiesDelegate;
-import org.chromium.components.feature_engagement.EventConstants;
-import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.ui.util.TokenHolder;
 
 /**
@@ -48,7 +43,6 @@
     private int mFullscreenMenuToken = TokenHolder.INVALID_TOKEN;
     private int mFullscreenHighlightToken = TokenHolder.INVALID_TOKEN;
     private final TopToolbarCoordinator mToolbar;
-    private final Supplier<Profile> mProfileSupplier;
     private final SetFocusFunction mSetUrlBarFocusFunction;
     private Runnable mRequestRenderRunnable;
     private Runnable mUpdateStateChangedListener;
@@ -63,7 +57,6 @@
      *         controls.
      * @param activity Activity in which this object lives.
      * @param toolbar Toolbar object that hosts the app menu button.
-     * @param profileSupplier Supplier of the current profile.
      * @param setUrlBarFocusFunction Function that allows setting focus on the url bar.
      * @param requestRenderRunnable Runnable that requests a re-rendering of the compositor view
      *         containing the app menu button.
@@ -72,13 +65,12 @@
      */
     public ToolbarAppMenuManager(ObservableSupplier<AppMenuCoordinator> appMenuCoordinatorSupplier,
             BrowserStateBrowserControlsVisibilityDelegate controlsVisibilityDelegate,
-            Activity activity, TopToolbarCoordinator toolbar, Supplier<Profile> profileSupplier,
+            Activity activity, TopToolbarCoordinator toolbar,
             SetFocusFunction setUrlBarFocusFunction, Runnable requestRenderRunnable,
             boolean shouldShowAppUpdateBadge, Supplier<Boolean> isInOverviewModeSupplier) {
         mControlsVisibilityDelegate = controlsVisibilityDelegate;
         mActivity = activity;
         mToolbar = toolbar;
-        mProfileSupplier = profileSupplier;
         mSetUrlBarFocusFunction = setUrlBarFocusFunction;
         mAppMenuCoordinatorSupplier = appMenuCoordinatorSupplier;
         mAppMenuCoordinatorSupplierObserver = this::onAppMenuInitialized;
@@ -173,13 +165,6 @@
         mAppMenuButtonHelper.setOnAppMenuShownListener(() -> {
             RecordUserAction.record("MobileToolbarShowMenu");
             mToolbar.onMenuShown();
-
-            // Assume data saver footer is shown only if data reduction proxy is enabled.
-            if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()) {
-                Profile profile = mProfileSupplier.get();
-                Tracker tracker = TrackerFactory.getTrackerForProfile(profile);
-                tracker.notifyEvent(EventConstants.OVERFLOW_OPENED_WITH_DATA_SAVER_SHOWN);
-            }
         });
         mToolbar.setAppMenuButtonHelper(mAppMenuButtonHelper);
         mAppMenuPropertiesDelegate = appMenuCoordinator.getAppMenuPropertiesDelegate();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
index e81579f..e73a80d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -320,7 +320,7 @@
         mControlsVisibilityDelegate = controlsVisibilityDelegate;
 
         mAppMenuManager = new ToolbarAppMenuManager(appMenuCoordinatorSupplier,
-                mControlsVisibilityDelegate, mActivity, mToolbar, mProfileSupplier,
+                mControlsVisibilityDelegate, mActivity, mToolbar,
                 (focus, type)
                         -> setUrlBarFocus(focus, type),
                 mActivity.getCompositorViewHolder()::requestFocus, shouldShowUpdateBadge,
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index b2f2406..d71e9f6 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -41,6 +41,7 @@
 chrome_junit_test_java_sources += tab_management_junit_java_sources
 chrome_test_java_sources += tab_management_test_java_sources
 chrome_test_java_sources += share_test_java_sources
+chrome_junit_test_java_sources += share_junit_test_java_sources
 
 if (enable_arcore) {
   chrome_java_sources += [
@@ -51,15 +52,3 @@
     "java/src/org/chromium/chrome/browser/vr/ArImmersiveOverlay.java",
   ]
 }
-
-if (enable_password_change_in_leaked_dialog) {
-  chrome_java_sources += [
-    "java/src/org/chromium/chrome/browser/password_manager/CredentialLeakDialogPasswordChangeBridge.java",
-    "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeContents.java",
-    "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeCoordinator.java",
-    "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeMediator.java",
-    "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeProperties.java",
-    "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeView.java",
-    "java/src/org/chromium/chrome/browser/password_manager/PasswordManagerDialogPasswordChangeViewBinder.java",
-  ]
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
index e6dab55c..bbd75a9 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -7,7 +7,6 @@
 import android.content.ClipData;
 import android.content.ClipboardManager;
 import android.content.Context;
-import android.net.Uri;
 import android.support.test.InstrumentationRegistry;
 import android.support.test.filters.LargeTest;
 import android.support.test.filters.MediumTest;
@@ -54,6 +53,7 @@
 import org.chromium.content_public.browser.test.util.TestTouchUtils;
 import org.chromium.net.test.EmbeddedTestServer;
 import org.chromium.policy.test.annotations.Policies;
+import org.chromium.ui.base.Clipboard;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -436,7 +436,7 @@
 
         Integer[] expectedItems = {R.id.contextmenu_save_image,
                 R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_by_image,
-                R.id.contextmenu_share_image};
+                R.id.contextmenu_share_image, R.id.contextmenu_copy_image};
         Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab};
         expectedItems =
                 addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems);
@@ -455,7 +455,7 @@
 
         Integer[] expectedItems = {R.id.contextmenu_save_image,
                 R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_with_google_lens,
-                R.id.contextmenu_share_image};
+                R.id.contextmenu_share_image, R.id.contextmenu_copy_image};
         Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab};
         expectedItems =
                 addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems);
@@ -494,7 +494,8 @@
         ContextMenu menu = ContextMenuUtils.openContextMenu(tab, "testImage");
 
         Integer[] expectedItems = {R.id.contextmenu_save_image,
-                R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image};
+                R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image,
+                R.id.contextmenu_copy_image};
         Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab};
         expectedItems =
                 addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems);
@@ -515,7 +516,8 @@
 
         // Search with Google Lens is only supported when Google is the default search provider.
         Integer[] expectedItems = {R.id.contextmenu_save_image,
-                R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image};
+                R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_share_image,
+                R.id.contextmenu_copy_image};
         Integer[] featureItems = {R.id.contextmenu_open_image_in_ephemeral_tab};
         expectedItems =
                 addItemsIf(EphemeralTabCoordinator.isSupported(), expectedItems, featureItems);
@@ -534,7 +536,8 @@
                 R.id.contextmenu_open_in_incognito_tab, R.id.contextmenu_copy_link_address,
                 R.id.contextmenu_save_link_as, R.id.contextmenu_save_image,
                 R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_by_image,
-                R.id.contextmenu_share_image, R.id.contextmenu_share_link};
+                R.id.contextmenu_share_image, R.id.contextmenu_share_link,
+                R.id.contextmenu_copy_image};
         Integer[] featureItems = {R.id.contextmenu_open_in_ephemeral_tab,
                 R.id.contextmenu_open_image_in_ephemeral_tab};
         expectedItems =
@@ -557,7 +560,8 @@
                 R.id.contextmenu_open_in_incognito_tab, R.id.contextmenu_copy_link_address,
                 R.id.contextmenu_save_link_as, R.id.contextmenu_save_image,
                 R.id.contextmenu_open_image_in_new_tab, R.id.contextmenu_search_with_google_lens,
-                R.id.contextmenu_share_image, R.id.contextmenu_share_link};
+                R.id.contextmenu_share_image, R.id.contextmenu_share_link,
+                R.id.contextmenu_copy_image};
         Integer[] featureItems = {R.id.contextmenu_open_in_ephemeral_tab,
                 R.id.contextmenu_open_image_in_ephemeral_tab};
         expectedItems =
@@ -611,6 +615,9 @@
     @Feature({"Browser", "ContextMenu"})
     @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_COPY_IMAGE})
     public void testCopyImage() throws Throwable {
+        // Clear the clipboard.
+        Clipboard.getInstance().setText("");
+
         hardcodeTestImageForSharing(TEST_GIF_IMAGE_FILE_EXTENSION);
         Tab tab = mDownloadTestRule.getActivity().getActivityTab();
         // Allow all thread policies temporarily in main thread to avoid
@@ -623,12 +630,23 @@
                     R.id.contextmenu_copy_image);
         }
 
-        String imageUriString = getClipboardUri().toString();
+        CriteriaHelper.pollUiThread(new Criteria() {
+            @Override
+            public boolean isSatisfied() {
+                return Clipboard.getInstance().getImageUri() != null;
+            }
+        });
+
+        String imageUriString = Clipboard.getInstance().getImageUri().toString();
+
         Assert.assertTrue("Image content prefix is not correct",
                 imageUriString.startsWith(
                         "content://org.chromium.chrome.tests.FileProvider/images/screenshot/"));
         Assert.assertTrue("Image extension is not correct",
                 imageUriString.endsWith(TEST_GIF_IMAGE_FILE_EXTENSION));
+
+        // Clean up the clipboard.
+        Clipboard.getInstance().setText("");
     }
 
     /**
@@ -706,23 +724,6 @@
         return clipboardTextRef.get();
     }
 
-    private Uri getClipboardUri() throws Throwable {
-        final AtomicReference<Uri> clipboardUriRef = new AtomicReference<>();
-        mDownloadTestRule.runOnUiThread(new Runnable() {
-            @Override
-            public void run() {
-                ClipboardManager clipMgr =
-                        (ClipboardManager) mDownloadTestRule.getActivity().getSystemService(
-                                Context.CLIPBOARD_SERVICE);
-                ClipData clipData = clipMgr.getPrimaryClip();
-                Assert.assertNotNull("Primary clip is null", clipData);
-                Assert.assertTrue("Primary clip contains no items.", clipData.getItemCount() > 0);
-                clipboardUriRef.set(clipData.getItemAt(0).getUri());
-            }
-        });
-        return clipboardUriRef.get();
-    }
-
     /**
      * Hardcode image bytes to non-null arbitrary data.
      * @param extension Image file extension.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
index 238a509..8ff71e3 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerTest.java
@@ -31,7 +31,8 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.UrlUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.compositor.layouts.OverviewModeController;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.omnibox.UrlBar;
@@ -39,8 +40,8 @@
 import org.chromium.chrome.browser.tab.TabStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.tab.TabTestUtils;
 import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid;
+import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.FullscreenTestUtils;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.content_public.browser.GestureListenerManager;
@@ -69,7 +70,8 @@
 })
 public class FullscreenManagerTest {
     @Rule
-    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
+    public ChromeActivityTestRule<? extends ChromeActivity> mActivityTestRule =
+            new ChromeActivityTestRule(ChromeTabbedActivity.class);
 
     private static final String LONG_HTML_WITH_AUTO_FOCUS_INPUT_TEST_PAGE =
             UrlUtils.encodeHtmlDataUri("<html>"
@@ -420,40 +422,17 @@
 
         Tab tab = mActivityTestRule.getActivity().getActivityTab();
         final TabWebContentsDelegateAndroid delegate = TabTestUtils.getTabWebContentsDelegate(tab);
-        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, delegate::rendererUnresponsive);
+        PostTask.runOrPostTask(
+                UiThreadTaskTraits.DEFAULT, () -> { delegate.rendererUnresponsive(); });
         FullscreenManagerTestUtils.waitForBrowserControlsPosition(mActivityTestRule, 0);
 
-        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, delegate::rendererResponsive);
+        PostTask.runOrPostTask(
+                UiThreadTaskTraits.DEFAULT, () -> { delegate.rendererResponsive(); });
 
         // TODO(tedchoc): This is running into timing issues with the renderer offset logic.
         // waitForBrowserControlsToBeMoveable(getActivity().getActivityTab());
     }
 
-    @Test
-    @LargeTest
-    @Feature({"Fullscreen"})
-    public void testControlsShownOnUnresponsiveRendererUponExitingTabSwitcherMode()
-            throws Exception {
-        FullscreenManagerTestUtils.disableBrowserOverrides();
-        mActivityTestRule.startMainActivityWithURL(LONG_HTML_TEST_PAGE);
-
-        ChromeFullscreenManager fullscreenManager =
-                mActivityTestRule.getActivity().getFullscreenManager();
-        Assert.assertEquals(fullscreenManager.getTopControlOffset(), 0f, 0);
-
-        FullscreenManagerTestUtils.scrollBrowserControls(mActivityTestRule, false);
-
-        setTabSwitcherModeAndWait(true);
-        Tab tab = mActivityTestRule.getActivity().getActivityTab();
-        final TabWebContentsDelegateAndroid delegate = TabTestUtils.getTabWebContentsDelegate(tab);
-        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, delegate::rendererUnresponsive);
-        setTabSwitcherModeAndWait(false);
-
-        FullscreenManagerTestUtils.waitForBrowserControlsPosition(mActivityTestRule, 0);
-
-        PostTask.runOrPostTask(UiThreadTaskTraits.DEFAULT, delegate::rendererResponsive);
-    }
-
     /* @LargeTest
      * @Feature({"Fullscreen"})
      */
@@ -552,17 +531,4 @@
             }
         });
     }
-
-    /**
-     * Enter or exit the tab switcher with animations and wait for the scene to change.
-     * @param inSwitcher Whether to enter or exit the tab switcher.
-     */
-    private void setTabSwitcherModeAndWait(boolean inSwitcher) {
-        OverviewModeController controller = mActivityTestRule.getActivity().getLayoutManager();
-        if (inSwitcher) {
-            TestThreadUtils.runOnUiThreadBlocking(() -> controller.showOverview(false));
-        } else {
-            TestThreadUtils.runOnUiThreadBlocking(() -> controller.hideOverview(false));
-        }
-    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
index ea3b2c3..ebf7e524 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/media/ui/PictureInPictureControllerTest.java
@@ -112,6 +112,16 @@
                 "window.location.href = 'https://www.example.com/';"));
     }
 
+    @Test
+    @MediumTest
+    @CommandLineFlags.Add({"enable-features=Portals"})
+    @MinAndroidSdkLevel(Build.VERSION_CODES.O)
+    public void testExitPipOnPortalActivation() throws Throwable {
+        testExitOn(()
+                           -> JavaScriptUtils.executeJavaScript(getWebContents(),
+                                   "document.querySelector('portal').activate();"));
+    }
+
     /** Tests that PiP is left when the video leaves fullscreen. */
     @Test
     @MediumTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index 1b9de6ad..95d6a9f 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -92,8 +92,8 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.
 Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "disable-features=IPH_FeedHeaderMenu"})
-@Features.
-DisableFeatures({ChromeFeatureList.EXPLORE_SITES, ChromeFeatureList.REPORT_FEED_USER_ACTIONS})
+@Features.DisableFeatures({ChromeFeatureList.EXPLORE_SITES,
+        ChromeFeatureList.REPORT_FEED_USER_ACTIONS, ChromeFeatureList.QUERY_TILES})
 public class NewTabPageTest {
     private static final int ARTICLE_SECTION_HEADER_POSITION = 1;
     private static final int SIGNIN_PROMO_POSITION = 2;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java
index 84f6b86..94cf7210 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/HomepagePromoTest.java
@@ -80,6 +80,7 @@
 @RunWith(ChromeJUnit4ClassRunner.class)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @EnableFeatures(ChromeFeatureList.HOMEPAGE_PROMO_CARD)
+@Features.DisableFeatures(ChromeFeatureList.QUERY_TILES)
 public class HomepagePromoTest {
     public static final String PARTNER_HOMEPAGE_URL = "http://127.0.0.1:8000/foo.html";
     public static final String CUSTOM_TEST_URL = "http://127.0.0.1:8000/bar.html";
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
index 4ba3dd4..3232099 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
@@ -103,7 +103,6 @@
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
 import org.chromium.components.browser_ui.settings.ChromeBaseCheckBoxPreference;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.sync.ModelType;
@@ -624,7 +623,7 @@
         // empty.
         setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password"));
         overrideProfileSyncService(false, false);
-        SigninTestUtil.addAndSignInTestAccount();
+        mBrowserTestRule.addAndSignInTestAccount();
 
         mSettingsActivityTestRule.startSettingsActivity();
         PasswordSettings savedPasswordPrefs = mSettingsActivityTestRule.getFragment();
@@ -645,7 +644,7 @@
         // empty.
         setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password"));
         overrideProfileSyncService(false, true);
-        SigninTestUtil.addAndSignInTestAccount();
+        mBrowserTestRule.addAndSignInTestAccount();
 
         mSettingsActivityTestRule.startSettingsActivity();
         PasswordSettings savedPasswordPrefs = mSettingsActivityTestRule.getFragment();
@@ -666,7 +665,7 @@
         // empty.
         setPasswordSource(new SavedPasswordEntry("https://example.com", "test user", "password"));
         overrideProfileSyncService(true, true);
-        SigninTestUtil.addAndSignInTestAccount();
+        mBrowserTestRule.addAndSignInTestAccount();
 
         mSettingsActivityTestRule.startSettingsActivity();
         PasswordSettings savedPasswordPrefs = mSettingsActivityTestRule.getFragment();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/AutomaticEmbargoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/AutomaticEmbargoTest.java
new file mode 100644
index 0000000..59a8e0f
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/permissions/AutomaticEmbargoTest.java
@@ -0,0 +1,117 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.permissions;
+
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.LargeTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.content_public.common.ContentSwitches;
+import org.chromium.ui.modaldialog.DialogDismissalCause;
+
+/**
+ * Test suite for permissions automatic embargo logic.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class AutomaticEmbargoTest {
+    @Rule
+    public PermissionTestRule mPermissionRule = new PermissionTestRule(true /* useHttpsServer */);
+
+    private static final String GEOLOCATION_TEST_FILE =
+            "/chrome/test/data/geolocation/geolocation_on_load.html";
+    private static final String NOTIFICATIONS_TEST_FILE =
+            "/chrome/test/data/notifications/notification_tester.html";
+    private static final String MIDI_TEST_FILE = "/content/test/data/android/midi_permissions.html";
+    private static final String MEDIA_TEST_FILE =
+            "/content/test/data/android/media_permissions.html";
+
+    private static final int NUMBER_OF_DISMISSALS = 3;
+
+    @Before
+    public void setUp() throws Exception {
+        mPermissionRule.setUpActivity();
+    }
+
+    private void runTest(final String testFile, final String javascript, final String updaterPrefix,
+            final int nUpdates) throws Exception {
+        Tab tab = mPermissionRule.getActivity().getActivityTab();
+        PermissionUpdateWaiter updateWaiter =
+                new PermissionUpdateWaiter(updaterPrefix, mPermissionRule.getActivity());
+        tab.addObserver(updateWaiter);
+
+        for (int i = 0; i < NUMBER_OF_DISMISSALS; ++i) {
+            mPermissionRule.setUpUrl(testFile);
+            mPermissionRule.runJavaScriptCodeInCurrentTab(javascript);
+            PermissionTestRule.waitForDialog(mPermissionRule.getActivity());
+            TestThreadUtils.runOnUiThreadBlocking(() -> {
+                mPermissionRule.getActivity()
+                        .getModalDialogManager()
+                        .getCurrentPresenterForTest()
+                        .dismissCurrentDialog(DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE);
+            });
+            InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+        }
+
+        mPermissionRule.runNoPromptTest(updateWaiter, testFile, javascript, nUpdates, false, true);
+        tab.removeObserver(updateWaiter);
+    }
+
+    @Test
+    @LargeTest
+    @Feature({"Location"})
+    public void testGeolocationEmbargo() throws Exception {
+        runTest(GEOLOCATION_TEST_FILE, "", "Denied", 0);
+    }
+
+    @Test
+    @LargeTest
+    @Feature({"Notifications"})
+    public void testNotificationsEmbargo() throws Exception {
+        runTest(NOTIFICATIONS_TEST_FILE, "requestPermission()", "request-callback-denied", 0);
+    }
+
+    @Test
+    @LargeTest
+    @Feature({"MIDI"})
+    public void testMIDIEmbargo() throws Exception {
+        runTest(MIDI_TEST_FILE, "", "fail", 0);
+    }
+
+    @Test
+    @LargeTest
+    @Feature({"MediaPermissions"})
+    @CommandLineFlags.Add({ContentSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM})
+    public void testCameraEmbargo() throws Exception {
+        runTest(MEDIA_TEST_FILE, "initiate_getMicrophone()", "deny", 0);
+    }
+
+    @Test
+    @LargeTest
+    @Feature({"MediaPermissions"})
+    @CommandLineFlags.Add({ContentSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM})
+    public void testMicrophoneEmbargo() throws Exception {
+        runTest(MEDIA_TEST_FILE, "initiate_getCamera()", "deny", 0);
+    }
+
+    @Test
+    @LargeTest
+    @Feature({"MediaPermissions"})
+    @CommandLineFlags.Add({ContentSwitches.USE_FAKE_DEVICE_FOR_MEDIA_STREAM})
+    public void testMicrophoneAndCameraEmbargo() throws Exception {
+        runTest(MEDIA_TEST_FILE, "initiate_getCombined()", "deny", 0);
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHostTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHostTest.java
index 485a15c..47890e4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHostTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/photo_picker/DecoderServiceHostTest.java
@@ -39,8 +39,8 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 public class DecoderServiceHostTest implements DecoderServiceHost.DecoderStatusCallback,
                                                DecoderServiceHost.ImagesDecodedCallback {
-    // The timeout (in seconds) to wait for the decoding.
-    private static final long WAIT_TIMEOUT_SECONDS = 5L;
+    // The timeout (in milliseconds) to wait for the decoding.
+    private static final int WAIT_TIMEOUT_MS = 7500;
 
     // The base test file path.
     private static final String TEST_FILE_PATH = "chrome/test/data/android/photo_picker/";
@@ -100,12 +100,12 @@
     private void waitForDecoder() throws Exception {
         int callCount = mOnDecoderReadyCallback.getCallCount();
         mOnDecoderReadyCallback.waitForCallback(
-                callCount, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+                callCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
     }
 
     private void waitForThumbnailDecode() throws Exception {
         int callCount = mOnDecodedCallback.getCallCount();
-        mOnDecodedCallback.waitForCallback(callCount, 1, WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
+        mOnDecodedCallback.waitForCallback(callCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
     }
 
     private void decodeImage(DecoderServiceHost host, Uri uri, @PickerBitmap.TileTypes int fileType,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
index ade5871073..290730f4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/searchwidget/SearchActivityTest.java
@@ -12,7 +12,6 @@
 import android.app.Activity;
 import android.app.Instrumentation;
 import android.app.Instrumentation.ActivityMonitor;
-import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -22,8 +21,6 @@
 import android.view.KeyEvent;
 import android.view.ViewGroup;
 
-import androidx.core.content.FileProvider;
-
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -36,7 +33,6 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.Callback;
 import org.chromium.base.ContentUriUtils;
-import org.chromium.base.ContextUtils;
 import org.chromium.base.IntentUtils;
 import org.chromium.base.test.params.ParameterAnnotations;
 import org.chromium.base.test.params.ParameterSet;
@@ -46,6 +42,7 @@
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
+import org.chromium.chrome.browser.FileProviderHelper;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.document.ChromeLauncherActivity;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -86,7 +83,6 @@
 import org.chromium.url.GURL;
 
 import java.io.ByteArrayOutputStream;
-import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
@@ -178,18 +174,6 @@
         }
     }
 
-    // Helper class for clipboard Omnibox test.
-    private class FileProviderHelper implements ContentUriUtils.FileProviderUtil {
-        private static final String API_AUTHORITY_SUFFIX = ".FileProvider";
-
-        @Override
-        public Uri getContentUriFromFile(File file) {
-            Context appContext = ContextUtils.getApplicationContext();
-            return FileProvider.getUriForFile(
-                    appContext, appContext.getPackageName() + API_AUTHORITY_SUFFIX, file);
-        }
-    }
-
     @Rule
     public MultiActivityTestRule mTestRule = new MultiActivityTestRule();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java
index 57127cd..60b705e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/LensUtilsTest.java
@@ -18,7 +18,6 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
@@ -38,7 +37,7 @@
     @Test
     @SmallTest
     public void getShareWithGoogleLensIntentSignedInTest() {
-        SigninTestUtil.signIn(SigninTestUtil.addTestAccount("test@gmail.com"));
+        mBrowserTestRule.addAndSignInTestAccount();
 
         Intent intentNoUri = getShareWithGoogleLensIntentOnUiThread(Uri.EMPTY,
                 /* isIncognito= */ false, 1234L, /* srcUrl */ "", /* titleOrAltText */ "");
@@ -65,7 +64,7 @@
     @Test
     @SmallTest
     public void getShareWithGoogleLensIntentIncognitoTest() {
-        SigninTestUtil.signIn(SigninTestUtil.addTestAccount("test@gmail.com"));
+        mBrowserTestRule.addAndSignInTestAccount();
         Intent intentNoUri = getShareWithGoogleLensIntentOnUiThread(Uri.EMPTY,
                 /* isIncognito= */ true, 1234L, /* srcUrl */ "", /* titleOrAltText */ "");
         Assert.assertEquals("Intent without image has incorrect URI", "googleapp://lens",
@@ -93,7 +92,7 @@
     @SmallTest
     public void getShareWithGoogleLensIntentWithVariationsTest() {
         LensUtils.setFakeVariationsForTesting(" 123 456 ");
-        SigninTestUtil.signIn(SigninTestUtil.addTestAccount("test@gmail.com"));
+        mBrowserTestRule.addAndSignInTestAccount();
 
         final String contentUrl = "content://image-url";
         Intent intentWithContentUri = getShareWithGoogleLensIntentOnUiThread(Uri.parse(contentUrl),
@@ -117,7 +116,7 @@
     @SmallTest
     public void getShareWithGoogleLensIntentWithVariationsIncognitoTest() {
         LensUtils.setFakeVariationsForTesting(" 123 456 ");
-        SigninTestUtil.signIn(SigninTestUtil.addTestAccount("test@gmail.com"));
+        mBrowserTestRule.addAndSignInTestAccount();
 
         final String contentUrl = "content://image-url";
         Intent intentWithContentUri = getShareWithGoogleLensIntentOnUiThread(Uri.parse(contentUrl),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplIntegrationTest.java
index beb520d..2e016f2 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplIntegrationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplIntegrationTest.java
@@ -13,6 +13,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import org.chromium.base.Callback;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
@@ -117,7 +118,7 @@
                 @Override
                 void share(ShareParams params, ChromeShareExtras chromeShareParams,
                         BottomSheetController controller, Supplier<Tab> tabProvider,
-                        long shareStartTime) {
+                        Callback<Tab> printCallback, long shareStartTime) {
                     paramsRef.set(params);
                     helper.notifyCalled();
                 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
index f307952..bf2e4f8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.sync.FakeProfileSyncService;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
-import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
 import org.chromium.components.signin.ChromeSigninController;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
@@ -58,7 +57,7 @@
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
         // Override before signing in, otherwise regular ProfileSyncService will be created.
         overrideProfileSyncService();
-        SigninTestUtil.addAndSignInTestAccount();
+        mChromeBrowserTestRule.addAndSignInTestAccount();
 
         // PassphraseActivity won't start if an account isn't set.
         Assert.assertNotNull(ChromeSigninController.get().getSignedInAccountName());
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTrackerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTrackerTest.java
new file mode 100644
index 0000000..1cae285
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedSliceViewTrackerTest.java
@@ -0,0 +1,207 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.feed.v2;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.graphics.Rect;
+import android.support.test.filters.SmallTest;
+import android.view.View;
+import android.view.ViewTreeObserver;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+import java.util.Arrays;
+
+/** Unit tests for {@link FeedSliceViewTracker}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class FeedSliceViewTrackerTest {
+    // Mocking dependencies that are always present, but using a real FeedListContentManager.
+    @Mock
+    RecyclerView mParentView;
+    @Mock
+    FeedSliceViewTracker.Observer mObserver;
+    @Mock
+    LinearLayoutManager mLayoutManager;
+    @Mock
+    ViewTreeObserver mViewTreeObserver;
+    FeedListContentManager mContentManager;
+
+    FeedSliceViewTracker mTracker;
+
+    // Child view mocks are used as needed in some tests.
+    @Mock
+    View mChildA;
+    @Mock
+    View mChildB;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mContentManager = new FeedListContentManager(null, null);
+        doReturn(mLayoutManager).when(mParentView).getLayoutManager();
+        doReturn(mViewTreeObserver).when(mParentView).getViewTreeObserver();
+        mTracker = Mockito.spy(new FeedSliceViewTracker(mParentView, mContentManager, mObserver));
+    }
+
+    @Test
+    @SmallTest
+    public void testIsItemVisible_JustEnoughnViewport() {
+        mockViewDimensions(mChildA, 10, 10);
+        mockGetChildVisibleRect(mChildA, 0, 7);
+        Assert.assertTrue(mTracker.isViewVisible(mChildA));
+    }
+
+    @Test
+    @SmallTest
+    public void testIsItemVisible_NotEnoughnViewport() {
+        mockViewDimensions(mChildA, 10, 10);
+        mockGetChildVisibleRect(mChildA, 0, 6);
+        Assert.assertFalse(mTracker.isViewVisible(mChildA));
+    }
+
+    @Test
+    @SmallTest
+    public void testIsItemVisible_ZeroAreaInViewport() {
+        mockViewDimensions(mChildA, 10, 10);
+        mockGetChildVisibleRect(mChildA, 0, 0);
+        Assert.assertFalse(mTracker.isViewVisible(mChildA));
+    }
+
+    @Test
+    @SmallTest
+    public void testIsItemVisible_getChildVisibleRectReturnsFalse() {
+        mockViewDimensions(mChildA, 10, 10);
+        mockGetChildVisibleRectIsEmpty(mChildA);
+        Assert.assertFalse(mTracker.isViewVisible(mChildA));
+    }
+
+    @Test
+    @SmallTest
+    public void testIsItemVisible_ZeroArea() {
+        mockViewDimensions(mChildA, 0, 0);
+        mockGetChildVisibleRect(mChildA, 0, 0);
+        Assert.assertFalse(mTracker.isViewVisible(mChildA));
+    }
+
+    @Test
+    @SmallTest
+    public void testOnPreDraw_BothVisibleAreReportedExactlyOnce() {
+        mContentManager.addContents(0,
+                Arrays.asList(new FeedListContentManager.FeedContent[] {
+                        new FeedListContentManager.NativeViewContent("key1", mChildA),
+                        new FeedListContentManager.NativeViewContent("key2", mChildB),
+                }));
+        doReturn(0).when(mLayoutManager).findFirstVisibleItemPosition();
+        doReturn(1).when(mLayoutManager).findLastVisibleItemPosition();
+        doReturn(mChildA).when(mLayoutManager).findViewByPosition(eq(0));
+        doReturn(mChildB).when(mLayoutManager).findViewByPosition(eq(1));
+
+        doReturn(true).when(mTracker).isViewVisible(mChildA);
+        doReturn(true).when(mTracker).isViewVisible(mChildB);
+
+        mTracker.onPreDraw();
+
+        verify(mObserver).sliceVisible(eq("key1"));
+        verify(mObserver).sliceVisible(eq("key2"));
+
+        mTracker.onPreDraw(); // Does not repeat call to sliceVisible().
+    }
+
+    @Test
+    @SmallTest
+    public void testOnPreDraw_OnlyOneVisible() {
+        mContentManager.addContents(0,
+                Arrays.asList(new FeedListContentManager.FeedContent[] {
+                        new FeedListContentManager.NativeViewContent("key1", mChildA),
+                        new FeedListContentManager.NativeViewContent("key2", mChildB),
+                }));
+        doReturn(0).when(mLayoutManager).findFirstVisibleItemPosition();
+        doReturn(1).when(mLayoutManager).findLastVisibleItemPosition();
+        doReturn(mChildA).when(mLayoutManager).findViewByPosition(eq(0));
+        doReturn(mChildB).when(mLayoutManager).findViewByPosition(eq(1));
+
+        doReturn(false).when(mTracker).isViewVisible(mChildA);
+        doReturn(true).when(mTracker).isViewVisible(mChildB);
+
+        mTracker.onPreDraw();
+
+        verify(mObserver).sliceVisible(eq("key2"));
+    }
+
+    @Test
+    @SmallTest
+    public void testOnPreDraw_EmptyRecyclerView() {
+        mContentManager.addContents(0,
+                Arrays.asList(new FeedListContentManager.FeedContent[] {
+                        new FeedListContentManager.NativeViewContent("key1", mChildA),
+                        new FeedListContentManager.NativeViewContent("key2", mChildB),
+                }));
+        doReturn(RecyclerView.NO_POSITION).when(mLayoutManager).findFirstVisibleItemPosition();
+        doReturn(RecyclerView.NO_POSITION).when(mLayoutManager).findLastVisibleItemPosition();
+
+        mTracker.onPreDraw();
+    }
+
+    @Test
+    @SmallTest
+    public void testDestroy() {
+        doReturn(true).when(mViewTreeObserver).isAlive();
+        mTracker.destroy();
+        verify(mViewTreeObserver).removeOnPreDrawListener(any());
+
+        mTracker.destroy(); // A second destroy() does nothing.
+    }
+
+    void mockViewDimensions(View view, int width, int height) {
+        when(view.getWidth()).thenReturn(10);
+        when(view.getHeight()).thenReturn(10);
+    }
+
+    void mockGetChildVisibleRect(View child, int rectTop, int rectBottom) {
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocation) {
+                Rect rect = (Rect) invocation.getArguments()[1];
+                rect.top = rectTop;
+                rect.bottom = rectBottom;
+                return true;
+            }
+        })
+                .when(mParentView)
+                .getChildVisibleRect(eq(child), any(), any());
+    }
+
+    void mockGetChildVisibleRectIsEmpty(View child) {
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(InvocationOnMock invocation) {
+                return false;
+            }
+        })
+                .when(mParentView)
+                .getChildVisibleRect(eq(child), any(), any());
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java
index d60b8f8a..bbd4aace 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/v2/FeedStreamSurfaceTest.java
@@ -336,6 +336,45 @@
         verify(mSnackbarManager).showSnackbar(any());
     }
 
+    @Test
+    @SmallTest
+    public void testSurfaceClosed() {
+        FeedListContentManager contentManager =
+                mFeedStreamSurface.getFeedListContentManagerForTesting();
+
+        // Set 2 header views first.
+        View v0 = new View(mActivity);
+        View v1 = new View(mActivity);
+        mFeedStreamSurface.setHeaderViews(Arrays.asList(v0, v1));
+        assertEquals(2, contentManager.getItemCount());
+        assertEquals(v0,
+                ((FeedListContentManager.NativeViewContent) contentManager.getContent(0))
+                        .getNativeView());
+        assertEquals(v1,
+                ((FeedListContentManager.NativeViewContent) contentManager.getContent(1))
+                        .getNativeView());
+        final int headers = 2;
+
+        // Add 3 new slices.
+        StreamUpdate update = StreamUpdate.newBuilder()
+                                      .addUpdatedSlices(createSliceUpdateForNewXSurfaceSlice("a"))
+                                      .addUpdatedSlices(createSliceUpdateForNewXSurfaceSlice("b"))
+                                      .addUpdatedSlices(createSliceUpdateForNewXSurfaceSlice("c"))
+                                      .build();
+        mFeedStreamSurface.onStreamUpdated(update.toByteArray());
+        assertEquals(headers + 3, contentManager.getItemCount());
+
+        // Closing the surface should remove all non-header contents.
+        mFeedStreamSurface.surfaceClosed();
+        assertEquals(headers, contentManager.getItemCount());
+        assertEquals(v0,
+                ((FeedListContentManager.NativeViewContent) contentManager.getContent(0))
+                        .getNativeView());
+        assertEquals(v1,
+                ((FeedListContentManager.NativeViewContent) contentManager.getContent(1))
+                        .getNativeView());
+    }
+
     private SliceUpdate createSliceUpdateForExistingSlice(String sliceId) {
         return SliceUpdate.newBuilder().setSliceId(sliceId).build();
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerUnitTest.java
index 2ce6a44..cd6dca8 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/fullscreen/FullscreenManagerUnitTest.java
@@ -29,7 +29,6 @@
 import org.chromium.base.UserDataHost;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
@@ -58,8 +57,6 @@
     @Mock
     private TabModelSelector mTabModelSelector;
     @Mock
-    private ActivityTabProvider mActivityTabProvider;
-    @Mock
     private android.content.res.Resources mResources;
     @Mock
     private BrowserControlsStateProvider.Observer mBrowserControlsStateProviderObserver;
@@ -93,8 +90,8 @@
         ChromeFullscreenManager fullscreenManager = new ChromeFullscreenManager(
                 mActivity, ChromeFullscreenManager.ControlsPosition.TOP);
         mFullscreenManager = spy(fullscreenManager);
-        mFullscreenManager.initialize(mControlContainer, mActivityTabProvider, mTabModelSelector,
-                R.dimen.control_container_height);
+        mFullscreenManager.initialize(
+                mControlContainer, mTabModelSelector, R.dimen.control_container_height);
         mFullscreenManager.addObserver(mBrowserControlsStateProviderObserver);
         when(mFullscreenManager.getTab()).thenReturn(mTab);
     }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManagerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManagerTest.java
index 704e839d..ff06ada 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManagerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/toolbar/ToolbarAppMenuManagerTest.java
@@ -18,12 +18,10 @@
 import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.supplier.ObservableSupplierImpl;
-import org.chromium.base.supplier.Supplier;
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
 import org.chromium.chrome.browser.omnibox.LocationBar;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.toolbar.top.TopToolbarCoordinator;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuButtonHelper;
 import org.chromium.chrome.browser.ui.appmenu.AppMenuCoordinator;
@@ -43,8 +41,6 @@
     @Mock
     private TopToolbarCoordinator mToolbar;
     @Mock
-    private Supplier<Profile> mProfileSupplier;
-    @Mock
     private ToolbarAppMenuManager.SetFocusFunction mFocusFunction;
     @Mock
     private AppMenuCoordinator mAppMenuCoordinator;
@@ -79,9 +75,9 @@
         mMenuUiState = new UpdateMenuItemHelper.MenuUiState();
         doReturn(mMenuUiState).when(mUpdateMenuItemHelper).getUiState();
 
-        mToolbarAppMenuManager = new ToolbarAppMenuManager(mAppMenuSupplier,
-                mControlsVisibilityDelegate, mActivity, mToolbar, mProfileSupplier, mFocusFunction,
-                mRequestRenderRunnable, true, () -> false);
+        mToolbarAppMenuManager =
+                new ToolbarAppMenuManager(mAppMenuSupplier, mControlsVisibilityDelegate, mActivity,
+                        mToolbar, mFocusFunction, mRequestRenderRunnable, true, () -> false);
     }
 
     @Test
@@ -153,9 +149,9 @@
 
     @Test
     public void testAppMenuUpdateBadge_activityShouldNotShow() {
-        ToolbarAppMenuManager newManager = new ToolbarAppMenuManager(mAppMenuSupplier,
-                mControlsVisibilityDelegate, mActivity, mToolbar, mProfileSupplier, mFocusFunction,
-                mRequestRenderRunnable, false, () -> false);
+        ToolbarAppMenuManager newManager =
+                new ToolbarAppMenuManager(mAppMenuSupplier, mControlsVisibilityDelegate, mActivity,
+                        mToolbar, mFocusFunction, mRequestRenderRunnable, false, () -> false);
 
         doReturn(true).when(mActivity).isDestroyed();
         newManager.updateStateChanged();
diff --git a/chrome/android/modules/chrome_bundle_tmpl.gni b/chrome/android/modules/chrome_bundle_tmpl.gni
index ce5fdca..773ec29e1 100644
--- a/chrome/android/modules/chrome_bundle_tmpl.gni
+++ b/chrome/android/modules/chrome_bundle_tmpl.gni
@@ -80,6 +80,7 @@
                              "keystore_name",
                              "keystore_password",
                              "keystore_path",
+                             "lint_suppressions_dep",
                              "lint_suppressions_file",
                              "manifest_package",
                              "min_sdk_version",
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index b7f41ec3..7d10296d6 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -238,6 +238,7 @@
       "//chromeos/services/media_perception/public/mojom",
       "//chromeos/services/multidevice_setup/public/mojom",
       "//chromeos/services/network_config/public/mojom",
+      "//components/chromeos_camera/common:camera_app_helper",
       "//media/capture/video/chromeos/mojom:cros_camera",
     ]
   }
diff --git a/chrome/app/printing_strings.grdp b/chrome/app/printing_strings.grdp
index d4da801..01cbffb 100644
--- a/chrome/app/printing_strings.grdp
+++ b/chrome/app/printing_strings.grdp
@@ -108,20 +108,15 @@
              desc="Option shown on printer drop-down list for saving previewed document to Google Drive.">
       Save to Google Drive
     </message>
-    <message name="IDS_PRINT_PREVIEW_SUMMARY_FORMAT_SHORT" desc="Print summary, explaining to the user how many pages will be printed.">
-      <ph name="NUMBER_OF_SHEETS">$1<ex>10</ex></ph> <ph name="SHEETS_LABEL">$2<ex>sheets of paper</ex></ph>
+    <message name="IDS_PRINT_PREVIEW_SHEET_SUMMARY_LABEL" desc="Print summary, explaining to the user how many pages will be printed.">
+    {COUNT, plural,
+      =1 {1 sheet of paper}
+      other {{COUNT} sheets of paper}}
     </message>
-    <message name="IDS_PRINT_PREVIEW_SHEETS_LABEL_PLURAL" desc="Label shown in the print preview summary.">
-      sheets of paper
-    </message>
-    <message name="IDS_PRINT_PREVIEW_SHEETS_LABEL_SINGULAR" desc="Label shown in the print preview summary.">
-      sheet of paper
-    </message>
-    <message name="IDS_PRINT_PREVIEW_PAGE_LABEL_SINGULAR" desc="Label shown in the print preview summary.">
-      page
-    </message>
-    <message name="IDS_PRINT_PREVIEW_PAGE_LABEL_PLURAL" desc="Label shown in the print preview summary.">
-      pages
+    <message name="IDS_PRINT_PREVIEW_PAGE_SUMMARY_LABEL" desc="Print summary, explaining to the user how many pages will be saved.">
+    {COUNT, plural,
+      =1 {1 page}
+      other {{COUNT} pages}}
     </message>
     <message name="IDS_PRINT_PREVIEW_PAGE_RANGE_SYNTAX_INSTRUCTION" desc="Instruction shown when the user enters an invalid page range.">
       Invalid page range, use <ph name="EXAMPLE_PAGE_RANGE">$1<ex>e.g. 1-5, 8, 11-13</ex></ph>
@@ -326,15 +321,10 @@
         End User License Agreement
       </message>
       <message name="IDS_PRINT_PREVIEW_SHEETS_LIMIT_ERROR_MESSAGE" desc="Sheets limit error message, explaining to the user why printing is blocked.">
-        Exceeds limit of <ph name="NUMBER_OF_SHEETS">$1<ex>10</ex></ph> <ph name="SHEETS_LABEL">$2<ex>sheets of paper</ex></ph>
+      {COUNT, plural,
+        =1 {Exceeds limit of 1 sheet of paper}
+        other {Exceeds limit of {COUNT} sheets of paper}}
       </message>
-      <message name="IDS_PRINT_PREVIEW_SHEETS_LIMIT_LABEL_SINGULAR" desc="Label shown in the sheets limit error message.">
-        sheet of paper
-      </message>
-      <message name="IDS_PRINT_PREVIEW_SHEETS_LIMIT_LABEL_PLURAL" desc="Label shown in the sheets limit error message.">
-        sheets of paper
-      </message>
-
     </if>
     <if expr="not chromeos">
       <message name="IDS_PRINT_PREVIEW_SYSTEM_DIALOG_OPTION" desc="Option allowing the user to access advanced printer settings using the native print system dialog instead of printing through the print preview mechanism. Shortcut key is not translated">
diff --git a/chrome/app/theme/default_100_percent/common/hide_password_hover.png b/chrome/app/theme/default_100_percent/common/hide_password_hover.png
deleted file mode 100644
index cb5ccc8..0000000
--- a/chrome/app/theme/default_100_percent/common/hide_password_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_100_percent/common/show_password_hover.png b/chrome/app/theme/default_100_percent/common/show_password_hover.png
deleted file mode 100644
index f9a65b7..0000000
--- a/chrome/app/theme/default_100_percent/common/show_password_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/hide_password_hover.png b/chrome/app/theme/default_200_percent/common/hide_password_hover.png
deleted file mode 100644
index b190edf7..0000000
--- a/chrome/app/theme/default_200_percent/common/hide_password_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/default_200_percent/common/show_password_hover.png b/chrome/app/theme/default_200_percent/common/show_password_hover.png
deleted file mode 100644
index aa0093b..0000000
--- a/chrome/app/theme/default_200_percent/common/show_password_hover.png
+++ /dev/null
Binary files differ
diff --git a/chrome/app/theme/theme_resources.grd b/chrome/app/theme/theme_resources.grd
index a156bc8..ffe5c58 100644
--- a/chrome/app/theme/theme_resources.grd
+++ b/chrome/app/theme/theme_resources.grd
@@ -133,7 +133,6 @@
       </if>
       <if expr="not is_android">
         <structure type="chrome_scaled_image" name="IDR_HELP_MENU" file="common/help_16.png" />
-        <structure type="chrome_scaled_image" name="IDR_HIDE_PASSWORD_HOVER" file="common/hide_password_hover.png" />
         <if expr="not chromeos">
         <!-- User Manager tutorial -->
         <structure type="chrome_scaled_image" name="IDR_ICON_USER_MANAGER_TUTORIAL_YOUR_CHROME" file="common/user_manager_tutorial/your_chrome.png" />
@@ -270,7 +269,6 @@
       </if>
       <if expr="not is_android">
         <structure type="chrome_scaled_image" name="IDR_SETTINGS_FAVICON" file="common/favicon_settings.png" />
-        <structure type="chrome_scaled_image" name="IDR_SHOW_PASSWORD_HOVER" file="common/show_password_hover.png" />
       </if>
       <if expr="chromeos">
         <structure type="chrome_scaled_image" name="IDR_SMB_ICON" file="cros/smb_icon.png" />
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 9669fcd6..6305b764 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -683,16 +683,6 @@
     "media/cast_mirroring_service_host.h",
     "media/cast_remoting_connector.cc",
     "media/cast_remoting_connector.h",
-    "media/feeds/media_feeds_contents_observer.cc",
-    "media/feeds/media_feeds_contents_observer.h",
-    "media/feeds/media_feeds_converter.cc",
-    "media/feeds/media_feeds_converter.h",
-    "media/feeds/media_feeds_fetcher.cc",
-    "media/feeds/media_feeds_fetcher.h",
-    "media/feeds/media_feeds_service.cc",
-    "media/feeds/media_feeds_service.h",
-    "media/feeds/media_feeds_service_factory.cc",
-    "media/feeds/media_feeds_service_factory.h",
     "media/feeds/media_feeds_utils.cc",
     "media/feeds/media_feeds_utils.h",
     "media/history/media_history_contents_observer.cc",
@@ -1027,6 +1017,8 @@
     "optimization_guide/optimization_guide_permissions_util.h",
     "optimization_guide/optimization_guide_session_statistic.cc",
     "optimization_guide/optimization_guide_session_statistic.h",
+    "optimization_guide/optimization_guide_test_util.cc",
+    "optimization_guide/optimization_guide_test_util.h",
     "optimization_guide/optimization_guide_top_host_provider.cc",
     "optimization_guide/optimization_guide_top_host_provider.h",
     "optimization_guide/optimization_guide_util.cc",
@@ -1993,7 +1985,6 @@
     ":expired_flags_list",
     ":ntp_background_proto",
     ":permissions_proto",
-    ":reporting_record_proto",
     ":resource_prefetch_predictor_proto",
     ":status_proto",
     ":tab_state_db_content_proto",
@@ -2143,8 +2134,10 @@
     "//components/policy/core/browser",
     "//components/policy/proto",
     "//components/policy/proto:policy_record_constants",
+    "//components/policy/proto:reporting_record_proto",
     "//components/prefs",
-    "//components/prerender",
+    "//components/prerender/common",
+    "//components/prerender/common:mojo_bindings",
     "//components/previews/content",
     "//components/previews/core",
     "//components/profile_metrics",
@@ -2158,7 +2151,6 @@
     "//components/safe_browsing/core/common:safe_browsing_policy_handler",
     "//components/safe_search_api",
     "//components/safe_search_api:safe_search_client",
-    "//components/schema_org:extractor",
     "//components/schema_org/common:improved_mojom",
     "//components/search",
     "//components/search_engines",
@@ -3126,15 +3118,6 @@
       ]
       deps += [ "//chrome/android/modules/dev_ui/provider:native" ]
     }
-
-    if (enable_password_change_in_leaked_dialog) {
-      sources += [
-        "password_manager/credential_leak_password_change_controller_android.cc",
-        "password_manager/credential_leak_password_change_controller_android.h",
-      ]
-
-      defines += [ "ENABLE_PASSWORD_CHANGE" ]
-    }
   } else {  # !is_android
     sources += [
       "accessibility/caption_controller.cc",
@@ -3353,6 +3336,16 @@
       "lifetime/termination_notification.h",
       "media/capture_access_handler_base.cc",
       "media/capture_access_handler_base.h",
+      "media/feeds/media_feeds_contents_observer.cc",
+      "media/feeds/media_feeds_contents_observer.h",
+      "media/feeds/media_feeds_converter.cc",
+      "media/feeds/media_feeds_converter.h",
+      "media/feeds/media_feeds_fetcher.cc",
+      "media/feeds/media_feeds_fetcher.h",
+      "media/feeds/media_feeds_service.cc",
+      "media/feeds/media_feeds_service.h",
+      "media/feeds/media_feeds_service_factory.cc",
+      "media/feeds/media_feeds_service_factory.h",
       "media/unified_autoplay_config.cc",
       "media/unified_autoplay_config.h",
       "media/webrtc/desktop_capture_devices_util.cc",
@@ -3878,6 +3871,7 @@
       "//components/image_fetcher/core",
       "//components/keep_alive_registry",
       "//components/ntp_snippets",
+      "//components/schema_org:extractor",
       "//components/services/app_service:lib",
       "//components/services/app_service/public/cpp:app_file_handling",
       "//components/services/app_service/public/cpp:app_update",
@@ -4747,6 +4741,8 @@
       "signin/dice_tab_helper.h",
       "signin/dice_web_signin_interceptor.cc",
       "signin/dice_web_signin_interceptor.h",
+      "signin/dice_web_signin_interceptor_delegate.cc",
+      "signin/dice_web_signin_interceptor_delegate.h",
       "signin/dice_web_signin_interceptor_factory.cc",
       "signin/dice_web_signin_interceptor_factory.h",
       "signin/logout_tab_helper.cc",
@@ -6218,12 +6214,6 @@
   }
 }
 
-proto_library("reporting_record_proto") {
-  proto_in_dir = "//"
-  sources = [ "policy/messaging_layer/proto/record.proto" ]
-  deps = [ "//components/policy/proto:policy_record_constants" ]
-}
-
 proto_library("status_proto") {
   sources = [ "policy/messaging_layer/util/status.proto" ]
   generate_python = false
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b5d8db87..ad5fc6a 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -482,7 +482,8 @@
 
 #if defined(OS_ANDROID)
 const FeatureEntry::FeatureParam kCloseTabSuggestionsStale_Immediate[] = {
-    {"baseline_tab_suggestions", "true"}};
+    {"baseline_tab_suggestions", "true"},
+    {"baseline_close_tab_suggestions", "true"}};
 const FeatureEntry::FeatureParam kCloseTabSuggestionsStale_4Hours[] = {
     {"close_tab_suggestions_stale_time_ms", "14400000"}};
 const FeatureEntry::FeatureParam kCloseTabSuggestionsStale_8Hours[] = {
@@ -497,10 +498,16 @@
     {"close_tab_features_site_engagement_enabled", "true"},
     {"close_tab_features_site_engagement_threshold", "90.0"},
 };
+const FeatureEntry::FeatureParam kGroupAndCloseTabSuggestions_Immediate[] = {
+    {"baseline_tab_suggestions", "true"},
+    {"baseline_group_tab_suggestions", "true"},
+    {"baseline_close_tab_suggestions", "true"}};
 
 const FeatureEntry::FeatureVariation kCloseTabSuggestionsStaleVariations[] = {
-    {"Immediate", kCloseTabSuggestionsStale_Immediate,
+    {"Close Immediate", kCloseTabSuggestionsStale_Immediate,
      base::size(kCloseTabSuggestionsStale_Immediate), nullptr},
+    {"Group+Close Immediate", kGroupAndCloseTabSuggestions_Immediate,
+     base::size(kGroupAndCloseTabSuggestions_Immediate), nullptr},
     {"4 hours", kCloseTabSuggestionsStale_4Hours,
      base::size(kCloseTabSuggestionsStale_4Hours), nullptr},
     {"8 hours", kCloseTabSuggestionsStale_8Hours,
@@ -2634,6 +2641,10 @@
      flag_descriptions::kTerminalSystemAppLegacySettingsName,
      flag_descriptions::kTerminalSystemAppLegacySettingsDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(features::kTerminalSystemAppLegacySettings)},
+    {"pluginvm-show-camera-permissions",
+     flag_descriptions::kPluginVmShowCameraPermissionsName,
+     flag_descriptions::kPluginVmShowCameraPermissionsDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kPluginVmShowCameraPermissions)},
 #endif  // OS_CHROMEOS
 #if defined(OS_CHROMEOS) || defined(OS_LINUX)
 #if BUILDFLAG(USE_TCMALLOC)
@@ -2681,9 +2692,9 @@
      flag_descriptions::kPreviewsAllowedDescription, kOsAll,
      FEATURE_VALUE_TYPE(previews::features::kPreviews)},
     {"ignore-previews-blocklist",
-     flag_descriptions::kIgnorePreviewsBlacklistName,
-     flag_descriptions::kIgnorePreviewsBlacklistDescription, kOsAll,
-     SINGLE_VALUE_TYPE(previews::switches::kIgnorePreviewsBlacklist)},
+     flag_descriptions::kIgnorePreviewsBlocklistName,
+     flag_descriptions::kIgnorePreviewsBlocklistDescription, kOsAll,
+     SINGLE_VALUE_TYPE(previews::switches::kIgnorePreviewsBlocklist)},
     {"enable-data-reduction-proxy-server-experiment",
      flag_descriptions::kEnableDataReductionProxyServerExperimentName,
      flag_descriptions::kEnableDataReductionProxyServerExperimentDescription,
@@ -3569,6 +3580,23 @@
      flag_descriptions::kOmniboxUIHideSteadyStateUrlPathQueryAndRefDescription,
      kOsAll, FEATURE_VALUE_TYPE(omnibox::kHideSteadyStateUrlPathQueryAndRef)},
 
+    {"omnibox-ui-reveal-steady-state-url-path-query-and-ref-on-hover",
+     flag_descriptions::
+         kOmniboxUIRevealSteadyStateUrlPathQueryAndRefOnHoverName,
+     flag_descriptions::
+         kOmniboxUIRevealSteadyStateUrlPathQueryAndRefOnHoverDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(omnibox::kRevealSteadyStateUrlPathQueryAndRefOnHover)},
+
+    {"omnibox-ui-hide-steady-state-url-path-query-and-ref-on-interaction",
+     flag_descriptions::
+         kOmniboxUIHideSteadyStateUrlPathQueryAndRefOnInteractionName,
+     flag_descriptions::
+         kOmniboxUIHideSteadyStateUrlPathQueryAndRefOnInteractionDescription,
+     kOsDesktop,
+     FEATURE_VALUE_TYPE(
+         omnibox::kHideSteadyStateUrlPathQueryAndRefOnInteraction)},
+
     {"omnibox-ui-max-autocomplete-matches",
      flag_descriptions::kOmniboxUIMaxAutocompleteMatchesName,
      flag_descriptions::kOmniboxUIMaxAutocompleteMatchesDescription,
@@ -4223,7 +4251,7 @@
     {"enable-resampling-input-events",
      flag_descriptions::kEnableResamplingInputEventsName,
      flag_descriptions::kEnableResamplingInputEventsDescription, kOsAll,
-     FEATURE_WITH_PARAMS_VALUE_TYPE(features::kResamplingInputEvents,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(blink::features::kResamplingInputEvents,
                                     kResamplingInputEventsFeatureVariations,
                                     "ResamplingInputEvents")},
 
diff --git a/chrome/browser/accessibility/caption_controller.cc b/chrome/browser/accessibility/caption_controller.cc
index d0ab7d5..620d9e8 100644
--- a/chrome/browser/accessibility/caption_controller.cc
+++ b/chrome/browser/accessibility/caption_controller.cc
@@ -163,14 +163,14 @@
   caption_bubble_controllers_.erase(browser);
 }
 
-void CaptionController::DispatchTranscription(
+bool CaptionController::DispatchTranscription(
     content::WebContents* web_contents,
     const chrome::mojom::TranscriptionResultPtr& transcription_result) {
   Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
   if (!browser || !caption_bubble_controllers_.count(browser))
-    return;
-  caption_bubble_controllers_[browser]->OnTranscription(transcription_result,
-                                                        web_contents);
+    return false;
+  return caption_bubble_controllers_[browser]->OnTranscription(
+      transcription_result, web_contents);
 }
 
 CaptionBubbleController*
diff --git a/chrome/browser/accessibility/caption_controller.h b/chrome/browser/accessibility/caption_controller.h
index 94d34f1d..ca97d51e 100644
--- a/chrome/browser/accessibility/caption_controller.h
+++ b/chrome/browser/accessibility/caption_controller.h
@@ -68,8 +68,9 @@
   void Init();
 
   // Routes a transcription to the CaptionBubbleController that belongs to the
-  // appropriate browser.
-  void DispatchTranscription(
+  // appropriate browser. Returns whether the transcription result was routed
+  // successfully. Transcriptions will halt if this returns false.
+  bool DispatchTranscription(
       content::WebContents* web_contents,
       const chrome::mojom::TranscriptionResultPtr& transcription_result);
 
diff --git a/chrome/browser/accessibility/caption_host_impl.cc b/chrome/browser/accessibility/caption_host_impl.cc
index f16d93d5..deaa6ec 100644
--- a/chrome/browser/accessibility/caption_host_impl.cc
+++ b/chrome/browser/accessibility/caption_host_impl.cc
@@ -40,21 +40,28 @@
 CaptionHostImpl::~CaptionHostImpl() = default;
 
 void CaptionHostImpl::OnTranscription(
-    chrome::mojom::TranscriptionResultPtr transcription_result) {
-  if (!frame_host_)
+    chrome::mojom::TranscriptionResultPtr transcription_result,
+    OnTranscriptionCallback reply) {
+  if (!frame_host_) {
+    std::move(reply).Run(false);
     return;
+  }
   content::WebContents* web_contents =
       content::WebContents::FromRenderFrameHost(frame_host_);
   if (!web_contents) {
     frame_host_ = nullptr;
+    std::move(reply).Run(false);
     return;
   }
   Profile* profile =
       Profile::FromBrowserContext(web_contents->GetBrowserContext());
-  if (!profile)
+  if (!profile) {
+    std::move(reply).Run(false);
     return;
-  CaptionControllerFactory::GetForProfile(profile)->DispatchTranscription(
-      web_contents, transcription_result);
+  }
+  std::move(reply).Run(
+      CaptionControllerFactory::GetForProfile(profile)->DispatchTranscription(
+          web_contents, transcription_result));
 }
 
 void CaptionHostImpl::RenderFrameDeleted(content::RenderFrameHost* frame_host) {
diff --git a/chrome/browser/accessibility/caption_host_impl.h b/chrome/browser/accessibility/caption_host_impl.h
index 04451796..3e3615e6 100644
--- a/chrome/browser/accessibility/caption_host_impl.h
+++ b/chrome/browser/accessibility/caption_host_impl.h
@@ -38,7 +38,8 @@
 
   // chrome::mojom::CaptionHost:
   void OnTranscription(
-      chrome::mojom::TranscriptionResultPtr transcription_result) override;
+      chrome::mojom::TranscriptionResultPtr transcription_result,
+      OnTranscriptionCallback reply) override;
 
   // content::WebContentsObserver:
   void RenderFrameDeleted(content::RenderFrameHost* frame_host) override;
diff --git a/chrome/browser/android/feed/v2/feed_service_bridge.cc b/chrome/browser/android/feed/v2/feed_service_bridge.cc
index 3cde7d8..83eb8732 100644
--- a/chrome/browser/android/feed/v2/feed_service_bridge.cc
+++ b/chrome/browser/android/feed/v2/feed_service_bridge.cc
@@ -41,8 +41,7 @@
 
 bool FeedServiceBridge::IsEnabled() {
   Profile* profile = ProfileManager::GetLastUsedProfile();
-  return FeedServiceFactory::GetForBrowserContext(profile)->IsEnabled(
-      *profile->GetPrefs());
+  return FeedService::IsEnabled(*profile->GetPrefs());
 }
 
 }  // namespace feed
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc b/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc
index 008f4d5..d40d267 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc
+++ b/chrome/browser/android/vr/arcore_device/arcore_device_provider.cc
@@ -16,6 +16,7 @@
 void ArCoreDeviceProvider::Initialize(
     base::RepeatingCallback<void(mojom::XRDeviceId,
                                  mojom::VRDisplayInfoPtr,
+                                 mojom::XRDeviceDataPtr,
                                  mojo::PendingRemote<mojom::XRRuntime>)>
         add_device_callback,
     base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
@@ -24,9 +25,9 @@
     DVLOG(2) << __func__ << ": ARCore is supported, creating device";
     arcore_device_ = std::make_unique<ArCoreDevice>();
 
-    add_device_callback.Run(arcore_device_->GetId(),
-                            arcore_device_->GetVRDisplayInfo(),
-                            arcore_device_->BindXRRuntime());
+    add_device_callback.Run(
+        arcore_device_->GetId(), arcore_device_->GetVRDisplayInfo(),
+        arcore_device_->GetDeviceData(), arcore_device_->BindXRRuntime());
   }
   initialized_ = true;
   std::move(initialization_complete).Run();
diff --git a/chrome/browser/android/vr/arcore_device/arcore_device_provider.h b/chrome/browser/android/vr/arcore_device/arcore_device_provider.h
index c8f65e7..204f943 100644
--- a/chrome/browser/android/vr/arcore_device/arcore_device_provider.h
+++ b/chrome/browser/android/vr/arcore_device/arcore_device_provider.h
@@ -22,6 +22,7 @@
   void Initialize(
       base::RepeatingCallback<void(mojom::XRDeviceId,
                                    mojom::VRDisplayInfoPtr,
+                                   mojom::XRDeviceDataPtr,
                                    mojo::PendingRemote<mojom::XRRuntime>)>
           add_device_callback,
       base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
diff --git a/chrome/browser/apps/app_service/plugin_vm_apps.cc b/chrome/browser/apps/app_service/plugin_vm_apps.cc
index b56702a..9d72759 100644
--- a/chrome/browser/apps/app_service/plugin_vm_apps.cc
+++ b/chrome/browser/apps/app_service/plugin_vm_apps.cc
@@ -35,6 +35,8 @@
 constexpr PermissionInfo permission_infos[] = {
     {app_management::mojom::PluginVmPermissionType::PRINTING,
      plugin_vm::prefs::kPluginVmPrintersAllowed},
+    {app_management::mojom::PluginVmPermissionType::CAMERA,
+     plugin_vm::prefs::kPluginVmCameraSharing},
 };
 
 const char* PermissionToPrefName(
diff --git a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
index 1d662dc..e8f093a3 100644
--- a/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
+++ b/chrome/browser/apps/guest_view/web_view_interactive_browsertest.cc
@@ -153,8 +153,8 @@
 class WebViewInteractiveTest : public extensions::PlatformAppBrowserTest {
  public:
   WebViewInteractiveTest()
-      : guest_web_contents_(NULL),
-        embedder_web_contents_(NULL),
+      : guest_web_contents_(nullptr),
+        embedder_web_contents_(nullptr),
         corner_(gfx::Point()),
         mouse_click_result_(false),
         first_click_(true) {
@@ -410,8 +410,7 @@
   class PopupCreatedObserver {
    public:
     PopupCreatedObserver()
-        : initial_widget_count_(0),
-          last_render_widget_host_(NULL) {}
+        : initial_widget_count_(0), last_render_widget_host_(nullptr) {}
 
     ~PopupCreatedObserver() {}
 
diff --git a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc
index e0b1cecb..b02eb92 100644
--- a/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc
+++ b/chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc
@@ -74,7 +74,7 @@
 class MediaGalleriesGalleryWatchApiTest : public extensions::ExtensionApiTest {
  public:
   MediaGalleriesGalleryWatchApiTest()
-      : extension_(NULL), background_host_(NULL) {}
+      : extension_(nullptr), background_host_(nullptr) {}
   ~MediaGalleriesGalleryWatchApiTest() override {}
 
  protected:
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
index 0baab60..9ebff6a 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -348,7 +348,7 @@
       url, *input, GetTemplateURLService(), base::string16());
   for (auto* browser : *BrowserList::GetInstance()) {
     // Only look at same profile (and anonymity level).
-    if (browser->profile()->IsSameProfileAndType(profile_)) {
+    if (profile_ == browser->profile()) {
       for (int i = 0; i < browser->tab_strip_model()->count(); ++i) {
         content::WebContents* web_contents =
             browser->tab_strip_model()->GetWebContentsAt(i);
diff --git a/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc b/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc
index a0e8595..a5434389 100644
--- a/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc
+++ b/chrome/browser/bookmarks/managed_bookmark_service_unittest.cc
@@ -58,7 +58,7 @@
 
 class ManagedBookmarkServiceTest : public testing::Test {
  public:
-  ManagedBookmarkServiceTest() : managed_(NULL), model_(NULL) {}
+  ManagedBookmarkServiceTest() : managed_(nullptr), model_(nullptr) {}
   ~ManagedBookmarkServiceTest() override {}
 
   void SetUp() override {
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index 5e1fa5b..ee3f7e6 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -560,12 +560,12 @@
     PreviewsService* previews_service =
         PreviewsServiceFactory::GetForProfile(profile_);
     if (previews_service)
-      previews_service->ClearBlackList(delete_begin_, delete_end_);
+      previews_service->ClearBlockList(delete_begin_, delete_end_);
 
     HeavyAdService* heavy_ad_service =
         HeavyAdServiceFactory::GetForBrowserContext(profile_);
     if (heavy_ad_service && heavy_ad_service->heavy_ad_blocklist()) {
-      heavy_ad_service->heavy_ad_blocklist()->ClearBlackList(delete_begin_,
+      heavy_ad_service->heavy_ad_blocklist()->ClearBlockList(delete_begin_,
                                                              delete_end_);
     }
 
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
index 94d3e5b..fbef8b92 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_unittest.cc
@@ -295,8 +295,8 @@
     cookie_manager_->GetCookieList(
         Origin1(), net::CookieOptions::MakeAllInclusive(),
         base::BindLambdaForTesting(
-            [&](const net::CookieStatusList& cookie_list,
-                const net::CookieStatusList& excluded_cookies) {
+            [&](const net::CookieAccessResultList& cookie_list,
+                const net::CookieAccessResultList& excluded_cookies) {
               std::string cookie_line =
                   net::CanonicalCookie::BuildCookieLine(cookie_list);
               if (cookie_line == "A=1") {
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc
index e250881..ff519b6 100644
--- a/chrome/browser/chrome_browser_interface_binders.cc
+++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -14,7 +14,6 @@
 #include "chrome/browser/dom_distiller/dom_distiller_service_factory.h"
 #include "chrome/browser/engagement/site_engagement_details.mojom.h"
 #include "chrome/browser/language/translate_frame_binder.h"
-#include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
 #include "chrome/browser/media/history/media_history_store.mojom.h"
 #include "chrome/browser/media/media_engagement_score_details.mojom.h"
 #include "chrome/browser/navigation_predictor/navigation_predictor.h"
@@ -31,7 +30,6 @@
 #include "chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom.h"
 #include "chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.h"
 #include "chrome/browser/ui/webui/media/media_engagement_ui.h"
-#include "chrome/browser/ui/webui/media/media_feeds_ui.h"
 #include "chrome/browser/ui/webui/media/media_history_ui.h"
 #include "chrome/browser/ui/webui/omnibox/omnibox.mojom.h"
 #include "chrome/browser/ui/webui/omnibox/omnibox_ui.h"
@@ -102,11 +100,13 @@
 #else
 #include "chrome/browser/accessibility/caption_host_impl.h"
 #include "chrome/browser/badging/badge_manager.h"
+#include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
 #include "chrome/browser/payments/payment_request_factory.h"
 #include "chrome/browser/speech/speech_recognition_service.h"
 #include "chrome/browser/speech/speech_recognition_service_factory.h"
 #include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
 #include "chrome/browser/ui/webui/downloads/downloads_ui.h"
+#include "chrome/browser/ui/webui/media/media_feeds_ui.h"
 #include "chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom.h"
 #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h"
 #include "chrome/common/caption.mojom.h"
@@ -265,7 +265,8 @@
 
 void BindPrerenderCanceler(
     content::RenderFrameHost* frame_host,
-    mojo::PendingReceiver<mojom::PrerenderCanceler> receiver) {
+    mojo::PendingReceiver<
+        components::prerender::common::mojom::PrerenderCanceler> receiver) {
   auto* web_contents = content::WebContents::FromRenderFrameHost(frame_host);
   if (!web_contents)
     return;
@@ -375,7 +376,7 @@
   map->Add<dom_distiller::mojom::DistillerJavaScriptService>(
       base::BindRepeating(&BindDistillerJavaScriptService));
 
-  map->Add<mojom::PrerenderCanceler>(
+  map->Add<components::prerender::common::mojom::PrerenderCanceler>(
       base::BindRepeating(&BindPrerenderCanceler));
 
   map->Add<blink::mojom::PrerenderProcessor>(
@@ -463,9 +464,6 @@
       media::mojom::MediaEngagementScoreDetailsProvider, MediaEngagementUI>(
       map);
 
-  RegisterWebUIControllerInterfaceBinder<media_feeds::mojom::MediaFeedsStore,
-                                         MediaFeedsUI>(map);
-
   RegisterWebUIControllerInterfaceBinder<
       media_history::mojom::MediaHistoryStore, MediaHistoryUI>(map);
 
@@ -491,6 +489,9 @@
 
   RegisterWebUIControllerInterfaceBinder<
       new_tab_page::mojom::PageHandlerFactory, NewTabPageUI>(map);
+
+  RegisterWebUIControllerInterfaceBinder<media_feeds::mojom::MediaFeedsStore,
+                                         MediaFeedsUI>(map);
 #endif
 
 #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/chrome_browser_main.cc b/chrome/browser/chrome_browser_main.cc
index 317aae11..d7518c3 100644
--- a/chrome/browser/chrome_browser_main.cc
+++ b/chrome/browser/chrome_browser_main.cc
@@ -486,7 +486,7 @@
       result_code_(service_manager::RESULT_CODE_NORMAL_EXIT),
       should_call_pre_main_loop_start_startup_on_variations_service_(
           !parameters.ui_task),
-      profile_(NULL),
+      profile_(nullptr),
       run_message_loop_(true),
       startup_data_(startup_data) {
   DCHECK(startup_data_);
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 3a7df7f7..7b7a7e1 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -115,6 +115,8 @@
 #include "chrome/browser/resource_coordinator/background_tab_navigation_throttle.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
+#include "chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h"
+#include "chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.h"
 #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h"
 #include "chrome/browser/safe_browsing/delayed_warning_navigation_throttle.h"
 #include "chrome/browser/safe_browsing/safe_browsing_navigation_throttle.h"
@@ -228,7 +230,7 @@
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
-#include "components/prerender/prerender_final_status.h"
+#include "components/prerender/common/prerender_final_status.h"
 #include "components/previews/content/previews_decider.h"
 #include "components/previews/content/previews_decider_impl.h"
 #include "components/previews/content/previews_ui_service.h"
@@ -447,6 +449,7 @@
 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/media/unified_autoplay_config.h"
+#include "chrome/browser/safe_browsing/dm_token_utils.h"
 #include "chrome/browser/search/instant_service.h"
 #include "chrome/browser/search/instant_service_factory.h"
 #include "chrome/browser/serial/chrome_serial_delegate.h"
@@ -930,9 +933,10 @@
 
 #endif
 
-mojo::PendingRemote<chrome::mojom::PrerenderCanceler> GetPrerenderCanceler(
-    const base::Callback<content::WebContents*()>& wc_getter) {
-  mojo::PendingRemote<chrome::mojom::PrerenderCanceler> canceler;
+mojo::PendingRemote<components::prerender::common::mojom::PrerenderCanceler>
+GetPrerenderCanceler(const base::Callback<content::WebContents*()>& wc_getter) {
+  mojo::PendingRemote<components::prerender::common::mojom::PrerenderCanceler>
+      canceler;
   prerender::PrerenderContents::FromWebContents(wc_getter.Run())
       ->AddPrerenderCancelerReceiver(canceler.InitWithNewPipeAndPassReceiver());
   return canceler;
@@ -4329,16 +4333,27 @@
       request.url, *profile->GetPrefs());
   if (!matches_enterprise_whitelist) {
     // |url_lookup_service| is used when real time url check is enabled.
-    safe_browsing::RealTimeUrlLookupServiceBase* url_lookup_service =
-        // |safe_browsing_service_| may be unavailable in tests.
-        safe_browsing_service_ &&
-                safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup(
-                    profile->GetPrefs(), profile->IsOffTheRecord(),
-                    g_browser_process->variations_service())
-            ? safe_browsing::RealTimeUrlLookupServiceFactory::GetForProfile(
-                  profile)
-            : nullptr;
+    safe_browsing::RealTimeUrlLookupServiceBase* url_lookup_service = nullptr;
 
+#if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
+    if (safe_browsing::RealTimePolicyEngine::CanPerformEnterpriseFullURLLookup(
+            safe_browsing::GetDMToken(profile).is_valid(),
+            profile->IsOffTheRecord())) {
+      url_lookup_service =
+          safe_browsing::ChromeEnterpriseRealTimeUrlLookupServiceFactory::
+              GetForProfile(profile);
+    }
+#endif
+
+    // |safe_browsing_service_| may be unavailable in tests.
+    if (!url_lookup_service && safe_browsing_service_ &&
+        safe_browsing::RealTimePolicyEngine::CanPerformFullURLLookup(
+            profile->GetPrefs(), profile->IsOffTheRecord(),
+            g_browser_process->variations_service())) {
+      url_lookup_service =
+          safe_browsing::RealTimeUrlLookupServiceFactory::GetForProfile(
+              profile);
+    }
     result.push_back(safe_browsing::BrowserURLLoaderThrottle::Create(
         base::BindOnce(
             &ChromeContentBrowserClient::GetSafeBrowsingUrlCheckerDelegate,
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn
index 8b71380..2362ebe 100644
--- a/chrome/browser/chromeos/BUILD.gn
+++ b/chrome/browser/chromeos/BUILD.gn
@@ -1754,6 +1754,8 @@
     "net/dhcp_wpad_url_client.h",
     "net/network_diagnostics/dns_latency_routine.cc",
     "net/network_diagnostics/dns_latency_routine.h",
+    "net/network_diagnostics/dns_resolution_routine.cc",
+    "net/network_diagnostics/dns_resolution_routine.h",
     "net/network_diagnostics/dns_resolver_present_routine.cc",
     "net/network_diagnostics/dns_resolver_present_routine.h",
     "net/network_diagnostics/gateway_can_be_pinged_routine.cc",
@@ -3100,6 +3102,7 @@
     "mobile/mobile_activator_unittest.cc",
     "net/client_cert_store_chromeos_unittest.cc",
     "net/network_diagnostics/dns_latency_routine_unittest.cc",
+    "net/network_diagnostics/dns_resolution_routine_unittest.cc",
     "net/network_diagnostics/dns_resolver_present_routine_unittest.cc",
     "net/network_diagnostics/gateway_can_be_pinged_routine_unittest.cc",
     "net/network_diagnostics/has_secure_wifi_connection_routine_unittest.cc",
diff --git a/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.cc b/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.cc
index 2c91d28c..08faf76 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.cc
+++ b/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.cc
@@ -55,11 +55,11 @@
 }
 
 void AndroidSmsPairingStateTrackerImpl::OnCookiesRetrieved(
-    const net::CookieStatusList& cookies,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies,
+    const net::CookieAccessResultList& excluded_cookies) {
   bool was_previously_paired = was_paired_on_last_update_;
-  for (const auto& cookie_with_status : cookies) {
-    const net::CanonicalCookie& cookie = cookie_with_status.cookie;
+  for (const auto& cookie_with_access_result : cookies) {
+    const net::CanonicalCookie& cookie = cookie_with_access_result.cookie;
     if (cookie.Name() == kMessagesPairStateCookieName) {
       PA_LOG(VERBOSE) << "Cookie says Messages paired: " << cookie.Value();
       was_paired_on_last_update_ = cookie.Value() == kPairedCookieValue;
diff --git a/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.h b/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.h
index 16e19c0..90e38980a 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.h
+++ b/chrome/browser/chromeos/android_sms/android_sms_pairing_state_tracker_impl.h
@@ -45,8 +45,8 @@
   network::mojom::CookieManager* GetCookieManager();
 
   void AttemptFetchMessagesPairingState();
-  void OnCookiesRetrieved(const net::CookieStatusList& cookies,
-                          const net::CookieStatusList& excluded_cookies);
+  void OnCookiesRetrieved(const net::CookieAccessResultList& cookies,
+                          const net::CookieAccessResultList& excluded_cookies);
 
   void AddCookieChangeListener();
 
diff --git a/chrome/browser/chromeos/app_mode/fake_cws.cc b/chrome/browser/chromeos/app_mode/fake_cws.cc
index 3a1ee4a..93ec4ec 100644
--- a/chrome/browser/chromeos/app_mode/fake_cws.cc
+++ b/chrome/browser/chromeos/app_mode/fake_cws.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_util.h"
 #include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/strings/string_tokenizer.h"
 #include "base/strings/string_util.h"
 #include "base/threading/thread_restrictions.h"
 #include "chrome/common/chrome_paths.h"
@@ -21,6 +22,7 @@
 #include "extensions/common/extensions_client.h"
 #include "net/base/url_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/http_request.h"
 
 using net::test_server::BasicHttpResponse;
 using net::test_server::HttpRequest;
@@ -59,6 +61,63 @@
       "$APPS"
     "</gupdate>";
 
+const char kAppNoUpdateTemplateJSON[] =
+    "{\"appid\": \"$AppId\","
+    " \"status\": \"ok\","
+    " \"updatecheck\": { \"status\": \"noupdate\" }"
+    "}";
+
+const char kAppHasUpdateTemplateJSON[] =
+    "{"
+    "  \"appid\": \"$AppId\","
+    "  \"status\": \"ok\","
+    "  \"updatecheck\": {"
+    "    \"status\": \"ok\","
+    "    \"manifest\": {"
+    "      \"version\": \"$Version\","
+    "      \"packages\": {"
+    "        \"package\": ["
+    "          {"
+    "            \"fp\": \"1.$FP\","
+    "            \"size\": \"$Size\","
+    "            \"hash_sha256\": \"$FP\","
+    "            \"name\": \"\""
+    "          }"
+    "        ]"
+    "      }"
+    "    },"
+    "    \"urls\": { \"url\": [ { \"codebase\": \"$CrxDownloadUrl\"} ] }"
+    "  }"
+    "}";
+
+const char kUpdateContentTemplateJSON[] =
+    ")]}'\n"
+    "{"
+    "  \"response\": {"
+    "    \"protocol\": \"3.1\","
+    "    \"daystart\": {"
+    "      \"elapsed_days\": 2569,"
+    "      \"elapsed_seconds\": 36478"
+    "    },"
+    "    \"app\": ["
+    "      $APPS"
+    "    ]"
+    "  }"
+    "}";
+
+const char kAppIdHeader[] = "X-Goog-Update-AppId";
+
+bool GetAppIdsFromHeader(const HttpRequest::HeaderMap& headers,
+                         std::vector<std::string>* ids) {
+  if (headers.count(kAppIdHeader) == 0)
+    return false;
+  base::StringTokenizer t(headers.at(kAppIdHeader), ",");
+  while (t.GetNext()) {
+    ids->push_back(t.token());
+  }
+  return !ids->empty();
+}
+
 bool GetAppIdsFromUpdateUrl(const GURL& update_url,
                             std::vector<std::string>* ids) {
   for (net::QueryIterator it(update_url); !it.IsAtEnd(); it.Advance()) {
@@ -80,6 +139,40 @@
 // FakeCWS will hold the ScopedIgnoreContentVerifierForTest instance.
 bool g_is_fakecws_active = false;
 
+std::string ApplyHasNoUpdateTemplate(std::string app_id,
+                                     bool use_json,
+                                     bool use_private_store) {
+  std::string update_check_content(use_json ? kAppNoUpdateTemplateJSON
+                                            : kAppNoUpdateTemplate);
+  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$AppId",
+                                     app_id);
+  return update_check_content;
+}
+
+std::string ApplyHasUpdateTemplate(std::string app_id,
+                                   GURL download_url,
+                                   std::string sha256_hex,
+                                   int size,
+                                   std::string version,
+                                   bool use_json,
+                                   bool use_private_store) {
+  std::string update_check_content(
+      use_json ? kAppHasUpdateTemplateJSON
+               : use_private_store ? kPrivateStoreAppHasUpdateTemplate
+                                   : kAppHasUpdateTemplate);
+  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$AppId",
+                                     app_id);
+  base::ReplaceSubstringsAfterOffset(&update_check_content, 0,
+                                     "$CrxDownloadUrl", download_url.spec());
+  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$FP",
+                                     sha256_hex);
+  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$Size",
+                                     base::NumberToString(size));
+  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$Version",
+                                     version);
+  return update_check_content;
+}
+
 }  // namespace
 
 FakeCWS::FakeCWS() : update_check_count_(0) {
@@ -101,8 +194,7 @@
 }
 
 void FakeCWS::Init(net::EmbeddedTestServer* embedded_test_server) {
-  has_update_template_ = kAppHasUpdateTemplate;
-  no_update_template_ = kAppNoUpdateTemplate;
+  use_private_store_templates_ = false;
   update_check_end_point_ = "/update_check.xml";
 
   SetupWebStoreURL(embedded_test_server->base_url());
@@ -113,8 +205,7 @@
 
 void FakeCWS::InitAsPrivateStore(net::EmbeddedTestServer* embedded_test_server,
                                  const std::string& update_check_end_point) {
-  has_update_template_ = kPrivateStoreAppHasUpdateTemplate;
-  no_update_template_ = kAppNoUpdateTemplate;
+  use_private_store_templates_ = true;
   update_check_end_point_ = update_check_end_point;
 
   SetupWebStoreURL(embedded_test_server->base_url());
@@ -143,25 +234,14 @@
   const std::string sha256 = crypto::SHA256HashString(crx_content);
   const std::string sha256_hex = base::HexEncode(sha256.c_str(), sha256.size());
 
-  std::string update_check_content(has_update_template_);
-  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$AppId",
-                                     app_id);
-  base::ReplaceSubstringsAfterOffset(
-      &update_check_content, 0, "$CrxDownloadUrl", crx_download_url.spec());
-  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$FP",
-                                     sha256_hex);
-  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$Size",
-                                     base::NumberToString(crx_content.size()));
-  base::ReplaceSubstringsAfterOffset(&update_check_content, 0, "$Version",
-                                     version);
-  id_to_update_check_content_map_[app_id] = update_check_content;
+  id_to_update_check_content_map_[app_id] =
+      base::BindRepeating(&ApplyHasUpdateTemplate, app_id, crx_download_url,
+                          sha256_hex, crx_content.size(), version);
 }
 
 void FakeCWS::SetNoUpdate(const std::string& app_id) {
-  std::string app_update_check_content(no_update_template_);
-  base::ReplaceSubstringsAfterOffset(&app_update_check_content, 0, "$AppId",
-                                     app_id);
-  id_to_update_check_content_map_[app_id] = app_update_check_content;
+  id_to_update_check_content_map_[app_id] =
+      base::BindRepeating(&ApplyHasNoUpdateTemplate, app_id);
 }
 
 int FakeCWS::GetUpdateCheckCountAndReset() {
@@ -199,19 +279,25 @@
 }
 
 bool FakeCWS::GetUpdateCheckContent(const std::vector<std::string>& ids,
-                                    std::string* update_check_content) {
+                                    std::string* update_check_content,
+                                    bool use_json) {
   std::string apps_content;
+  bool need_comma = false;
   for (const std::string& id : ids) {
     std::string app_update_content;
     auto it = id_to_update_check_content_map_.find(id);
     if (it == id_to_update_check_content_map_.end())
       return false;
-    apps_content.append(it->second);
+    if (need_comma)
+      apps_content.append(",");
+    apps_content.append(it->second.Run(use_json, use_private_store_templates_));
+    need_comma = use_json;
   }
   if (apps_content.empty())
     return false;
 
-  *update_check_content = kUpdateContentTemplate;
+  *update_check_content =
+      use_json ? kUpdateContentTemplateJSON : kUpdateContentTemplate;
   base::ReplaceSubstringsAfterOffset(update_check_content, 0, "$APPS",
                                      apps_content);
   return true;
@@ -224,14 +310,18 @@
   if (request_path.find(update_check_end_point_) != std::string::npos &&
       !id_to_update_check_content_map_.empty()) {
     std::vector<std::string> ids;
-    if (GetAppIdsFromUpdateUrl(request_url, &ids)) {
+    if (GetAppIdsFromHeader(request.headers, &ids) ||
+        GetAppIdsFromUpdateUrl(request_url, &ids)) {
+      bool use_json =
+          request.content.size() > 0 && request.content.at(0) == '{';
       std::string update_check_content;
-      if (GetUpdateCheckContent(ids, &update_check_content)) {
+      if (GetUpdateCheckContent(ids, &update_check_content, use_json)) {
         ++update_check_count_;
         std::unique_ptr<BasicHttpResponse> http_response(
             new BasicHttpResponse());
         http_response->set_code(net::HTTP_OK);
-        http_response->set_content_type("text/xml");
+        if (!use_json)
+          http_response->set_content_type("text/xml");
         http_response->set_content(update_check_content);
         return std::move(http_response);
       }
diff --git a/chrome/browser/chromeos/app_mode/fake_cws.h b/chrome/browser/chromeos/app_mode/fake_cws.h
index 3c7a50d..5ec959e9 100644
--- a/chrome/browser/chromeos/app_mode/fake_cws.h
+++ b/chrome/browser/chromeos/app_mode/fake_cws.h
@@ -10,6 +10,7 @@
 #include <string>
 #include <vector>
 
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "extensions/browser/scoped_ignore_content_verifier_for_test.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
@@ -58,7 +59,8 @@
   void OverrideGalleryCommandlineSwitches();
 
   bool GetUpdateCheckContent(const std::vector<std::string>& ids,
-                             std::string* update_check_content);
+                             std::string* update_check_content,
+                             bool use_json);
 
   // Request handler for kiosk app update server.
   std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
@@ -66,12 +68,13 @@
 
   GURL web_store_url_;
 
-  std::string has_update_template_;
-  std::string no_update_template_;
+  bool use_private_store_templates_;
   std::string update_check_end_point_;
 
-  // Map keyed by app_id to app_update_content.
-  std::map<std::string, std::string> id_to_update_check_content_map_;
+  // Map keyed by app_id to partially-bound functions that can generate the
+  // app's update content.
+  std::map<std::string, base::RepeatingCallback<std::string(bool, bool)>>
+      id_to_update_check_content_map_;
   int update_check_count_;
 
   // FakeCWS overrides Chrome Web Store URLs, so extensions it provides in tests
diff --git a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
index 597fa2a7..5e98ab4 100644
--- a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -540,6 +540,50 @@
           GetDeviceProperties(mojom::BluetoothPropertyType::ALL, device));
     }
   }
+
+  TrackPairingState(device);
+}
+
+void ArcBluetoothBridge::TrackPairingState(const BluetoothDevice* device) {
+  const std::string addr = device->GetAddress();
+
+  // A device in pairing is in |devices_paired_by_arc_| from CreateBond() is
+  // called until at least pairing is finished (either succeed or fail), so we
+  // don't need to do anything here if the device is not in the list.
+  if (devices_paired_by_arc_.find(addr) == devices_paired_by_arc_.end())
+    return;
+
+  const auto itr = devices_pairing_.find(addr);
+  bool was_pairing = itr != devices_pairing_.end();
+
+  // The actions we need to take depends on the combination of |was_pairing|,
+  // IsConnecting() and IsPaired():
+  // If not |was_pairing|:
+  // - !IsConnecting() means device is not pairing, do nothing;
+  // - IsPaired() means device has already been paired, do nothing;
+  // - IsConnecting() && !IsPaired() means device is pairing now, we should add
+  //   it into our list.
+  // If |was_pairing|:
+  // - IsPaired() means pairing succeeded, we should remove the device from our
+  //   list.
+  // - IsConnecting() && !IsPaired() means device is still in pairing, do
+  //   nothing;
+  // - !IsConnecting() && !IsPaired() means pairing failed, we should notify
+  //   Android, and remove the device from our list;
+  if (!was_pairing) {
+    if (device->IsConnecting() && !device->IsPaired())
+      devices_pairing_.insert(addr);
+    return;
+  }
+
+  if (device->IsPaired()) {
+    devices_pairing_.erase(itr);
+  } else if (!device->IsConnecting()) {
+    LOG(WARNING) << "Pairing failed for device " << addr;
+    OnPairedError(mojom::BluetoothAddress::From(addr),
+                  BluetoothDevice::ERROR_FAILED);
+    devices_pairing_.erase(itr);
+  }
 }
 
 void ArcBluetoothBridge::DeviceAddressChanged(BluetoothAdapter* adapter,
@@ -3166,6 +3210,7 @@
     }
   }
   arc_bluetooth_bridge_->devices_paired_by_arc_.clear();
+  arc_bluetooth_bridge_->devices_pairing_.clear();
 
   // Cleanup for GATT connections.
   // TODO(b/151573141): Remove the following loops when Chrome can perform hard
diff --git a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h
index c9a6aab3..f7cf99d7 100644
--- a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h
+++ b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.h
@@ -539,6 +539,15 @@
 
   void SendDevice(const device::BluetoothDevice* device) const;
 
+  // Detects the pairing state change from DeviceChanged(). Two actions will be
+  // taken in this function:
+  // - Updates |devices_pairing_| to reflect the set of ongoing pairing requests
+  //   initiated by ARC;
+  // - Notifies Android of the pairing failure.
+  // Note that notifying Android of the pairing success is handled in
+  // DevicePairedChange() but not in this function.
+  void TrackPairingState(const device::BluetoothDevice* device);
+
   // Data structures for RFCOMM listening/connecting sockets that live in
   // Chrome.
   struct RfcommListeningSocket {
@@ -618,6 +627,12 @@
   // lingering.
   std::set<std::string> devices_paired_by_arc_;
 
+  // The devices that ARC has tried to pair by CreateBond() and is in pairing
+  // state. This should be a subset of |devices_paired_by_arc_|. We maintain
+  // this set to detect the pairing failure signal. Please refer to
+  // TrackPairingState() for more details.
+  std::set<std::string> devices_pairing_;
+
   // {state, connection}
   // - For established connection from remote device, this is {CONNECTED, null}.
   // - For ongoing connection to remote device, this is {CONNECTING, null}.
diff --git a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc
index 2747d70..9b99e7bc 100644
--- a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc
+++ b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.cc
@@ -67,11 +67,6 @@
   return false;
 }
 
-void ArcPictureInPictureWindowControllerImpl::SetAlwaysHidePlayPauseButton(
-    bool is_visible) {
-  // Should be a no-op on ARC. This is managed on the Android side.
-}
-
 void ArcPictureInPictureWindowControllerImpl::SkipAd() {
   // Should be a no-op on ARC. This is managed on the Android side.
 }
diff --git a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h
index 6182fae..a03b024 100644
--- a/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h
+++ b/chrome/browser/chromeos/arc/pip/arc_picture_in_picture_window_controller_impl.h
@@ -41,7 +41,6 @@
   bool TogglePlayPause() override;
   void UpdatePlaybackState(bool is_playing,
                            bool reached_end_of_stream) override;
-  void SetAlwaysHidePlayPauseButton(bool is_visible) override;
   void SkipAd() override;
   void NextTrack() override;
   void PreviousTrack() override;
diff --git a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc
index 00ed0cd..9f980cd 100644
--- a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc
+++ b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.cc
@@ -22,6 +22,9 @@
 
 namespace crostini {
 
+const char kCrostiniDefaultAnsibleVersion[] =
+    "ansible;2.2.1.0-2+deb9u1;all;debian-stable-main";
+
 namespace {
 
 chromeos::CiceroneClient* GetCiceroneClient() {
diff --git a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h
index 0cfb62c8..b7e704b3 100644
--- a/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h
+++ b/chrome/browser/chromeos/crostini/ansible/ansible_management_service.h
@@ -16,8 +16,7 @@
 namespace crostini {
 
 // TODO(okalitova): Install Ansible from backports repo once this is feasible.
-constexpr char kCrostiniDefaultAnsibleVersion[] =
-    "ansible;2.2.1.0-2+deb9u1;all;debian-stable-main";
+extern const char kCrostiniDefaultAnsibleVersion[];
 
 // AnsibleManagementService is responsible for Crostini default
 // container management using Ansible.
diff --git a/chrome/browser/chromeos/crostini/crostini_shelf_utils.cc b/chrome/browser/chromeos/crostini/crostini_shelf_utils.cc
index 23689ba..1ca9aa5 100644
--- a/chrome/browser/chromeos/crostini/crostini_shelf_utils.cc
+++ b/chrome/browser/chromeos/crostini/crostini_shelf_utils.cc
@@ -16,7 +16,11 @@
 namespace {
 
 // This prefix is used as a prefix when generating shelf ids for windows we
-// couldn't match to an app.
+// couldn't match to an app. It is also used for crostini web dialogs (e.g.
+// crostini installer/upgrader) which need to appear in the shelf.
+//
+// Note: if the value is changed, you will also need to manually update
+// kCrostiniInstallerShelfId and kCrostiniUpgraderShelfId.
 constexpr char kCrostiniShelfIdPrefix[] = "crostini:";
 // Prefix of the ApplicationId set on exo windows for X apps.
 constexpr char kCrostiniWindowAppIdPrefix[] = "org.chromium.termina.";
@@ -110,6 +114,15 @@
 
 }  // namespace
 
+// Generated by kCrostiniShelfIdPrefix +
+// crx_file::id_util::GenerateId("org.chromium.crostini_installer_ui");
+const char kCrostiniInstallerShelfId[] =
+    "crostini:lgklmfidjpchchhenipajmkhgipggknm";
+// Generated by kCrostiniShelfIdPrefix +
+// crx_file::id_util::GenerateId("org.chromium.crostini_upgrader_ui");
+const char kCrostiniUpgraderShelfId[] =
+    "crostini:aenmilhipebeoopgeckcghmmeongcbgo";
+
 // The code follows these steps to identify apps and returns the first match:
 // 1) If the Startup Id is set, look for a matching desktop file id.
 // 2) Ignore windows if the App Id is not set.
diff --git a/chrome/browser/chromeos/crostini/crostini_shelf_utils.h b/chrome/browser/chromeos/crostini/crostini_shelf_utils.h
index 40a3bcd..ab5939c 100644
--- a/chrome/browser/chromeos/crostini/crostini_shelf_utils.h
+++ b/chrome/browser/chromeos/crostini/crostini_shelf_utils.h
@@ -12,6 +12,11 @@
 
 namespace crostini {
 
+// The installer/upgrader should set the id on the window so that it will appear
+// on the shelf.
+extern const char kCrostiniInstallerShelfId[];
+extern const char kCrostiniUpgraderShelfId[];
+
 // Returns a shelf app id for an exo window startup id or app id.
 //
 // First try to return a desktop file id matching the |window_startup_id|.
diff --git a/chrome/browser/chromeos/crostini/crostini_util.cc b/chrome/browser/chromeos/crostini/crostini_util.cc
index 5c59455..bd86d31 100644
--- a/chrome/browser/chromeos/crostini/crostini_util.cc
+++ b/chrome/browser/chromeos/crostini/crostini_util.cc
@@ -49,6 +49,28 @@
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/l10n/time_format.h"
 
+namespace crostini {
+
+// We use an arbitrary well-formed extension id for the Terminal app, this
+// is equal to GenerateId("Terminal").
+const char kCrostiniTerminalId[] = "oajcgpnkmhaalajejhlfpacbiokdnnfe";
+// web_app::GenerateAppIdFromURL(
+//     GURL("chrome-untrusted://terminal/html/terminal.html"))
+const char kCrostiniTerminalSystemAppId[] = "fhicihalidkgcimdmhpohldehjmcabcf";
+
+const char kCrostiniDefaultVmName[] = "termina";
+const char kCrostiniDefaultContainerName[] = "penguin";
+const char kCrostiniDefaultUsername[] = "emperor";
+// In order to be compatible with sync folder id must match standard.
+// Generated using crx_file::id_util::GenerateId("LinuxAppsFolder")
+const char kCrostiniFolderId[] = "ddolnhmblagmcagkedkbfejapapdimlk";
+const char kCrostiniDefaultImageServerUrl[] =
+    "https://storage.googleapis.com/cros-containers/%d";
+const char kCrostiniStretchImageAlias[] = "debian/stretch";
+const char kCrostiniBusterImageAlias[] = "debian/buster";
+
+const base::FilePath::CharType kHomeDirectory[] = FILE_PATH_LITERAL("/home");
+
 namespace {
 
 constexpr char kCrostiniAppLaunchHistogram[] = "Crostini.AppLaunch";
@@ -191,8 +213,9 @@
     base::FilePath path;
     if (!file_manager::util::ConvertFileSystemURLToPathInsideCrostini(
             profile, url, &path)) {
-      return std::move(callback).Run(false,
-                                     "Invalid file: " + url.DebugString());
+      OnLaunchFailed(app_id, crostini::CrostiniResult::UNKNOWN_ERROR);
+      return std::move(callback).Run(
+          false, "Cannot share file with crostini: " + url.DebugString());
     }
     if (url.mount_filesystem_id() !=
         file_manager::util::GetCrostiniMountPointName(profile)) {
@@ -299,8 +322,6 @@
 
 }  // namespace
 
-namespace crostini {
-
 ContainerId::ContainerId(std::string vm_name,
                          std::string container_name) noexcept
     : vm_name(std::move(vm_name)), container_name(std::move(container_name)) {}
diff --git a/chrome/browser/chromeos/crostini/crostini_util.h b/chrome/browser/chromeos/crostini/crostini_util.h
index afa167c..d7ebaf4 100644
--- a/chrome/browser/chromeos/crostini/crostini_util.h
+++ b/chrome/browser/chromeos/crostini/crostini_util.h
@@ -32,10 +32,27 @@
 
 class Profile;
 
-// TODO(crbug.com/1004708): Move Is*[Enabled|Allowed] functions to
-// CrostiniFeatures.
 namespace crostini {
 
+// We use an arbitrary well-formed extension id for the Terminal app, this
+// is equal to GenerateId("Terminal").
+extern const char kCrostiniTerminalId[];
+// web_app::GenerateAppIdFromURL(
+//     GURL("chrome-untrusted://terminal/html/terminal.html"))
+extern const char kCrostiniTerminalSystemAppId[];
+
+extern const char kCrostiniDefaultVmName[];
+extern const char kCrostiniDefaultContainerName[];
+extern const char kCrostiniDefaultUsername[];
+// In order to be compatible with sync folder id must match standard.
+// Generated using crx_file::id_util::GenerateId("LinuxAppsFolder")
+extern const char kCrostiniFolderId[];
+extern const char kCrostiniDefaultImageServerUrl[];
+extern const char kCrostiniStretchImageAlias[];
+extern const char kCrostiniBusterImageAlias[];
+
+extern const base::FilePath::CharType kHomeDirectory[];
+
 struct LinuxPackageInfo;
 
 // A unique identifier for our containers.
@@ -189,28 +206,6 @@
 // migrating terminals when TerminalSystemApp feature changes.
 const std::string& GetDeletedTerminalId();
 
-// We use an arbitrary well-formed extension id for the Terminal app, this
-// is equal to GenerateId("Terminal").
-constexpr char kCrostiniTerminalId[] = "oajcgpnkmhaalajejhlfpacbiokdnnfe";
-// web_app::GenerateAppIdFromURL(
-//     GURL("chrome-untrusted://terminal/html/terminal.html"))
-constexpr char kCrostiniTerminalSystemAppId[] =
-    "fhicihalidkgcimdmhpohldehjmcabcf";
-
-constexpr char kCrostiniDefaultVmName[] = "termina";
-constexpr char kCrostiniDefaultContainerName[] = "penguin";
-constexpr char kCrostiniDefaultUsername[] = "emperor";
-// In order to be compatible with sync folder id must match standard.
-// Generated using crx_file::id_util::GenerateId("LinuxAppsFolder")
-constexpr char kCrostiniFolderId[] = "ddolnhmblagmcagkedkbfejapapdimlk";
-constexpr char kCrostiniDefaultImageServerUrl[] =
-    "https://storage.googleapis.com/cros-containers/%d";
-constexpr char kCrostiniStretchImageAlias[] = "debian/stretch";
-constexpr char kCrostiniBusterImageAlias[] = "debian/buster";
-
-constexpr base::FilePath::CharType kHomeDirectory[] =
-    FILE_PATH_LITERAL("/home");
-
 // Add a newly created LXD container to the kCrostiniContainers pref
 void AddNewLxdContainerToPrefs(Profile* profile,
                                const ContainerId& container_id);
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
index b8a784b..bab33c6 100644
--- a/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
+++ b/chrome/browser/chromeos/extensions/file_manager/private_api_misc.cc
@@ -780,10 +780,15 @@
       Params;
   const std::unique_ptr<Params> params(Params::Create(*args_));
   EXTENSION_FUNCTION_VALIDATE(params);
+  // TODO(crbug.com/1057591): Unexpected crashes in
+  // GuestOsSharePath::GetPersistedSharedPaths with null profile_.
+  CHECK(browser_context());
   Profile* profile = Profile::FromBrowserContext(browser_context());
+  CHECK(profile);
 
   auto* guest_os_share_path =
       guest_os::GuestOsSharePath::GetForProfile(profile);
+  CHECK(guest_os_share_path);
   bool first_for_session = params->observe_first_for_session &&
                            guest_os_share_path->GetAndSetFirstForSession();
   auto shared_paths =
diff --git a/chrome/browser/chromeos/file_manager/file_tasks.cc b/chrome/browser/chromeos/file_manager/file_tasks.cc
index 4bfc7076..bee1a60 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks.cc
@@ -789,7 +789,7 @@
   FindFileBrowserHandlerTasks(profile, file_urls, result_list_ptr);
 
   // 5. Find and append Guest OS tasks.
-  FindGuestOsTasks(profile, entries, result_list_ptr,
+  FindGuestOsTasks(profile, entries, file_urls, result_list_ptr,
                    // Done. Apply post-filtering and callback.
                    base::BindOnce(PostProcessFoundTasks, profile, entries,
                                   std::move(callback), std::move(result_list)));
diff --git a/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc b/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc
index f13bcc2..2a292cb 100644
--- a/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/file_tasks_unittest.cc
@@ -43,6 +43,8 @@
 #include "extensions/common/extension_builder.h"
 #include "extensions/common/manifest.h"
 #include "google_apis/drive/drive_api_parser.h"
+#include "net/base/escape.h"
+#include "storage/browser/file_system/external_mount_points.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "url/gurl.h"
@@ -1358,6 +1360,25 @@
         ->UpdateMimeTypes(mime_types_list);
   }
 
+  void SetUp() override {
+    storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+        util::GetDownloadsMountPointName(&test_profile_),
+        storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(),
+        util::GetMyFilesFolderForProfile(&test_profile_));
+  }
+
+  void TearDown() override {
+    storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+        util::GetDownloadsMountPointName(&test_profile_));
+  }
+
+  GURL PathToURL(const std::string& path) {
+    std::string virtual_path = net::EscapeUrlEncodedData(
+        util::GetDownloadsMountPointName(&test_profile_) + "/" + path,
+        /*use_plus=*/false);
+    return GURL("filesystem:chrome-extension://id/external/" + virtual_path);
+  }
+
   crostini::CrostiniTestHelper crostini_test_helper_;
   base::FilePath crostini_folder_;
   std::string text_app_id_;
@@ -1369,8 +1390,7 @@
 TEST_F(FileManagerFileTasksCrostiniTest, BasicFiles) {
   std::vector<extensions::EntryInfo> entries{
       {crostini_folder_.Append("foo.txt"), "text/plain", false}};
-  std::vector<GURL> file_urls{
-      GURL("filesystem:chrome-extension://id/dir/foo.txt")};
+  std::vector<GURL> file_urls{PathToURL("dir/foo.txt")};
 
   std::vector<FullTaskDescriptor> tasks;
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
@@ -1380,7 +1400,7 @@
 
   // Multiple text files
   entries.emplace_back(crostini_folder_.Append("bar.txt"), "text/plain", false);
-  file_urls.emplace_back("filesystem:chrome-extension://id/dir/bar.txt");
+  file_urls.emplace_back(PathToURL("dir/bar.txt"));
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
                                                file_urls, &tasks);
   ASSERT_EQ(1U, tasks.size());
@@ -1390,14 +1410,14 @@
 TEST_F(FileManagerFileTasksCrostiniTest, Directories) {
   std::vector<extensions::EntryInfo> entries{
       {crostini_folder_.Append("dir"), "", true}};
-  std::vector<GURL> file_urls{GURL("filesystem:chrome-extension://id/dir/dir")};
+  std::vector<GURL> file_urls{PathToURL("dir/dir")};
   std::vector<FullTaskDescriptor> tasks;
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
                                                file_urls, &tasks);
   EXPECT_EQ(0U, tasks.size());
 
   entries.emplace_back(crostini_folder_.Append("foo.txt"), "text/plain", false);
-  file_urls.emplace_back("filesystem:chrome-extension://id/dir/foo.txt");
+  file_urls.emplace_back(PathToURL("dir/foo.txt"));
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
                                                file_urls, &tasks);
   EXPECT_EQ(0U, tasks.size());
@@ -1407,9 +1427,8 @@
   std::vector<extensions::EntryInfo> entries{
       {crostini_folder_.Append("foo.gif"), "image/gif", false},
       {crostini_folder_.Append("bar.gif"), "image/gif", false}};
-  std::vector<GURL> file_urls{
-      GURL("filesystem:chrome-extension://id/dir/foo.gif"),
-      GURL("filesystem:chrome-extension://id/dir/bar.gif")};
+  std::vector<GURL> file_urls{PathToURL("dir/foo.gif"),
+                              PathToURL("dir/bar.gif")};
 
   std::vector<FullTaskDescriptor> tasks;
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
@@ -1426,9 +1445,8 @@
   std::vector<extensions::EntryInfo> entries{
       {crostini_folder_.Append("foo.gif"), "image/gif", false},
       {crostini_folder_.Append("bar.png"), "image/png", false}};
-  std::vector<GURL> file_urls{
-      GURL("filesystem:chrome-extension://id/dir/foo.gif"),
-      GURL("filesystem:chrome-extension://id/dir/bar.png")};
+  std::vector<GURL> file_urls{PathToURL("dir/foo.gif"),
+                              PathToURL("dir/bar.png")};
 
   std::vector<FullTaskDescriptor> tasks;
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
@@ -1437,7 +1455,7 @@
   EXPECT_EQ(image_app_id_, tasks[0].task_descriptor().app_id);
 
   entries.emplace_back(crostini_folder_.Append("qux.mp4"), "video/mp4", false);
-  file_urls.emplace_back("filesystem:chrome-extension://id/dir/qux.mp4");
+  file_urls.emplace_back(PathToURL("dir/qux.mp4"));
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
                                                file_urls, &tasks);
   EXPECT_EQ(0U, tasks.size());
@@ -1447,9 +1465,8 @@
   std::vector<extensions::EntryInfo> entries{
       {crostini_folder_.Append("bar1.foo"), "text/plain", false},
       {crostini_folder_.Append("bar2.foo"), "application/octet-stream", false}};
-  std::vector<GURL> file_urls{
-      GURL("filesystem:chrome-extension://id/dir/bar1.foo"),
-      GURL("filesystem:chrome-extension://id/dir/bar2.foo")};
+  std::vector<GURL> file_urls{PathToURL("dir/bar1.foo"),
+                              PathToURL("dir/bar2.foo")};
 
   std::vector<FullTaskDescriptor> tasks;
   FindAllTypesOfTasksSynchronousWrapper().Call(&test_profile_, entries,
diff --git a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc
index b7bfc8d7..ddf9efe 100644
--- a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.cc
@@ -20,12 +20,14 @@
 #include "chrome/browser/chromeos/crostini/crostini_mime_types_service_factory.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
 #include "chrome/browser/chromeos/file_manager/app_id.h"
+#include "chrome/browser/chromeos/file_manager/fileapi_util.h"
 #include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service_factory.h"
 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_files.h"
 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_util.h"
 #include "extensions/browser/entry_info.h"
+#include "storage/browser/file_system/file_system_context.h"
 #include "storage/browser/file_system/file_system_url.h"
 #include "ui/base/layout.h"
 #include "ui/display/types/display_constants.h"
@@ -205,9 +207,21 @@
 void FindGuestOsApps(
     Profile* profile,
     const std::vector<extensions::EntryInfo>& entries,
+    const std::vector<GURL>& file_urls,
     std::vector<std::string>* app_ids,
     std::vector<std::string>* app_names,
     std::vector<guest_os::GuestOsRegistryService::VmType>* vm_types) {
+  // Ensure all files can be shared with VMs.
+  storage::FileSystemContext* file_system_context =
+      util::GetFileSystemContextForExtensionId(profile, kFileManagerAppId);
+  base::FilePath not_used;
+  for (const GURL& file_url : file_urls) {
+    if (!file_manager::util::ConvertFileSystemURLToPathInsideCrostini(
+            profile, file_system_context->CrackURL(file_url), &not_used)) {
+      return;
+    }
+  }
+
   auto* registry_service =
       guest_os::GuestOsRegistryServiceFactory::GetForProfile(profile);
   crostini::CrostiniMimeTypesService* mime_types_service =
@@ -227,6 +241,7 @@
 
 void FindGuestOsTasks(Profile* profile,
                       const std::vector<extensions::EntryInfo>& entries,
+                      const std::vector<GURL>& file_urls,
                       std::vector<FullTaskDescriptor>* result_list,
                       base::OnceClosure completion_closure) {
   if (!crostini::CrostiniFeatures::Get()->IsUIAllowed(profile) &&
@@ -238,8 +253,8 @@
   std::vector<std::string> result_app_ids;
   std::vector<std::string> result_app_names;
   std::vector<guest_os::GuestOsRegistryService::VmType> result_vm_types;
-  FindGuestOsApps(profile, entries, &result_app_ids, &result_app_names,
-                  &result_vm_types);
+  FindGuestOsApps(profile, entries, file_urls, &result_app_ids,
+                  &result_app_names, &result_vm_types);
 
   if (result_app_ids.empty()) {
     std::move(completion_closure).Run();
diff --git a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.h b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.h
index 993c93ea..3273767 100644
--- a/chrome/browser/chromeos/file_manager/guest_os_file_tasks.h
+++ b/chrome/browser/chromeos/file_manager/guest_os_file_tasks.h
@@ -33,6 +33,7 @@
 void FindGuestOsApps(
     Profile* profile,
     const std::vector<extensions::EntryInfo>& entries,
+    const std::vector<GURL>& file_urls,
     std::vector<std::string>* app_ids,
     std::vector<std::string>* app_names,
     std::vector<guest_os::GuestOsRegistryService::VmType>* vm_types);
@@ -41,6 +42,7 @@
 // |result_list|, and calls back to |callback| once finished.
 void FindGuestOsTasks(Profile* profile,
                       const std::vector<extensions::EntryInfo>& entries,
+                      const std::vector<GURL>& file_urls,
                       std::vector<FullTaskDescriptor>* result_list,
                       base::OnceClosure completion_closure);
 
diff --git a/chrome/browser/chromeos/file_manager/guest_os_file_tasks_unittest.cc b/chrome/browser/chromeos/file_manager/guest_os_file_tasks_unittest.cc
index 9737f3e6..9e38f5f 100644
--- a/chrome/browser/chromeos/file_manager/guest_os_file_tasks_unittest.cc
+++ b/chrome/browser/chromeos/file_manager/guest_os_file_tasks_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/files/file_path.h"
 #include "base/values.h"
 #include "chrome/browser/chromeos/crostini/crostini_pref_names.h"
+#include "chrome/browser/chromeos/file_manager/path_util.h"
 #include "chrome/browser/chromeos/guest_os/guest_os_pref_names.h"
 #include "chrome/browser/chromeos/guest_os/guest_os_registry_service.h"
 #include "chrome/test/base/testing_profile.h"
@@ -14,6 +15,8 @@
 #include "components/prefs/scoped_user_pref_update.h"
 #include "content/public/test/browser_task_environment.h"
 #include "extensions/browser/entry_info.h"
+#include "net/base/escape.h"
+#include "storage/browser/file_system/external_mount_points.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -28,11 +31,22 @@
 
 }  // namespace
 
-class CrostiniFileTasksTest : public testing::Test {
- public:
-  CrostiniFileTasksTest() = default;
-
+class GuestOsFileTasksTest : public testing::Test {
  protected:
+  GuestOsFileTasksTest() = default;
+
+  void SetUp() override {
+    storage::ExternalMountPoints::GetSystemInstance()->RegisterFileSystem(
+        util::GetDownloadsMountPointName(&profile_),
+        storage::kFileSystemTypeNativeLocal, storage::FileSystemMountOption(),
+        util::GetMyFilesFolderForProfile(&profile_));
+  }
+
+  void TearDown() override {
+    storage::ExternalMountPoints::GetSystemInstance()->RevokeFileSystem(
+        util::GetDownloadsMountPointName(&profile_));
+  }
+
   void AddApp(const std::string& id,
               const std::string& name,
               const std::vector<std::string>& mimes,
@@ -64,6 +78,11 @@
   void AddEntry(const std::string& path, const std::string& mime) {
     entries_.push_back(
         extensions::EntryInfo(base::FilePath(path), mime, false));
+    std::string virtual_path = net::EscapeUrlEncodedData(
+        util::GetDownloadsMountPointName(&profile_) + "/" + path,
+        /*use_plus=*/false);
+    urls_.push_back(
+        GURL("filesystem:chrome-extension://id/external/" + virtual_path));
   }
 
   void AddMime(const std::string& file_ext, const std::string& mime) {
@@ -82,116 +101,152 @@
   content::BrowserTaskEnvironment task_environment_;
   TestingProfile profile_;
   std::vector<extensions::EntryInfo> entries_;
+  std::vector<GURL> urls_;
   std::vector<std::string> app_ids_;
   std::vector<std::string> app_names_;
   std::vector<guest_os::GuestOsRegistryService::VmType> app_vm_types_;
 
-  DISALLOW_COPY_AND_ASSIGN(CrostiniFileTasksTest);
+  DISALLOW_COPY_AND_ASSIGN(GuestOsFileTasksTest);
 };
 
-TEST_F(CrostiniFileTasksTest, NoApps) {
+TEST_F(GuestOsFileTasksTest, CheckPathsCanBeShared) {
   AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
-  AddEntry("entry.txt", "test/mime2");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  AddEntry("entry.txt", "test/mime1");
+
+  // Share ok.
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
+  EXPECT_THAT(app_ids_, testing::ElementsAre("app1"));
+  EXPECT_THAT(app_names_, testing::ElementsAre("name1"));
+  EXPECT_THAT(app_vm_types_, testing::ElementsAre(VM_TERMINA));
+
+  // Share fails.
+  urls_.clear();
+  urls_.push_back(GURL("filesysytem://share/fail"));
+  app_ids_.clear();
+  app_names_.clear();
+  app_vm_types_.clear();
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::IsEmpty());
   EXPECT_THAT(app_names_, testing::IsEmpty());
   EXPECT_THAT(app_vm_types_, testing::IsEmpty());
 }
 
-TEST_F(CrostiniFileTasksTest, Termina_AppRegistered) {
+TEST_F(GuestOsFileTasksTest, NoApps) {
+  AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
+  AddEntry("entry.txt", "test/mime2");
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
+  EXPECT_THAT(app_ids_, testing::IsEmpty());
+  EXPECT_THAT(app_names_, testing::IsEmpty());
+  EXPECT_THAT(app_vm_types_, testing::IsEmpty());
+}
+
+TEST_F(GuestOsFileTasksTest, Termina_AppRegistered) {
   AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
   AddEntry("entry.txt", "test/mime1");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(VM_TERMINA));
 }
 
-TEST_F(CrostiniFileTasksTest, PluginVm_AppRegistered) {
+TEST_F(GuestOsFileTasksTest, PluginVm_AppRegistered) {
   AddApp("app1", "name1", {}, {"txt"}, PLUGIN_VM);
   AddEntry("entry.txt", "test/mime1");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(PLUGIN_VM));
 }
 
-TEST_F(CrostiniFileTasksTest, Termina_NotAllEntries) {
+TEST_F(GuestOsFileTasksTest, Termina_NotAllEntries) {
   AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
   AddApp("app2", "name2", {"test/mime2"}, {}, VM_TERMINA);
   AddEntry("entry1.txt", "test/mime1");
   AddEntry("entry2.txt", "test/mime2");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::IsEmpty());
   EXPECT_THAT(app_names_, testing::IsEmpty());
   EXPECT_THAT(app_vm_types_, testing::IsEmpty());
 }
 
-TEST_F(CrostiniFileTasksTest, PluginVm_NotAllEntries) {
+TEST_F(GuestOsFileTasksTest, PluginVm_NotAllEntries) {
   AddApp("app1", "name1", {}, {"txt"}, PLUGIN_VM);
   AddApp("app2", "name2", {}, {"jpg"}, PLUGIN_VM);
   AddEntry("entry1.txt", "test/mime1");
   AddEntry("entry2.jpg", "test/mime2");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::IsEmpty());
   EXPECT_THAT(app_names_, testing::IsEmpty());
   EXPECT_THAT(app_vm_types_, testing::IsEmpty());
 }
 
-TEST_F(CrostiniFileTasksTest, Termina_MultipleAppsRegistered) {
+TEST_F(GuestOsFileTasksTest, Termina_MultipleAppsRegistered) {
   AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
   AddApp("app2", "name2", {"test/mime1"}, {}, VM_TERMINA);
   AddEntry("entry.txt", "test/mime1");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1", "app2"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1", "name2"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(VM_TERMINA, VM_TERMINA));
 }
 
-TEST_F(CrostiniFileTasksTest, PluginVm_MultipleAppsRegistered) {
+TEST_F(GuestOsFileTasksTest, PluginVm_MultipleAppsRegistered) {
   AddApp("app1", "name1", {}, {"txt"}, PLUGIN_VM);
   AddApp("app2", "name2", {}, {"txt"}, PLUGIN_VM);
   AddEntry("entry.txt", "test/mime1");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1", "app2"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1", "name2"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(PLUGIN_VM, PLUGIN_VM));
 }
 
-TEST_F(CrostiniFileTasksTest, MultipleAppsFromMultipleVmsRegistered) {
+TEST_F(GuestOsFileTasksTest, MultipleAppsFromMultipleVmsRegistered) {
   AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
   AddApp("app2", "name2", {}, {"txt"}, PLUGIN_VM);
   AddEntry("entry.txt", "test/mime1");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1", "app2"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1", "name2"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(VM_TERMINA, PLUGIN_VM));
 }
 
-TEST_F(CrostiniFileTasksTest, AppRegisteredForTextPlain) {
+TEST_F(GuestOsFileTasksTest, AppRegisteredForTextPlain) {
   AddApp("app1", "name1", {"text/plain"}, {}, VM_TERMINA);
   AddEntry("entry.js", "text/javascript");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(VM_TERMINA));
 }
 
-TEST_F(CrostiniFileTasksTest, MimeServiceForTextPlain) {
+TEST_F(GuestOsFileTasksTest, MimeServiceForTextPlain) {
   AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
   AddEntry("entry.unknown", "text/plain");
   AddMime("unknown", "test/mime1");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(VM_TERMINA));
 }
 
-TEST_F(CrostiniFileTasksTest, MimeServiceForApplicationOctetStream) {
+TEST_F(GuestOsFileTasksTest, MimeServiceForApplicationOctetStream) {
   AddApp("app1", "name1", {"test/mime1"}, {}, VM_TERMINA);
   AddEntry("entry.unknown", "application/octet-stream");
   AddMime("unknown", "test/mime1");
-  FindGuestOsApps(&profile_, entries_, &app_ids_, &app_names_, &app_vm_types_);
+  FindGuestOsApps(&profile_, entries_, urls_, &app_ids_, &app_names_,
+                  &app_vm_types_);
   EXPECT_THAT(app_ids_, testing::ElementsAre("app1"));
   EXPECT_THAT(app_names_, testing::ElementsAre("name1"));
   EXPECT_THAT(app_vm_types_, testing::ElementsAre(VM_TERMINA));
diff --git a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
index bfd5d3c..fc385cb4 100644
--- a/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
+++ b/chrome/browser/chromeos/login/active_directory_login_browsertest.cc
@@ -103,7 +103,6 @@
 
 // Test successful Active Directory login.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, LoginSuccess) {
-  OobeBaseTest::WaitForSigninScreen();
   ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
   ad_login_.TestNoError();
   ad_login_.TestDomainHidden();
@@ -115,7 +114,6 @@
 // Tests that the Kerberos SSO environment variables are set correctly after
 // an Active Directory log in.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, KerberosVarsCopied) {
-  OobeBaseTest::WaitForSigninScreen();
   ad_login_.TestNoError();
   ad_login_.TestDomainHidden();
   ad_login_.SubmitActiveDirectoryCredentials(test_user_, kPassword);
@@ -134,7 +132,6 @@
 
 // Test different UI errors for Active Directory login.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, LoginErrors) {
-  OobeBaseTest::WaitForSigninScreen();
   ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
   ad_login_.TestNoError();
   ad_login_.TestDomainHidden();
@@ -175,7 +172,6 @@
 
 // Test successful Active Directory login from the password change screen.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, PasswordChange_LoginSuccess) {
-  OobeBaseTest::WaitForSigninScreen();
   ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
   ad_login_.TestLoginVisible();
   ad_login_.TestDomainHidden();
@@ -192,7 +188,6 @@
 
 // Test different UI errors for Active Directory password change screen.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest, PasswordChange_UIErrors) {
-  OobeBaseTest::WaitForSigninScreen();
   ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
   ad_login_.TestLoginVisible();
   ad_login_.TestDomainHidden();
@@ -227,7 +222,6 @@
 // Test reopening Active Directory password change screen clears errors.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginTest,
                        PasswordChange_ReopenClearErrors) {
-  OobeBaseTest::WaitForSigninScreen();
   ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
   ad_login_.TestLoginVisible();
   ad_login_.TestDomainHidden();
@@ -246,7 +240,6 @@
 
 // Tests that autocomplete works. Submits username without domain.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginAutocompleteTest, LoginSuccess) {
-  OobeBaseTest::WaitForSigninScreen();
   ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
   ad_login_.TestNoError();
   ad_login_.TestDomainVisible();
@@ -259,7 +252,6 @@
 
 // Tests that user could override autocomplete domain.
 IN_PROC_BROWSER_TEST_F(ActiveDirectoryLoginAutocompleteTest, TestAutocomplete) {
-  OobeBaseTest::WaitForSigninScreen();
   ASSERT_TRUE(InstallAttributes::Get()->IsActiveDirectoryManaged());
 
   ad_login_.TestLoginVisible();
diff --git a/chrome/browser/chromeos/login/existing_user_controller.cc b/chrome/browser/chromeos/login/existing_user_controller.cc
index 3b545509..e7a3952 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller.cc
@@ -17,12 +17,14 @@
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/logging.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "base/timer/elapsed_timer.h"
 #include "base/values.h"
 #include "base/version.h"
 #include "chrome/app/vector_icons/vector_icons.h"
@@ -508,7 +510,7 @@
 }
 
 void ExistingUserController::Init(const user_manager::UserList& users) {
-  time_init_ = base::Time::Now();
+  timer_init_ = std::make_unique<base::ElapsedTimer>();
   UpdateLoginDisplay(users);
   ConfigureAutoLogin();
 }
@@ -798,10 +800,10 @@
   }
   SendAccessibilityAlert(
       l10n_util::GetStringUTF8(IDS_CHROMEOS_ACC_LOGIN_SIGNING_IN));
-  if (!time_init_.is_null()) {
-    base::TimeDelta delta = base::Time::Now() - time_init_;
-    UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToLoginTime", delta);
-    time_init_ = base::Time();  // Reset to null.
+  if (timer_init_) {
+    base::UmaHistogramMediumTimes("Login.PromptToLoginTime",
+                                  timer_init_->Elapsed());
+    timer_init_.reset();
   }
   // Stop screen refresh timer - will be restarted on login screen again
   screen_refresh_timer_->Stop();
@@ -1889,10 +1891,10 @@
 
   PerformPreLoginActions(user_context);
 
-  if (!time_init_.is_null()) {
-    base::TimeDelta delta = base::Time::Now() - time_init_;
-    UMA_HISTOGRAM_MEDIUM_TIMES("Login.PromptToCompleteLoginTime", delta);
-    time_init_ = base::Time();  // Reset to null.
+  if (timer_init_) {
+    base::UmaHistogramMediumTimes("Login.PromptToCompleteLoginTime",
+                                  timer_init_->Elapsed());
+    timer_init_.reset();
   }
 
   // Fetch OAuth2 tokens if we have an auth code.
diff --git a/chrome/browser/chromeos/login/existing_user_controller.h b/chrome/browser/chromeos/login/existing_user_controller.h
index 794d4e1..06fe339 100644
--- a/chrome/browser/chromeos/login/existing_user_controller.h
+++ b/chrome/browser/chromeos/login/existing_user_controller.h
@@ -41,6 +41,7 @@
 #include "url/gurl.h"
 
 namespace base {
+class ElapsedTimer;
 class ListValue;
 }
 
@@ -404,9 +405,9 @@
   // Indicates use of local (not GAIA) authentication.
   bool auth_flow_offline_ = false;
 
-  // Time when the signin screen was first displayed. Used to measure the time
+  // Timer when the signin screen was first displayed. Used to measure the time
   // from showing the screen until a successful login is performed.
-  base::Time time_init_;
+  std::unique_ptr<base::ElapsedTimer> timer_init_;
 
   // Timer for the interval to wait for the reboot after TPM error UI was shown.
   base::OneShotTimer reboot_timer_;
diff --git a/chrome/browser/chromeos/login/saml/saml_browsertest.cc b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
index 549a332..bf13036 100644
--- a/chrome/browser/chromeos/login/saml/saml_browsertest.cc
+++ b/chrome/browser/chromeos/login/saml/saml_browsertest.cc
@@ -648,7 +648,7 @@
   }
 
   virtual void StartSamlAndWaitForIdpPageLoad(const std::string& gaia_email) {
-    WaitForSigninScreen();
+    OobeScreenWaiter(GaiaView::kScreenId).Wait();
 
     content::DOMMessageQueue message_queue;  // Start observe before SAML.
     SetupAuthFlowChangeListener();
@@ -713,6 +713,9 @@
 
   FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()};
 
+  chromeos::DeviceStateMixin device_state_{
+      &mixin_host_, chromeos::DeviceStateMixin::State::OOBE_COMPLETED_UNOWNED};
+
  private:
   FakeSamlIdp fake_saml_idp_;
 
@@ -1291,10 +1294,6 @@
   policy::MockConfigurationPolicyProvider provider_;
   net::CookieList cookie_list_;
 
-  chromeos::DeviceStateMixin device_state_{
-      &mixin_host_,
-      chromeos::DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED};
-
   // Add a fake user so the login screen does not show GAIA auth by default.
   // This enables tests to control when the GAIA is shown (and ensure it's
   // loaded after SAML config has been set up).
@@ -1309,6 +1308,8 @@
 
 SAMLPolicyTest::SAMLPolicyTest()
     : device_policy_(test_helper_.device_policy()) {
+  device_state_.SetState(
+      DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED);
   device_state_.set_skip_initial_policy_setup(true);
 }
 
@@ -1549,6 +1550,7 @@
   // Remove the offline login time limit for SAML users.
   SetSAMLOfflineSigninTimeLimitPolicy(-1);
 
+  ShowGAIALoginForm();
   LogInWithSAML(saml_test_users::kFirstUserCorpExampleComEmail,
                 kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
 }
@@ -1567,6 +1569,7 @@
   // Set the offline login time limit for SAML users to zero.
   SetSAMLOfflineSigninTimeLimitPolicy(0);
 
+  ShowGAIALoginForm();
   LogInWithSAML(saml_test_users::kFirstUserCorpExampleComEmail,
                 kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
 }
@@ -1582,6 +1585,7 @@
 
 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_PRE_TransferCookiesAffiliated) {
   fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1);
+  ShowGAIALoginForm();
   LogInWithSAML(saml_test_users::kFirstUserCorpExampleComEmail,
                 kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
 
@@ -1629,6 +1633,7 @@
 
 IN_PROC_BROWSER_TEST_F(SAMLPolicyTest, PRE_TransferCookiesUnaffiliated) {
   fake_saml_idp()->SetCookieValue(kSAMLIdPCookieValue1);
+  ShowGAIALoginForm();
   LogInWithSAML(saml_test_users::kFifthUserExampleTestEmail,
                 kTestAuthSIDCookie1, kTestAuthLSIDCookie1);
 
@@ -1792,11 +1797,9 @@
 // Verifies that password attributes are extracted and stored during a
 // successful log in - but only if the appropriate policy is enabled.
 IN_PROC_BROWSER_TEST_P(SAMLPasswordAttributesTest, LoginSucceeded) {
-  // LoginDisplayHostMojo does not show Oobe dialog by default.
-  LoginDisplayHost::default_host()->ShowGaiaDialog(EmptyAccountId());
-
   fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
   fake_saml_idp()->SetSamlResponseFile("saml_with_password_attributes.xml");
+  ShowGAIALoginForm();
   StartSamlAndWaitForIdpPageLoad(
       saml_test_users::kFirstUserCorpExampleComEmail);
 
@@ -1827,11 +1830,9 @@
 
 // Verify that no password attributes are stored when login fails.
 IN_PROC_BROWSER_TEST_P(SAMLPasswordAttributesTest, LoginFailed) {
-  // LoginDisplayHostMojo does not show Oobe dialog by default.
-  LoginDisplayHost::default_host()->ShowGaiaDialog(EmptyAccountId());
-
   fake_saml_idp()->SetLoginHTMLTemplate("saml_login.html");
   fake_saml_idp()->SetSamlResponseFile("saml_with_password_attributes.xml");
+  ShowGAIALoginForm();
   StartSamlAndWaitForIdpPageLoad(
       saml_test_users::kFirstUserCorpExampleComEmail);
 
diff --git a/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc
index c222cf37..c559c2f 100644
--- a/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/assistant_optin_flow_screen_browsertest.cc
@@ -443,7 +443,7 @@
   auto force_lib_assistant_enabled =
       AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true);
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   SetUpAssistantScreensForTest();
   ShowAssistantOptInFlowScreen();
@@ -486,7 +486,7 @@
   auto force_lib_assistant_enabled =
       AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true);
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   SetUpAssistantScreensForTest();
   ShowAssistantOptInFlowScreen();
@@ -540,7 +540,7 @@
   screen_waiter.Wait();
 
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   WaitForAssistantScreen("value-prop");
   TapWhenEnabled({"assistant-optin-flow-card", "value-prop", "next-button"});
@@ -578,7 +578,7 @@
   ShowAssistantOptInFlowScreen();
 
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   OobeScreenWaiter screen_waiter(AssistantOptInFlowScreenView::kScreenId);
   screen_waiter.set_assert_next_screen();
@@ -621,7 +621,7 @@
       AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(true);
   SetUpAssistantScreensForTest();
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   ShowAssistantOptInFlowScreen();
 
@@ -653,7 +653,7 @@
   assistant_settings_->set_consent_ui_flags(
       ScopedAssistantSettings::CONSENT_UI_FLAG_ASK_EMAIL_OPT_IN);
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   SetUpAssistantScreensForTest();
   ShowAssistantOptInFlowScreen();
@@ -701,7 +701,7 @@
   assistant_settings_->set_consent_ui_flags(
       ScopedAssistantSettings::CONSENT_UI_FLAG_ASK_EMAIL_OPT_IN);
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   SetUpAssistantScreensForTest();
   ShowAssistantOptInFlowScreen();
@@ -754,7 +754,7 @@
 
   SetUpAssistantScreensForTest();
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   ShowAssistantOptInFlowScreen();
 
@@ -796,7 +796,7 @@
 
   SetUpAssistantScreensForTest();
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   ShowAssistantOptInFlowScreen();
 
@@ -836,7 +836,7 @@
 
   SetUpAssistantScreensForTest();
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   ShowAssistantOptInFlowScreen();
 
@@ -925,7 +925,7 @@
 
   SetUpAssistantScreensForTest();
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   ShowAssistantOptInFlowScreen();
 
@@ -981,7 +981,7 @@
 
   SetUpAssistantScreensForTest();
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
 
   ShowAssistantOptInFlowScreen();
 
@@ -1037,7 +1037,7 @@
       ScopedAssistantSettings::CONSENT_UI_FLAG_WAA_DISABLED_BY_POLICY);
 
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
   SetUpAssistantScreensForTest();
   ShowAssistantOptInFlowScreen();
 
@@ -1062,7 +1062,7 @@
       ScopedAssistantSettings::CONSENT_UI_FLAG_ASSISTANT_DISABLED_BY_POLICY);
 
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
   SetUpAssistantScreensForTest();
   ShowAssistantOptInFlowScreen();
 
@@ -1085,7 +1085,7 @@
   auto force_lib_assistant_disabled =
       AssistantOptInFlowScreen::ForceLibAssistantEnabledForTesting(false);
   ash::AssistantState::Get()->NotifyStatusChanged(
-      chromeos::assistant::AssistantStatus::READY);
+      chromeos::assistant::AssistantStatus::NEW_READY);
   SetUpAssistantScreensForTest();
   ShowAssistantOptInFlowScreen();
 
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
index a0d13ee..d9fe17a 100644
--- a/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/sync_consent_browsertest.cc
@@ -314,6 +314,11 @@
   histogram_tester_.ExpectTotalCount(
       "OOBE.StepCompletionTimeByExitReason.Sync-consent.Next", 1);
   histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Sync-consent", 1);
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.Behavior",
+      SyncConsentScreen::SyncScreenBehavior::kShow, 1);
+  histogram_tester_.ExpectUniqueSample("OOBE.SyncConsentScreen.SyncEnabled",
+                                       true, 1);
 }
 
 class SyncConsentTestWithParams
@@ -473,6 +478,14 @@
   histogram_tester_.ExpectTotalCount(
       "OOBE.StepCompletionTimeByExitReason.Sync-consent.Next", 1);
   histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Sync-consent", 1);
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.Behavior",
+      SyncConsentScreen::SyncScreenBehavior::kShow, 1);
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.UserChoice",
+      SyncConsentScreenHandler::UserChoice::kAccepted, 1);
+  histogram_tester_.ExpectUniqueSample("OOBE.SyncConsentScreen.SyncEnabled",
+                                       true, 1);
 
   // Dialog is completed.
   EXPECT_TRUE(prefs->GetBoolean(chromeos::prefs::kSyncOobeCompleted));
@@ -513,6 +526,15 @@
   EXPECT_FALSE(settings->IsSyncEverythingEnabled());
   EXPECT_TRUE(settings->GetSelectedTypes().Empty());
 
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.Behavior",
+      SyncConsentScreen::SyncScreenBehavior::kShow, 1);
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.UserChoice",
+      SyncConsentScreenHandler::UserChoice::kDeclined, 1);
+  histogram_tester_.ExpectUniqueSample("OOBE.SyncConsentScreen.SyncEnabled",
+                                       false, 1);
+
   // Dialog is completed.
   EXPECT_TRUE(prefs->GetBoolean(chromeos::prefs::kSyncOobeCompleted));
 }
@@ -575,6 +597,12 @@
   // Dialog is completed.
   PrefService* prefs = ProfileManager::GetPrimaryUserProfile()->GetPrefs();
   EXPECT_TRUE(prefs->GetBoolean(chromeos::prefs::kSyncOobeCompleted));
+
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.Behavior",
+      SyncConsentScreen::SyncScreenBehavior::kSkipAndEnableNonBrandedBuild, 1);
+  histogram_tester_.ExpectUniqueSample("OOBE.SyncConsentScreen.SyncEnabled",
+                                       true, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(SyncConsentSplitSettingsSyncTest,
@@ -596,6 +624,12 @@
   // Dialog is completed.
   PrefService* prefs = ProfileManager::GetPrimaryUserProfile()->GetPrefs();
   EXPECT_TRUE(prefs->GetBoolean(chromeos::prefs::kSyncOobeCompleted));
+
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.Behavior",
+      SyncConsentScreen::SyncScreenBehavior::kSkipFeaturePolicy, 1);
+  // We don't test SyncEnabled because this test fakes the policy disable and
+  // the sync engine is still enabled.
 }
 
 // Tests for Active Directory accounts, which skip the dialog because they do
@@ -619,7 +653,7 @@
 
 IN_PROC_BROWSER_TEST_F(SyncConsentActiveDirectoryTest, LoginDoesNotStartSync) {
   // Sign in Active Directory user.
-  OobeBaseTest::WaitForSigninScreen();
+  ad_login_.TestLoginVisible();
   ad_login_.SubmitActiveDirectoryCredentials(
       "test-user@locally-managed.localhost", "password");
   test::WaitForLastScreenAndTapGetStarted();
@@ -640,6 +674,11 @@
   histogram_tester_.ExpectTotalCount(
       "OOBE.StepCompletionTimeByExitReason.Sync-consent.Next", 0);
   histogram_tester_.ExpectTotalCount("OOBE.StepCompletionTime.Sync-consent", 0);
+  histogram_tester_.ExpectUniqueSample(
+      "OOBE.SyncConsentScreen.Behavior",
+      SyncConsentScreen::SyncScreenBehavior::kSkipNonGaiaAccount, 1);
+  histogram_tester_.ExpectUniqueSample("OOBE.SyncConsentScreen.SyncEnabled",
+                                       false, 1);
 }
 
 // Tests that the SyncConsent screen performs a timezone request so that
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_screen.cc b/chrome/browser/chromeos/login/screens/sync_consent_screen.cc
index ad647b01..fe888cc 100644
--- a/chrome/browser/chromeos/login/screens/sync_consent_screen.cc
+++ b/chrome/browser/chromeos/login/screens/sync_consent_screen.cc
@@ -117,20 +117,33 @@
   DCHECK(profile_);
   // Always set completed, even if the dialog was skipped (e.g. by policy).
   profile_->GetPrefs()->SetBoolean(chromeos::prefs::kSyncOobeCompleted, true);
+  // Record whether the dialog was shown, skipped, etc.
+  base::UmaHistogramEnumeration("OOBE.SyncConsentScreen.Behavior", behavior_);
+  // Record the final state of the sync service.
+  syncer::SyncService* service = GetSyncService(profile_);
+  bool sync_enabled = service && service->CanSyncFeatureStart() &&
+                      service->GetUserSettings()->IsSyncEverythingEnabled();
+  base::UmaHistogramBoolean("OOBE.SyncConsentScreen.SyncEnabled", sync_enabled);
   exit_callback_.Run(result);
 }
 
 bool SyncConsentScreen::MaybeSkip() {
   Init();
 
-  if (behavior_ == SyncScreenBehavior::kSkip ||
-      behavior_ == SyncScreenBehavior::kSkipAndEnableSync) {
-    MaybeEnableSyncForSkip();
-    Finish(Result::NOT_APPLICABLE);
-    return true;
+  switch (behavior_) {
+    case SyncScreenBehavior::kUnknown:
+    case SyncScreenBehavior::kShow:
+      return false;
+    case SyncScreenBehavior::kSkipNonGaiaAccount:
+    case SyncScreenBehavior::kSkipPublicAccount:
+    case SyncScreenBehavior::kSkipFeaturePolicy:
+    case SyncScreenBehavior::kSkipAndEnableNonBrandedBuild:
+    case SyncScreenBehavior::kSkipAndEnableEmphemeralUser:
+    case SyncScreenBehavior::kSkipAndEnableScreenPolicy:
+      MaybeEnableSyncForSkip();
+      Finish(Result::NOT_APPLICABLE);
+      return true;
   }
-
-  return false;
 }
 
 void SyncConsentScreen::ShowImpl() {
@@ -180,16 +193,18 @@
   Finish(Result::NEXT);
 }
 
-void SyncConsentScreen::OnAcceptAndContinue(
+void SyncConsentScreen::OnContinue(
     const std::vector<int>& consent_description,
     int consent_confirmation,
-    bool enable_sync) {
+    SyncConsentScreenHandler::UserChoice choice) {
   DCHECK(chromeos::features::IsSplitSettingsSyncEnabled());
   if (is_hidden())
     return;
+  base::UmaHistogramEnumeration("OOBE.SyncConsentScreen.UserChoice", choice);
   // Record that the user saw the consent text, regardless of which features
   // they chose to enable.
   RecordConsent(CONSENT_GIVEN, consent_description, consent_confirmation);
+  bool enable_sync = choice == SyncConsentScreenHandler::UserChoice::kAccepted;
   UpdateSyncSettings(enable_sync);
   Finish(Result::NEXT);
 }
@@ -234,16 +249,27 @@
 }
 
 void SyncConsentScreen::MaybeEnableSyncForSkip() {
-  DCHECK(behavior_ == SyncScreenBehavior::kSkip ||
-         behavior_ == SyncScreenBehavior::kSkipAndEnableSync);
-
   // Prior to SplitSettingsSync, sync is autostarted during ProfileSyncService
   // creation, so sync is already in the right state.
   if (!chromeos::features::IsSplitSettingsSyncEnabled())
     return;
 
-  if (behavior_ == SyncScreenBehavior::kSkipAndEnableSync)
-    UpdateSyncSettings(/*enable_sync=*/true);
+  switch (behavior_) {
+    case SyncScreenBehavior::kUnknown:
+    case SyncScreenBehavior::kShow:
+      NOTREACHED();
+      return;
+    case SyncScreenBehavior::kSkipNonGaiaAccount:
+    case SyncScreenBehavior::kSkipPublicAccount:
+    case SyncScreenBehavior::kSkipFeaturePolicy:
+      // Nothing to do.
+      return;
+    case SyncScreenBehavior::kSkipAndEnableNonBrandedBuild:
+    case SyncScreenBehavior::kSkipAndEnableEmphemeralUser:
+    case SyncScreenBehavior::kSkipAndEnableScreenPolicy:
+      UpdateSyncSettings(/*enable_sync=*/true);
+      return;
+  }
 }
 
 // static
@@ -266,34 +292,34 @@
     const {
   // Skip for users without Gaia account (e.g. Active Directory).
   if (!user_->HasGaiaAccount())
-    return SyncScreenBehavior::kSkip;
+    return SyncScreenBehavior::kSkipNonGaiaAccount;
 
   // Skip for public user.
   if (user_->GetType() == user_manager::USER_TYPE_PUBLIC_ACCOUNT)
-    return SyncScreenBehavior::kSkip;
+    return SyncScreenBehavior::kSkipPublicAccount;
 
   // Skip for non-branded (e.g. developer) builds. Check this after the account
   // type checks so we don't try to enable sync in browser_tests for those
   // account types.
   if (!g_is_branded_build)
-    return SyncScreenBehavior::kSkipAndEnableSync;
+    return SyncScreenBehavior::kSkipAndEnableNonBrandedBuild;
 
   const user_manager::UserManager* user_manager =
       user_manager::UserManager::Get();
   // Skip for non-regular ephemeral users.
   if (user_manager->IsUserNonCryptohomeDataEphemeral(user_->GetAccountId()) &&
       (user_->GetType() != user_manager::USER_TYPE_REGULAR)) {
-    return SyncScreenBehavior::kSkipAndEnableSync;
+    return SyncScreenBehavior::kSkipAndEnableEmphemeralUser;
   }
 
   // Skip if the sync consent screen is disabled by policy, for example, in
   // education scenarios. https://crbug.com/841156
   if (!profile_->GetPrefs()->GetBoolean(::prefs::kEnableSyncConsent))
-    return SyncScreenBehavior::kSkipAndEnableSync;
+    return SyncScreenBehavior::kSkipAndEnableScreenPolicy;
 
   // Skip if sync-the-feature is disabled by policy.
   if (IsProfileSyncDisabledByPolicy())
-    return SyncScreenBehavior::kSkip;
+    return SyncScreenBehavior::kSkipFeaturePolicy;
 
   if (IsProfileSyncEngineInitialized())
     return SyncScreenBehavior::kShow;
@@ -312,19 +338,12 @@
   if (is_hidden() || behavior_ == old_behavior)
     return;
 
-  switch (behavior_) {
-    case SyncScreenBehavior::kShow:
-      view_->SetThrobberVisible(false /*visible*/);
-      GetSyncService(profile_)->RemoveObserver(this);
-      break;
-    case SyncScreenBehavior::kSkip:
-    case SyncScreenBehavior::kSkipAndEnableSync:
-      MaybeEnableSyncForSkip();
-      Finish(Result::NEXT);
-      break;
-    case SyncScreenBehavior::kUnknown:
-      NOTREACHED();
-      break;
+  if (behavior_ == SyncScreenBehavior::kShow) {
+    view_->SetThrobberVisible(false /*visible*/);
+    GetSyncService(profile_)->RemoveObserver(this);
+  } else {
+    MaybeEnableSyncForSkip();
+    Finish(Result::NEXT);
   }
 }
 
diff --git a/chrome/browser/chromeos/login/screens/sync_consent_screen.h b/chrome/browser/chromeos/login/screens/sync_consent_screen.h
index 18deaf9..3949614b 100644
--- a/chrome/browser/chromeos/login/screens/sync_consent_screen.h
+++ b/chrome/browser/chromeos/login/screens/sync_consent_screen.h
@@ -26,15 +26,22 @@
 // sign-in flow.
 class SyncConsentScreen : public BaseScreen,
                           public syncer::SyncServiceObserver {
- private:
+ public:
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused. Public for testing. See
+  // GetSyncScreenBehavior() for documentation on each case.
   enum class SyncScreenBehavior {
-    kUnknown,            // Not yet known.
-    kShow,               // Screen should be shown.
-    kSkip,               // Skip screen, don't change sync state.
-    kSkipAndEnableSync,  // Skip screen and enable sync.
+    kUnknown = 0,
+    kShow = 1,
+    kSkipNonGaiaAccount = 2,
+    kSkipPublicAccount = 3,
+    kSkipFeaturePolicy = 4,
+    kSkipAndEnableNonBrandedBuild = 5,
+    kSkipAndEnableEmphemeralUser = 6,
+    kSkipAndEnableScreenPolicy = 7,
+    kMaxValue = kSkipAndEnableScreenPolicy
   };
 
- public:
   enum ConsentGiven { CONSENT_NOT_GIVEN, CONSENT_GIVEN };
 
   enum class Result { NEXT, NOT_APPLICABLE };
@@ -87,9 +94,9 @@
                               const int consent_confirmation);
 
   // Reacts to "Yes, I'm in" and "No, thanks".
-  void OnAcceptAndContinue(const std::vector<int>& consent_description,
-                           int consent_confirmation,
-                           bool enable_sync);
+  void OnContinue(const std::vector<int>& consent_description,
+                  int consent_confirmation,
+                  SyncConsentScreenHandler::UserChoice choice);
 
   // Configures OS sync and browser sync.
   void UpdateSyncSettings(bool enable_sync);
diff --git a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
index 30f3eb0..ccff7c3 100644
--- a/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
+++ b/chrome/browser/chromeos/login/screens/update_screen_browsertest.cc
@@ -40,19 +40,25 @@
 namespace {
 
 const char kStubWifiGuid[] = "wlan0";
-const std::initializer_list<base::StringPiece> kCheckingForUpdatesDialogPath = {
-    "oobe-update-md", "checking-downloading-update",
-    "checking-for-updates-dialog"};
-const std::initializer_list<base::StringPiece> kUpdatingDialogPath = {
-    "oobe-update-md", "checking-downloading-update", "updating-dialog"};
-const std::initializer_list<base::StringPiece> kUpdatingProgressPath = {
-    "oobe-update-md", "checking-downloading-update", "updating-progress"};
-const std::initializer_list<base::StringPiece> kProgressMessagePath = {
-    "oobe-update-md", "checking-downloading-update", "progress-message"};
-const std::initializer_list<base::StringPiece> kUpdateCompletedDialog = {
-    "oobe-update-md", "checking-downloading-update", "update-complete-dialog"};
-const std::initializer_list<base::StringPiece> kCellularPermissionDialog = {
-    "oobe-update-md", "cellular-permission-dialog"};
+const test::UIPath kCheckingDownloadingUpdate = {"oobe-update",
+                                                 "checking-downloading-update"};
+const test::UIPath kCheckingForUpdatesDialog = {"oobe-update",
+                                                "checking-downloading-update",
+                                                "checking-for-updates-dialog"};
+const test::UIPath kUpdatingDialog = {
+    "oobe-update", "checking-downloading-update", "updating-dialog"};
+const test::UIPath kUpdatingProgress = {
+    "oobe-update", "checking-downloading-update", "updating-progress"};
+const test::UIPath kProgressMessage = {
+    "oobe-update", "checking-downloading-update", "progress-message"};
+const test::UIPath kUpdateCompletedDialog = {
+    "oobe-update", "checking-downloading-update", "update-complete-dialog"};
+const test::UIPath kCellularPermissionDialog = {"oobe-update",
+                                                "cellular-permission-dialog"};
+const test::UIPath kCellularPermissionNext = {"oobe-update",
+                                              "cellular-permission-next"};
+const test::UIPath kCellularPermissionBack = {"oobe-update",
+                                              "cellular-permission-back"};
 
 // These values should be kept in sync with the progress bar values in
 // chrome/browser/chromeos/login/version_updater/version_updater.cc.
@@ -167,12 +173,11 @@
 void UpdateScreenTest::CheckUpdatingDialogComponents(
     const int updating_progress_value,
     const std::string& progress_message_value) {
-  CheckPathVisiblity(kUpdatingDialogPath, true);
+  CheckPathVisiblity(kUpdatingDialog, true);
   test::OobeJS().ExpectEQ(
-      test::GetOobeElementPath(kUpdatingProgressPath) + ".value",
+      test::GetOobeElementPath(kUpdatingProgress) + ".value",
       updating_progress_value);
-  test::OobeJS().ExpectElementText(progress_message_value,
-                                   kProgressMessagePath);
+  test::OobeJS().ExpectElementText(progress_message_value, kProgressMessage);
 }
 
 IN_PROC_BROWSER_TEST_F(UpdateScreenTest, TestUpdateCheckDoneBeforeShow) {
@@ -229,10 +234,10 @@
   update_screen_waiter.set_assert_next_screen();
   update_screen_waiter.Wait();
 
-  test::OobeJS().ExpectVisible("oobe-update-md");
-  test::OobeJS().ExpectVisiblePath(kCheckingForUpdatesDialogPath);
+  test::OobeJS().ExpectVisible("oobe-update");
+  test::OobeJS().ExpectVisiblePath(kCheckingForUpdatesDialog);
   test::OobeJS().ExpectHiddenPath(kCellularPermissionDialog);
-  test::OobeJS().ExpectHiddenPath(kUpdatingDialogPath);
+  test::OobeJS().ExpectHiddenPath(kUpdatingDialog);
 
   status.set_current_operation(update_engine::Operation::IDLE);
   // GetLastStatus() will be called via ExitUpdate() called from
@@ -265,9 +270,9 @@
   update_screen_waiter.set_assert_next_screen();
   update_screen_waiter.Wait();
 
-  test::OobeJS().ExpectVisible("oobe-update-md");
-  test::OobeJS().ExpectVisiblePath(kCheckingForUpdatesDialogPath);
-  test::OobeJS().ExpectHiddenPath(kUpdatingDialogPath);
+  test::OobeJS().ExpectVisible("oobe-update");
+  test::OobeJS().ExpectVisiblePath(kCheckingForUpdatesDialog);
+  test::OobeJS().ExpectHiddenPath(kUpdatingDialog);
   test::OobeJS().ExpectHiddenPath(kCellularPermissionDialog);
   test::OobeJS().ExpectHiddenPath(kUpdateCompletedDialog);
 
@@ -281,8 +286,8 @@
   update_engine_client()->set_default_status(status);
   update_engine_client()->NotifyObserversThatStatusChanged(status);
 
-  test::OobeJS().CreateVisibilityWaiter(true, kUpdatingDialogPath)->Wait();
-  test::OobeJS().ExpectHiddenPath(kCheckingForUpdatesDialogPath);
+  test::OobeJS().CreateVisibilityWaiter(true, kUpdatingDialog)->Wait();
+  test::OobeJS().ExpectHiddenPath(kCheckingForUpdatesDialog);
   test::OobeJS().ExpectHiddenPath(kCellularPermissionDialog);
   test::OobeJS().ExpectHiddenPath(kUpdateCompletedDialog);
 
@@ -364,7 +369,7 @@
   ASSERT_TRUE(version_updater_->GetRebootTimerForTesting()->IsRunning());
   version_updater_->GetRebootTimerForTesting()->FireNow();
 
-  test::OobeJS().ExpectHiddenPath(kUpdatingDialogPath);
+  test::OobeJS().ExpectHiddenPath(kUpdatingDialog);
   test::OobeJS().ExpectVisiblePath(kUpdateCompletedDialog);
 }
 
@@ -454,10 +459,10 @@
   update_screen_waiter.set_assert_next_screen();
   update_screen_waiter.Wait();
 
-  test::OobeJS().ExpectVisible("oobe-update-md");
-  test::OobeJS().ExpectVisiblePath(kCheckingForUpdatesDialogPath);
+  test::OobeJS().ExpectVisible("oobe-update");
+  test::OobeJS().ExpectVisiblePath(kCheckingForUpdatesDialog);
   test::OobeJS().ExpectHiddenPath(kCellularPermissionDialog);
-  test::OobeJS().ExpectHiddenPath(kUpdatingDialogPath);
+  test::OobeJS().ExpectHiddenPath(kUpdatingDialog);
 
   status.set_current_operation(update_engine::Operation::IDLE);
   update_engine_client()->set_default_status(status);
@@ -597,21 +602,19 @@
   update_screen_waiter.set_assert_next_screen();
   update_screen_waiter.Wait();
 
-  test::OobeJS().ExpectVisible("oobe-update-md");
+  test::OobeJS().ExpectVisible("oobe-update");
   test::OobeJS().ExpectVisiblePath(kCellularPermissionDialog);
-  test::OobeJS().ExpectHiddenPath(
-      {"oobe-update-md", "checking-downloading-update"});
+  test::OobeJS().ExpectHiddenPath(kCheckingDownloadingUpdate);
 
-  test::OobeJS().TapOnPath({"oobe-update-md", "cellular-permission-next"});
+  test::OobeJS().TapOnPath(kCellularPermissionNext);
 
   test::OobeJS()
-      .CreateVisibilityWaiter(true,
-                              {"oobe-update-md", "checking-downloading-update"})
+      .CreateVisibilityWaiter(true, kCheckingDownloadingUpdate)
       ->Wait();
 
   test::OobeJS().ExpectHiddenPath(kCellularPermissionDialog);
-  test::OobeJS().ExpectHiddenPath(kCheckingForUpdatesDialogPath);
-  test::OobeJS().ExpectVisiblePath(kUpdatingDialogPath);
+  test::OobeJS().ExpectHiddenPath(kCheckingForUpdatesDialog);
+  test::OobeJS().ExpectVisiblePath(kUpdatingDialog);
 
   status.set_current_operation(update_engine::Operation::UPDATED_NEED_REBOOT);
   version_updater_->UpdateStatusChangedForTesting(status);
@@ -642,12 +645,11 @@
   update_screen_waiter.set_assert_next_screen();
   update_screen_waiter.Wait();
 
-  test::OobeJS().ExpectVisible("oobe-update-md");
+  test::OobeJS().ExpectVisible("oobe-update");
   test::OobeJS().ExpectVisiblePath(kCellularPermissionDialog);
-  test::OobeJS().ExpectHiddenPath(
-      {"oobe-update-md", "checking-downloading-update"});
+  test::OobeJS().ExpectHiddenPath(kCheckingDownloadingUpdate);
 
-  test::OobeJS().ClickOnPath({"oobe-update-md", "cellular-permission-back"});
+  test::OobeJS().ClickOnPath(kCellularPermissionBack);
 
   WaitForScreenResult();
   EXPECT_EQ(UpdateScreen::Result::UPDATE_ERROR, last_screen_result_.value());
diff --git a/chrome/browser/chromeos/login/test/oobe_base_test.cc b/chrome/browser/chromeos/login/test/oobe_base_test.cc
index d948534..a794cfa 100644
--- a/chrome/browser/chromeos/login/test/oobe_base_test.cc
+++ b/chrome/browser/chromeos/login/test/oobe_base_test.cc
@@ -174,7 +174,7 @@
 
 void OobeBaseTest::WaitForSigninScreen() {
   WizardController* wizard_controller = WizardController::default_controller();
-  if (wizard_controller)
+  if (wizard_controller && wizard_controller->is_initialized())
     wizard_controller->SkipToLoginForTesting();
 
   WizardController::SkipPostLoginScreensForTesting();
diff --git a/chrome/browser/chromeos/login/test/oobe_screens_utils.cc b/chrome/browser/chromeos/login/test/oobe_screens_utils.cc
index b51d687..bf15107f 100644
--- a/chrome/browser/chromeos/login/test/oobe_screens_utils.cc
+++ b/chrome/browser/chromeos/login/test/oobe_screens_utils.cc
@@ -65,7 +65,7 @@
 
 void WaitForUpdateScreen() {
   WaitFor(UpdateView::kScreenId);
-  test::OobeJS().CreateVisibilityWaiter(true, {"update"})->Wait();
+  test::OobeJS().CreateVisibilityWaiter(true, {"oobe-update"})->Wait();
 }
 
 void ExitUpdateScreenNoUpdate() {
diff --git a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
index ca8f1a0..a1b8fb4a 100644
--- a/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
+++ b/chrome/browser/chromeos/login/ui/login_display_host_mojo.cc
@@ -73,6 +73,9 @@
   // Preload webui-based OOBE for add user, kiosk apps, etc.
   LoadOobeDialog();
 
+  // Should be created after OobeUI loaded with the dialog.
+  wizard_controller_ = std::make_unique<WizardController>();
+
   GetLoginScreenCertProviderService()->pin_dialog_manager()->AddPinDialogHost(
       &security_token_pin_dialog_host_ash_impl_);
 }
@@ -107,7 +110,8 @@
   // Hide Gaia dialog in case empty list of users switched to a non-empty one.
   // And if the dialog shows login screen.
   if (was_zero_users && user_count_ != 0 && dialog_ && dialog_->IsVisible() &&
-      (!wizard_controller_ || wizard_controller_->login_screen_started())) {
+      (!wizard_controller_->is_initialized() ||
+       wizard_controller_->login_screen_started())) {
     HideOobeDialog();
   }
 }
@@ -191,8 +195,11 @@
   // screens to show.
   ObserveOobeUI();
 
-  if (features::IsOobeScreensPriorityEnabled() && wizard_controller_) {
-    wizard_controller_->AdvanceToScreen(first_screen);
+  if (features::IsOobeScreensPriorityEnabled()) {
+    if (wizard_controller_->is_initialized())
+      wizard_controller_->AdvanceToScreen(first_screen);
+    else
+      wizard_controller_->Init(first_screen);
   } else {
     wizard_controller_ = std::make_unique<WizardController>();
     wizard_controller_->Init(first_screen);
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc
index ec9c3c26..ff0a212 100644
--- a/chrome/browser/chromeos/login/wizard_controller.cc
+++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -353,6 +353,10 @@
         base::Bind(&WizardController::OnAccessibilityStatusChanged,
                    weak_factory_.GetWeakPtr()));
   }
+  if (GetOobeUI()) {
+    // could be null in unit tests.
+    screen_manager_->Init(CreateScreens());
+  }
 }
 
 WizardController::~WizardController() {
@@ -360,7 +364,8 @@
 }
 
 void WizardController::Init(OobeScreenId first_screen) {
-  screen_manager_->Init(CreateScreens());
+  DCHECK(!is_initialized());
+  is_initialized_ = true;
 
   prescribed_enrollment_config_ = g_browser_process->platform_part()
                                       ->browser_policy_connector_chromeos()
diff --git a/chrome/browser/chromeos/login/wizard_controller.h b/chrome/browser/chromeos/login/wizard_controller.h
index 205caa9..caec214 100644
--- a/chrome/browser/chromeos/login/wizard_controller.h
+++ b/chrome/browser/chromeos/login/wizard_controller.h
@@ -97,6 +97,8 @@
   // Zero-Touch Hands-Off Enrollment Flow.
   static bool UsingHandsOffEnrollment();
 
+  bool is_initialized() { return is_initialized_; }
+
   // Shows the first screen defined by |first_screen| or by default if the
   // parameter is empty.
   void Init(OobeScreenId first_screen);
@@ -421,6 +423,8 @@
 
   BaseScreen* hid_screen_ = nullptr;
 
+  bool is_initialized_ = false;
+
   base::WeakPtrFactory<WizardController> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(WizardController);
diff --git a/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.h b/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.h
index 9718caf..03cb8ceeb 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.h
+++ b/chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.h
@@ -30,8 +30,7 @@
                           public network::ResolveHostClientBase {
  public:
   using DnsLatencyRoutineCallback =
-      base::OnceCallback<void(mojom::RoutineVerdict,
-                              const std::vector<mojom::DnsLatencyProblem>&)>;
+      mojom::NetworkDiagnosticsRoutines::DnsLatencyCallback;
 
   DnsLatencyRoutine();
   ~DnsLatencyRoutine() override;
diff --git a/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.cc b/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.cc
new file mode 100644
index 0000000..f0add14c
--- /dev/null
+++ b/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.cc
@@ -0,0 +1,136 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h"
+
+#include <iterator>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/optional.h"
+#include "base/values.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "components/session_manager/core/session_manager.h"
+#include "content/public/browser/storage_partition.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+
+namespace chromeos {
+namespace network_diagnostics {
+namespace {
+
+constexpr char kHostname[] = "ccd-testing-v4.gstatic.com";
+constexpr int kHttpPort = 80;
+// For an explanation of error codes, see "net/base/net_error_list.h".
+constexpr int kRetryResponseCodes[] = {net::ERR_TIMED_OUT,
+                                       net::ERR_DNS_TIMED_OUT};
+
+Profile* GetUserProfile() {
+  // Use sign-in profile if user has not logged in
+  if (session_manager::SessionManager::Get()->IsUserSessionBlocked()) {
+    return ProfileHelper::GetSigninProfile();
+  }
+  // Use primary profile if user is logged in
+  return ProfileManager::GetPrimaryUserProfile();
+}
+
+}  // namespace
+
+DnsResolutionRoutine::DnsResolutionRoutine() {
+  profile_ = GetUserProfile();
+  DCHECK(profile_);
+  network_context_ =
+      content::BrowserContext::GetDefaultStoragePartition(profile_)
+          ->GetNetworkContext();
+  DCHECK(network_context_);
+  set_verdict(mojom::RoutineVerdict::kNotRun);
+}
+
+DnsResolutionRoutine::~DnsResolutionRoutine() = default;
+
+void DnsResolutionRoutine::RunTest(DnsResolutionRoutineCallback callback) {
+  if (!CanRun()) {
+    std::move(callback).Run(verdict(), std::move(problems_));
+    return;
+  }
+  routine_completed_callback_ = std::move(callback);
+  CreateHostResolver();
+  AttemptResolution();
+}
+
+void DnsResolutionRoutine::AnalyzeResultsAndExecuteCallback() {
+  if (!resolved_address_received_) {
+    set_verdict(mojom::RoutineVerdict::kProblem);
+    problems_.emplace_back(mojom::DnsResolutionProblem::kFailedToResolveHost);
+  } else {
+    set_verdict(mojom::RoutineVerdict::kNoProblem);
+  }
+  std::move(routine_completed_callback_).Run(verdict(), std::move(problems_));
+}
+
+void DnsResolutionRoutine::CreateHostResolver() {
+  host_resolver_.reset();
+  network_context()->CreateHostResolver(
+      net::DnsConfigOverrides(), host_resolver_.BindNewPipeAndPassReceiver());
+}
+
+void DnsResolutionRoutine::OnMojoConnectionError() {
+  CreateHostResolver();
+  OnComplete(net::ERR_NAME_NOT_RESOLVED, net::ResolveErrorInfo(net::ERR_FAILED),
+             base::nullopt);
+}
+
+void DnsResolutionRoutine::AttemptResolution() {
+  DCHECK(host_resolver_);
+  DCHECK(!receiver_.is_bound());
+
+  network::mojom::ResolveHostParametersPtr parameters =
+      network::mojom::ResolveHostParameters::New();
+  parameters->dns_query_type = net::DnsQueryType::A;
+  parameters->source = net::HostResolverSource::DNS;
+  parameters->cache_usage =
+      network::mojom::ResolveHostParameters::CacheUsage::DISALLOWED;
+
+  host_resolver_->ResolveHost(net::HostPortPair(kHostname, kHttpPort),
+                              net::NetworkIsolationKey::CreateTransient(),
+                              std::move(parameters),
+                              receiver_.BindNewPipeAndPassRemote());
+  // The host resolver is part of the network service, which may be run inside
+  // the browser process (in-process) or a dedicated utility process
+  // (out-of-process). If the network service crashes, the disconnect handler
+  // below will be invoked. See README in services/network for more information.
+  receiver_.set_disconnect_handler(base::BindOnce(
+      &DnsResolutionRoutine::OnMojoConnectionError, base::Unretained(this)));
+}
+
+void DnsResolutionRoutine::OnComplete(
+    int result,
+    const net::ResolveErrorInfo& resolve_error_info,
+    const base::Optional<net::AddressList>& resolved_addresses) {
+  receiver_.reset();
+
+  bool success = result == net::OK && !resolved_addresses->empty() &&
+                 resolved_addresses.has_value();
+  if (success) {
+    resolved_address_received_ = true;
+    AnalyzeResultsAndExecuteCallback();
+    return;
+  }
+  bool retry =
+      std::find(std::begin(kRetryResponseCodes), std::end(kRetryResponseCodes),
+                result) != std::end(kRetryResponseCodes) &&
+      num_retries_ > 0;
+  if (retry) {
+    num_retries_--;
+    AttemptResolution();
+  } else {
+    AnalyzeResultsAndExecuteCallback();
+  }
+}
+
+}  // namespace network_diagnostics
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h b/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h
new file mode 100644
index 0000000..1e2d5f6
--- /dev/null
+++ b/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h
@@ -0,0 +1,86 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_DNS_RESOLUTION_ROUTINE_H_
+#define CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_DNS_RESOLUTION_ROUTINE_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/optional.h"
+#include "chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_routine.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/cpp/resolve_host_client_base.h"
+#include "services/network/public/mojom/host_resolver.mojom.h"
+
+class Profile;
+
+namespace network {
+namespace mojom {
+class NetworkContext;
+}
+}  // namespace network
+
+namespace chromeos {
+namespace network_diagnostics {
+
+// Tests whether a DNS resolution can be completed successfully.
+class DnsResolutionRoutine : public NetworkDiagnosticsRoutine,
+                             public network::ResolveHostClientBase {
+ public:
+  using DnsResolutionRoutineCallback =
+      mojom::NetworkDiagnosticsRoutines::DnsResolutionCallback;
+
+  DnsResolutionRoutine();
+  ~DnsResolutionRoutine() override;
+
+  // NetworkDiagnosticsRoutine:
+  void AnalyzeResultsAndExecuteCallback() override;
+
+  // network::mojom::ResolveHostClient:
+  void OnComplete(
+      int result,
+      const net::ResolveErrorInfo& resolve_error_info,
+      const base::Optional<net::AddressList>& resolved_addresses) override;
+
+  // Run the core logic of this routine. Set |callback| to
+  // |routine_completed_callback_|, which is to be executed in
+  // AnalyzeResultsAndExecuteCallback().
+  void RunTest(DnsResolutionRoutineCallback callback);
+
+  void set_network_context_for_testing(
+      network::mojom::NetworkContext* network_context) {
+    network_context_ = network_context;
+  }
+  void set_profile_for_testing(Profile* profile) { profile_ = profile; }
+
+  network::mojom::NetworkContext* network_context() { return network_context_; }
+  Profile* profile() { return profile_; }
+
+ private:
+  void CreateHostResolver();
+  void OnMojoConnectionError();
+  void AttemptResolution();
+
+  // Unowned
+  Profile* profile_ = nullptr;
+  // Unowned
+  network::mojom::NetworkContext* network_context_ = nullptr;
+  static constexpr int kTotalNumRetries = 1;
+  int num_retries_ = kTotalNumRetries;
+  bool resolved_address_received_ = false;
+  net::AddressList resolved_addresses_;
+  std::vector<mojom::DnsResolutionProblem> problems_;
+  mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
+  mojo::Remote<network::mojom::HostResolver> host_resolver_;
+  DnsResolutionRoutineCallback routine_completed_callback_;
+
+  DISALLOW_COPY_AND_ASSIGN(DnsResolutionRoutine);
+};
+
+}  // namespace network_diagnostics
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_DNS_RESOLUTION_ROUTINE_H_
diff --git a/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine_unittest.cc b/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine_unittest.cc
new file mode 100644
index 0000000..0fdbe41b
--- /dev/null
+++ b/chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine_unittest.cc
@@ -0,0 +1,226 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h"
+
+#include <deque>
+
+#include "base/test/simple_test_tick_clock.h"
+#include "base/time/time.h"
+#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/session_manager/core/session_manager.h"
+#include "content/public/test/browser_task_environment.h"
+#include "services/network/test/test_network_context.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
+
+namespace chromeos {
+namespace network_diagnostics {
+
+namespace {
+
+const int kFakePortNumber = 1234;
+const char kFakeTestProfile[] = "test";
+
+net::IPEndPoint FakeIPAddress() {
+  return net::IPEndPoint(net::IPAddress::IPv4Localhost(), kFakePortNumber);
+}
+
+class FakeHostResolver : public network::mojom::HostResolver {
+ public:
+  struct DnsResult {
+    DnsResult(int32_t result,
+              net::ResolveErrorInfo resolve_error_info,
+              base::Optional<net::AddressList> resolved_addresses)
+        : result(result),
+          resolve_error_info(resolve_error_info),
+          resolved_addresses(resolved_addresses) {}
+
+    int result;
+    net::ResolveErrorInfo resolve_error_info;
+    base::Optional<net::AddressList> resolved_addresses;
+  };
+
+  FakeHostResolver(mojo::PendingReceiver<network::mojom::HostResolver> receiver,
+                   std::deque<DnsResult*> fake_dns_results)
+      : receiver_(this, std::move(receiver)),
+        fake_dns_results_(std::move(fake_dns_results)) {}
+  ~FakeHostResolver() override {}
+
+  // network::mojom::HostResolver
+  void ResolveHost(const net::HostPortPair& host,
+                   const net::NetworkIsolationKey& network_isolation_key,
+                   network::mojom::ResolveHostParametersPtr optional_parameters,
+                   mojo::PendingRemote<network::mojom::ResolveHostClient>
+                       pending_response_client) override {
+    mojo::Remote<network::mojom::ResolveHostClient> response_client(
+        std::move(pending_response_client));
+    DnsResult* result = fake_dns_results_.front();
+    DCHECK(result);
+    fake_dns_results_.pop_front();
+    response_client->OnComplete(result->result, result->resolve_error_info,
+                                result->resolved_addresses);
+  }
+  void MdnsListen(
+      const net::HostPortPair& host,
+      net::DnsQueryType query_type,
+      mojo::PendingRemote<network::mojom::MdnsListenClient> response_client,
+      MdnsListenCallback callback) override {
+    NOTREACHED();
+  }
+
+ private:
+  mojo::Receiver<network::mojom::HostResolver> receiver_;
+  // Use the list of fake dns results to fake different responses for multiple
+  // calls to the host_resolver's ResolveHost().
+  std::deque<DnsResult*> fake_dns_results_;
+};
+
+class FakeNetworkContext : public network::TestNetworkContext {
+ public:
+  FakeNetworkContext() = default;
+
+  explicit FakeNetworkContext(
+      std::deque<FakeHostResolver::DnsResult*> fake_dns_results)
+      : fake_dns_results_(std::move(fake_dns_results)) {}
+
+  ~FakeNetworkContext() override {}
+
+  // network::TestNetworkContext:
+  void CreateHostResolver(
+      const base::Optional<net::DnsConfigOverrides>& config_overrides,
+      mojo::PendingReceiver<network::mojom::HostResolver> receiver) override {
+    ASSERT_FALSE(resolver_);
+    resolver_ = std::make_unique<FakeHostResolver>(
+        std::move(receiver), std::move(fake_dns_results_));
+  }
+
+ private:
+  std::unique_ptr<FakeHostResolver> resolver_;
+  std::deque<FakeHostResolver::DnsResult*> fake_dns_results_;
+};
+
+}  // namespace
+
+class DnsResolutionRoutineTest : public ::testing::Test {
+ public:
+  DnsResolutionRoutineTest()
+      : profile_manager_(TestingBrowserProcess::GetGlobal()) {
+    session_manager::SessionManager::Get()->SetSessionState(
+        session_manager::SessionState::LOGIN_PRIMARY);
+  }
+
+  void RunTest(
+      mojom::RoutineVerdict expected_routine_verdict,
+      const std::vector<mojom::DnsResolutionProblem>& expected_problems) {
+    dns_resolution_routine_->RunTest(base::BindOnce(
+        &DnsResolutionRoutineTest::CompareVerdict, weak_factory_.GetWeakPtr(),
+        expected_routine_verdict, expected_problems));
+    run_loop_.Run();
+  }
+
+  void CompareVerdict(
+      mojom::RoutineVerdict expected_verdict,
+      const std::vector<mojom::DnsResolutionProblem>& expected_problems,
+      mojom::RoutineVerdict actual_verdict,
+      const std::vector<mojom::DnsResolutionProblem>& actual_problems) {
+    DCHECK(run_loop_.running());
+    EXPECT_EQ(expected_verdict, actual_verdict);
+    EXPECT_EQ(expected_problems, actual_problems);
+    run_loop_.Quit();
+  }
+
+  void SetUpFakeProperties(
+      std::deque<FakeHostResolver::DnsResult*> fake_dns_results) {
+    ASSERT_TRUE(profile_manager_.SetUp());
+
+    fake_network_context_ =
+        std::make_unique<FakeNetworkContext>(std::move(fake_dns_results));
+    test_profile_ = profile_manager_.CreateTestingProfile(kFakeTestProfile);
+  }
+
+  void SetUpDnsResolutionRoutine() {
+    dns_resolution_routine_ = std::make_unique<DnsResolutionRoutine>();
+    dns_resolution_routine_->set_network_context_for_testing(
+        fake_network_context_.get());
+    dns_resolution_routine_->set_profile_for_testing(test_profile_);
+  }
+
+  // Sets up required properties (via fakes) and runs the test.
+  //
+  // Parameters:
+  // |fake_dns_results|: Represents the results of a one or more DNS
+  // resolutions. |expected_routine_verdict|: Represents the expected verdict
+  // reported by this test. |expected_problems|: Represents the expected problem
+  // reported by this test.
+  void SetUpAndRunTest(
+      std::deque<FakeHostResolver::DnsResult*> fake_dns_results,
+      mojom::RoutineVerdict expected_routine_verdict,
+      const std::vector<mojom::DnsResolutionProblem>& expected_problems) {
+    SetUpFakeProperties(std::move(fake_dns_results));
+    SetUpDnsResolutionRoutine();
+    RunTest(expected_routine_verdict, expected_problems);
+  }
+
+ private:
+  content::BrowserTaskEnvironment task_environment_;
+  base::RunLoop run_loop_;
+  session_manager::SessionManager session_manager_;
+  std::unique_ptr<FakeNetworkContext> fake_network_context_;
+  // Unowned
+  Profile* test_profile_;
+  TestingProfileManager profile_manager_;
+  std::unique_ptr<DnsResolutionRoutine> dns_resolution_routine_;
+  base::WeakPtrFactory<DnsResolutionRoutineTest> weak_factory_{this};
+
+  DISALLOW_COPY_AND_ASSIGN(DnsResolutionRoutineTest);
+};
+
+// A passing routine requires an error code of net::OK and a non-empty
+// net::AddressList for the DNS resolution.
+TEST_F(DnsResolutionRoutineTest, TestSuccessfulResolution) {
+  std::deque<FakeHostResolver::DnsResult*> fake_dns_results;
+  auto successful_resolution = std::make_unique<FakeHostResolver::DnsResult>(
+      net::OK, net::ResolveErrorInfo(net::OK),
+      net::AddressList(FakeIPAddress()));
+  fake_dns_results.push_back(successful_resolution.get());
+  SetUpAndRunTest(std::move(fake_dns_results),
+                  mojom::RoutineVerdict::kNoProblem, {});
+}
+
+// Set up the |fake_dns_results| to return a DnsResult with an error code
+// net::ERR_NAME_NOT_RESOLVED faking a failed DNS resolution.
+TEST_F(DnsResolutionRoutineTest, TestResolutionFailure) {
+  std::deque<FakeHostResolver::DnsResult*> fake_dns_results;
+  auto failed_resolution = std::make_unique<FakeHostResolver::DnsResult>(
+      net::ERR_NAME_NOT_RESOLVED,
+      net::ResolveErrorInfo(net::ERR_NAME_NOT_RESOLVED), net::AddressList());
+  fake_dns_results.push_back(failed_resolution.get());
+  SetUpAndRunTest(std::move(fake_dns_results), mojom::RoutineVerdict::kProblem,
+                  {mojom::DnsResolutionProblem::kFailedToResolveHost});
+}
+
+// Set up the |fake_dns_results| to first return a DnsResult with an error code
+// net::ERR_DNS_TIMED_OUT faking a timed out DNS resolution. On the second
+// host resolution attempt, fake a net::OK resolution.
+TEST_F(DnsResolutionRoutineTest, TestSuccessOnRetry) {
+  std::deque<FakeHostResolver::DnsResult*> fake_dns_results;
+  auto timed_out_resolution = std::make_unique<FakeHostResolver::DnsResult>(
+      net::ERR_DNS_TIMED_OUT, net::ResolveErrorInfo(net::ERR_DNS_TIMED_OUT),
+      net::AddressList());
+  fake_dns_results.push_back(timed_out_resolution.get());
+  auto successful_resolution = std::make_unique<FakeHostResolver::DnsResult>(
+      net::OK, net::ResolveErrorInfo(net::OK),
+      net::AddressList(FakeIPAddress()));
+  fake_dns_results.push_back(successful_resolution.get());
+
+  fake_dns_results.push_back(successful_resolution.get());
+  SetUpAndRunTest(std::move(fake_dns_results),
+                  mojom::RoutineVerdict::kNoProblem, {});
+}
+
+}  // namespace network_diagnostics
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_diagnostics/dns_resolver_present_routine.h b/chrome/browser/chromeos/net/network_diagnostics/dns_resolver_present_routine.h
index 4187d9b..b223252 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/dns_resolver_present_routine.h
+++ b/chrome/browser/chromeos/net/network_diagnostics/dns_resolver_present_routine.h
@@ -19,6 +19,9 @@
 // resolution.
 class DnsResolverPresentRoutine : public NetworkDiagnosticsRoutine {
  public:
+  using DnsResolverPresentRoutineCallback =
+      mojom::NetworkDiagnosticsRoutines::DnsResolverPresentCallback;
+
   DnsResolverPresentRoutine();
   ~DnsResolverPresentRoutine() override;
 
@@ -29,8 +32,7 @@
   // Run the core logic of this routine. Set |callback| to
   // |routine_completed_callback_|, which is to be executed in
   // AnalyzeResultsAndExecuteCallback().
-  void RunTest(
-      mojom::NetworkDiagnosticsRoutines::DnsResolverPresentCallback callback);
+  void RunTest(DnsResolverPresentRoutineCallback callback);
 
  private:
   void FetchActiveNetworks();
@@ -47,8 +49,7 @@
   std::vector<mojom::DnsResolverPresentProblem> problems_;
   mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig>
       remote_cros_network_config_;
-  mojom::NetworkDiagnosticsRoutines::DnsResolverPresentCallback
-      routine_completed_callback_;
+  DnsResolverPresentRoutineCallback routine_completed_callback_;
 
   DISALLOW_COPY_AND_ASSIGN(DnsResolverPresentRoutine);
 };
diff --git a/chrome/browser/chromeos/net/network_diagnostics/gateway_can_be_pinged_routine.h b/chrome/browser/chromeos/net/network_diagnostics/gateway_can_be_pinged_routine.h
index febe7614..dcea264b 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/gateway_can_be_pinged_routine.h
+++ b/chrome/browser/chromeos/net/network_diagnostics/gateway_can_be_pinged_routine.h
@@ -21,9 +21,8 @@
 // Tests whether a device can ping all the gateways it is connected to.
 class GatewayCanBePingedRoutine : public NetworkDiagnosticsRoutine {
  public:
-  using GatewayCanBePingedRoutineCallback = base::OnceCallback<void(
-      mojom::RoutineVerdict,
-      const std::vector<mojom::GatewayCanBePingedProblem>&)>;
+  using GatewayCanBePingedRoutineCallback =
+      mojom::NetworkDiagnosticsRoutines::GatewayCanBePingedCallback;
 
   explicit GatewayCanBePingedRoutine(
       chromeos::DebugDaemonClient* debug_daemon_client);
diff --git a/chrome/browser/chromeos/net/network_diagnostics/has_secure_wifi_connection_routine.h b/chrome/browser/chromeos/net/network_diagnostics/has_secure_wifi_connection_routine.h
index c435db25..993c467 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/has_secure_wifi_connection_routine.h
+++ b/chrome/browser/chromeos/net/network_diagnostics/has_secure_wifi_connection_routine.h
@@ -18,9 +18,8 @@
 // Tests whether the WiFi connection uses a secure encryption method.
 class HasSecureWiFiConnectionRoutine : public NetworkDiagnosticsRoutine {
  public:
-  using HasSecureWiFiConnectionRoutineCallback = base::OnceCallback<void(
-      mojom::RoutineVerdict,
-      const std::vector<mojom::HasSecureWiFiConnectionProblem>&)>;
+  using HasSecureWiFiConnectionRoutineCallback =
+      mojom::NetworkDiagnosticsRoutines::HasSecureWiFiConnectionCallback;
 
   HasSecureWiFiConnectionRoutine();
   ~HasSecureWiFiConnectionRoutine() override;
diff --git a/chrome/browser/chromeos/net/network_diagnostics/lan_connectivity_routine.h b/chrome/browser/chromeos/net/network_diagnostics/lan_connectivity_routine.h
index c5ca5ff..e65c727 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/lan_connectivity_routine.h
+++ b/chrome/browser/chromeos/net/network_diagnostics/lan_connectivity_routine.h
@@ -22,7 +22,7 @@
 class LanConnectivityRoutine : public NetworkDiagnosticsRoutine {
  public:
   using LanConnectivityRoutineCallback =
-      base::OnceCallback<void(mojom::RoutineVerdict)>;
+      mojom::NetworkDiagnosticsRoutines::LanConnectivityCallback;
 
   LanConnectivityRoutine();
   ~LanConnectivityRoutine() override;
diff --git a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics.mojom b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics.mojom
index b24711c4..bbb103e 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics.mojom
+++ b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics.mojom
@@ -66,6 +66,13 @@
   kSignificantlyAboveThreshold,
 };
 
+// Messages related to the DnsResolution routine.
+[Extensible]
+enum DnsResolutionProblem {
+  // The routine was unable to successfully resolve the test host
+  kFailedToResolveHost,
+};
+
 // This interface is to be used by any clients that need to run specific
 // network-related diagnostics. Expected clients of this interface are
 // NetworkHealth, cros_healthd, and a connectivity diagnostics Web UI (to name
@@ -97,4 +104,8 @@
   // Tests whether the DNS latency is below an acceptable threshold.
   DnsLatency() => (RoutineVerdict verdict,
       array<DnsLatencyProblem> problem);
+
+  // Tests whether a DNS resolution can be completed successfully.
+  DnsResolution() => (RoutineVerdict verdict,
+      array<DnsResolutionProblem> problems);
 };
diff --git a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc
index 2210098..18adfe5 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc
+++ b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.h"
+#include "chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h"
 #include "chrome/browser/chromeos/net/network_diagnostics/dns_resolver_present_routine.h"
 #include "chrome/browser/chromeos/net/network_diagnostics/gateway_can_be_pinged_routine.h"
 #include "chrome/browser/chromeos/net/network_diagnostics/has_secure_wifi_connection_routine.h"
@@ -64,5 +65,10 @@
   dns_latency_routine.RunTest(std::move(callback));
 }
 
+void NetworkDiagnosticsImpl::DnsResolution(DnsResolutionCallback callback) {
+  DnsResolutionRoutine dns_resolution_routine;
+  dns_resolution_routine.RunTest(std::move(callback));
+}
+
 }  // namespace network_diagnostics
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h
index 7bae2e9..d2c277a 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h
+++ b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h
@@ -32,6 +32,7 @@
       HasSecureWiFiConnectionCallback callback) override;
   void DnsResolverPresent(DnsResolverPresentCallback callback) override;
   void DnsLatency(DnsLatencyCallback callback) override;
+  void DnsResolution(DnsResolutionCallback callback) override;
 
  private:
   mojo::ReceiverSet<mojom::NetworkDiagnosticsRoutines> receivers_;
diff --git a/chrome/browser/chromeos/net/network_diagnostics/signal_strength_routine.h b/chrome/browser/chromeos/net/network_diagnostics/signal_strength_routine.h
index 55f1343f0..f05e2c9 100644
--- a/chrome/browser/chromeos/net/network_diagnostics/signal_strength_routine.h
+++ b/chrome/browser/chromeos/net/network_diagnostics/signal_strength_routine.h
@@ -18,9 +18,8 @@
 // Tests the Network Interface Controller (NIC) signal strength.
 class SignalStrengthRoutine : public NetworkDiagnosticsRoutine {
  public:
-  using SignalStrengthRoutineCallback = base::OnceCallback<void(
-      mojom::RoutineVerdict,
-      const std::vector<mojom::SignalStrengthProblem>&)>;
+  using SignalStrengthRoutineCallback =
+      mojom::NetworkDiagnosticsRoutines::SignalStrengthCallback;
 
   SignalStrengthRoutine();
   ~SignalStrengthRoutine() override;
diff --git a/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc b/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc
index a5facbb..b33057b 100644
--- a/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc
+++ b/chrome/browser/chromeos/policy/fuzzer/policy_fuzzer.cc
@@ -7,6 +7,7 @@
 #include "base/check_op.h"
 #include "base/command_line.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/i18n/icu_util.h"
 #include "base/logging.h"
 #include "base/memory/weak_ptr.h"
 #include "base/path_service.h"
@@ -42,6 +43,7 @@
     CHECK(scoped_temp_dir.CreateUniqueTempDir());
     CHECK(base::PathService::Override(chrome::DIR_USER_DATA,
                                       scoped_temp_dir.GetPath()));
+    CHECK(base::i18n::InitializeICU());
   }
 
   base::ScopedTempDir scoped_temp_dir;
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 bd767de..511ad6c 100644
--- a/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
+++ b/chrome/browser/chromeos/power/ml/user_activity_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/chromeos/power/ml/idle_event_notifier.h"
+#include "chrome/browser/chromeos/power/ml/smart_dim/ml_agent.h"
 #include "chrome/browser/chromeos/power/ml/smart_dim/model.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_event.pb.h"
 #include "chrome/browser/chromeos/power/ml/user_activity_ukm_logger.h"
@@ -33,6 +34,8 @@
 #include "chromeos/dbus/power/fake_power_manager_client.h"
 #include "chromeos/dbus/power_manager/idle.pb.h"
 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h"
+#include "chromeos/services/machine_learning/public/cpp/fake_service_connection.h"
+#include "chromeos/services/machine_learning/public/cpp/service_connection.h"
 #include "components/session_manager/session_manager_types.h"
 #include "components/ukm/content/source_url_recorder.h"
 #include "components/ukm/test_ukm_recorder.h"
@@ -166,7 +169,8 @@
   DISALLOW_COPY_AND_ASSIGN(FakeSmartDimModel);
 };
 
-class UserActivityManagerTest : public ChromeRenderViewHostTestHarness {
+class UserActivityManagerTest : public ChromeRenderViewHostTestHarness,
+                                public ::testing::WithParamInterface<bool> {
  public:
   UserActivityManagerTest()
       : ChromeRenderViewHostTestHarness(
@@ -187,6 +191,10 @@
         &delegate_, &user_activity_detector_, PowerManagerClient::Get(),
         &session_manager_, observer.InitWithNewPipeAndPassReceiver(),
         &fake_user_manager_, &model_);
+
+    machine_learning::ServiceConnection::UseFakeServiceConnectionForTesting(
+        &fake_service_connection_);
+    use_new_ml_agent_ = GetParam();
   }
 
   void TearDown() override {
@@ -325,6 +333,8 @@
   // Only used to get SourceIds for URLs.
   ukm::TestAutoSetUkmRecorder ukm_recorder_;
   TabActivitySimulator tab_activity_simulator_;
+  machine_learning::FakeServiceConnectionImpl fake_service_connection_;
+  bool use_new_ml_agent_;
 
   const GURL url1_ = GURL("https://example1.com/");
   const GURL url2_ = GURL("https://example2.com/");
@@ -342,7 +352,7 @@
 
 // After an idle event, we have a ui::Event, we should expect one
 // UserActivityEvent.
-TEST_F(UserActivityManagerTest, LogAfterIdleEvent) {
+TEST_P(UserActivityManagerTest, LogAfterIdleEvent) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -369,7 +379,7 @@
 }
 
 // Get a user event before an idle event, we should not log it.
-TEST_F(UserActivityManagerTest, LogBeforeIdleEvent) {
+TEST_P(UserActivityManagerTest, LogBeforeIdleEvent) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -383,7 +393,7 @@
 
 // Get a user event, then an idle event, then another user event,
 // we should log the last one.
-TEST_F(UserActivityManagerTest, LogSecondEvent) {
+TEST_P(UserActivityManagerTest, LogSecondEvent) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -411,7 +421,7 @@
 }
 
 // Log multiple events.
-TEST_F(UserActivityManagerTest, LogMultipleEvents) {
+TEST_P(UserActivityManagerTest, LogMultipleEvents) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -496,7 +506,7 @@
   EXPECT_EQ(2, events[3].features().previous_negative_actions_count());
 }
 
-TEST_F(UserActivityManagerTest, UserCloseLid) {
+TEST_P(UserActivityManagerTest, UserCloseLid) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -511,7 +521,7 @@
   EXPECT_TRUE(events.empty());
 }
 
-TEST_F(UserActivityManagerTest, PowerChangeActivity) {
+TEST_P(UserActivityManagerTest, PowerChangeActivity) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -537,7 +547,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_F(UserActivityManagerTest, VideoActivity) {
+TEST_P(UserActivityManagerTest, VideoActivity) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -561,7 +571,7 @@
 
 // System remains idle, screen is dimmed then turned off, and system is finally
 // suspended.
-TEST_F(UserActivityManagerTest, SystemIdleSuspend) {
+TEST_P(UserActivityManagerTest, SystemIdleSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -590,7 +600,7 @@
 
 // System remains idle, screen is dimmed then turned off, but system is not
 // suspended.
-TEST_F(UserActivityManagerTest, SystemIdleNotSuspend) {
+TEST_P(UserActivityManagerTest, SystemIdleNotSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -609,7 +619,7 @@
 
 // Test system idle interrupt by user activity.
 // We should only observe user activity.
-TEST_F(UserActivityManagerTest, SystemIdleInterrupted) {
+TEST_P(UserActivityManagerTest, SystemIdleInterrupted) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -639,7 +649,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_F(UserActivityManagerTest, ScreenLockNoSuspend) {
+TEST_P(UserActivityManagerTest, ScreenLockNoSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -652,7 +662,7 @@
   ASSERT_EQ(0U, events.size());
 }
 
-TEST_F(UserActivityManagerTest, ScreenLockWithSuspend) {
+TEST_P(UserActivityManagerTest, ScreenLockWithSuspend) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -679,7 +689,7 @@
 
 // As we log when SuspendImminent is received, sleep duration from SuspendDone
 // doesn't make any difference.
-TEST_F(UserActivityManagerTest, SuspendIdleShortSleepDuration) {
+TEST_P(UserActivityManagerTest, SuspendIdleShortSleepDuration) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -703,7 +713,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_F(UserActivityManagerTest, SuspendLidClosed) {
+TEST_P(UserActivityManagerTest, SuspendLidClosed) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -726,7 +736,7 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_F(UserActivityManagerTest, SuspendOther) {
+TEST_P(UserActivityManagerTest, SuspendOther) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -750,7 +760,7 @@
 }
 
 // Test feature extraction.
-TEST_F(UserActivityManagerTest, FeatureExtraction) {
+TEST_P(UserActivityManagerTest, FeatureExtraction) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -800,7 +810,7 @@
   EXPECT_FALSE(features.screen_locked_initially());
 }
 
-TEST_F(UserActivityManagerTest, ManagedDevice) {
+TEST_P(UserActivityManagerTest, ManagedDevice) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -817,7 +827,7 @@
   EXPECT_EQ(UserActivityEvent::Features::MANAGED, features.device_management());
 }
 
-TEST_F(UserActivityManagerTest, DimAndOffDelays) {
+TEST_P(UserActivityManagerTest, DimAndOffDelays) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -836,7 +846,7 @@
   EXPECT_EQ(1, features.dim_to_screen_off_sec());
 }
 
-TEST_F(UserActivityManagerTest, DimDelays) {
+TEST_P(UserActivityManagerTest, DimDelays) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -855,7 +865,7 @@
   EXPECT_TRUE(!features.has_dim_to_screen_off_sec());
 }
 
-TEST_F(UserActivityManagerTest, OffDelays) {
+TEST_P(UserActivityManagerTest, OffDelays) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -876,7 +886,7 @@
 
 // Screen is off when idle event is reported. No subsequent change in screen
 // state.
-TEST_F(UserActivityManagerTest, InitialScreenOff) {
+TEST_P(UserActivityManagerTest, InitialScreenOff) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -908,7 +918,7 @@
 
 // Screen is off when idle event is reported. No subsequent change in screen
 // state.
-TEST_F(UserActivityManagerTest, InitialScreenStateFlipped) {
+TEST_P(UserActivityManagerTest, InitialScreenStateFlipped) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -941,7 +951,7 @@
 
 // Screen is off when idle event is reported. No subsequent change in screen
 // state.
-TEST_F(UserActivityManagerTest, ScreenOffStateChanged) {
+TEST_P(UserActivityManagerTest, ScreenOffStateChanged) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -970,14 +980,25 @@
   EqualEvent(expected_event, events[0].event());
 }
 
-TEST_F(UserActivityManagerTest, ScreenDimDeferredWithFinalEvent) {
+TEST_P(UserActivityManagerTest, ScreenDimDeferredWithFinalEvent) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+  if (use_new_ml_agent_) {
+    SmartDimMlAgent::GetInstance()->ResetForTesting();
+    scoped_feature_list.InitWithFeaturesAndParameters(
+        {{features::kUserActivityPrediction, params},
+         {features::kSmartDimNewMlAgent, {{}}}},
+        {});
+  } else {
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+  }
 
+  // sigmoid(0.43) * 100 = 60
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{0.43});
   model_.set_inactivity_score(60);
   model_.set_decision_threshold(65);
 
@@ -988,8 +1009,12 @@
   ReportUserActivity(nullptr);
   EXPECT_TRUE(should_defer);
 
-  std::string histogram("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(histogram, 1);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCompleteDuration", 1);
+
+  if (use_new_ml_agent_)
+    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
+                                       0, 1);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   ASSERT_EQ(1U, events.size());
@@ -1011,14 +1036,25 @@
   EqualModelPrediction(expected_prediction, events[0].model_prediction());
 }
 
-TEST_F(UserActivityManagerTest, ScreenDimDeferredWithoutFinalEvent) {
+TEST_P(UserActivityManagerTest, ScreenDimDeferredWithoutFinalEvent) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+  if (use_new_ml_agent_) {
+    SmartDimMlAgent::GetInstance()->ResetForTesting();
+    scoped_feature_list.InitWithFeaturesAndParameters(
+        {{features::kUserActivityPrediction, params},
+         {features::kSmartDimNewMlAgent, {{}}}},
+        {});
+  } else {
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+  }
 
+  // sigmoid(0.43) * 100 = 60
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{0.43});
   model_.set_inactivity_score(60);
   model_.set_decision_threshold(65);
 
@@ -1028,8 +1064,12 @@
   task_environment()->RunUntilIdle();
   EXPECT_TRUE(should_defer);
 
-  std::string histogram("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(histogram, 1);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCompleteDuration", 1);
+
+  if (use_new_ml_agent_)
+    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
+                                       0, 1);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   EXPECT_TRUE(events.empty());
@@ -1037,14 +1077,25 @@
 
 // Tests the cancellation of a Smart Dim decision request, immediately after it
 // has been requested.
-TEST_F(UserActivityManagerTest, ScreenDimRequestCanceled) {
+TEST_P(UserActivityManagerTest, ScreenDimRequestCanceled) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+  if (use_new_ml_agent_) {
+    SmartDimMlAgent::GetInstance()->ResetForTesting();
+    scoped_feature_list.InitWithFeaturesAndParameters(
+        {{features::kUserActivityPrediction, params},
+         {features::kSmartDimNewMlAgent, {{}}}},
+        {});
+  } else {
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+  }
 
+  // sigmoid(0.43) * 100 = 60
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{0.43});
   model_.set_inactivity_score(60);
   model_.set_decision_threshold(65);
 
@@ -1057,10 +1108,14 @@
   task_environment()->RunUntilIdle();
   EXPECT_FALSE(should_defer);
 
-  std::string hist_complete("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(hist_complete, 0);
-  std::string hist_cancel("PowerML.SmartDimModel.RequestCanceledDuration");
-  histogram_tester.ExpectTotalCount(hist_cancel, 1);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCompleteDuration", 0);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCanceledDuration", 1);
+
+  if (use_new_ml_agent_)
+    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
+                                       0, 1);
 
   // Since the pending SmartDim decision request was canceled, we shouldn't
   // have any UserActivityEvent generated.
@@ -1070,14 +1125,25 @@
 
 // Tests the cancellation of a Smart Dim decision request, when two idle events
 // occur in quick succession. This verifies that only one request is serviced.
-TEST_F(UserActivityManagerTest, ScreenDimConsecutiveRequests) {
+TEST_P(UserActivityManagerTest, ScreenDimConsecutiveRequests) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+  if (use_new_ml_agent_) {
+    SmartDimMlAgent::GetInstance()->ResetForTesting();
+    scoped_feature_list.InitWithFeaturesAndParameters(
+        {{features::kUserActivityPrediction, params},
+         {features::kSmartDimNewMlAgent, {{}}}},
+        {});
+  } else {
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+  }
 
+  // sigmoid(0.43) * 100 = 60
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{0.43});
   model_.set_inactivity_score(60);
   model_.set_decision_threshold(65);
 
@@ -1090,10 +1156,14 @@
   ReportUserActivity(nullptr);
   EXPECT_NE(should_defer_1, should_defer_2);
 
-  std::string hist_complete("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(hist_complete, 1);
-  std::string hist_cancel("PowerML.SmartDimModel.RequestCanceledDuration");
-  histogram_tester.ExpectTotalCount(hist_cancel, 1);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCompleteDuration", 1);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCanceledDuration", 1);
+
+  if (use_new_ml_agent_)
+    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
+                                       0, 2);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   ASSERT_EQ(1U, events.size());
@@ -1115,14 +1185,25 @@
   EqualModelPrediction(expected_prediction, events[0].model_prediction());
 }
 
-TEST_F(UserActivityManagerTest, ScreenDimNotDeferred) {
+TEST_P(UserActivityManagerTest, ScreenDimNotDeferred) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
-      {"dim_threshold", base::NumberToString(0.5)}};
+      {"dim_threshold", base::NumberToString(0.0)}};
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+  if (use_new_ml_agent_) {
+    SmartDimMlAgent::GetInstance()->ResetForTesting();
+    scoped_feature_list.InitWithFeaturesAndParameters(
+        {{features::kUserActivityPrediction, params},
+         {features::kSmartDimNewMlAgent, {{}}}},
+        {});
+  } else {
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+  }
 
+  // sigmoid(0.43) * 100 = 60
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{0.43});
   model_.set_inactivity_score(60);
   model_.set_decision_threshold(50);
 
@@ -1133,8 +1214,12 @@
   ReportUserActivity(nullptr);
   EXPECT_FALSE(should_defer);
 
-  std::string histogram("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(histogram, 1);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCompleteDuration", 1);
+
+  if (use_new_ml_agent_)
+    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
+                                       0, 1);
 
   const std::vector<UserActivityEvent>& events = delegate_.events();
   ASSERT_EQ(1U, events.size());
@@ -1148,16 +1233,27 @@
   EqualModelPrediction(expected_prediction, events[0].model_prediction());
 }
 
-TEST_F(UserActivityManagerTest, TwoScreenDimImminentWithEventInBetween) {
+TEST_P(UserActivityManagerTest, TwoScreenDimImminentWithEventInBetween) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
-      {"dim_threshold", base::NumberToString(0.5)}};
+      {"dim_threshold", base::NumberToString(0.0)}};
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+  if (use_new_ml_agent_) {
+    SmartDimMlAgent::GetInstance()->ResetForTesting();
+    scoped_feature_list.InitWithFeaturesAndParameters(
+        {{features::kUserActivityPrediction, params},
+         {features::kSmartDimNewMlAgent, {{}}}},
+        {});
+  } else {
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+  }
   model_.set_decision_threshold(50);
 
   // 1st ScreenDimImminent gets deferred
+  // sigmoid(-0.4) * 100 = 40
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{-0.4});
   model_.set_inactivity_score(40);
 
   const IdleEventNotifier::ActivityData data;
@@ -1171,14 +1267,21 @@
                 base::TimeDelta::FromSeconds(3));
 
   // 2nd ScreenDimImminent is not deferred despite model score says so.
+  // sigmoid(-1.35) * 100 = 20
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{-1.35});
   model_.set_inactivity_score(20);
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10));
   ReportIdleEvent(data, &should_defer);
   task_environment()->RunUntilIdle();
   EXPECT_FALSE(should_defer);
 
-  std::string histogram("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(histogram, 2);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCompleteDuration", 2);
+
+  if (use_new_ml_agent_)
+    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
+                                       0, 2);
 
   // Log when a SuspendImminent is received
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(20));
@@ -1224,16 +1327,27 @@
   EqualModelPrediction(expected_prediction2, events[1].model_prediction());
 }
 
-TEST_F(UserActivityManagerTest, TwoScreenDimImminentWithoutEventInBetween) {
+TEST_P(UserActivityManagerTest, TwoScreenDimImminentWithoutEventInBetween) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
-      {"dim_threshold", base::NumberToString(0.5)}};
+      {"dim_threshold", base::NumberToString(0.0)}};
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      features::kUserActivityPrediction, params);
+  if (use_new_ml_agent_) {
+    SmartDimMlAgent::GetInstance()->ResetForTesting();
+    scoped_feature_list.InitWithFeaturesAndParameters(
+        {{features::kUserActivityPrediction, params},
+         {features::kSmartDimNewMlAgent, {{}}}},
+        {});
+  } else {
+    scoped_feature_list.InitAndEnableFeatureWithParameters(
+        features::kUserActivityPrediction, params);
+  }
   model_.set_decision_threshold(50);
 
   // 1st ScreenDimImminent gets deferred
+  // sigmoid(-0.4) * 100 = 40
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{-0.4});
   model_.set_inactivity_score(40);
   const IdleEventNotifier::ActivityData data;
   bool should_defer = false;
@@ -1242,14 +1356,21 @@
   EXPECT_TRUE(should_defer);
 
   // 2nd ScreenDimImminent is not deferred despite model score says so.
+  // sigmoid(-1.35) * 100 = 20
+  fake_service_connection_.SetOutputValue(std::vector<int64_t>{1L},
+                                          std::vector<double>{-1.35});
   model_.set_inactivity_score(20);
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(10));
   ReportIdleEvent(data, &should_defer);
   task_environment()->RunUntilIdle();
   EXPECT_FALSE(should_defer);
 
-  std::string histogram("PowerML.SmartDimModel.RequestCompleteDuration");
-  histogram_tester.ExpectTotalCount(histogram, 2);
+  histogram_tester.ExpectTotalCount(
+      "PowerML.SmartDimModel.RequestCompleteDuration", 2);
+
+  if (use_new_ml_agent_)
+    histogram_tester.ExpectBucketCount("PowerML.SmartDimComponent.WorkerType",
+                                       0, 2);
 
   // Log when a SuspendImminent is received
   task_environment()->FastForwardBy(base::TimeDelta::FromSeconds(20));
@@ -1290,7 +1411,7 @@
   EqualModelPrediction(expected_prediction2, events[0].model_prediction());
 }
 
-TEST_F(UserActivityManagerTest, ModelError) {
+TEST_P(UserActivityManagerTest, ModelError) {
   base::HistogramTester histogram_tester;
   const std::map<std::string, std::string> params = {
       {"dim_threshold", "0.651"}};
@@ -1332,7 +1453,7 @@
 }
 
 // Test is flaky. See https://crbug.com/938055.
-TEST_F(UserActivityManagerTest, DISABLED_BasicTabs) {
+TEST_P(UserActivityManagerTest, DISABLED_BasicTabs) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1364,7 +1485,7 @@
 }
 
 // Test is flaky. See https://crbug.com/938141.
-TEST_F(UserActivityManagerTest, DISABLED_MultiBrowsersAndTabs) {
+TEST_P(UserActivityManagerTest, DISABLED_MultiBrowsersAndTabs) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1411,7 +1532,7 @@
   tab_strip_model3->CloseAllTabs();
 }
 
-TEST_F(UserActivityManagerTest, Incognito) {
+TEST_P(UserActivityManagerTest, Incognito) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1439,7 +1560,7 @@
   tab_strip_model->CloseAllTabs();
 }
 
-TEST_F(UserActivityManagerTest, NoOpenTabs) {
+TEST_P(UserActivityManagerTest, NoOpenTabs) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(features::kUserActivityPrediction);
 
@@ -1460,6 +1581,10 @@
   EXPECT_FALSE(features.has_has_form_entry());
 }
 
+INSTANTIATE_TEST_SUITE_P(UserActivityManagerTestInstantiation,
+                         UserActivityManagerTest,
+                         testing::Values(false, true));
+
 }  // namespace ml
 }  // namespace power
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/printers_sync_bridge.cc b/chrome/browser/chromeos/printing/printers_sync_bridge.cc
index 5ee0e3b4..5518cd84 100644
--- a/chrome/browser/chromeos/printing/printers_sync_bridge.cc
+++ b/chrome/browser/chromeos/printing/printers_sync_bridge.cc
@@ -62,19 +62,15 @@
 bool ResolveInvalidPpdReference(sync_pb::PrinterSpecifics* specifics) {
   auto* ppd_ref = specifics->mutable_ppd_reference();
 
-  if (!ppd_ref->autoconf()) {
-    base::UmaHistogramBoolean("Printing.CUPS.InvalidPpdResolved", false);
+  if (!ppd_ref->autoconf())
     return false;
-  }
 
   if (!ppd_ref->has_user_supplied_ppd_url() &&
       !ppd_ref->has_effective_make_and_model()) {
-    base::UmaHistogramBoolean("Printing.CUPS.InvalidPpdResolved", false);
     return false;
   }
 
   ppd_ref->clear_autoconf();
-  base::UmaHistogramBoolean("Printing.CUPS.InvalidPpdResolved", true);
   return true;
 }
 
diff --git a/chrome/browser/chromeos/printing/zeroconf_printer_detector_unittest.cc b/chrome/browser/chromeos/printing/zeroconf_printer_detector_unittest.cc
index 8c2451c9..b944552d 100644
--- a/chrome/browser/chromeos/printing/zeroconf_printer_detector_unittest.cc
+++ b/chrome/browser/chromeos/printing/zeroconf_printer_detector_unittest.cc
@@ -430,7 +430,11 @@
   }
 
  protected:
-  base::test::TaskEnvironment task_environment_;
+  // Runs pending tasks regardless of delay.
+  void CompleteTasks() { task_environment_.FastForwardUntilNoTasksRemain(); }
+
+  base::test::TaskEnvironment task_environment_{
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
 
   // Device listers fakes.  These are initialized when the test is constructed.
   // These pointers don't involve ownership; ownership of the listers starts
@@ -461,44 +465,44 @@
 TEST_F(ZeroconfPrinterDetectorTest, SingleIppPrinter) {
   ipp_lister_->Announce("Printer1");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer1", ServiceType::kIpp)});
 }
 
 TEST_F(ZeroconfPrinterDetectorTest, SingleIppsPrinter) {
   ipps_lister_->Announce("Printer2");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer2", ServiceType::kIpps)});
 }
 
 TEST_F(ZeroconfPrinterDetectorTest, SingleIppEverywherePrinter) {
   ippe_lister_->Announce("Printer3");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer3", ServiceType::kIppE)});
 }
 
 TEST_F(ZeroconfPrinterDetectorTest, SingleIppsEverywherePrinter) {
   ippse_lister_->Announce("Printer4");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer4", ServiceType::kIppsE)});
 }
 
 TEST_F(ZeroconfPrinterDetectorTest, SingleSocketPrinter) {
   socket_lister_->Announce("Printer5");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kSocket)});
 }
 
 // Test that an announce after the detector creation shows up as a printer.
 TEST_F(ZeroconfPrinterDetectorTest, AnnounceAfterDetectorCreation) {
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ippse_lister_->Announce("Printer4");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer4", ServiceType::kIppsE)});
 }
 
@@ -507,7 +511,7 @@
 TEST_F(ZeroconfPrinterDetectorTest, StableIds) {
   ipp_lister_->Announce("Printer1");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_FALSE(printers_found_callbacks_.empty());
   ASSERT_EQ(1U, printers_found_callbacks_.back().size());
   // Grab the id when it's an IPPS printer We should continue to get the same id
@@ -516,20 +520,20 @@
 
   // Remove it as an IPP printer, add it as an IPPS printer.
   ipp_lister_->Remove("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_TRUE(printers_found_callbacks_.back().empty());
   ipps_lister_->Announce("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_EQ(1U, printers_found_callbacks_.back().size());
   // Id should be the same.
   ASSERT_EQ(id, printers_found_callbacks_.back()[0].printer.id());
 
   // Remove it as an IPPS printer, add it as an IPP-Everywhere printer.
   ipps_lister_->Remove("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_TRUE(printers_found_callbacks_.back().empty());
   ippe_lister_->Announce("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_EQ(1U, printers_found_callbacks_.back().size());
   // Id should be the same.
   ASSERT_EQ(id, printers_found_callbacks_.back()[0].printer.id());
@@ -537,20 +541,20 @@
   // Remove it as an IPP-Everywhere printer, add it as an IPPS-Everywhere
   // printer.
   ippe_lister_->Remove("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_TRUE(printers_found_callbacks_.back().empty());
   ippse_lister_->Announce("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_EQ(1U, printers_found_callbacks_.back().size());
   // Id should be the same.
   ASSERT_EQ(id, printers_found_callbacks_.back()[0].printer.id());
 
   // Remove it as an IPPS-Everywhere printer, add it as a socket printer.
   ippse_lister_->Remove("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_TRUE(printers_found_callbacks_.back().empty());
   socket_lister_->Announce("Printer1");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ASSERT_EQ(1U, printers_found_callbacks_.back().size());
   // Id should be the same.
   ASSERT_EQ(id, printers_found_callbacks_.back()[0].printer.id());
@@ -564,14 +568,14 @@
   ipp_lister_->Announce("Printer8");
   ipp_lister_->Announce("Printer9");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIpp),
                      MakeExpectedPrinter("Printer6", ServiceType::kIpp),
                      MakeExpectedPrinter("Printer7", ServiceType::kIpp),
                      MakeExpectedPrinter("Printer8", ServiceType::kIpp),
                      MakeExpectedPrinter("Printer9", ServiceType::kIpp)});
   ipp_lister_->Remove("Printer7");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIpp),
                      MakeExpectedPrinter("Printer6", ServiceType::kIpp),
                      MakeExpectedPrinter("Printer8", ServiceType::kIpp),
@@ -589,31 +593,31 @@
   ippse_lister_->Announce("Printer5");
   socket_lister_->Announce("Printer5");
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   // IPPS-E is highest priority.
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIppsE)});
   ippse_lister_->Remove("Printer5");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   // IPP-E is highest remaining priority.
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIppE)});
 
   ippe_lister_->Remove("Printer5");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   // IPPS is highest remaining priority.
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIpps)});
 
   ipps_lister_->Remove("Printer5");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   // IPP is highest remaining priority.
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kIpp)});
 
   ipp_lister_->Remove("Printer5");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   // Socket is only remaining entry.
   ExpectPrintersAre({MakeExpectedPrinter("Printer5", ServiceType::kSocket)});
 
   socket_lister_->Remove("Printer5");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   // No entries left.
   ExpectPrintersEmpty();
 }
@@ -632,7 +636,7 @@
   socket_lister_->Announce("Printer11");
 
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer6", ServiceType::kIpp),
                      MakeExpectedPrinter("Printer7", ServiceType::kIpps),
                      MakeExpectedPrinter("Printer8", ServiceType::kIppE),
@@ -642,7 +646,7 @@
 
   ipps_lister_->Clear();
 
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   // With the IPPS lister cleared, all printers should be cleared.
   ExpectPrintersEmpty();
 
@@ -651,12 +655,12 @@
 
   // Just for kicks, announce something new at this point.
   ipps_lister_->Announce("Printer12");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer12", ServiceType::kIpps)});
 
   // Clear out the IPPS lister, which will clear all printers too.
   ipps_lister_->Clear();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
 
   // With the IPPS lister cleared, Printer12 should disappear.
   ExpectPrintersEmpty();
@@ -673,7 +677,7 @@
   socket_lister_->Announce("Printer16");
 
   CreateDetector();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer12", ServiceType::kIpps),
                      MakeExpectedPrinter("Printer13", ServiceType::kIpps),
                      MakeExpectedPrinter("Printer14", ServiceType::kIppsE),
@@ -682,7 +686,7 @@
 
   ippe_lister_->Announce("Printer13");
   ipp_lister_->Announce("Printer17");
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersAre({MakeExpectedPrinter("Printer12", ServiceType::kIpps),
                      MakeExpectedPrinter("Printer13", ServiceType::kIppE),
                      MakeExpectedPrinter("Printer14", ServiceType::kIppsE),
@@ -693,9 +697,25 @@
   ipp_lister_->Remove("NonexistantPrinter");
   ipps_lister_->Remove("Printer12");
   ipps_lister_->Clear();
-  task_environment_.RunUntilIdle();
+  CompleteTasks();
   ExpectPrintersEmpty();
 }
 
+// Verify tasks are cleaned up properly when class is destroyed.
+TEST_F(ZeroconfPrinterDetectorTest, DestroyedWithTasksPending) {
+  CreateDetector();
+  // Cause a callback to be queued.
+  ipp_lister_->Announce("TestPrinter");
+  // Run listers but don't run the delayed tasks.
+  task_environment_.RunUntilIdle();
+
+  // Delete the detector.
+  detector_.reset();
+
+  // Clear task queues where we would crash if we did something wrong.
+  task_environment_.FastForwardUntilNoTasksRemain();
+  SUCCEED();
+}
+
 }  // namespace
 }  // namespace chromeos
diff --git a/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc b/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc
index 38bacbe..4984aef 100644
--- a/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc
+++ b/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.cc
@@ -244,15 +244,15 @@
   MigrateDataReductionProxyOffProxyPrefs(profile_prefs);
 }
 
-void DataReductionProxyChromeSettings::SetIgnoreLongTermBlackListRules(
-    bool ignore_long_term_black_list_rules) {
+void DataReductionProxyChromeSettings::SetIgnoreLongTermBlockListRules(
+    bool ignore_long_term_block_list_rules) {
   // |previews_service| is null if |profile_| is off the record.
   PreviewsService* previews_service =
       PreviewsServiceFactory::GetForProfile(profile_);
   if (previews_service && previews_service->previews_ui_service()) {
     previews_service->previews_ui_service()
-        ->SetIgnoreLongTermBlackListForServerPreviews(
-            ignore_long_term_black_list_rules);
+        ->SetIgnoreLongTermBlockListForServerPreviews(
+            ignore_long_term_block_list_rules);
   }
 }
 
diff --git a/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h b/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h
index a8508fc..781c8d7 100644
--- a/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h
+++ b/chrome/browser/data_reduction_proxy/data_reduction_proxy_chrome_settings.h
@@ -74,8 +74,8 @@
   // Public for testing.
   void MigrateDataReductionProxyOffProxyPrefs(PrefService* prefs);
 
-  void SetIgnoreLongTermBlackListRules(
-      bool ignore_long_term_black_list_rules) override;
+  void SetIgnoreLongTermBlockListRules(
+      bool ignore_long_term_block_list_rules) override;
 
   // Builds an instance of DataReductionProxyData from the given |handle| and
   // |headers|.
diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc
index 1b441f5c..98ab93a 100644
--- a/chrome/browser/devtools/devtools_file_helper.cc
+++ b/chrome/browser/devtools/devtools_file_helper.cc
@@ -17,7 +17,7 @@
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/devtools/devtools_file_watcher.h"
 #include "chrome/browser/download/download_prefs.h"
@@ -245,9 +245,9 @@
 
   const base::Value* path_value;
   if (file_map->Get(base::MD5String(url), &path_value)) {
-    // Ignore base::GetValueAsFilePath() failure since we handle empty
-    // |initial_path| below.
-    ignore_result(base::GetValueAsFilePath(*path_value, &initial_path));
+    base::Optional<base::FilePath> path = util::ValueToFilePath(*path_value);
+    if (path)
+      initial_path = std::move(*path);
   }
 
   if (initial_path.empty()) {
@@ -301,7 +301,7 @@
   DictionaryPrefUpdate update(profile_->GetPrefs(),
                               prefs::kDevToolsEditedFiles);
   base::DictionaryValue* files_map = update.Get();
-  files_map->SetKey(base::MD5String(url), base::CreateFilePathValue(path));
+  files_map->SetKey(base::MD5String(url), util::FilePathToValue(path));
   std::string file_system_path = path.AsUTF8Unsafe();
   callback.Run(file_system_path);
   file_task_runner_->PostTask(FROM_HERE, BindOnce(&WriteToFile, path, content));
diff --git a/chrome/browser/devtools/devtools_sanity_browsertest.cc b/chrome/browser/devtools/devtools_sanity_browsertest.cc
index 02df905..2c5d47d 100644
--- a/chrome/browser/devtools/devtools_sanity_browsertest.cc
+++ b/chrome/browser/devtools/devtools_sanity_browsertest.cc
@@ -216,7 +216,7 @@
 
 class DevToolsSanityTest : public InProcessBrowserTest {
  public:
-  DevToolsSanityTest() : window_(NULL) {}
+  DevToolsSanityTest() : window_(nullptr) {}
 
   void SetUpOnMainThread() override {
     host_resolver()->AddRule("*", "127.0.0.1");
@@ -618,7 +618,7 @@
 
 class WorkerDevToolsSanityTest : public InProcessBrowserTest {
  public:
-  WorkerDevToolsSanityTest() : window_(NULL) {}
+  WorkerDevToolsSanityTest() : window_(nullptr) {}
 
  protected:
   class WorkerCreationObserver : public DevToolsAgentHostObserver {
diff --git a/chrome/browser/diagnostics/diagnostics_controller.cc b/chrome/browser/diagnostics/diagnostics_controller.cc
index 42a7889..d25885d 100644
--- a/chrome/browser/diagnostics/diagnostics_controller.cc
+++ b/chrome/browser/diagnostics/diagnostics_controller.cc
@@ -26,7 +26,7 @@
   return base::Singleton<DiagnosticsController>::get();
 }
 
-DiagnosticsController::DiagnosticsController() : writer_(NULL) {}
+DiagnosticsController::DiagnosticsController() : writer_(nullptr) {}
 
 DiagnosticsController::~DiagnosticsController() {}
 
diff --git a/chrome/browser/download/android/chrome_duplicate_download_infobar_delegate.cc b/chrome/browser/download/android/chrome_duplicate_download_infobar_delegate.cc
index c1f447e..2ed22921 100644
--- a/chrome/browser/download/android/chrome_duplicate_download_infobar_delegate.cc
+++ b/chrome/browser/download/android/chrome_duplicate_download_infobar_delegate.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "chrome/browser/download/android/download_controller.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/ui/android/infobars/duplicate_download_infobar.h"
@@ -26,10 +27,14 @@
     download::PathValidationResult result,
     const base::FilePath& target_path) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (result == download::PathValidationResult::SUCCESS)
-    callback.Run(DownloadConfirmationResult::CONFIRMED, target_path);
-  else
-    callback.Run(DownloadConfirmationResult::FAILED, base::FilePath());
+  if (result == download::PathValidationResult::SUCCESS) {
+    callback.Run(DownloadConfirmationResult::CONFIRMED, target_path,
+                 base::nullopt /*download_schedule*/);
+
+  } else {
+    callback.Run(DownloadConfirmationResult::FAILED, base::FilePath(),
+                 base::nullopt /*download_schedule*/);
+  }
 }
 
 }  // namespace
@@ -101,7 +106,8 @@
     return true;
 
   file_selected_callback_.Run(DownloadConfirmationResult::CANCELED,
-                              base::FilePath());
+                              base::FilePath(),
+                              base::nullopt /*download_schedule*/);
   return true;
 }
 
diff --git a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java
index d688cc1..00f1f19 100644
--- a/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java
+++ b/chrome/browser/download/android/java/src/org/chromium/chrome/browser/download/DownloadDialogBridge.java
@@ -254,6 +254,22 @@
         PrefServiceBridge.getInstance().setInteger(Pref.PROMPT_FOR_DOWNLOAD_ANDROID, status);
     }
 
+    /**
+     * @return The prompt status for download later dialog.
+     */
+    @DownloadLaterPromptStatus
+    public static int getDownloadLaterPromptStatus() {
+        return PrefServiceBridge.getInstance().getInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS);
+    }
+
+    /**
+     * Sets the prompt status for download later dialog.
+     * @param status New status to update the download later prmopt status.
+     */
+    public static void setDownloadLaterPromptStatus(@DownloadLaterPromptStatus int status) {
+        PrefServiceBridge.getInstance().setInteger(Pref.DOWNLOAD_LATER_PROMPT_STATUS, status);
+    }
+
     @NativeMethods
     interface Natives {
         void onComplete(long nativeDownloadDialogBridge, DownloadDialogBridge caller,
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc
index b28c711..9a46e59a 100644
--- a/chrome/browser/download/chrome_download_manager_delegate.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate.cc
@@ -254,17 +254,18 @@
   switch (result.location_result) {
     case DownloadLocationDialogResult::USER_CONFIRMED:
       callback.Run(DownloadConfirmationResult::CONFIRMED_WITH_DIALOG,
-                   result.file_path);
+                   result.file_path, std::move(result.download_schedule));
       break;
     case DownloadLocationDialogResult::USER_CANCELED:
-      callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
+      callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath(),
+                   base::nullopt);
       break;
     case DownloadLocationDialogResult::DUPLICATE_DIALOG:
       // TODO(xingliu): Figure out the dialog behavior on multiple downloads.
       // Currently we just let other downloads continue, which doesn't make
       // sense.
       callback.Run(DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-                   result.file_path);
+                   result.file_path, std::move(result.download_schedule));
       break;
   }
 }
@@ -851,6 +852,8 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!download->IsTransient());
 
+// TODO(xingliu): We should abstract a DownloadFilePicker interface and make all
+// platform use it.
 #if defined(OS_ANDROID)
   content::WebContents* web_contents =
       content::DownloadItemUtils::GetWebContents(download);
@@ -858,20 +861,21 @@
     if (reason == DownloadConfirmationReason::SAVE_AS) {
       // If this is a 'Save As' download, just run without confirmation.
       callback.Run(DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-                   suggested_path);
+                   suggested_path, base::nullopt /*download_schedule*/);
     } else if (!web_contents ||
                reason == DownloadConfirmationReason::UNEXPECTED) {
       // If there are no web_contents and there are no errors (ie. location
       // dialog is only being requested because of a user preference), continue.
       if (reason == DownloadConfirmationReason::PREFERENCE) {
         callback.Run(DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-                     suggested_path);
+                     suggested_path, base::nullopt /*download_schedule*/);
         return;
       }
 
       if (reason == DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE) {
         OnDownloadCanceled(download, true /* has_no_external_storage */);
-        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
+        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath(),
+                     base::nullopt /*download_schedule*/);
         return;
       }
 
@@ -880,13 +884,15 @@
       // gets killed, and user tries to resume a download while another app has
       // created the target file (not the temporary .crdownload file).
       OnDownloadCanceled(download, false /* has_no_external_storage */);
-      callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
+      callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath(),
+                   base::nullopt /*download_schedule*/);
     } else if (reason == DownloadConfirmationReason::TARGET_CONFLICT) {
       // If there is a file that already has the same name, try to generate a
       // unique name for the new download (ie. "image (1).png" vs "image.png").
       base::FilePath download_dir;
       if (!base::android::GetDownloadsDirectory(&download_dir)) {
-        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
+        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath(),
+                     base::nullopt /*download_schedule*/);
         return;
       }
 
@@ -941,7 +947,8 @@
 
       case DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE:
         OnDownloadCanceled(download, true /* has_no_external_storage */);
-        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
+        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath(),
+                     base::nullopt /*download_schedule*/);
         return;
 
       case DownloadConfirmationReason::PREFERENCE:
@@ -957,7 +964,7 @@
 
       case DownloadConfirmationReason::SAVE_AS:
         callback.Run(DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-                     suggested_path);
+                     suggested_path, base::nullopt /*download_schedule*/);
         return;
 
       case DownloadConfirmationReason::TARGET_CONFLICT:
@@ -975,7 +982,8 @@
       // created the target file (not the temporary .crdownload file).
       case DownloadConfirmationReason::UNEXPECTED:
         OnDownloadCanceled(download, false /* has_no_external_storage */);
-        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath());
+        callback.Run(DownloadConfirmationResult::CANCELED, base::FilePath(),
+                     base::nullopt /*download_schedule*/);
         return;
     }
   }
@@ -999,7 +1007,7 @@
     const DownloadTargetDeterminerDelegate::ConfirmationCallback& callback,
     DownloadConfirmationResult result,
     const base::FilePath& virtual_path) {
-  callback.Run(result, virtual_path);
+  callback.Run(result, virtual_path, base::nullopt /*download_schedule*/);
   if (!file_picker_callbacks_.empty()) {
     base::OnceClosure callback = std::move(file_picker_callbacks_.front());
     base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1055,10 +1063,11 @@
     // If user chose not to show download location dialog, uses current unique
     // target path.
     callback.Run(DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-                 target_path);
+                 target_path, base::nullopt /*download_schedule*/);
   } else {
     // If the name generation failed, fail the download.
-    callback.Run(DownloadConfirmationResult::FAILED, base::FilePath());
+    callback.Run(DownloadConfirmationResult::FAILED, base::FilePath(),
+                 base::nullopt /*download_schedule*/);
   }
 }
 
diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
index 4635e27..9e656ee0 100644
--- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/files/file_util.h"
 #include "base/guid.h"
 #include "base/location.h"
+#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -100,11 +101,7 @@
   ~MockWebContentsDelegate() override {}
 };
 
-// Google Mock action that posts a task to the current message loop that invokes
-// the first argument of the mocked method as a callback. Said argument must be
-// a base::Callback<void(ParamType0, ParamType1)>. |result0| and |result1| must
-// be of ParamType0 and ParamType1 respectively and will be bound as such.
-//
+// Post a task on the current thread and forward all 3 parameters.
 // Example:
 //    class FooClass {
 //     public:
@@ -112,11 +109,12 @@
 //    };
 //    ...
 //    EXPECT_CALL(mock_fooclass_instance, Foo(callback))
-//      .WillOnce(ScheduleCallback2(false, "hello"));
+//      .WillOnce(ScheduleCallback3(false, "hello", base::nullopt));
 //
-ACTION_P2(ScheduleCallback2, result0, result1) {
+
+ACTION_P3(ScheduleCallback3, result0, result1, result2) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
-      FROM_HERE, base::BindOnce(arg0, result0, result1));
+      FROM_HERE, base::BindOnce(arg0, result0, result1, result2));
 }
 
 // Struct for holding the result of calling DetermineDownloadTarget.
@@ -501,7 +499,7 @@
 }
 
 // Determine download target for |download_item| after enabling active content
-// download blocking with the |parameters| enabled. Verify |extension|,
+// download blocking with the |parameers| enabled. Verify |extension|,
 // |interrupt_reason| and |mixed_content_status|. Used by
 // BlockedAsActiveContent_ tests.
 void ChromeDownloadManagerDelegateTest::VerifyMixedContentExtensionOverride(
@@ -567,8 +565,9 @@
     base::FilePath user_selected_path(GetPathInDownloadDir("bar/baz.txt"));
     EXPECT_CALL(*delegate(), RequestConfirmation(save_as_download.get(),
                                                  expected_prompt_path, _, _))
-        .WillOnce(WithArg<3>(ScheduleCallback2(
-            DownloadConfirmationResult::CONFIRMED, user_selected_path)));
+        .WillOnce(
+            WithArg<3>(ScheduleCallback3(DownloadConfirmationResult::CONFIRMED,
+                                         user_selected_path, base::nullopt)));
     DetermineDownloadTarget(save_as_download.get(), &result);
     EXPECT_EQ(user_selected_path, result.target_path);
     VerifyAndClearExpectations();
@@ -581,8 +580,9 @@
     base::FilePath expected_prompt_path(GetPathInDownloadDir("bar/foo.txt"));
     EXPECT_CALL(*delegate(), RequestConfirmation(save_as_download.get(),
                                                  expected_prompt_path, _, _))
-        .WillOnce(WithArg<3>(ScheduleCallback2(
-            DownloadConfirmationResult::CANCELED, base::FilePath())));
+        .WillOnce(
+            WithArg<3>(ScheduleCallback3(DownloadConfirmationResult::CANCELED,
+                                         base::FilePath(), base::nullopt)));
     DetermineDownloadTarget(save_as_download.get(), &result);
     VerifyAndClearExpectations();
   }
@@ -604,8 +604,9 @@
     base::FilePath expected_prompt_path(GetPathInDownloadDir("foo.txt"));
     EXPECT_CALL(*delegate(), RequestConfirmation(save_as_download.get(),
                                                  expected_prompt_path, _, _))
-        .WillOnce(WithArg<3>(ScheduleCallback2(
-            DownloadConfirmationResult::CANCELED, base::FilePath())));
+        .WillOnce(
+            WithArg<3>(ScheduleCallback3(DownloadConfirmationResult::CANCELED,
+                                         base::FilePath(), base::nullopt)));
     DetermineDownloadTarget(save_as_download.get(), &result);
     VerifyAndClearExpectations();
   }
@@ -631,8 +632,9 @@
   EXPECT_CALL(
       *delegate(),
       RequestConfirmation(_, _, DownloadConfirmationReason::TARGET_CONFLICT, _))
-      .WillOnce(WithArg<3>(ScheduleCallback2(
-          DownloadConfirmationResult::CONFIRMED, kExpectedPath)));
+      .WillOnce(
+          WithArg<3>(ScheduleCallback3(DownloadConfirmationResult::CONFIRMED,
+                                       kExpectedPath, base::nullopt)));
   DetermineDownloadTarget(download_item.get(), &result);
   EXPECT_EQ(download::DownloadItem::TARGET_DISPOSITION_PROMPT,
             result.disposition);
@@ -718,8 +720,9 @@
   EXPECT_CALL(
       *delegate(),
       RequestConfirmation(_, _, DownloadConfirmationReason::TARGET_CONFLICT, _))
-      .WillOnce(WithArg<3>(ScheduleCallback2(
-          DownloadConfirmationResult::CONFIRMED, kExpectedPath)));
+      .WillOnce(
+          WithArg<3>(ScheduleCallback3(DownloadConfirmationResult::CONFIRMED,
+                                       kExpectedPath, base::nullopt)));
 
   pref_service()->SetInteger(
       prefs::kDownloadRestrictions,
@@ -1237,11 +1240,15 @@
 namespace {
 // Verify the file picker confirmation result matches |expected_result|. Run
 // |completion_closure| on completion.
-void VerifyFilePickerConfirmation(DownloadConfirmationResult expected_result,
-                                  base::RepeatingClosure completion_closure,
-                                  DownloadConfirmationResult result,
-                                  const base::FilePath& virtual_path) {
+void VerifyFilePickerConfirmation(
+    DownloadConfirmationResult expected_result,
+    base::RepeatingClosure completion_closure,
+    DownloadConfirmationResult result,
+    const base::FilePath& virtual_path,
+    base::Optional<download::DownloadSchedule> download_schedule) {
   ASSERT_EQ(result, expected_result);
+  ASSERT_FALSE(download_schedule)
+      << "DownloadSchedule is only used on Android.";
   std::move(completion_closure).Run();
 }
 }  // namespace
@@ -1729,99 +1736,6 @@
 }  // namespace
 
 TEST_F(ChromeDownloadManagerDelegateTest, RequestConfirmation_Android) {
-  // TODO(xingliu): Delete this test when download location change feature
-  // flag is deleted.
-  base::test::ScopedFeatureList scoped_list;
-  scoped_list.InitAndDisableFeature(features::kDownloadsLocationChange);
-  EXPECT_FALSE(
-      base::FeatureList::IsEnabled(features::kDownloadsLocationChange));
-
-  enum class WebContents { AVAILABLE, NONE };
-  enum class ExpectPath { FULL, EMPTY };
-  enum class ExpectInfoBar { YES, NO };
-  struct {
-    DownloadConfirmationReason confirmation_reason;
-    DownloadConfirmationResult expected_result;
-    WebContents web_contents;
-    ExpectInfoBar info_bar;
-    ExpectPath path;
-  } kTestCases[] = {
-      {DownloadConfirmationReason::TARGET_PATH_NOT_WRITEABLE,
-       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
-       ExpectInfoBar::NO, ExpectPath::EMPTY},
-
-      {DownloadConfirmationReason::NAME_TOO_LONG,
-       DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-       WebContents::AVAILABLE, ExpectInfoBar::NO, ExpectPath::FULL},
-
-      {DownloadConfirmationReason::TARGET_NO_SPACE,
-       DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-       WebContents::AVAILABLE, ExpectInfoBar::NO, ExpectPath::FULL},
-
-      {DownloadConfirmationReason::SAVE_AS,
-       DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-       WebContents::AVAILABLE, ExpectInfoBar::NO, ExpectPath::FULL},
-
-      // This case results in an infobar. The logic above dismisses the infobar
-      // and counts it for testing. The functionality of the infobar is not
-      // tested here other than that dimssing the infobar is treated as a user
-      // initiated cancellation.
-      {DownloadConfirmationReason::TARGET_CONFLICT,
-       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
-       ExpectInfoBar::YES, ExpectPath::EMPTY},
-
-      {DownloadConfirmationReason::TARGET_CONFLICT,
-       DownloadConfirmationResult::CANCELED, WebContents::NONE,
-       ExpectInfoBar::NO, ExpectPath::EMPTY},
-
-      {DownloadConfirmationReason::UNEXPECTED,
-       DownloadConfirmationResult::CANCELED, WebContents::AVAILABLE,
-       ExpectInfoBar::NO, ExpectPath::EMPTY},
-  };
-
-  EXPECT_CALL(*delegate(), RequestConfirmation(_, _, _, _))
-      .WillRepeatedly(Invoke(
-          delegate(),
-          &TestChromeDownloadManagerDelegate::RequestConfirmationConcrete));
-  InfoBarService::CreateForWebContents(web_contents());
-  base::FilePath fake_path = GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
-  GURL url("http://example.com");
-  AndroidDownloadInfobarCounter infobar_counter(web_contents());
-
-  for (const auto& test_case : kTestCases) {
-    std::unique_ptr<download::MockDownloadItem> download_item =
-        CreateActiveDownloadItem(1);
-    content::DownloadItemUtils::AttachInfo(
-        download_item.get(), profile(),
-        test_case.web_contents == WebContents::AVAILABLE ? web_contents()
-                                                         : nullptr);
-    EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(url));
-    infobar_counter.CheckAndResetInfobarCount();
-
-    base::RunLoop loop;
-    const auto callback = base::Bind(
-        [](const base::Closure& quit_closure,
-           DownloadConfirmationResult expected_result,
-           const base::FilePath& expected_path,
-           DownloadConfirmationResult actual_result,
-           const base::FilePath& actual_path) {
-          EXPECT_EQ(expected_result, actual_result);
-          EXPECT_EQ(expected_path, actual_path);
-          quit_closure.Run();
-        },
-        loop.QuitClosure(), test_case.expected_result,
-        test_case.path == ExpectPath::FULL ? fake_path : base::FilePath());
-    delegate()->RequestConfirmation(download_item.get(), fake_path,
-                                    test_case.confirmation_reason, callback);
-    loop.Run();
-
-    EXPECT_EQ(test_case.info_bar == ExpectInfoBar::YES ? 1 : 0,
-              infobar_counter.CheckAndResetInfobarCount());
-  }
-}
-
-TEST_F(ChromeDownloadManagerDelegateTest,
-       RequestConfirmation_Android_WithLocationChangeEnabled) {
   DeleteContents();
   SetContents(CreateTestWebContents());
 
@@ -1841,6 +1755,7 @@
     WebContents web_contents;
     DownloadLocationDialogType dialog_type;
     ExpectPath path;
+    base::Optional<download::DownloadSchedule> download_schedule;
   } kTestCases[] = {
       // SAVE_AS
       {DownloadConfirmationReason::SAVE_AS,
@@ -1901,10 +1816,9 @@
           &TestChromeDownloadManagerDelegate::RequestConfirmationConcrete));
   base::FilePath fake_path = GetPathInDownloadDir(FILE_PATH_LITERAL("foo.txt"));
   GURL url("http://example.com");
-  TestDownloadDialogBridge* location_dialog_bridge =
-      new TestDownloadDialogBridge();
+  TestDownloadDialogBridge* dialog_bridge = new TestDownloadDialogBridge();
   delegate()->SetDownloadDialogBridgeForTesting(
-      static_cast<DownloadDialogBridge*>(location_dialog_bridge));
+      static_cast<DownloadDialogBridge*>(dialog_bridge));
 
   for (const auto& test_case : kTestCases) {
     std::unique_ptr<download::MockDownloadItem> download_item =
@@ -1914,29 +1828,33 @@
         test_case.web_contents == WebContents::AVAILABLE ? web_contents()
                                                          : nullptr);
     EXPECT_CALL(*download_item, GetURL()).WillRepeatedly(ReturnRef(url));
-    location_dialog_bridge->ResetStoredVariables();
+    dialog_bridge->ResetStoredVariables();
 
     base::RunLoop loop;
     const auto callback = base::BindRepeating(
         [](const base::RepeatingClosure& quit_closure,
            DownloadConfirmationResult expected_result,
            const base::FilePath& expected_path,
+           base::Optional<download::DownloadSchedule> expected_schedule,
            DownloadConfirmationResult actual_result,
-           const base::FilePath& actual_path) {
+           const base::FilePath& actual_path,
+           base::Optional<download::DownloadSchedule> download_schedule) {
           EXPECT_EQ(expected_result, actual_result);
           EXPECT_EQ(expected_path, actual_path);
+          EXPECT_EQ(expected_schedule, download_schedule);
           quit_closure.Run();
         },
         loop.QuitClosure(), test_case.expected_result,
-        test_case.path == ExpectPath::FULL ? fake_path : base::FilePath());
+        test_case.path == ExpectPath::FULL ? fake_path : base::FilePath(),
+        test_case.download_schedule);
     delegate()->RequestConfirmation(download_item.get(), fake_path,
                                     test_case.confirmation_reason, callback);
     loop.Run();
 
     EXPECT_EQ(
         test_case.dialog_type != DownloadLocationDialogType::NO_DIALOG ? 1 : 0,
-        location_dialog_bridge->GetDialogShownCount());
-    EXPECT_EQ(test_case.dialog_type, location_dialog_bridge->GetDialogType());
+        dialog_bridge->GetDialogShownCount());
+    EXPECT_EQ(test_case.dialog_type, dialog_bridge->GetDialogType());
 
     EXPECT_CALL(*download_item, GetState())
         .WillRepeatedly(Return(DownloadItem::COMPLETE));
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc
index a996e15..b4c6ef8 100644
--- a/chrome/browser/download/download_prefs.cc
+++ b/chrome/browser/download/download_prefs.cc
@@ -36,6 +36,7 @@
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
+#include "components/download/public/common/download_features.h"
 #include "components/download/public/common/download_item.h"
 #include "components/policy/core/browser/url_blacklist_manager.h"
 #include "components/pref_registry/pref_registry_syncable.h"
@@ -303,6 +304,14 @@
       prefs::kPromptForDownloadAndroid,
       static_cast<int>(download_prompt_status),
       user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+
+  if (base::FeatureList::IsEnabled(download::features::kDownloadLater)) {
+    registry->RegisterIntegerPref(
+        prefs::kDownloadLaterPromptStatus,
+        static_cast<int>(DownloadLaterPromptStatus::SHOW_INITIAL),
+        user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+  }
+
   registry->RegisterBooleanPref(
       prefs::kShowMissingSdCardErrorAndroid,
       base::FeatureList::IsEnabled(features::kDownloadsLocationChange));
diff --git a/chrome/browser/download/download_prefs_unittest.cc b/chrome/browser/download/download_prefs_unittest.cc
index 33b288a..e556311 100644
--- a/chrome/browser/download/download_prefs_unittest.cc
+++ b/chrome/browser/download/download_prefs_unittest.cc
@@ -6,9 +6,11 @@
 
 #include "base/files/file_path.h"
 #include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/download/download_prompt_status.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_profile.h"
+#include "components/download/public/common/download_features.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
 #include "components/safe_browsing/core/file_type_policies.h"
@@ -40,18 +42,29 @@
   content::BrowserTaskEnvironment task_environment_;
   base::HistogramTester histogram_tester;
 
+#ifdef OS_ANDROID
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(download::features::kDownloadLater);
+#endif  // OS_ANDROID
+
   // Download prefs are registered when creating the profile.
   TestingProfile profile;
   DownloadPrefs prefs(&profile);
 
 #ifdef OS_ANDROID
-  // Download prompt pref should be registered correctly.
+  // Download prompt prefs should be registered correctly.
   histogram_tester.ExpectBucketCount("MobileDownload.DownloadPromptStatus",
                                      DownloadPromptStatus::SHOW_INITIAL, 1);
   int prompt_status = profile.GetTestingPrefService()->GetInteger(
       prefs::kPromptForDownloadAndroid);
   EXPECT_EQ(prompt_status,
             static_cast<int>(DownloadPromptStatus::SHOW_INITIAL));
+
+  int download_later_prompt_status =
+      profile.GetTestingPrefService()->GetInteger(
+          prefs::kDownloadLaterPromptStatus);
+  EXPECT_EQ(download_later_prompt_status,
+            static_cast<int>(DownloadLaterPromptStatus::SHOW_INITIAL));
 #endif  // OS_ANDROID
 }
 
diff --git a/chrome/browser/download/download_prompt_status.h b/chrome/browser/download/download_prompt_status.h
index 97d27282..9c6fecb 100644
--- a/chrome/browser/download/download_prompt_status.h
+++ b/chrome/browser/download/download_prompt_status.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PROMPT_STATUS_H_
 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PROMPT_STATUS_H_
 
-// The status of the download prompt.
+// The status of the download location prompt.
 // A Java counterpart will be generated for this enum.
 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.download
 enum class DownloadPromptStatus {
@@ -15,4 +15,14 @@
   MAX_VALUE
 };
 
+// The status of the download later prompt.
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.download
+enum class DownloadLaterPromptStatus {
+  SHOW_INITIAL,     // Show the prompt because it hasn't been shown before.
+  SHOW_PREFERENCE,  // Show the prompt because user indicated preference.
+  DONT_SHOW,        // Don't show the prompt because user indicated preference.
+  MAX_VALUE
+};
+
 #endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_PROMPT_STATUS_H_
diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc
index 06445db..b5bb5e0 100644
--- a/chrome/browser/download/download_target_determiner.cc
+++ b/chrome/browser/download/download_target_determiner.cc
@@ -524,12 +524,14 @@
 
 void DownloadTargetDeterminer::RequestConfirmationDone(
     DownloadConfirmationResult result,
-    const base::FilePath& virtual_path) {
+    const base::FilePath& virtual_path,
+    base::Optional<download::DownloadSchedule> download_schedule) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK(!download_->IsTransient());
   DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe();
 #if defined(OS_ANDROID)
   is_checking_dialog_confirmed_path_ = false;
+  download_schedule_ = std::move(download_schedule);
 #endif
   if (result == DownloadConfirmationResult::CANCELED) {
     RecordDownloadCancelReason(DownloadCancelReason::kTargetConfirmationResult);
@@ -980,6 +982,7 @@
   target_info->mime_type = mime_type_;
   target_info->is_filetype_handled_safely = is_filetype_handled_safely_;
   target_info->mixed_content_status = mixed_content_status_;
+  target_info->download_schedule = std::move(download_schedule_);
 
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
diff --git a/chrome/browser/download/download_target_determiner.h b/chrome/browser/download/download_target_determiner.h
index aa217e8..3dc27593 100644
--- a/chrome/browser/download/download_target_determiner.h
+++ b/chrome/browser/download/download_target_determiner.h
@@ -206,8 +206,10 @@
 
   // Callback invoked after the file picker completes. Cancels the download if
   // the user cancels the file picker.
-  void RequestConfirmationDone(DownloadConfirmationResult result,
-                               const base::FilePath& virtual_path);
+  void RequestConfirmationDone(
+      DownloadConfirmationResult result,
+      const base::FilePath& virtual_path,
+      base::Optional<download::DownloadSchedule> download_schedule);
 
   // Up until this point, the path that was used is considered to be a virtual
   // path. This step determines the local file system path corresponding to this
@@ -356,6 +358,7 @@
   DownloadTargetDeterminerDelegate* delegate_;
   CompletionCallback completion_callback_;
   base::CancelableTaskTracker history_tracker_;
+  base::Optional<download::DownloadSchedule> download_schedule_;
 
   base::WeakPtrFactory<DownloadTargetDeterminer> weak_ptr_factory_{this};
 
diff --git a/chrome/browser/download/download_target_determiner_delegate.h b/chrome/browser/download/download_target_determiner_delegate.h
index 24dcc14..6b723e3 100644
--- a/chrome/browser/download/download_target_determiner_delegate.h
+++ b/chrome/browser/download/download_target_determiner_delegate.h
@@ -8,11 +8,13 @@
 #include <string>
 
 #include "base/callback_forward.h"
+#include "base/optional.h"
 #include "chrome/browser/download/download_confirmation_reason.h"
 #include "chrome/browser/download/download_confirmation_result.h"
 #include "components/download/public/common/download_danger_type.h"
 #include "components/download/public/common/download_item.h"
 #include "components/download/public/common/download_path_reservation_tracker.h"
+#include "components/download/public/common/download_schedule.h"
 
 namespace base {
 class FilePath;
@@ -48,8 +50,10 @@
   //    selection, then this parameter will be the empty path. On Chrome OS,
   //    this path may contain virtual mount points if the user chose a virtual
   //    path (e.g. Google Drive).
-  typedef base::Callback<void(DownloadConfirmationResult,
-                              const base::FilePath& virtual_path)>
+  typedef base::Callback<void(
+      DownloadConfirmationResult,
+      const base::FilePath& virtual_path,
+      base::Optional<download::DownloadSchedule> download_schedule)>
       ConfirmationCallback;
 
   // Callback to be invoked when DetermineLocalPath() completes. The argument
diff --git a/chrome/browser/download/download_target_determiner_unittest.cc b/chrome/browser/download/download_target_determiner_unittest.cc
index d38a2174..4261adb 100644
--- a/chrome/browser/download/download_target_determiner_unittest.cc
+++ b/chrome/browser/download/download_target_determiner_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/files/file_path.h"
 #include "base/location.h"
 #include "base/observer_list.h"
+#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
@@ -19,7 +20,7 @@
 #include "base/strings/string_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/download/chrome_download_manager_delegate.h"
 #include "chrome/browser/download/download_confirmation_result.h"
@@ -118,12 +119,16 @@
       FROM_HERE, base::BindOnce(std::move(arg0), result0));
 }
 
-// Similar to ScheduleCallback, but binds 2 arguments.
 ACTION_P2(ScheduleCallback2, result0, result1) {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE, base::BindOnce(std::move(arg0), result0, result1));
 }
 
+ACTION_P3(ScheduleCallback3, result0, result1, result2) {
+  base::ThreadTaskRunnerHandle::Get()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(arg0), result0, result1, result2));
+}
+
 // Used with DownloadTestCase. Indicates the type of test case. The expectations
 // for the test is set based on the type.
 enum TestCaseType {
@@ -424,7 +429,7 @@
     const base::FilePath& path) {
   profile()->GetTestingPrefService()->SetManagedPref(
       prefs::kDownloadDefaultDirectory,
-      base::Value::ToUniquePtrValue(base::CreateFilePathValue(path)));
+      base::Value::ToUniquePtrValue(util::FilePathToValue(path)));
 }
 
 void DownloadTargetDeterminerTest::SetPromptForDownload(bool prompt) {
@@ -572,7 +577,8 @@
     const base::FilePath& suggested_path,
     DownloadConfirmationReason reason,
     const ConfirmationCallback& callback) {
-  callback.Run(DownloadConfirmationResult::CONFIRMED, suggested_path);
+  callback.Run(DownloadConfirmationResult::CONFIRMED, suggested_path,
+               base::nullopt);
 }
 
 // static
@@ -659,8 +665,9 @@
 
        EXPECT_LOCAL_PATH}};
   ON_CALL(*delegate(), RequestConfirmation(_, _, _, _))
-      .WillByDefault(WithArg<3>(ScheduleCallback2(
-          DownloadConfirmationResult::CANCELED, base::FilePath())));
+      .WillByDefault(
+          WithArg<3>(ScheduleCallback3(DownloadConfirmationResult::CANCELED,
+                                       base::FilePath(), base::nullopt)));
   RunTestCasesWithActiveItem(kCancelSaveAsTestCases,
                              base::size(kCancelSaveAsTestCases));
 }
@@ -931,9 +938,9 @@
     EXPECT_CALL(*delegate(), RequestConfirmation(
                                  _, test_virtual_dir().AppendASCII("bar.txt"),
                                  DownloadConfirmationReason::SAVE_AS, _))
-        .WillOnce(WithArg<3>(
-            ScheduleCallback2(DownloadConfirmationResult::CONFIRMED,
-                              test_virtual_dir().AppendASCII("prompted.txt"))));
+        .WillOnce(WithArg<3>(ScheduleCallback3(
+            DownloadConfirmationResult::CONFIRMED,
+            test_virtual_dir().AppendASCII("prompted.txt"), base::nullopt)));
     RunTestCasesWithActiveItem(&kSaveAsToVirtualDir, 1);
   }
 
@@ -955,9 +962,10 @@
     EXPECT_CALL(*delegate(), RequestConfirmation(
                                  _, test_virtual_dir().AppendASCII("bar.txt"),
                                  DownloadConfirmationReason::SAVE_AS, _))
-        .WillOnce(WithArg<3>(ScheduleCallback2(
+        .WillOnce(WithArg<3>(ScheduleCallback3(
             DownloadConfirmationResult::CONFIRMED,
-            GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")))));
+            GetPathInDownloadDir(FILE_PATH_LITERAL("foo-x.txt")),
+            base::nullopt)));
     RunTestCasesWithActiveItem(&kSaveAsToLocalDir, 1);
   }
 
@@ -1399,9 +1407,10 @@
       RequestConfirmation(
           _, GetPathInDownloadDir(FILE_PATH_LITERAL("save-as.kindabad")),
           DownloadConfirmationReason::SAVE_AS, _))
-      .WillOnce(WithArg<3>(ScheduleCallback2(
+      .WillOnce(WithArg<3>(ScheduleCallback3(
           DownloadConfirmationResult::CONTINUE_WITHOUT_CONFIRMATION,
-          GetPathInDownloadDir(FILE_PATH_LITERAL("foo.kindabad")))));
+          GetPathInDownloadDir(FILE_PATH_LITERAL("foo.kindabad")),
+          base::nullopt)));
   RunTestCasesWithActiveItem(&kTestCase, 1);
 }
 
@@ -1425,9 +1434,10 @@
       RequestConfirmation(
           _, GetPathInDownloadDir(FILE_PATH_LITERAL("save-as.kindabad")),
           DownloadConfirmationReason::SAVE_AS, _))
-      .WillOnce(WithArg<3>(ScheduleCallback2(
+      .WillOnce(WithArg<3>(ScheduleCallback3(
           DownloadConfirmationResult::CONFIRMED,
-          GetPathInDownloadDir(FILE_PATH_LITERAL("foo.kindabad")))));
+          GetPathInDownloadDir(FILE_PATH_LITERAL("foo.kindabad")),
+          base::nullopt)));
   RunTestCasesWithActiveItem(&kTestCase, 1);
 }
 
diff --git a/chrome/browser/download/download_target_info.h b/chrome/browser/download/download_target_info.h
index d3f8219..87a5cf3b 100644
--- a/chrome/browser/download/download_target_info.h
+++ b/chrome/browser/download/download_target_info.h
@@ -8,9 +8,11 @@
 #include <string>
 
 #include "base/files/file_path.h"
+#include "base/optional.h"
 #include "components/download/public/common/download_danger_type.h"
 #include "components/download/public/common/download_interrupt_reasons.h"
 #include "components/download/public/common/download_item.h"
+#include "components/download/public/common/download_schedule.h"
 #include "components/safe_browsing/core/proto/download_file_types.pb.h"
 
 struct DownloadTargetInfo {
@@ -80,6 +82,9 @@
 
   // What sort of blocking should be used if the download is of mixed content.
   download::DownloadItem::MixedContentStatus mixed_content_status;
+
+  // Defines when to start the download, used by download later feature.
+  base::Optional<download::DownloadSchedule> download_schedule;
 };
 
 #endif  // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TARGET_INFO_H_
diff --git a/chrome/browser/download/download_ui_controller_unittest.cc b/chrome/browser/download/download_ui_controller_unittest.cc
index 258fb39..d824730 100644
--- a/chrome/browser/download/download_ui_controller_unittest.cc
+++ b/chrome/browser/download/download_ui_controller_unittest.cc
@@ -165,11 +165,10 @@
 }
 
 DownloadUIControllerTest::DownloadUIControllerTest()
-    : download_history_manager_observer_(NULL),
-      manager_observer_(NULL),
-      notified_item_(NULL),
-      notified_item_receiver_factory_(&notified_item_) {
-}
+    : download_history_manager_observer_(nullptr),
+      manager_observer_(nullptr),
+      notified_item_(nullptr),
+      notified_item_receiver_factory_(&notified_item_) {}
 
 void DownloadUIControllerTest::SetUp() {
   ChromeRenderViewHostTestHarness::SetUp();
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index f14ca91..c16661b9 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -190,6 +190,8 @@
     "api/identity/identity_constants.h",
     "api/identity/identity_get_accounts_function.cc",
     "api/identity/identity_get_accounts_function.h",
+    "api/identity/identity_get_auth_token_error.cc",
+    "api/identity/identity_get_auth_token_error.h",
     "api/identity/identity_get_auth_token_function.cc",
     "api/identity/identity_get_auth_token_function.h",
     "api/identity/identity_get_profile_user_info_function.cc",
@@ -1004,11 +1006,10 @@
       "//ash/keyboard/ui:resources_grit_grit",
       "//ash/public/cpp",
       "//chrome/browser/chromeos/crostini:crostini_installer_types_mojom",
+      "//chrome/browser/resources/chromeos/camera:chrome_camera_app",
       "//chrome/browser/ui/webui/settings/chromeos/constants:mojom",
       "//chromeos",
       "//chromeos/attestation",
-      "//chromeos/components/camera_app_ui",
-      "//chromeos/components/camera_app_ui:mojo_bindings",
       "//chromeos/components/proximity_auth",
       "//chromeos/constants",
       "//chromeos/cryptohome",
@@ -1029,6 +1030,7 @@
       "//chromeos/system",
       "//chromeos/tpm",
       "//components/arc",
+      "//components/chromeos_camera:camera_app_helper",
       "//components/constrained_window",
       "//components/drive",
       "//components/user_manager",
diff --git a/chrome/browser/extensions/activity_log/activity_log.cc b/chrome/browser/extensions/activity_log/activity_log.cc
index 392a1d0..3c5cf1b1 100644
--- a/chrome/browser/extensions/activity_log/activity_log.cc
+++ b/chrome/browser/extensions/activity_log/activity_log.cc
@@ -460,7 +460,7 @@
 
 // Use GetInstance instead of directly creating an ActivityLog.
 ActivityLog::ActivityLog(content::BrowserContext* context)
-    : database_policy_(NULL),
+    : database_policy_(nullptr),
       database_policy_type_(ActivityLogPolicy::POLICY_INVALID),
       profile_(Profile::FromBrowserContext(context)),
       extension_system_(ExtensionSystem::Get(context)),
diff --git a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
index 5f90d3df..8671eb1 100644
--- a/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/api/bookmarks/bookmark_api_helpers_unittest.cc
@@ -35,11 +35,11 @@
 class ExtensionBookmarksTest : public testing::Test {
  public:
   ExtensionBookmarksTest()
-      : managed_(NULL),
-        model_(NULL),
-        node_(NULL),
-        node2_(NULL),
-        folder_(NULL) {}
+      : managed_(nullptr),
+        model_(nullptr),
+        node_(nullptr),
+        node2_(nullptr),
+        folder_(nullptr) {}
 
   void SetUp() override {
     profile_.CreateBookmarkModel(false);
diff --git a/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc b/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
index 0e07e7a..45681c2fb 100644
--- a/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
+++ b/chrome/browser/extensions/api/braille_display_private/mock_braille_controller.cc
@@ -9,7 +9,7 @@
 namespace braille_display_private {
 
 MockBrailleController::MockBrailleController()
-    : available_(false), observer_(NULL) {}
+    : available_(false), observer_(nullptr) {}
 
 std::unique_ptr<DisplayState> MockBrailleController::GetDisplayState() {
   std::unique_ptr<DisplayState> state(new DisplayState());
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
index eedd272..54d4ece 100644
--- a/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
+++ b/chrome/browser/extensions/api/content_settings/content_settings_apitest.cc
@@ -45,7 +45,7 @@
 
 class ExtensionContentSettingsApiTest : public ExtensionApiTest {
  public:
-  ExtensionContentSettingsApiTest() : profile_(NULL) {}
+  ExtensionContentSettingsApiTest() : profile_(nullptr) {}
 
   void SetUpOnMainThread() override {
     ExtensionApiTest::SetUpOnMainThread();
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.cc b/chrome/browser/extensions/api/cookies/cookies_api.cc
index dbb3e99..5dbb6f6 100644
--- a/chrome/browser/extensions/api/cookies/cookies_api.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_api.cc
@@ -256,16 +256,17 @@
 }
 
 void CookiesGetFunction::GetCookieListCallback(
-    const net::CookieStatusList& cookie_status_list,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookie_list,
+    const net::CookieAccessResultList& excluded_cookies) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  for (const net::CookieWithStatus& cookie_with_status : cookie_status_list) {
+  for (const net::CookieWithAccessResult& cookie_with_access_result :
+       cookie_list) {
     // Return the first matching cookie. Relies on the fact that the
     // CookieManager interface returns them in canonical order (longest path,
     // then earliest creation time).
-    if (cookie_with_status.cookie.Name() == parsed_args_->details.name) {
+    if (cookie_with_access_result.cookie.Name() == parsed_args_->details.name) {
       api::cookies::Cookie api_cookie = cookies_helpers::CreateCookie(
-          cookie_with_status.cookie, *parsed_args_->details.store_id);
+          cookie_with_access_result.cookie, *parsed_args_->details.store_id);
       Respond(ArgumentList(api::cookies::Get::Results::Create(api_cookie)));
       return;
     }
@@ -336,14 +337,14 @@
 }
 
 void CookiesGetAllFunction::GetCookieListCallback(
-    const net::CookieStatusList& cookie_status_list,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookie_list,
+    const net::CookieAccessResultList& excluded_cookies) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   ResponseValue response;
   if (extension()) {
     std::vector<api::cookies::Cookie> match_vector;
-    cookies_helpers::AppendMatchingCookiesFromCookieStatusListToVector(
-        cookie_status_list, &parsed_args_->details, extension(), &match_vector);
+    cookies_helpers::AppendMatchingCookiesFromCookieAccessResultListToVector(
+        cookie_list, &parsed_args_->details, extension(), &match_vector);
 
     response =
         ArgumentList(api::cookies::GetAll::Results::Create(match_vector));
@@ -437,7 +438,8 @@
     // is generated.
     success_ = false;
     state_ = SET_COMPLETED;
-    GetCookieListCallback(net::CookieStatusList(), net::CookieStatusList());
+    GetCookieListCallback(net::CookieAccessResultList(),
+                          net::CookieAccessResultList());
     return AlreadyResponded();
   }
 
@@ -469,8 +471,8 @@
 }
 
 void CookiesSetFunction::GetCookieListCallback(
-    const net::CookieStatusList& cookie_list,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookie_list,
+    const net::CookieAccessResultList& excluded_cookies) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   DCHECK_EQ(SET_COMPLETED, state_);
   state_ = GET_COMPLETED;
@@ -485,16 +487,17 @@
   }
 
   ResponseValue value;
-  for (const net::CookieWithStatus& cookie_with_status : cookie_list) {
+  for (const net::CookieWithAccessResult& cookie_with_access_result :
+       cookie_list) {
     // Return the first matching cookie. Relies on the fact that the
     // CookieMonster returns them in canonical order (longest path, then
     // earliest creation time).
     std::string name =
         parsed_args_->details.name.get() ? *parsed_args_->details.name
                                          : std::string();
-    if (cookie_with_status.cookie.Name() == name) {
+    if (cookie_with_access_result.cookie.Name() == name) {
       api::cookies::Cookie api_cookie = cookies_helpers::CreateCookie(
-          cookie_with_status.cookie, *parsed_args_->details.store_id);
+          cookie_with_access_result.cookie, *parsed_args_->details.store_id);
       value = ArgumentList(api::cookies::Set::Results::Create(api_cookie));
       break;
     }
diff --git a/chrome/browser/extensions/api/cookies/cookies_api.h b/chrome/browser/extensions/api/cookies/cookies_api.h
index 5fd7d6d0..a506809 100644
--- a/chrome/browser/extensions/api/cookies/cookies_api.h
+++ b/chrome/browser/extensions/api/cookies/cookies_api.h
@@ -106,8 +106,9 @@
   ResponseAction Run() override;
 
  private:
-  void GetCookieListCallback(const net::CookieStatusList& cookie_status_list,
-                             const net::CookieStatusList& excluded_cookies);
+  void GetCookieListCallback(
+      const net::CookieAccessResultList& cookie_list,
+      const net::CookieAccessResultList& excluded_cookies);
 
   GURL url_;
   mojo::Remote<network::mojom::CookieManager> store_browser_cookie_manager_;
@@ -131,8 +132,9 @@
   // For the two different callback signatures for getting cookies for a URL vs
   // getting all cookies. They do the same thing.
   void GetAllCookiesCallback(const net::CookieList& cookie_list);
-  void GetCookieListCallback(const net::CookieStatusList& cookie_status_list,
-                             const net::CookieStatusList& excluded_cookies);
+  void GetCookieListCallback(
+      const net::CookieAccessResultList& cookie_list,
+      const net::CookieAccessResultList& excluded_cookies);
 
   GURL url_;
   mojo::Remote<network::mojom::CookieManager> store_browser_cookie_manager_;
@@ -152,8 +154,9 @@
 
  private:
   void SetCanonicalCookieCallback(net::CookieInclusionStatus set_cookie_result);
-  void GetCookieListCallback(const net::CookieStatusList& cookie_list,
-                             const net::CookieStatusList& excluded_cookies);
+  void GetCookieListCallback(
+      const net::CookieAccessResultList& cookie_list,
+      const net::CookieAccessResultList& excluded_cookies);
 
   enum { NO_RESPONSE, SET_COMPLETED, GET_COMPLETED } state_;
   GURL url_;
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.cc b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
index 43bb161..9aee1f61 100644
--- a/chrome/browser/extensions/api/cookies/cookies_helpers.cc
+++ b/chrome/browser/extensions/api/cookies/cookies_helpers.cc
@@ -182,14 +182,14 @@
   }
 }
 
-void AppendMatchingCookiesFromCookieStatusListToVector(
-    const net::CookieStatusList& all_cookies_with_statuses,
+void AppendMatchingCookiesFromCookieAccessResultListToVector(
+    const net::CookieAccessResultList& all_cookies_with_access_result,
     const GetAll::Params::Details* details,
     const Extension* extension,
     std::vector<Cookie>* match_vector) {
-  for (const net::CookieWithStatus& cookie_with_status :
-       all_cookies_with_statuses) {
-    const net::CanonicalCookie& cookie = cookie_with_status.cookie;
+  for (const net::CookieWithAccessResult& cookie_with_access_result :
+       all_cookies_with_access_result) {
+    const net::CanonicalCookie& cookie = cookie_with_access_result.cookie;
     AppendCookieToVectorIfMatchAndHasHostPermission(cookie, details, extension,
                                                     match_vector);
   }
diff --git a/chrome/browser/extensions/api/cookies/cookies_helpers.h b/chrome/browser/extensions/api/cookies/cookies_helpers.h
index 298b16e..9d5acf0 100644
--- a/chrome/browser/extensions/api/cookies/cookies_helpers.h
+++ b/chrome/browser/extensions/api/cookies/cookies_helpers.h
@@ -85,9 +85,10 @@
     const Extension* extension,
     std::vector<api::cookies::Cookie>* match_vector);
 
-// Same as above except takes a CookieStatusList (and ignores the statuses).
-void AppendMatchingCookiesFromCookieStatusListToVector(
-    const net::CookieStatusList& all_cookies_with_statuses,
+// Same as above except takes a CookieAccessResultList (and ignores the access
+// results).
+void AppendMatchingCookiesFromCookieAccessResultListToVector(
+    const net::CookieAccessResultList& all_cookies_with_access_result,
     const api::cookies::GetAll::Params::Details* details,
     const Extension* extension,
     std::vector<api::cookies::Cookie>* match_vector);
diff --git a/chrome/browser/extensions/api/debugger/debugger_api.cc b/chrome/browser/extensions/api/debugger/debugger_api.cc
index 253ce75..3aaf286 100644
--- a/chrome/browser/extensions/api/debugger/debugger_api.cc
+++ b/chrome/browser/extensions/api/debugger/debugger_api.cc
@@ -389,9 +389,7 @@
 
 // DebuggerFunction -----------------------------------------------------------
 
-DebuggerFunction::DebuggerFunction()
-    : client_host_(NULL) {
-}
+DebuggerFunction::DebuggerFunction() : client_host_(nullptr) {}
 
 DebuggerFunction::~DebuggerFunction() = default;
 
diff --git a/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc b/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
index 65865c42..4a99b45 100644
--- a/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
+++ b/chrome/browser/extensions/api/declarative_content/request_content_script_apitest.cc
@@ -113,7 +113,7 @@
 };
 
 RequestContentScriptAPITest::RequestContentScriptAPITest()
-    : extension_(NULL) {}
+    : extension_(nullptr) {}
 
 testing::AssertionResult RequestContentScriptAPITest::RunTest(
     PermissionOrMatcherType manifest_permission,
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index ee1f90c..1400449 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -320,10 +320,9 @@
 class DownloadExtensionTest : public ExtensionApiTest {
  public:
   DownloadExtensionTest()
-    : extension_(NULL),
-      incognito_browser_(NULL),
-      current_browser_(NULL) {
-  }
+      : extension_(nullptr),
+        incognito_browser_(nullptr),
+        current_browser_(nullptr) {}
 
  protected:
   // Used with CreateHistoryDownloads
@@ -1481,21 +1480,13 @@
   ASSERT_EQ(items[2]->GetTargetFilePath().value(), item_name);
 }
 
-// https://crbug.com/874946, flaky on Win.
-#if defined(OS_WIN)
-#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \
-  DISABLED_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
-#else
-#define MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito \
-  DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito
-#endif
 // Test that incognito downloads are only visible in incognito contexts, and
 // test that on-record downloads are visible in both incognito and on-record
 // contexts, for DownloadsSearchFunction, DownloadsPauseFunction,
 // DownloadsResumeFunction, and DownloadsCancelFunction.
 IN_PROC_BROWSER_TEST_F(
     DownloadExtensionTest,
-    MAYBE_DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
+    DownloadExtensionTest_SearchPauseResumeCancelGetFileIconIncognito) {
   std::unique_ptr<base::Value> result_value;
   base::ListValue* result_list = NULL;
   base::DictionaryValue* result_dict = NULL;
@@ -1873,18 +1864,9 @@
                                          result_id)));
 }
 
-#if defined(OS_WIN)
-// This test is very flaky on Win. http://crbug.com/248438
-#define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
-    DISABLED_DownloadExtensionTest_Download_UnsafeHeaders
-#else
-#define MAYBE_DownloadExtensionTest_Download_UnsafeHeaders \
-    DownloadExtensionTest_Download_UnsafeHeaders
-#endif
-
 // Test that we disallow certain headers case-insensitively.
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
-                       MAYBE_DownloadExtensionTest_Download_UnsafeHeaders) {
+                       DownloadExtensionTest_Download_UnsafeHeaders) {
   LoadExtension("downloads_split");
   ASSERT_TRUE(StartEmbeddedTestServer());
   GoOnTheRecord();
@@ -1961,6 +1943,7 @@
       download_url.c_str())).c_str());
 }
 
+// This test is very flaky on Win. http://crbug.com/248438
 #if defined(OS_WIN)
 #define MAYBE_DownloadExtensionTest_Download_Subdirectory\
         DISABLED_DownloadExtensionTest_Download_Subdirectory
@@ -4379,12 +4362,14 @@
   prompt->InvokeActionForTesting(DownloadDangerPrompt::ACCEPT);
 }
 
-#if defined(OS_MACOSX)
-// Flakily triggers and assert on Mac.
+#if defined(OS_MACOSX) && !defined(NDEBUG)
+// Flaky on Mac debug, failing with a timeout.
 // http://crbug.com/180759
-#define MAYBE_DownloadExtensionTest_AcceptDanger DISABLED_DownloadExtensionTest_AcceptDanger
+#define MAYBE_DownloadExtensionTest_AcceptDanger \
+  DISABLED_DownloadExtensionTest_AcceptDanger
 #else
-#define MAYBE_DownloadExtensionTest_AcceptDanger DownloadExtensionTest_AcceptDanger
+#define MAYBE_DownloadExtensionTest_AcceptDanger \
+  DownloadExtensionTest_AcceptDanger
 #endif
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        MAYBE_DownloadExtensionTest_AcceptDanger) {
diff --git a/chrome/browser/extensions/api/extension_action/extension_action_api.cc b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
index b2fa34c..6844e48c 100644
--- a/chrome/browser/extensions/api/extension_action/extension_action_api.cc
+++ b/chrome/browser/extensions/api/extension_action/extension_action_api.cc
@@ -240,11 +240,10 @@
 //
 
 ExtensionActionFunction::ExtensionActionFunction()
-    : details_(NULL),
+    : details_(nullptr),
       tab_id_(ExtensionAction::kDefaultTabId),
-      contents_(NULL),
-      extension_action_(NULL) {
-}
+      contents_(nullptr),
+      extension_action_(nullptr) {}
 
 ExtensionActionFunction::~ExtensionActionFunction() {
 }
diff --git a/chrome/browser/extensions/api/gcm/gcm_apitest.cc b/chrome/browser/extensions/api/gcm/gcm_apitest.cc
index d9b189cf..623b7a0 100644
--- a/chrome/browser/extensions/api/gcm/gcm_apitest.cc
+++ b/chrome/browser/extensions/api/gcm/gcm_apitest.cc
@@ -60,7 +60,7 @@
 
 class GcmApiTest : public ExtensionApiTest {
  public:
-  GcmApiTest() : fake_gcm_profile_service_(NULL) {}
+  GcmApiTest() : fake_gcm_profile_service_(nullptr) {}
 
  protected:
   void SetUpCommandLine(base::CommandLine* command_line) override;
diff --git a/chrome/browser/extensions/api/identity/identity_apitest.cc b/chrome/browser/extensions/api/identity/identity_apitest.cc
index 6398331..1e734e4a 100644
--- a/chrome/browser/extensions/api/identity/identity_apitest.cc
+++ b/chrome/browser/extensions/api/identity/identity_apitest.cc
@@ -14,6 +14,7 @@
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "build/buildflag.h"
@@ -23,6 +24,7 @@
 #include "chrome/browser/extensions/api/identity/identity_api.h"
 #include "chrome/browser/extensions/api/identity/identity_constants.h"
 #include "chrome/browser/extensions/api/identity/identity_get_accounts_function.h"
+#include "chrome/browser/extensions/api/identity/identity_get_auth_token_error.h"
 #include "chrome/browser/extensions/api/identity/identity_get_auth_token_function.h"
 #include "chrome/browser/extensions/api/identity/identity_get_profile_user_info_function.h"
 #include "chrome/browser/extensions/api/identity/identity_launch_web_auth_flow_function.h"
@@ -91,8 +93,11 @@
 namespace errors = identity_constants;
 namespace utils = extension_function_test_utils;
 
-static const char kAccessToken[] = "auth_token";
-static const char kExtensionId[] = "ext_id";
+const char kAccessToken[] = "auth_token";
+const char kExtensionId[] = "ext_id";
+
+const char kGetAuthTokenResultHistogramName[] =
+    "Signin.Extensions.GetAuthTokenResult";
 
 #if defined(OS_CHROMEOS)
 void InitNetwork() {
@@ -910,6 +915,8 @@
     id_api()->mint_queue()->RequestComplete(type, key, request);
   }
 
+  base::HistogramTester* histogram_tester() { return &histogram_tester_; }
+
   base::OnceClosure on_access_token_requested_;
 
  private:
@@ -922,6 +929,7 @@
     std::move(on_access_token_requested_).Run();
   }
 
+  base::HistogramTester histogram_tester_;
   std::string extension_id_;
   std::set<std::string> oauth_scopes_;
 };
@@ -934,6 +942,9 @@
   EXPECT_EQ(std::string(errors::kInvalidClientId), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kInvalidClientId, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoScopes) {
@@ -944,6 +955,9 @@
   EXPECT_EQ(std::string(errors::kInvalidScopes), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kEmptyScopes, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveNotSignedIn) {
@@ -954,6 +968,9 @@
   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kUserNotSignedIn, 1);
 }
 
 // The signin flow is simply not used on ChromeOS.
@@ -968,6 +985,9 @@
   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kSignInFailed, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -990,6 +1010,9 @@
   EXPECT_EQ(std::string(errors::kBrowserSigninNotAllowed), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kBrowserSigninNotAllowed, 1);
 }
 #endif
 
@@ -1004,6 +1027,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1016,6 +1042,9 @@
       utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
   EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure,
                                base::CompareCase::INSENSITIVE_ASCII));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1033,6 +1062,9 @@
 
   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
             GetCachedToken(CoreAccountId()).status());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaConsentInteractionRequired, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1048,6 +1080,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1063,6 +1098,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1081,6 +1119,9 @@
   // in a valid state.
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 // The signin flow is simply not used on ChromeOS.
@@ -1101,6 +1142,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 #endif
 
@@ -1119,6 +1163,9 @@
   EXPECT_FALSE(func->scope_ui_shown());
   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
             GetCachedToken(CoreAccountId()).status());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveSuccess) {
@@ -1136,6 +1183,9 @@
   EXPECT_FALSE(func->scope_ui_shown());
   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
             GetCachedToken(CoreAccountId()).status());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveLoginCanceled) {
@@ -1151,6 +1201,9 @@
   EXPECT_TRUE(func->login_ui_shown());
 #endif
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kSignInFailed, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1167,6 +1220,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 // The interactive login flow is always short-circuited out with failure on
@@ -1185,6 +1241,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1200,6 +1259,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1214,6 +1276,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1231,6 +1296,9 @@
   EXPECT_EQ(std::string(kAccessToken), access_token);
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1245,6 +1313,9 @@
   EXPECT_EQ(std::string(errors::kUserRejected), error);
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1262,6 +1333,9 @@
   EXPECT_EQ(std::string(kAccessToken), access_token);
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 #endif
 
@@ -1276,6 +1350,9 @@
   EXPECT_EQ(std::string(errors::kUserRejected), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1290,6 +1367,9 @@
   EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kPageLoadFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1304,6 +1384,9 @@
   EXPECT_EQ(std::string(errors::kInvalidRedirect), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kInvalidRedirect, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1320,6 +1403,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1338,6 +1424,9 @@
   // The login UI should not be shown as the account is in a valid state.
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
 }
 
 // The signin flow is simply not used on ChromeOS.
@@ -1360,6 +1449,9 @@
 
   EXPECT_TRUE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
 }
 #endif
 
@@ -1368,15 +1460,24 @@
   SignIn("primary@example.com");
   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
 
-  std::map<std::string, std::string> error_map;
-  error_map.insert(std::make_pair("access_denied", errors::kUserRejected));
-  error_map.insert(std::make_pair("invalid_scope", errors::kInvalidScopes));
-  error_map.insert(std::make_pair(
-      "unmapped_error", std::string(errors::kAuthFailure) + "unmapped_error"));
+  struct TestCase {
+    std::string oauth_error;
+    std::string error_message;
+    IdentityGetAuthTokenError::State error_state;
+  };
 
-  for (std::map<std::string, std::string>::const_iterator it =
-           error_map.begin();
-       it != error_map.end(); ++it) {
+  std::vector<TestCase> test_cases;
+  test_cases.push_back({"access_denied", errors::kUserRejected,
+                        IdentityGetAuthTokenError::State::kOAuth2AccessDenied});
+  test_cases.push_back(
+      {"invalid_scope", errors::kInvalidScopes,
+       IdentityGetAuthTokenError::State::kOAuth2InvalidScopes});
+  test_cases.push_back({"unmapped_error",
+                        std::string(errors::kAuthFailure) + "unmapped_error",
+                        IdentityGetAuthTokenError::State::kOAuth2Failure});
+
+  for (const auto& test_case : test_cases) {
+    base::HistogramTester histogram_tester;
     scoped_refptr<FakeGetAuthTokenFunction> func(
         new FakeGetAuthTokenFunction());
     func->set_extension(extension.get());
@@ -1384,12 +1485,14 @@
     // flow to be leaked.
     id_api()->EraseAllCachedTokens();
     func->push_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
-    func->set_scope_ui_oauth_error(it->first);
+    func->set_scope_ui_oauth_error(test_case.oauth_error);
     std::string error = utils::RunFunctionAndReturnError(
         func.get(), "[{\"interactive\": true}]", browser());
-    EXPECT_EQ(it->second, error);
+    EXPECT_EQ(test_case.error_message, error);
     EXPECT_FALSE(func->login_ui_shown());
     EXPECT_TRUE(func->scope_ui_shown());
+    histogram_tester.ExpectUniqueSample(kGetAuthTokenResultHistogramName,
+                                        test_case.error_state, 1);
   }
 }
 
@@ -1410,6 +1513,9 @@
 
   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
             GetCachedToken(CoreAccountId()).status());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 #if !defined(OS_MACOSX)
@@ -1444,6 +1550,9 @@
   // The login screen should not be shown when the browser process is shutting
   // down.
   EXPECT_FALSE(func->login_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowAuthFailure, 1);
 }
 #endif  // !defined(OS_MACOSX)
 
@@ -1478,6 +1587,9 @@
   EXPECT_EQ(std::string(kAccessToken), access_token);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
@@ -1512,6 +1624,9 @@
   EXPECT_EQ(std::string(kAccessToken), access_token);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueueShutdown) {
@@ -1543,6 +1658,9 @@
   EXPECT_FALSE(func->scope_ui_shown());
 
   QueueRequestComplete(type, &queued_request);
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kCanceled, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveShutdown) {
@@ -1557,6 +1675,9 @@
   // After the request is canceled, the function will complete.
   func->OnIdentityAPIShutdown();
   EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kCanceled, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1583,6 +1704,10 @@
   EXPECT_FALSE(func->scope_ui_shown());
 
   QueueRequestComplete(type, &queued_request);
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaConsentInteractionAlreadyRunning,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NonInteractiveCacheHit) {
@@ -1604,6 +1729,9 @@
   EXPECT_EQ(std::string(kAccessToken), access_token);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 // Checks that the first account in Gaia cookie can be used when extensions are
@@ -1637,6 +1765,9 @@
     std::string error =
         utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
     EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kUserNotSignedIn, 1);
   } else {
     // Use the account from Gaia cookies.
     std::unique_ptr<base::Value> value(
@@ -1644,6 +1775,9 @@
     std::string access_token;
     EXPECT_TRUE(value->GetAsString(&access_token));
     EXPECT_EQ(std::string(kAccessToken), access_token);
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kNone, 1);
   }
 
   EXPECT_FALSE(func->login_ui_shown());
@@ -1669,6 +1803,9 @@
   EXPECT_EQ(std::string(errors::kNoGrant), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaConsentInteractionRequired, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveCacheHit) {
@@ -1706,6 +1843,9 @@
   EXPECT_EQ(std::string(kAccessToken), access_token);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 // The interactive login UI is never shown on ChromeOS, so tests of the
@@ -1735,6 +1875,9 @@
   EXPECT_TRUE(func->scope_ui_shown());
   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
             GetCachedToken(CoreAccountId()).status());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 #endif
 
@@ -1761,6 +1904,9 @@
   EXPECT_EQ(kAccessToken, value->GetString());
   EXPECT_TRUE(func->scope_ui_shown());
   EXPECT_FALSE(GetCachedGaiaId().has_value());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1786,6 +1932,9 @@
   EXPECT_EQ(std::string(errors::kUserRejected), error);
   EXPECT_TRUE(func->scope_ui_shown());
   EXPECT_FALSE(GetCachedGaiaId().has_value());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithChromeClientId) {
@@ -1824,6 +1973,9 @@
 
   id_api()->Shutdown();
   EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kCanceled, 1);
 }
 
 // Ensure that when there are multiple active function calls, IdentityAPI
@@ -1892,6 +2044,9 @@
             GetCachedToken(CoreAccountId()).status());
   EXPECT_THAT(func->login_access_tokens(),
               testing::ElementsAre(primary_account_access_token));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ManuallyIssueTokenFailure) {
@@ -1919,6 +2074,9 @@
           GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE)
               .ToString(),
       WaitForError(func.get()));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1948,6 +2106,9 @@
             GetCachedToken(CoreAccountId()).status());
   EXPECT_THAT(func->login_access_tokens(),
               testing::ElementsAre(primary_account_access_token));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -1979,6 +2140,9 @@
             GetCachedToken(CoreAccountId()).status());
   EXPECT_THAT(func->login_access_tokens(),
               testing::ElementsAre(primary_account_access_token));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2005,6 +2169,9 @@
     EXPECT_EQ(std::string(errors::kUserNonPrimary), error);
     EXPECT_FALSE(func->login_ui_shown());
     EXPECT_FALSE(func->scope_ui_shown());
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kUserNonPrimary, 1);
     return;
   }
 
@@ -2024,6 +2191,9 @@
             GetCachedToken(secondary_account_id).status());
   EXPECT_THAT(func->login_access_tokens(),
               testing::ElementsAre(secondary_account_access_token));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2040,10 +2210,17 @@
       func.get(), "[{\"account\": { \"id\": \"unknown@example.com\" } }]",
       browser());
   std::string expected_error;
-  if (id_api()->AreExtensionsRestrictedToPrimaryAccount())
+  if (id_api()->AreExtensionsRestrictedToPrimaryAccount()) {
     EXPECT_EQ(errors::kUserNonPrimary, error);
-  else
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kUserNonPrimary, 1);
+  } else {
     EXPECT_EQ(errors::kUserNotSignedIn, error);
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kUserNotSignedIn, 1);
+  }
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2066,6 +2243,9 @@
                                base::CompareCase::INSENSITIVE_ASCII));
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kMintTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2086,6 +2266,9 @@
       browser());
   EXPECT_TRUE(base::StartsWith(error, errors::kAuthFailure,
                                base::CompareCase::INSENSITIVE_ASCII));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGetAccessTokenAuthFailure, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
@@ -2109,6 +2292,9 @@
   EXPECT_EQ(std::string(errors::kUserRejected), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_TRUE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kGaiaFlowRejected, 1);
 }
 
 // Tests that Chrome remembers user's choice of an account at the end of the
@@ -2144,6 +2330,9 @@
 
     if (id_api()->AreExtensionsRestrictedToPrimaryAccount()) {
       EXPECT_EQ(std::string(errors::kUserNonPrimary), WaitForError(func.get()));
+      histogram_tester()->ExpectUniqueSample(
+          kGetAuthTokenResultHistogramName,
+          IdentityGetAuthTokenError::State::kRemoteConsentUserNonPrimary, 1);
       return;
     }
 
@@ -2161,6 +2350,9 @@
     EXPECT_THAT(func->login_access_tokens(),
                 testing::ElementsAre(primary_account_access_token,
                                      secondary_account_access_token));
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kNone, 1);
   }
 
   {
@@ -2176,6 +2368,9 @@
     EXPECT_EQ(std::string(kAccessToken), access_token);
     EXPECT_FALSE(func->login_ui_shown());
     EXPECT_FALSE(func->scope_ui_shown());
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kNone, 2);
   }
 }
 
@@ -2208,6 +2403,9 @@
     EXPECT_EQ(std::string(errors::kUserNonPrimary), error);
     EXPECT_FALSE(func->login_ui_shown());
     EXPECT_FALSE(func->scope_ui_shown());
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kUserNonPrimary, 1);
   } else {
     // Extensions can show the login UI for secondary accounts, and get the auth
     // token.
@@ -2218,6 +2416,9 @@
     EXPECT_EQ(std::string(kAccessToken), access_token);
     EXPECT_TRUE(func->login_ui_shown());
     EXPECT_TRUE(func->scope_ui_shown());
+    histogram_tester()->ExpectUniqueSample(
+        kGetAuthTokenResultHistogramName,
+        IdentityGetAuthTokenError::State::kNone, 1);
   }
 }
 #endif
@@ -2238,6 +2439,9 @@
   EXPECT_EQ(2ul, token_key->scopes.size());
   EXPECT_TRUE(base::Contains(token_key->scopes, "scope1"));
   EXPECT_TRUE(base::Contains(token_key->scopes, "scope2"));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmpty) {
@@ -2249,6 +2453,9 @@
       func.get(), "[{\"scopes\": []}]", browser()));
 
   EXPECT_EQ(errors::kInvalidScopes, error);
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kEmptyScopes, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmail) {
@@ -2266,6 +2473,9 @@
   const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
   EXPECT_EQ(1ul, token_key->scopes.size());
   EXPECT_TRUE(base::Contains(token_key->scopes, "email"));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmailFooBar) {
@@ -2285,6 +2495,9 @@
   EXPECT_TRUE(base::Contains(token_key->scopes, "email"));
   EXPECT_TRUE(base::Contains(token_key->scopes, "foo"));
   EXPECT_TRUE(base::Contains(token_key->scopes, "bar"));
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 #if defined(OS_CHROMEOS)
@@ -2340,6 +2553,9 @@
   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
   EXPECT_FALSE(func->login_ui_shown());
   EXPECT_FALSE(func->scope_ui_shown());
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName,
+      IdentityGetAuthTokenError::State::kNotWhitelistedInPublicSession, 1);
 }
 
 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionPublicSessionTest, Whitelisted) {
@@ -2354,6 +2570,9 @@
   std::string access_token;
   EXPECT_TRUE(value->GetAsString(&access_token));
   EXPECT_EQ(std::string(kAccessToken), access_token);
+  histogram_tester()->ExpectUniqueSample(
+      kGetAuthTokenResultHistogramName, IdentityGetAuthTokenError::State::kNone,
+      1);
 }
 
 #endif
diff --git a/chrome/browser/extensions/api/identity/identity_get_auth_token_error.cc b/chrome/browser/extensions/api/identity/identity_get_auth_token_error.cc
new file mode 100644
index 0000000..7f02651
--- /dev/null
+++ b/chrome/browser/extensions/api/identity/identity_get_auth_token_error.cc
@@ -0,0 +1,112 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/api/identity/identity_get_auth_token_error.h"
+
+#include "base/strings/string_piece.h"
+#include "chrome/browser/extensions/api/identity/identity_constants.h"
+
+namespace extensions {
+
+// static
+IdentityGetAuthTokenError IdentityGetAuthTokenError::FromGaiaFlowAuthError(
+    base::StringPiece error_message) {
+  return IdentityGetAuthTokenError(State::kGaiaFlowAuthFailure, error_message);
+}
+
+// static
+IdentityGetAuthTokenError IdentityGetAuthTokenError::FromMintTokenAuthError(
+    base::StringPiece error_message) {
+  return IdentityGetAuthTokenError(State::kMintTokenAuthFailure, error_message);
+}
+
+// static
+IdentityGetAuthTokenError
+IdentityGetAuthTokenError::FromGetAccessTokenAuthError(
+    base::StringPiece error_message) {
+  return IdentityGetAuthTokenError(State::kGetAccessTokenAuthFailure,
+                                   error_message);
+}
+
+// static
+IdentityGetAuthTokenError IdentityGetAuthTokenError::FromOAuth2Error(
+    base::StringPiece oauth2_error) {
+  const char kOAuth2ErrorAccessDenied[] = "access_denied";
+  const char kOAuth2ErrorInvalidScope[] = "invalid_scope";
+
+  if (oauth2_error == kOAuth2ErrorAccessDenied) {
+    return IdentityGetAuthTokenError(
+        IdentityGetAuthTokenError::State::kOAuth2AccessDenied);
+  } else if (oauth2_error == kOAuth2ErrorInvalidScope) {
+    return IdentityGetAuthTokenError(
+        IdentityGetAuthTokenError::State::kOAuth2InvalidScopes);
+  } else {
+    return IdentityGetAuthTokenError(
+        IdentityGetAuthTokenError::State::kOAuth2Failure, oauth2_error);
+  }
+}
+
+IdentityGetAuthTokenError::IdentityGetAuthTokenError()
+    : IdentityGetAuthTokenError(State::kNone) {}
+
+IdentityGetAuthTokenError::IdentityGetAuthTokenError(State state)
+    : IdentityGetAuthTokenError(state, base::StringPiece()) {}
+
+IdentityGetAuthTokenError::State IdentityGetAuthTokenError::state() const {
+  return state_;
+}
+
+std::string IdentityGetAuthTokenError::ToString() const {
+  switch (state_) {
+    case State::kNone:
+      return std::string();
+    case State::kInvalidClientId:
+      return identity_constants::kInvalidClientId;
+    case State::kEmptyScopes:
+    case State::kOAuth2InvalidScopes:
+      return identity_constants::kInvalidScopes;
+    case State::kGaiaFlowAuthFailure:
+    case State::kMintTokenAuthFailure:
+    case State::kGetAccessTokenAuthFailure:
+    case State::kOAuth2Failure:
+      return identity_constants::kAuthFailure + error_message_;
+    case State::kNoGrant:
+    case State::kGaiaConsentInteractionRequired:
+    case State::kGaiaConsentInteractionAlreadyRunning:
+      return identity_constants::kNoGrant;
+    case State::kOAuth2AccessDenied:
+    case State::kGaiaFlowRejected:
+    case State::kRemoteConsentFlowRejected:
+      return identity_constants::kUserRejected;
+    case State::kUserNotSignedIn:
+    case State::kNotWhitelistedInPublicSession:
+    case State::kSignInFailed:
+    case State::kRemoteConsentUserNotSignedIn:
+      return identity_constants::kUserNotSignedIn;
+    case State::kUserNonPrimary:
+    case State::kRemoteConsentUserNonPrimary:
+      return identity_constants::kUserNonPrimary;
+    case State::kBrowserSigninNotAllowed:
+      return identity_constants::kBrowserSigninNotAllowed;
+    case State::kInvalidRedirect:
+      return identity_constants::kInvalidRedirect;
+    case State::kOffTheRecord:
+      return identity_constants::kOffTheRecord;
+    case State::kPageLoadFailure:
+    case State::kRemoteConsentPageLoadFailure:
+      return identity_constants::kPageLoadFailure;
+    case State::kSetAccountsInCookieFailure:
+      return identity_constants::kSetAccountsInCookieFailure;
+    case State::kInvalidConsentResult:
+      return identity_constants::kInvalidConsentResult;
+    case State::kCanceled:
+      return identity_constants::kCanceled;
+  }
+}
+
+IdentityGetAuthTokenError::IdentityGetAuthTokenError(State state,
+                                                     base::StringPiece error)
+    : state_(state), error_message_(error) {}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/identity_get_auth_token_error.h b/chrome/browser/extensions/api/identity/identity_get_auth_token_error.h
new file mode 100644
index 0000000..e03a89ce
--- /dev/null
+++ b/chrome/browser/extensions/api/identity/identity_get_auth_token_error.h
@@ -0,0 +1,90 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_AUTH_TOKEN_ERROR_H_
+#define CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_AUTH_TOKEN_ERROR_H_
+
+#include <string>
+
+#include "base/strings/string_piece_forward.h"
+
+namespace extensions {
+
+class IdentityGetAuthTokenError {
+ public:
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class State {
+    kNone = 0,
+    kInvalidClientId = 1,
+    kEmptyScopes = 2,
+    kOAuth2InvalidScopes = 3,
+    kGaiaFlowAuthFailure = 4,
+    kMintTokenAuthFailure = 5,
+    kGetAccessTokenAuthFailure = 6,
+    kOAuth2Failure = 7,
+    kNoGrant = 8,
+    kGaiaConsentInteractionRequired = 9,
+    kGaiaConsentInteractionAlreadyRunning = 10,
+    kOAuth2AccessDenied = 11,
+    kGaiaFlowRejected = 12,
+    kRemoteConsentFlowRejected = 13,
+    kUserNotSignedIn = 14,
+    kNotWhitelistedInPublicSession = 15,
+    kSignInFailed = 16,
+    kRemoteConsentUserNotSignedIn = 17,
+    kUserNonPrimary = 18,
+    kRemoteConsentUserNonPrimary = 19,
+    kBrowserSigninNotAllowed = 20,
+    kInvalidRedirect = 21,
+    kOffTheRecord = 22,
+    kPageLoadFailure = 23,
+    kRemoteConsentPageLoadFailure = 24,
+    kSetAccountsInCookieFailure = 25,
+    kInvalidConsentResult = 26,
+    kCanceled = 27,
+    kMaxValue = kCanceled,
+  };
+
+  // Constructs a |State::kGaiaFlowAuthFailure| error with an |error_message|.
+  static IdentityGetAuthTokenError FromGaiaFlowAuthError(
+      base::StringPiece error_message);
+
+  // Constructs a |State::kMintTokenAuthFailure| error with an
+  // |error_message|.
+  static IdentityGetAuthTokenError FromMintTokenAuthError(
+      base::StringPiece error_message);
+
+  // Constructs a |State::kGetAccessTokenAuthFailure| error with an
+  // |error_message|.
+  static IdentityGetAuthTokenError FromGetAccessTokenAuthError(
+      base::StringPiece error_message);
+
+  // Constructs an IdentityGetAuthTokenError from |oauth2_error|.
+  static IdentityGetAuthTokenError FromOAuth2Error(
+      base::StringPiece oauth2_error);
+
+  // Constructs a |State::kNone| error.
+  IdentityGetAuthTokenError();
+
+  // Constructs an IdentityGetAuthTokenError from |state| with no additional
+  // data.
+  explicit IdentityGetAuthTokenError(State state);
+
+  State state() const;
+
+  // Returns an error message that can be returned to the developer in
+  // chrome.runtime.lastError.
+  std::string ToString() const;
+
+ private:
+  IdentityGetAuthTokenError(State state, base::StringPiece error);
+
+  State state_;
+  std::string error_message_;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_API_IDENTITY_IDENTITY_GET_AUTH_TOKEN_ERROR_H_
diff --git a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
index 6b6c09d..93e6567 100644
--- a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
+++ b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/feature_list.h"
 #include "base/location.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/notreached.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
@@ -18,6 +19,7 @@
 #include "chrome/browser/browser_process_platform_part.h"
 #include "chrome/browser/extensions/api/identity/identity_api.h"
 #include "chrome/browser/extensions/api/identity/identity_constants.h"
+#include "chrome/browser/extensions/api/identity/identity_get_auth_token_error.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/chrome_device_id_helper.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -77,6 +79,11 @@
   return version_info::GetChannelString(chrome::GetChannel());
 }
 
+void RecordFunctionResult(const IdentityGetAuthTokenError& error) {
+  base::UmaHistogramEnumeration("Signin.Extensions.GetAuthTokenResult",
+                                error.state());
+}
+
 }  // namespace
 
 IdentityGetAuthTokenFunction::IdentityGetAuthTokenFunction()
@@ -104,7 +111,10 @@
                                     this, "extension", extension()->id());
 
   if (GetProfile()->IsOffTheRecord()) {
-    return RespondNow(Error(identity_constants::kOffTheRecord));
+    IdentityGetAuthTokenError error(
+        IdentityGetAuthTokenError::State::kOffTheRecord);
+    RecordFunctionResult(error);
+    return RespondNow(Error(error.ToString()));
   }
 
   std::unique_ptr<api::identity::GetAuthToken::Params> params(
@@ -122,7 +132,10 @@
   // Check that the necessary information is present in the manifest.
   oauth2_client_id_ = GetOAuth2ClientId();
   if (oauth2_client_id_.empty()) {
-    return RespondNow(Error(identity_constants::kInvalidClientId));
+    IdentityGetAuthTokenError error(
+        IdentityGetAuthTokenError::State::kInvalidClientId);
+    RecordFunctionResult(error);
+    return RespondNow(Error(error.ToString()));
   }
 
   std::set<std::string> scopes(oauth2_info.scopes.begin(),
@@ -140,7 +153,10 @@
   }
 
   if (scopes.empty()) {
-    return RespondNow(Error(identity_constants::kInvalidScopes));
+    IdentityGetAuthTokenError error(
+        IdentityGetAuthTokenError::State::kEmptyScopes);
+    RecordFunctionResult(error);
+    return RespondNow(Error(error.ToString()));
   }
 
   token_key_.scopes = scopes;
@@ -186,7 +202,8 @@
   // than the primary account.
   if (primary_account_only && !extension_gaia_id.empty() &&
       extension_gaia_id != primary_account_info.gaia) {
-    CompleteFunctionWithError(identity_constants::kUserNonPrimary);
+    CompleteFunctionWithError(IdentityGetAuthTokenError(
+        IdentityGetAuthTokenError::State::kUserNonPrimary));
     return;
   }
 
@@ -230,7 +247,8 @@
 
   if (connector->IsEnterpriseManaged() && (is_kiosk || is_public_session)) {
     if (is_public_session && !IsOriginWhitelistedInPublicSession()) {
-      CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+      CompleteFunctionWithError(IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kNotWhitelistedInPublicSession));
       return;
     }
 
@@ -243,10 +261,11 @@
       !IdentityManagerFactory::GetForProfile(GetProfile())
            ->HasAccountWithRefreshToken(account_info->account_id)) {
     if (!ShouldStartSigninFlow()) {
-      CompleteFunctionWithError(
+      IdentityGetAuthTokenError error(
           IsBrowserSigninAllowed(GetProfile())
-              ? identity_constants::kUserNotSignedIn
-              : identity_constants::kBrowserSigninNotAllowed);
+              ? IdentityGetAuthTokenError::State::kUserNotSignedIn
+              : IdentityGetAuthTokenError::State::kBrowserSigninNotAllowed);
+      CompleteFunctionWithError(error);
       return;
     }
     // Display a login prompt.
@@ -303,14 +322,16 @@
 
 void IdentityGetAuthTokenFunction::CompleteFunctionWithResult(
     const std::string& access_token) {
+  RecordFunctionResult(IdentityGetAuthTokenError());
   CompleteAsyncRun(OneArgument(std::make_unique<base::Value>(access_token)));
 }
 
 void IdentityGetAuthTokenFunction::CompleteFunctionWithError(
-    const std::string& error) {
+    const IdentityGetAuthTokenError& error) {
   TRACE_EVENT_NESTABLE_ASYNC_INSTANT1("identity", "CompleteFunctionWithError",
-                                      this, "error", error);
-  CompleteAsyncRun(Error(error));
+                                      this, "error", error.ToString());
+  RecordFunctionResult(error);
+  CompleteAsyncRun(Error(error.ToString()));
 }
 
 bool IdentityGetAuthTokenFunction::ShouldStartSigninFlow() {
@@ -394,7 +415,8 @@
 
     if (type == IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE) {
       // GAIA told us to do a consent UI.
-      CompleteFunctionWithError(identity_constants::kNoGrant);
+      CompleteFunctionWithError(IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kGaiaConsentInteractionRequired));
       return;
     }
     // TODO(https://crbug.com/1026237): figure out whether this can be ignored
@@ -402,7 +424,9 @@
     if (!id_api->mint_queue()->empty(
             IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE, token_key_)) {
       // Another call is going through a consent UI.
-      CompleteFunctionWithError(identity_constants::kNoGrant);
+      CompleteFunctionWithError(
+          IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::
+                                        kGaiaConsentInteractionAlreadyRunning));
       return;
     }
   }
@@ -438,7 +462,9 @@
         // Always force minting token for ChromeOS kiosk app and public session.
         if (user_manager::UserManager::Get()->IsLoggedInAsPublicAccount() &&
             !IsOriginWhitelistedInPublicSession()) {
-          CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+          CompleteFunctionWithError(
+              IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::
+                                            kNotWhitelistedInPublicSession));
           return;
         }
 
@@ -559,8 +585,8 @@
       break;
   }
 
-  CompleteFunctionWithError(std::string(identity_constants::kAuthFailure) +
-                            error.ToString());
+  CompleteFunctionWithError(
+      IdentityGetAuthTokenError::FromMintTokenAuthError(error.ToString()));
 }
 
 void IdentityGetAuthTokenFunction::OnIssueAdviceSuccess(
@@ -617,6 +643,20 @@
   }
 }
 
+bool IdentityGetAuthTokenFunction::TryRecoverFromServiceAuthError(
+    const GoogleServiceAuthError& error) {
+  // If this is really an authentication error and not just a transient
+  // network error, then we show signin UI if appropriate.
+  if (error.state() != GoogleServiceAuthError::CONNECTION_FAILED &&
+      error.state() != GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
+    if (ShouldStartSigninFlow()) {
+      StartSigninFlow();
+      return true;
+    }
+  }
+  return false;
+}
+
 void IdentityGetAuthTokenFunction::OnPrimaryAccountSet(
     const CoreAccountInfo& primary_account_info) {
   if (account_listening_mode_ != AccountListeningMode::kListeningPrimaryAccount)
@@ -638,7 +678,8 @@
 
 void IdentityGetAuthTokenFunction::SigninFailed() {
   TRACE_EVENT_NESTABLE_ASYNC_INSTANT0("identity", "SigninFailed", this);
-  CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+  CompleteFunctionWithError(IdentityGetAuthTokenError(
+      IdentityGetAuthTokenError::State::kSignInFailed));
 }
 
 void IdentityGetAuthTokenFunction::OnGaiaFlowFailure(
@@ -646,43 +687,40 @@
     GoogleServiceAuthError service_error,
     const std::string& oauth_error) {
   CompleteMintTokenFlow();
-  std::string error;
+  IdentityGetAuthTokenError error;
 
   switch (failure) {
     case GaiaWebAuthFlow::WINDOW_CLOSED:
-      error = identity_constants::kUserRejected;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kGaiaFlowRejected);
       break;
 
     case GaiaWebAuthFlow::INVALID_REDIRECT:
-      error = identity_constants::kInvalidRedirect;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kInvalidRedirect);
       break;
 
     case GaiaWebAuthFlow::SERVICE_AUTH_ERROR:
-      // If this is really an authentication error and not just a transient
-      // network error, then we show signin UI if appropriate.
-      if (service_error.state() != GoogleServiceAuthError::CONNECTION_FAILED &&
-          service_error.state() !=
-              GoogleServiceAuthError::SERVICE_UNAVAILABLE) {
-        if (ShouldStartSigninFlow()) {
-          StartSigninFlow();
-          return;
-        }
+      if (TryRecoverFromServiceAuthError(service_error)) {
+        return;
       }
-      error = std::string(identity_constants::kAuthFailure) +
-              service_error.ToString();
+      error = IdentityGetAuthTokenError::FromGaiaFlowAuthError(
+          service_error.ToString());
       break;
 
     case GaiaWebAuthFlow::OAUTH_ERROR:
-      error = MapOAuth2ErrorToDescription(oauth_error);
+      error = IdentityGetAuthTokenError::FromOAuth2Error(oauth_error);
       break;
 
     case GaiaWebAuthFlow::LOAD_FAILED:
-      error = identity_constants::kPageLoadFailure;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kPageLoadFailure);
       break;
 
     default:
       NOTREACHED() << "Unexpected error from gaia web auth flow: " << failure;
-      error = identity_constants::kInvalidRedirect;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kInvalidRedirect);
       break;
   }
 
@@ -709,27 +747,32 @@
 void IdentityGetAuthTokenFunction::OnGaiaRemoteConsentFlowFailed(
     GaiaRemoteConsentFlow::Failure failure) {
   CompleteMintTokenFlow();
-  std::string error;
+  IdentityGetAuthTokenError error;
 
   switch (failure) {
     case GaiaRemoteConsentFlow::WINDOW_CLOSED:
-      error = identity_constants::kUserRejected;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kRemoteConsentFlowRejected);
       break;
 
     case GaiaRemoteConsentFlow::SET_ACCOUNTS_IN_COOKIE_FAILED:
-      error = identity_constants::kSetAccountsInCookieFailure;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kSetAccountsInCookieFailure);
       break;
 
     case GaiaRemoteConsentFlow::LOAD_FAILED:
-      error = identity_constants::kPageLoadFailure;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kRemoteConsentPageLoadFailure);
       break;
 
     case GaiaRemoteConsentFlow::INVALID_CONSENT_RESULT:
-      error = identity_constants::kInvalidConsentResult;
+      error = IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kInvalidConsentResult);
       break;
 
     case GaiaRemoteConsentFlow::NO_GRANT:
-      error = identity_constants::kNoGrant;
+      error =
+          IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::kNoGrant);
       break;
 
     case GaiaRemoteConsentFlow::NONE:
@@ -752,7 +795,8 @@
       IdentityManagerFactory::GetForProfile(GetProfile())
           ->FindExtendedAccountInfoForAccountWithRefreshTokenByGaiaId(gaia_id);
   if (!account) {
-    CompleteFunctionWithError(identity_constants::kUserNotSignedIn);
+    CompleteFunctionWithError(IdentityGetAuthTokenError(
+        IdentityGetAuthTokenError::State::kRemoteConsentUserNotSignedIn));
     return;
   }
 
@@ -761,7 +805,8 @@
         IdentityManagerFactory::GetForProfile(GetProfile())
             ->GetPrimaryAccountId();
     if (primary_account_id != account->account_id) {
-      CompleteFunctionWithError(identity_constants::kUserNonPrimary);
+      CompleteFunctionWithError(IdentityGetAuthTokenError(
+          IdentityGetAuthTokenError::State::kRemoteConsentUserNonPrimary));
       return;
     }
   }
@@ -797,8 +842,13 @@
     TRACE_EVENT_NESTABLE_ASYNC_END1("identity", "GetAccessToken", this, "error",
                                     error.ToString());
 
-    OnGaiaFlowFailure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR, error,
-                      std::string());
+    CompleteMintTokenFlow();
+    if (TryRecoverFromServiceAuthError(error)) {
+      return;
+    }
+    CompleteFunctionWithError(
+        IdentityGetAuthTokenError::FromGetAccessTokenAuthError(
+            error.ToString()));
   }
 }
 
@@ -843,7 +893,8 @@
       ->mint_queue()
       ->RequestCancel(token_key_, this);
 
-  CompleteFunctionWithError(identity_constants::kCanceled);
+  CompleteFunctionWithError(
+      IdentityGetAuthTokenError(IdentityGetAuthTokenError::State::kCanceled));
 }
 
 #if defined(OS_CHROMEOS)
@@ -966,19 +1017,6 @@
   return identity_manager->HasAccountWithRefreshToken(token_key_.account_id);
 }
 
-std::string IdentityGetAuthTokenFunction::MapOAuth2ErrorToDescription(
-    const std::string& error) {
-  const char kOAuth2ErrorAccessDenied[] = "access_denied";
-  const char kOAuth2ErrorInvalidScope[] = "invalid_scope";
-
-  if (error == kOAuth2ErrorAccessDenied)
-    return std::string(identity_constants::kUserRejected);
-  else if (error == kOAuth2ErrorInvalidScope)
-    return std::string(identity_constants::kInvalidScopes);
-  else
-    return std::string(identity_constants::kAuthFailure) + error;
-}
-
 std::string IdentityGetAuthTokenFunction::GetOAuth2ClientId() const {
   const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension());
   std::string client_id = oauth2_info.client_id;
diff --git a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
index 77dae78..97ba8b22 100644
--- a/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
+++ b/chrome/browser/extensions/api/identity/identity_get_auth_token_function.h
@@ -28,6 +28,7 @@
 }  // namespace signin
 
 namespace extensions {
+class IdentityGetAuthTokenError;
 
 // identity.getAuthToken fetches an OAuth 2 function for the
 // caller. The request has three sub-flows: non-interactive,
@@ -155,6 +156,11 @@
   void OnPrimaryAccountSet(
       const CoreAccountInfo& primary_account_info) override;
 
+  // Attempts to show the signin UI after the service auth error if this error
+  // isn't transient.
+  // Returns true iff the signin flow was triggered.
+  bool TryRecoverFromServiceAuthError(const GoogleServiceAuthError& error);
+
   // ExtensionFunction:
   ResponseAction Run() override;
 
@@ -162,7 +168,7 @@
   void StartAsyncRun();
   void CompleteAsyncRun(ResponseValue response);
   void CompleteFunctionWithResult(const std::string& access_token);
-  void CompleteFunctionWithError(const std::string& error);
+  void CompleteFunctionWithError(const IdentityGetAuthTokenError& error);
 
   // Whether a signin flow should be initiated in the user's current state.
   bool ShouldStartSigninFlow();
@@ -202,10 +208,6 @@
   // Checks if there is a master login token to mint tokens for the extension.
   bool HasRefreshTokenForTokenKeyAccount() const;
 
-  // Maps OAuth2 protocol errors to an error message returned to the
-  // developer in chrome.runtime.lastError.
-  std::string MapOAuth2ErrorToDescription(const std::string& error);
-
   std::string GetOAuth2ClientId() const;
 
   // Returns true if extensions are restricted to the primary account.
diff --git a/chrome/browser/extensions/api/messaging/native_message_process_host.cc b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
index 6dba3532..d1d51bfa 100644
--- a/chrome/browser/extensions/api/messaging/native_message_process_host.cc
+++ b/chrome/browser/extensions/api/messaging/native_message_process_host.cc
@@ -59,7 +59,7 @@
     const std::string& source_extension_id,
     const std::string& native_host_name,
     std::unique_ptr<NativeProcessLauncher> launcher)
-    : client_(NULL),
+    : client_(nullptr),
       source_extension_id_(source_extension_id),
       native_host_name_(native_host_name),
       launcher_(std::move(launcher)),
diff --git a/chrome/browser/extensions/api/preference/preference_apitest.cc b/chrome/browser/extensions/api/preference/preference_apitest.cc
index 3dfd9b01..f37fe57 100644
--- a/chrome/browser/extensions/api/preference/preference_apitest.cc
+++ b/chrome/browser/extensions/api/preference/preference_apitest.cc
@@ -42,7 +42,7 @@
 
 class ExtensionPreferenceApiTest : public extensions::ExtensionApiTest {
  protected:
-  ExtensionPreferenceApiTest() : profile_(NULL) {}
+  ExtensionPreferenceApiTest() : profile_(nullptr) {}
 
   void CheckPreferencesSet() {
     PrefService* prefs = profile_->GetPrefs();
diff --git a/chrome/browser/extensions/api/resources_private/resources_private_api.cc b/chrome/browser/extensions/api/resources_private/resources_private_api.cc
index 908ec40..67f9665 100644
--- a/chrome/browser/extensions/api/resources_private/resources_private_api.cc
+++ b/chrome/browser/extensions/api/resources_private/resources_private_api.cc
@@ -10,21 +10,15 @@
 
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
-#include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/extensions/api/resources_private.h"
 #include "chrome/grit/generated_resources.h"
-#include "components/strings/grit/components_strings.h"
-#include "components/zoom/page_zoom_constants.h"
 #include "pdf/buildflags.h"
 #include "printing/buildflags/buildflags.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/webui/web_ui_util.h"
 
 #if BUILDFLAG(ENABLE_PDF)
-#include "pdf/pdf_features.h"
-#if defined(OS_CHROMEOS)
-#include "chrome/browser/chromeos/login/ui/login_display_host.h"
-#endif  // defined(OS_CHROMEOS)
+#include "chrome/browser/pdf/pdf_extension_util.h"
 #endif  // BUILDFLAG(ENABLE_PDF)
 
 // To add a new component to this API, simply:
@@ -42,112 +36,6 @@
                   l10n_util::GetStringUTF16(IDS_EXTENSION_CONFIRM_PERMISSIONS));
 }
 
-void AddStringsForPdf(base::DictionaryValue* dict) {
-#if BUILDFLAG(ENABLE_PDF)
-  static constexpr webui::LocalizedString kPdfResources[] = {
-    {"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE},
-    {"passwordPrompt", IDS_PDF_NEED_PASSWORD},
-    {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT},
-    {"passwordInvalid", IDS_PDF_PASSWORD_INVALID},
-    {"pageLoading", IDS_PDF_PAGE_LOADING},
-    {"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED},
-    {"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE},
-    {"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON},
-    {"bookmarks", IDS_PDF_BOOKMARKS},
-    {"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER},
-    {"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW},
-    {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
-    {"tooltipPrint", IDS_PDF_TOOLTIP_PRINT},
-    {"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE},
-    {"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH},
-    {"tooltipTwoUpViewEnable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_ENABLE},
-    {"tooltipTwoUpViewDisable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_DISABLE},
-    {"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN},
-    {"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT},
-#if defined(OS_CHROMEOS)
-    {"tooltipAnnotate", IDS_PDF_ANNOTATION_ANNOTATE},
-    {"annotationDocumentTooLarge", IDS_PDF_ANNOTATION_DOCUMENT_TOO_LARGE},
-    {"annotationDocumentProtected", IDS_PDF_ANNOTATION_DOCUMENT_PROTECTED},
-    {"annotationDocumentRotated", IDS_PDF_ANNOTATION_DOCUMENT_ROTATED},
-    {"annotationPen", IDS_PDF_ANNOTATION_PEN},
-    {"annotationHighlighter", IDS_PDF_ANNOTATION_HIGHLIGHTER},
-    {"annotationEraser", IDS_PDF_ANNOTATION_ERASER},
-    {"annotationUndo", IDS_PDF_ANNOTATION_UNDO},
-    {"annotationRedo", IDS_PDF_ANNOTATION_REDO},
-    {"annotationExpand", IDS_PDF_ANNOTATION_EXPAND},
-    {"annotationColorBlack", IDS_PDF_ANNOTATION_COLOR_BLACK},
-    {"annotationColorRed", IDS_PDF_ANNOTATION_COLOR_RED},
-    {"annotationColorYellow", IDS_PDF_ANNOTATION_COLOR_YELLOW},
-    {"annotationColorGreen", IDS_PDF_ANNOTATION_COLOR_GREEN},
-    {"annotationColorCyan", IDS_PDF_ANNOTATION_COLOR_CYAN},
-    {"annotationColorPurple", IDS_PDF_ANNOTATION_COLOR_PURPLE},
-    {"annotationColorBrown", IDS_PDF_ANNOTATION_COLOR_BROWN},
-    {"annotationColorWhite", IDS_PDF_ANNOTATION_COLOR_WHITE},
-    {"annotationColorCrimson", IDS_PDF_ANNOTATION_COLOR_CRIMSON},
-    {"annotationColorAmber", IDS_PDF_ANNOTATION_COLOR_AMBER},
-    {"annotationColorAvocadoGreen", IDS_PDF_ANNOTATION_COLOR_AVOCADO_GREEN},
-    {"annotationColorCobaltBlue", IDS_PDF_ANNOTATION_COLOR_COBALT_BLUE},
-    {"annotationColorDeepPurple", IDS_PDF_ANNOTATION_COLOR_DEEP_PURPLE},
-    {"annotationColorDarkBrown", IDS_PDF_ANNOTATION_COLOR_DARK_BROWN},
-    {"annotationColorDarkGrey", IDS_PDF_ANNOTATION_COLOR_DARK_GREY},
-    {"annotationColorHotPink", IDS_PDF_ANNOTATION_COLOR_HOT_PINK},
-    {"annotationColorOrange", IDS_PDF_ANNOTATION_COLOR_ORANGE},
-    {"annotationColorLime", IDS_PDF_ANNOTATION_COLOR_LIME},
-    {"annotationColorBlue", IDS_PDF_ANNOTATION_COLOR_BLUE},
-    {"annotationColorViolet", IDS_PDF_ANNOTATION_COLOR_VIOLET},
-    {"annotationColorTeal", IDS_PDF_ANNOTATION_COLOR_TEAL},
-    {"annotationColorLightGrey", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREY},
-    {"annotationColorLightPink", IDS_PDF_ANNOTATION_COLOR_LIGHT_PINK},
-    {"annotationColorLightOrange", IDS_PDF_ANNOTATION_COLOR_LIGHT_ORANGE},
-    {"annotationColorLightGreen", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREEN},
-    {"annotationColorLightBlue", IDS_PDF_ANNOTATION_COLOR_LIGHT_BLUE},
-    {"annotationColorLavender", IDS_PDF_ANNOTATION_COLOR_LAVENDER},
-    {"annotationColorLightTeal", IDS_PDF_ANNOTATION_COLOR_LIGHT_TEAL},
-    {"annotationSize1", IDS_PDF_ANNOTATION_SIZE1},
-    {"annotationSize2", IDS_PDF_ANNOTATION_SIZE2},
-    {"annotationSize3", IDS_PDF_ANNOTATION_SIZE3},
-    {"annotationSize4", IDS_PDF_ANNOTATION_SIZE4},
-    {"annotationSize8", IDS_PDF_ANNOTATION_SIZE8},
-    {"annotationSize12", IDS_PDF_ANNOTATION_SIZE12},
-    {"annotationSize16", IDS_PDF_ANNOTATION_SIZE16},
-    {"annotationSize20", IDS_PDF_ANNOTATION_SIZE20},
-    {"annotationFormWarningTitle", IDS_PDF_DISCARD_FORM_CHANGES},
-    {"annotationFormWarningDetail", IDS_PDF_DISCARD_FORM_CHANGES_DETAIL},
-    {"annotationFormWarningKeepEditing", IDS_PDF_KEEP_EDITING},
-    {"annotationFormWarningDiscard", IDS_PDF_DISCARD},
-#endif  // defined(OS_CHROMEOS)
-  };
-  for (const auto& resource : kPdfResources)
-    dict->SetString(resource.name, l10n_util::GetStringUTF16(resource.id));
-
-  dict->SetString("presetZoomFactors", zoom::GetPresetZoomFactorsAsJSON());
-#endif  // BUILDFLAG(ENABLE_PDF)
-}
-
-void AddAdditionalDataForPdf(base::DictionaryValue* dict) {
-#if BUILDFLAG(ENABLE_PDF)
-  dict->SetKey("pdfFormSaveEnabled",
-               base::Value(base::FeatureList::IsEnabled(
-                   chrome_pdf::features::kSaveEditedPDFForm)));
-  dict->SetKey("pdfTwoUpViewEnabled",
-               base::Value(base::FeatureList::IsEnabled(
-                   chrome_pdf::features::kPDFTwoUpView)));
-  dict->SetKey("pdfViewerUpdateEnabled",
-               base::Value(base::FeatureList::IsEnabled(
-                   chrome_pdf::features::kPDFViewerUpdate)));
-
-  bool enable_printing = true;
-  bool enable_annotations = false;
-#if defined(OS_CHROMEOS)
-  // For Chrome OS, enable printing only if we are not at OOBE.
-  enable_printing = !chromeos::LoginDisplayHost::default_host();
-  enable_annotations = true;
-#endif  // defined(OS_CHROMEOS)
-  dict->SetKey("printingEnabled", base::Value(enable_printing));
-  dict->SetKey("pdfAnnotationsEnabled", base::Value(enable_annotations));
-#endif  // BUILDFLAG(ENABLE_PDF)
-}
-
 }  // namespace
 
 namespace get_strings = api::resources_private::GetStrings;
@@ -167,10 +55,12 @@
     case api::resources_private::COMPONENT_IDENTITY:
       AddStringsForIdentity(dict.get());
       break;
-    case api::resources_private::COMPONENT_PDF:
-      AddStringsForPdf(dict.get());
-      AddAdditionalDataForPdf(dict.get());
-      break;
+#if BUILDFLAG(ENABLE_PDF)
+    case api::resources_private::COMPONENT_PDF: {
+      pdf_extension_util::AddStrings(dict.get());
+      pdf_extension_util::AddAdditionalData(dict.get());
+    } break;
+#endif  // BUILDFLAG(ENABLE_PDF)
     case api::resources_private::COMPONENT_NONE:
       NOTREACHED();
   }
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index bc44d214..a6411045 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -1211,8 +1211,7 @@
   return true;
 }
 
-TabsUpdateFunction::TabsUpdateFunction() : web_contents_(NULL) {
-}
+TabsUpdateFunction::TabsUpdateFunction() : web_contents_(nullptr) {}
 
 ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
   std::unique_ptr<tabs::Update::Params> params(
diff --git a/chrome/browser/extensions/app_background_page_apitest.cc b/chrome/browser/extensions/app_background_page_apitest.cc
index d2052b4..59f7254 100644
--- a/chrome/browser/extensions/app_background_page_apitest.cc
+++ b/chrome/browser/extensions/app_background_page_apitest.cc
@@ -145,8 +145,7 @@
 // Native Client embeds.
 class AppBackgroundPageNaClTest : public AppBackgroundPageApiTest {
  public:
-  AppBackgroundPageNaClTest()
-      : extension_(NULL) {}
+  AppBackgroundPageNaClTest() : extension_(nullptr) {}
   ~AppBackgroundPageNaClTest() override {}
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
index af3a918..1b2387f 100644
--- a/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
+++ b/chrome/browser/extensions/chrome_component_extension_resource_manager.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/extensions/chrome_component_extension_resource_manager.h"
 
+#include <string>
+
 #include "base/check.h"
 #include "base/path_service.h"
 #include "base/stl_util.h"
@@ -13,18 +15,24 @@
 #include "chrome/grit/chrome_unscaled_resources.h"
 #include "chrome/grit/component_extension_resources_map.h"
 #include "chrome/grit/theme_resources.h"
+#include "extensions/common/constants.h"
+#include "pdf/buildflags.h"
+#include "ui/base/resource/resource_bundle.h"
 
 #if defined(OS_CHROMEOS)
 #include "ash/keyboard/ui/resources/keyboard_resource_util.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/file_manager/file_manager_string_util.h"
-#include "extensions/common/constants.h"
 #include "third_party/ink/grit/ink_resources.h"
-#include "ui/base/resource/resource_bundle.h"
 #include "ui/file_manager/file_manager_resource_util.h"
 #include "ui/file_manager/grit/file_manager_resources.h"
 #endif
 
+#if BUILDFLAG(ENABLE_PDF)
+#include <utility>
+#include "chrome/browser/pdf/pdf_extension_util.h"
+#endif
+
 namespace extensions {
 
 ChromeComponentExtensionResourceManager::
@@ -78,6 +86,21 @@
       keyboard_resources,
       keyboard_resource_size);
 #endif
+
+#if BUILDFLAG(ENABLE_PDF)
+  // ResourceBundle is not always initialized in unit tests.
+  if (ui::ResourceBundle::HasSharedInstance()) {
+    base::Value dict(base::Value::Type::DICTIONARY);
+    pdf_extension_util::AddStrings(&dict);
+    pdf_extension_util::AddAdditionalData(&dict);
+
+    ui::TemplateReplacements pdf_viewer_replacements;
+    ui::TemplateReplacementsFromDictionaryValue(
+        base::Value::AsDictionaryValue(dict), &pdf_viewer_replacements);
+    extension_template_replacements_[extension_misc::kPdfExtensionId] =
+        std::move(pdf_viewer_replacements);
+  }
+#endif
 }
 
 ChromeComponentExtensionResourceManager::
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc
index c9a3c72d..4b64874 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_client.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -8,6 +8,8 @@
 
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "base/optional.h"
+#include "base/strings/string_util.h"
 #include "base/version.h"
 #include "build/build_config.h"
 #include "chrome/browser/app_mode/app_mode_utils.h"
@@ -60,6 +62,7 @@
 #include "extensions/browser/extensions_browser_interface_binders.h"
 #include "extensions/browser/pref_names.h"
 #include "extensions/browser/url_request_util.h"
+#include "extensions/common/extension_urls.h"
 #include "extensions/common/features/feature_channel.h"
 
 #if defined(OS_CHROMEOS)
@@ -77,6 +80,9 @@
 
 namespace {
 
+const char kCrxUrlPath[] = "/service/update2/crx";
+const char kJsonUrlPath[] = "/service/update2/json";
+
 // If true, the extensions client will behave as though there is always a
 // new chrome update.
 bool g_did_chrome_update_for_testing = false;
@@ -443,8 +449,17 @@
 scoped_refptr<update_client::UpdateClient>
 ChromeExtensionsBrowserClient::CreateUpdateClient(
     content::BrowserContext* context) {
+  base::Optional<GURL> override_url;
+  GURL update_url = extension_urls::GetWebstoreUpdateUrl();
+  if (update_url != extension_urls::GetDefaultWebstoreUpdateUrl()) {
+    if (update_url.path() == kCrxUrlPath) {
+      override_url = update_url.GetWithEmptyPath().Resolve(kJsonUrlPath);
+    } else {
+      override_url = update_url;
+    }
+  }
   return update_client::UpdateClientFactory(
-      ChromeUpdateClientConfig::Create(context));
+      ChromeUpdateClientConfig::Create(context, override_url));
 }
 
 std::unique_ptr<content::BluetoothChooser>
diff --git a/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc b/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc
index 54c74ff..6c0af0c 100644
--- a/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc
+++ b/chrome/browser/extensions/chrome_extensions_browser_interface_binders.cc
@@ -20,11 +20,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/speech/extension_api/tts_engine_extension_observer.h"
 #include "chrome/common/extensions/extension_constants.h"
-#include "chromeos/components/camera_app_ui/camera_app_helper.mojom.h"
-#include "chromeos/components/camera_app_ui/camera_app_helper_impl.h"
 #include "chromeos/services/media_perception/public/mojom/media_perception.mojom.h"
 #include "chromeos/services/tts/public/mojom/tts_service.mojom.h"
 #include "components/arc/intent_helper/arc_intent_helper_bridge.h"
+#include "components/chromeos_camera/camera_app_helper_impl.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/media_device_id.h"
 #include "content/public/browser/video_capture_service.h"
diff --git a/chrome/browser/extensions/error_console/error_console_browsertest.cc b/chrome/browser/extensions/error_console/error_console_browsertest.cc
index 6d1f721..4b7bcb0 100644
--- a/chrome/browser/extensions/error_console/error_console_browsertest.cc
+++ b/chrome/browser/extensions/error_console/error_console_browsertest.cc
@@ -132,7 +132,7 @@
 
 class ErrorConsoleBrowserTest : public ExtensionBrowserTest {
  public:
-  ErrorConsoleBrowserTest() : error_console_(NULL) { }
+  ErrorConsoleBrowserTest() : error_console_(nullptr) {}
   ~ErrorConsoleBrowserTest() override {}
 
  protected:
diff --git a/chrome/browser/extensions/extension_browsertest.cc b/chrome/browser/extensions/extension_browsertest.cc
index ba028116..206257d 100644
--- a/chrome/browser/extensions/extension_browsertest.cc
+++ b/chrome/browser/extensions/extension_browsertest.cc
@@ -128,7 +128,7 @@
       start_menu_override_(base::DIR_START_MENU),
       common_start_menu_override_(base::DIR_COMMON_START_MENU),
 #endif
-      profile_(NULL),
+      profile_(nullptr),
       verifier_format_override_(crx_file::VerifierFormat::CRX3) {
   EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
 }
diff --git a/chrome/browser/extensions/extension_commands_global_registry.cc b/chrome/browser/extensions/extension_commands_global_registry.cc
index 5eff2d6..17d736a 100644
--- a/chrome/browser/extensions/extension_commands_global_registry.cc
+++ b/chrome/browser/extensions/extension_commands_global_registry.cc
@@ -15,9 +15,9 @@
     content::BrowserContext* context)
     : ExtensionKeybindingRegistry(context,
                                   ExtensionKeybindingRegistry::ALL_EXTENSIONS,
-                                  NULL),
+                                  nullptr),
       browser_context_(context),
-      registry_for_active_window_(NULL) {
+      registry_for_active_window_(nullptr) {
   Init();
 }
 
diff --git a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
index 1aeecc7..98e073a2 100644
--- a/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
+++ b/chrome/browser/extensions/extension_disabled_ui_browsertest.cc
@@ -65,10 +65,7 @@
         test_dir.AppendASCII("v1"),
         scoped_temp_dir_.GetPath().AppendASCII("permissions1.crx"), pem_path,
         base::FilePath());
-    path_v2_ = PackExtensionWithOptions(
-        test_dir.AppendASCII("v2"),
-        scoped_temp_dir_.GetPath().AppendASCII("permissions2.crx"), pem_path,
-        base::FilePath());
+    path_v2_ = test_dir.AppendASCII("v2.crx");
     path_v3_ = PackExtensionWithOptions(
         test_dir.AppendASCII("v3"),
         scoped_temp_dir_.GetPath().AppendASCII("permissions3.crx"), pem_path,
@@ -233,13 +230,12 @@
         if (path == "/autoupdate/updates.xml") {
           content::URLLoaderInterceptor::WriteResponse(
               test_data_dir_.AppendASCII("permissions_increase")
-                  .AppendASCII("updates.xml"),
+                  .AppendASCII("updates.json"),
               params->client.get());
           return true;
         } else if (path == "/autoupdate/v2.crx") {
-          content::URLLoaderInterceptor::WriteResponse(
-              scoped_temp_dir_.GetPath().AppendASCII("permissions2.crx"),
-              params->client.get());
+          content::URLLoaderInterceptor::WriteResponse(path_v2_,
+                                                       params->client.get());
           return true;
         }
         return false;
@@ -283,9 +279,8 @@
               params->client.get());
           return true;
         } else if (path == "/autoupdate/v2.crx") {
-          content::URLLoaderInterceptor::WriteResponse(
-              scoped_temp_dir_.GetPath().AppendASCII("permissions2.crx"),
-              params->client.get());
+          content::URLLoaderInterceptor::WriteResponse(path_v2_,
+                                                       params->client.get());
           return true;
         }
         return false;
diff --git a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc
index 03808924..9e7ec2c9 100644
--- a/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc
+++ b/chrome/browser/extensions/extension_gcm_app_handler_unittest.cc
@@ -245,7 +245,7 @@
 
   ExtensionGCMAppHandlerTest()
       : task_environment_(content::BrowserTaskEnvironment::REAL_IO_THREAD),
-        extension_service_(NULL),
+        extension_service_(nullptr),
         registration_result_(gcm::GCMClient::UNKNOWN_ERROR),
         unregistration_result_(gcm::GCMClient::UNKNOWN_ERROR) {}
 
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index b20b5d4..50eada2 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -4973,9 +4973,9 @@
     result_ = result.IsInclude();
   }
 
-  void GetAllCookiesCallback(const net::CookieStatusList& list,
-                             const net::CookieStatusList& excluded_list) {
-    list_ = net::cookie_util::StripStatuses(list);
+  void GetAllCookiesCallback(const net::CookieAccessResultList& list,
+                             const net::CookieAccessResultList& excluded_list) {
+    list_ = net::cookie_util::StripAccessResults(list);
   }
   net::CookieList list_;
   bool result_;
@@ -5120,9 +5120,9 @@
 
 void GetCookiesSaveData(std::vector<net::CanonicalCookie>* result_out,
                         base::OnceClosure callback,
-                        const net::CookieStatusList& result,
-                        const net::CookieStatusList& excluded_cookies) {
-  *result_out = net::cookie_util::StripStatuses(result);
+                        const net::CookieAccessResultList& result,
+                        const net::CookieAccessResultList& excluded_cookies) {
+  *result_out = net::cookie_util::StripAccessResults(result);
   std::move(callback).Run();
 }
 
diff --git a/chrome/browser/extensions/extension_user_script_loader_unittest.cc b/chrome/browser/extensions/extension_user_script_loader_unittest.cc
index f082883..c6184c7 100644
--- a/chrome/browser/extensions/extension_user_script_loader_unittest.cc
+++ b/chrome/browser/extensions/extension_user_script_loader_unittest.cc
@@ -43,7 +43,7 @@
 class ExtensionUserScriptLoaderTest : public testing::Test,
                                       public content::NotificationObserver {
  public:
-  ExtensionUserScriptLoaderTest() : shared_memory_(NULL) {}
+  ExtensionUserScriptLoaderTest() : shared_memory_(nullptr) {}
 
   void SetUp() override {
     ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
diff --git a/chrome/browser/extensions/external_provider_impl_unittest.cc b/chrome/browser/extensions/external_provider_impl_unittest.cc
index baa092f..fa4505f3 100644
--- a/chrome/browser/extensions/external_provider_impl_unittest.cc
+++ b/chrome/browser/extensions/external_provider_impl_unittest.cc
@@ -232,7 +232,8 @@
       extension_misc::kInAppPaymentsSupportAppId));
 }
 
-TEST_F(ExternalProviderImplTest, BlockedExternalUserProviders) {
+// Failing, see crbug.com/1092345.
+TEST_F(ExternalProviderImplTest, DISABLED_BlockedExternalUserProviders) {
   OverrideExternalExtensionsPath();
   InitServiceWithExternalProviders(true);
 
@@ -245,7 +246,8 @@
   EXPECT_FALSE(registry()->GetInstalledExtension(kExternalAppId));
 }
 
-TEST_F(ExternalProviderImplTest, NotBlockedExternalUserProviders) {
+// Failing, see crbug.com/1092345.
+TEST_F(ExternalProviderImplTest, DISABLED_NotBlockedExternalUserProviders) {
   OverrideExternalExtensionsPath();
   InitServiceWithExternalProviders(false);
 
diff --git a/chrome/browser/extensions/tab_helper.cc b/chrome/browser/extensions/tab_helper.cc
index c755a86..278307bd 100644
--- a/chrome/browser/extensions/tab_helper.cc
+++ b/chrome/browser/extensions/tab_helper.cc
@@ -78,7 +78,7 @@
 TabHelper::TabHelper(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
-      extension_app_(NULL),
+      extension_app_(nullptr),
       script_executor_(new ScriptExecutor(web_contents)),
       extension_action_runner_(new ExtensionActionRunner(web_contents)),
       declarative_net_request_helper_(web_contents) {
diff --git a/chrome/browser/extensions/test_blacklist.cc b/chrome/browser/extensions/test_blacklist.cc
index 9ac06a5e0..7dacadce 100644
--- a/chrome/browser/extensions/test_blacklist.cc
+++ b/chrome/browser/extensions/test_blacklist.cc
@@ -49,15 +49,13 @@
   states_.clear();
 }
 
-
 TestBlacklist::TestBlacklist()
-    : blacklist_(NULL),
+    : blacklist_(nullptr),
       blacklist_db_(new FakeSafeBrowsingDatabaseManager(true)),
-      scoped_blacklist_db_(blacklist_db_) {
-}
+      scoped_blacklist_db_(blacklist_db_) {}
 
 TestBlacklist::TestBlacklist(Blacklist* blacklist)
-    : blacklist_(NULL),
+    : blacklist_(nullptr),
       blacklist_db_(new FakeSafeBrowsingDatabaseManager(true)),
       scoped_blacklist_db_(blacklist_db_) {
   Attach(blacklist);
diff --git a/chrome/browser/extensions/updater/chrome_update_client_config.cc b/chrome/browser/extensions/updater/chrome_update_client_config.cc
index 5a9a967e..e8a43267 100644
--- a/chrome/browser/extensions/updater/chrome_update_client_config.cc
+++ b/chrome/browser/extensions/updater/chrome_update_client_config.cc
@@ -99,14 +99,16 @@
 // For privacy reasons, requires encryption of the component updater
 // communication with the update backend.
 ChromeUpdateClientConfig::ChromeUpdateClientConfig(
-    content::BrowserContext* context)
+    content::BrowserContext* context,
+    base::Optional<GURL> url_override)
     : context_(context),
       impl_(ExtensionUpdateClientCommandLineConfigPolicy(
                 base::CommandLine::ForCurrentProcess()),
             /*require_encryption=*/true),
       pref_service_(ExtensionPrefs::Get(context)->pref_service()),
       activity_data_service_(std::make_unique<ExtensionActivityDataService>(
-          ExtensionPrefs::Get(context))) {
+          ExtensionPrefs::Get(context))),
+      url_override_(url_override) {
   DCHECK(pref_service_);
 }
 
@@ -127,10 +129,14 @@
 }
 
 std::vector<GURL> ChromeUpdateClientConfig::UpdateUrl() const {
+  if (url_override_.has_value())
+    return {*url_override_};
   return impl_.UpdateUrl();
 }
 
 std::vector<GURL> ChromeUpdateClientConfig::PingUrl() const {
+  if (url_override_.has_value())
+    return {*url_override_};
   return impl_.PingUrl();
 }
 
@@ -220,6 +226,8 @@
 }
 
 bool ChromeUpdateClientConfig::EnabledCupSigning() const {
+  if (url_override_.has_value())
+    return false;
   return impl_.EnabledCupSigning();
 }
 
@@ -245,10 +253,11 @@
 
 // static
 scoped_refptr<ChromeUpdateClientConfig> ChromeUpdateClientConfig::Create(
-    content::BrowserContext* context) {
+    content::BrowserContext* context,
+    base::Optional<GURL> update_url_override) {
   FactoryCallback& factory = GetFactoryCallback();
-  return factory.is_null() ? scoped_refptr<ChromeUpdateClientConfig>(
-                                 new ChromeUpdateClientConfig(context))
+  return factory.is_null() ? base::MakeRefCounted<ChromeUpdateClientConfig>(
+                                 context, update_url_override)
                            : factory.Run(context);
 }
 
diff --git a/chrome/browser/extensions/updater/chrome_update_client_config.h b/chrome/browser/extensions/updater/chrome_update_client_config.h
index 0af35de..ac02720 100644
--- a/chrome/browser/extensions/updater/chrome_update_client_config.h
+++ b/chrome/browser/extensions/updater/chrome_update_client_config.h
@@ -13,9 +13,12 @@
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/optional.h"
 #include "components/component_updater/configurator_impl.h"
 #include "components/update_client/configurator.h"
 
+class GURL;
+
 namespace content {
 class BrowserContext;
 }
@@ -37,7 +40,11 @@
           content::BrowserContext* context)>;
 
   static scoped_refptr<ChromeUpdateClientConfig> Create(
-      content::BrowserContext* context);
+      content::BrowserContext* context,
+      base::Optional<GURL> url_override);
+
+  ChromeUpdateClientConfig(content::BrowserContext* context,
+                           base::Optional<GURL> url_override);
 
   int InitialDelay() const override;
   int NextCheckDelay() const override;
@@ -71,7 +78,6 @@
   friend class base::RefCountedThreadSafe<ChromeUpdateClientConfig>;
   friend class ExtensionUpdateClientBaseTest;
 
-  explicit ChromeUpdateClientConfig(content::BrowserContext* context);
   ~ChromeUpdateClientConfig() override;
 
   // Injects a new client config by changing the creation factory.
@@ -87,6 +93,7 @@
   scoped_refptr<update_client::NetworkFetcherFactory> network_fetcher_factory_;
   scoped_refptr<update_client::UnzipperFactory> unzip_factory_;
   scoped_refptr<update_client::PatcherFactory> patch_factory_;
+  base::Optional<GURL> url_override_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeUpdateClientConfig);
 };
diff --git a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc
index 697fe49..610ce86 100644
--- a/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc
+++ b/chrome/browser/extensions/updater/extension_update_client_base_browsertest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/extensions/updater/extension_update_client_base_browsertest.h"
 
 #include "base/bind.h"
+#include "base/optional.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
@@ -32,7 +33,7 @@
   TestChromeUpdateClientConfig(content::BrowserContext* context,
                                const std::vector<GURL>& update_url,
                                const std::vector<GURL>& ping_url)
-      : extensions::ChromeUpdateClientConfig(context),
+      : extensions::ChromeUpdateClientConfig(context, base::nullopt),
         update_url_(update_url),
         ping_url_(ping_url) {}
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 9bcbc057..eef55a2 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1864,8 +1864,8 @@
   },
   {
     "name": "enable-notification-indicator",
-    "owners": [ "newcomer" ],
-    "expiry_milestone": 83
+    "owners": [ "mmourgos", "newcomer" ],
+    "expiry_milestone": 88
   },
   {
     "name": "enable-offer-store-unmasked-wallet-cards",
@@ -3397,8 +3397,13 @@
   },
   {
     "name": "omnibox-ui-hide-steady-state-url-path-query-and-ref",
-    "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
-    "expiry_milestone": 76
+    "owners": [ "tommycli", "estark", "carlosil", "chrome-omnibox-team@google.com" ],
+    "expiry_milestone": 89
+  },
+  {
+    "name": "omnibox-ui-hide-steady-state-url-path-query-and-ref-on-interaction",
+    "owners": [ "estark", "carlosil", "chrome-security-enamel@google.com" ],
+    "expiry_milestone": 89
   },
   {
     "name": "omnibox-ui-hide-steady-state-url-scheme",
@@ -3416,6 +3421,11 @@
     "expiry_milestone": 85
   },
   {
+    "name": "omnibox-ui-reveal-steady-state-url-path-query-and-ref-on-hover",
+    "owners": [ "estark", "carlosil", "chrome-security-enamel@google.com" ],
+    "expiry_milestone": 89
+  },
+  {
     "name": "omnibox-ui-swap-title-and-url",
     "owners": [ "tommycli", "chrome-omnibox-team@google.com" ],
     "expiry_milestone": 76
@@ -3585,7 +3595,12 @@
   {
     "name": "photo-picker-video-support",
     "owners": [ "finnur" ],
-    "expiry_milestone": 83
+    "expiry_milestone": 86
+  },
+  {
+    "name": "pluginvm-show-camera-permissions",
+    "owners": [ "danielng"],
+    "expiry_milestone": 87
   },
   {
     "name": "pointer-support",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 26072cc6..dfa55568e 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1138,8 +1138,8 @@
     "Overrides the built-in software rendering list and enables "
     "GPU-acceleration on unsupported system configurations.";
 
-const char kIgnorePreviewsBlacklistName[] = "Ignore Previews Blocklist";
-const char kIgnorePreviewsBlacklistDescription[] =
+const char kIgnorePreviewsBlocklistName[] = "Ignore Previews Blocklist";
+const char kIgnorePreviewsBlocklistDescription[] =
     "Ignore decisions made by the PreviewsBlockList";
 
 const char kImprovedCookieControlsName[] =
@@ -1444,6 +1444,22 @@
     "In the omnibox, hide the path, query and ref from steady state displayed "
     "URLs. Hidden portions are restored during editing.";
 
+const char kOmniboxUIRevealSteadyStateUrlPathQueryAndRefOnHoverName[] =
+    "Omnibox UI Reveal Steady-State URL Path, Query, and Ref On Hover";
+const char kOmniboxUIRevealSteadyStateUrlPathQueryAndRefOnHoverDescription[] =
+    "In the omnibox, reveal the path, query and ref from steady state "
+    "displayed URLs on hover. Only has an effect when "
+    "omnibox-ui-hide-steady-state-url-path-query-and-ref is enabled.";
+
+const char kOmniboxUIHideSteadyStateUrlPathQueryAndRefOnInteractionName[] =
+    "Omnibox UI Hide Steady-State URL Path, Query, and Ref On Interaction";
+const char
+    kOmniboxUIHideSteadyStateUrlPathQueryAndRefOnInteractionDescription[] =
+        "In the omnibox, hide the path, query and ref from steady state "
+        "displayed URLs when the user interacts with the page. Only has an "
+        "effect when "
+        "omnibox-ui-hide-steady-state-url-path-query-and-ref is enabled.";
+
 const char kOmniboxUIMaxAutocompleteMatchesName[] =
     "Omnibox UI Max Autocomplete Matches";
 const char kOmniboxUIMaxAutocompleteMatchesDescription[] =
@@ -3859,6 +3875,11 @@
 const char kTerminalSystemAppLegacySettingsDescription[] =
     "Use the legacy settings page for Terminal System App.";
 
+const char kPluginVmShowCameraPermissionsName[] =
+    "Show Plugin VM camera permissions";
+const char kPluginVmShowCameraPermissionsDescription[] =
+    "Displays camera permissions for Plugin VM in the app settings.";
+
 const char kTetherName[] = "Instant Tethering";
 const char kTetherDescription[] =
     "Enables Instant Tethering. Instant Tethering allows your nearby Google "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 84c3ed3..7e486760 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -677,8 +677,8 @@
 extern const char kIgnoreGpuBlacklistName[];
 extern const char kIgnoreGpuBlacklistDescription[];
 
-extern const char kIgnorePreviewsBlacklistName[];
-extern const char kIgnorePreviewsBlacklistDescription[];
+extern const char kIgnorePreviewsBlocklistName[];
+extern const char kIgnorePreviewsBlocklistDescription[];
 
 extern const char kImprovedCookieControlsName[];
 extern const char kImprovedCookieControlsDescription[];
@@ -852,6 +852,15 @@
 extern const char kOmniboxUIHideSteadyStateUrlPathQueryAndRefName[];
 extern const char kOmniboxUIHideSteadyStateUrlPathQueryAndRefDescription[];
 
+extern const char kOmniboxUIRevealSteadyStateUrlPathQueryAndRefOnHoverName[];
+extern const char
+    kOmniboxUIRevealSteadyStateUrlPathQueryAndRefOnHoverDescription[];
+
+extern const char
+    kOmniboxUIHideSteadyStateUrlPathQueryAndRefOnInteractionName[];
+extern const char
+    kOmniboxUIHideSteadyStateUrlPathQueryAndRefOnInteractionDescription[];
+
 extern const char kOmniboxUIMaxAutocompleteMatchesName[];
 extern const char kOmniboxUIMaxAutocompleteMatchesDescription[];
 
@@ -2093,6 +2102,9 @@
 extern const char kTerminalSystemAppLegacySettingsName[];
 extern const char kTerminalSystemAppLegacySettingsDescription[];
 
+extern const char kPluginVmShowCameraPermissionsName[];
+extern const char kPluginVmShowCameraPermissionsDescription[];
+
 extern const char kTrimOnFreezeName[];
 extern const char kTrimOnFreezeDescription[];
 
diff --git a/chrome/browser/flags/README.md b/chrome/browser/flags/README.md
new file mode 100644
index 0000000..24dac65
--- /dev/null
+++ b/chrome/browser/flags/README.md
@@ -0,0 +1,101 @@
+# Feature Flags and Switches
+
+## Overview
+
+This module provides an API to check flags and switches from Java code.
+
+Feature flags and switches are used to control application behavior. They are
+extensive described in the
+[Configuration Documentation](https://chromium.googlesource.com/chromium/src/+/refs/heads/master/docs/configuration.md).
+
+## Feature Flags
+
+Feature flags are declared in C++ as a `base::Feature`. How to declare them is
+covered in
+[Adding a new feature flag](https://chromium.googlesource.com/chromium/src/+/refs/heads/master/docs/how_to_add_your_feature_flag.md).
+
+To check the flag state in native code, call
+`FeatureList::IsEnabled(kMyFeature))`.
+
+To check the flag state in Java code, first export them to Java:
+
+1.  Put a pointer to the `base::Feature` into `kFeaturesExposedToJava` in
+    [`chrome_feature_list.cc`](https://cs.chromium.org/chromium/src/chrome/browser/flags/android/chrome_feature_list.cc)
+2.  Create a String constant in
+    [`ChromeFeatureList.java`](https://cs.chromium.org/chromium/src/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java)
+    with the the flag name (passed as parameter to the `base::Feature`
+    constructor) as value.
+
+Then, from the Java code, check the value of the flag by calling
+[`ChromeFeatureList.isEnabled(ChromeFeatureList.MY_FEATURE)`](https://cs.chromium.org/chromium/src/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java).
+
+Note that this call requires native to be initialized. If native might not be
+initialized when the check is run, there are two ways of proceeding:
+
+1.  Use a cached value of the flag from the previous run by calling
+    [`CachedFeatureFlags.isEnabled(ChromeFeatureList.MY_FEATURE)`](https://cs.chromium.org/chromium/src/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java).
+    This caching is only done for a subset of the flags. To register your flag,
+    specify a default value in `CachedFeatureFlags.sDefaults` and add it to
+    [`ChromeCachedFlags.cacheNativeFlags()`](https://cs.chromium.org/chromium/src/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java)
+2.  Check
+    [`FeatureList.isInitialized()`](https://cs.chromium.org/chromium/src/base/android/java/src/org/chromium/base/FeatureList.java)
+    before calling `ChromeFeatureList.isEnabled()`, and handle the case where
+    native is not initialized.
+
+## Switches
+
+A switch is just a string, unlike feature flags, which are a `base::Feature`
+objects. Switches are declared separately in native and in Java, though both
+[`base::CommandLine`](https://cs.chromium.org/chromium/src/base/command_line.h)
+in native are
+[`CommandLine`](https://cs.chromium.org/chromium/src/base/android/java/src/org/chromium/base/CommandLine.java)
+in Java return the same state.
+
+To create a switch in Native, declare it as a `const char kMySwitch =
+"my-switch"` and call
+`base::CommandLine::ForCurrentProcess()->HasSwitch(kMySwitch)`.
+
+To create a switch in Java, add it to
+[ChromeSwitches.java.tmpl](https://cs.chromium.org/chromium/src/chrome/browser/flags/android/java_templates/ChromeSwitches.java.tmpl).
+It will automatically be surfaced in the generated
+[ChromeSwitches.java](https://cs.chromium.org/chromium/src/out/android-Debug/gen/chrome/browser/flags/java/generated_java/input_srcjars/org/chromium/chrome/browser/flags/ChromeSwitches.java?q=DISABLE_FULLSCREEN&dr=CSs).
+Then, check it with
+`CommandLine.getInstance().hasSwitch(ChromeSwitches.MY_SWITCH)`.
+
+For switches used in both native and Java, simply declare them twice,
+separately, as per instructions above, with the same string.
+
+## Variations
+
+Though feature flags are boolean, enabled feature flags can have multiple
+variations of the same feature. The code generates these variations by getting
+parameters from the field trial API.
+
+In native, the field trial API can be accessed by the functions in
+[field_trial_params.h](https://cs.chromium.org/chromium/src/base/metrics/field_trial_params.h),
+passing the `base::feature`. For example,
+`GetFieldTrialParamByFeatureAsInt(kMyFeature, "MyParameter", 0)` will return the
+value that should be used for the parameter `"MyParameter"` of `kMyFeature`. If
+not available the default value `0` is returned.
+
+In Java,
+[`ChromeFeatureList`](https://cs.chromium.org/chromium/src/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java)
+offers the same API with
+`ChromeFeatureList.getFieldTrialParamByFeatureAsInt(ChromeFeatureList.MY_FEATURE,
+"MyParameter", 0)`. As with `isEnabled()`, this call requires native to be
+started. If that is not guaranteed, the same options are available:
+
+1.  Use a cached value of the parameter from the previous run. To do so, declare
+    a
+    [`static final IntCachedFieldTrialParameter`](https://cs.chromium.org/chromium/src/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/IntCachedFieldTrialParameter.java)
+    MY_CACHED_PARAM object and call `MY_CACHED_PARAM.getValue()`. Again, this
+    caching is only done for a subset of the parameters. To register yours, add
+    it to
+    [`ChromeCachedFlags.cacheNativeFlags()`](https://cs.chromium.org/chromium/src/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java)
+2.  Check
+    [`FeatureList.isInitialized()`](https://cs.chromium.org/chromium/src/base/android/java/src/org/chromium/base/FeatureList.java)before
+    calling `ChromeFeatureList.getFieldTrialParamByFeatureAsInt()`, and handle
+    the case where native is not initialized.
+
+`Int` used as an example, but parameters can also be of the types `String`,
+`Double` and `Boolean`.
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index ff35d38a..6f8516d2 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -75,6 +75,7 @@
     &autofill::features::kAutofillTouchToFill,
     &device::kWebAuthPhoneSupport,
     &download::features::kDownloadAutoResumptionNative,
+    &download::features::kDownloadLater,
     &download::features::kUseDownloadOfflineContentProvider,
     &features::kClearOldBrowsingData,
     &features::kDownloadsLocationChange,
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 1ba2b4c8..8ed493d 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -278,6 +278,7 @@
     public static final String DOWNLOAD_OFFLINE_CONTENT_PROVIDER =
             "UseDownloadOfflineContentProvider";
     public static final String DOWNLOADS_LOCATION_CHANGE = "DownloadsLocationChange";
+    public static final String DOWNLOAD_LATER = "DownloadLater";
     public static final String DRAW_VERTICALLY_EDGE_TO_EDGE = "DrawVerticallyEdgeToEdge";
     public static final String DUET_TABSTRIP_INTEGRATION_ANDROID = "DuetTabStripIntegrationAndroid";
     public static final String EPHEMERAL_TAB_USING_BOTTOM_SHEET = "EphemeralTabUsingBottomSheet";
diff --git a/chrome/browser/gcm/gcm_profile_service_unittest.cc b/chrome/browser/gcm/gcm_profile_service_unittest.cc
index 251bea8..957d3e90 100644
--- a/chrome/browser/gcm/gcm_profile_service_unittest.cc
+++ b/chrome/browser/gcm/gcm_profile_service_unittest.cc
@@ -143,11 +143,10 @@
 };
 
 GCMProfileServiceTest::GCMProfileServiceTest()
-    : gcm_profile_service_(NULL),
+    : gcm_profile_service_(nullptr),
       gcm_app_handler_(new FakeGCMAppHandler),
       registration_result_(GCMClient::UNKNOWN_ERROR),
-      send_result_(GCMClient::UNKNOWN_ERROR) {
-}
+      send_result_(GCMClient::UNKNOWN_ERROR) {}
 
 GCMProfileServiceTest::~GCMProfileServiceTest() {
 }
diff --git a/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.cc b/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.cc
index 8065353f..bd58784f 100644
--- a/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.cc
+++ b/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.cc
@@ -27,10 +27,10 @@
 }  // namespace
 
 HeavyAdBlocklist::HeavyAdBlocklist(
-    std::unique_ptr<blacklist::OptOutStore> opt_out_store,
+    std::unique_ptr<blocklist::OptOutStore> opt_out_store,
     base::Clock* clock,
-    blacklist::OptOutBlacklistDelegate* blacklist_delegate)
-    : OptOutBlacklist(std::move(opt_out_store), clock, blacklist_delegate) {
+    blocklist::OptOutBlocklistDelegate* blocklist_delegate)
+    : OptOutBlocklist(std::move(opt_out_store), clock, blocklist_delegate) {
   Init();
 }
 
@@ -69,7 +69,7 @@
   return false;
 }
 
-blacklist::BlacklistData::AllowedTypesAndVersions
+blocklist::BlocklistData::AllowedTypesAndVersions
 HeavyAdBlocklist::GetAllowedTypes() const {
   return {{static_cast<int>(HeavyAdBlocklistType::kHeavyAdOnlyType),
            GetBlocklistParamValue(kTypeVersion, 0)}};
diff --git a/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.h b/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.h
index d741f12..a166971 100644
--- a/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.h
+++ b/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist.h
@@ -15,29 +15,29 @@
 class Clock;
 }
 
-namespace blacklist {
-class OptOutBlacklistDelegate;
+namespace blocklist {
+class OptOutBlocklistDelegate;
 class OptOutStore;
-}  // namespace blacklist
+}  // namespace blocklist
 
 // The heavy ad intervention only supports one type for the blocklist.
 enum class HeavyAdBlocklistType {
   kHeavyAdOnlyType = 0,
 };
 
-// A class that manages opt out blacklist parameters for the heavy ad
+// A class that manages opt out blocklist parameters for the heavy ad
 // intervention. The blocklist is used to allow at most 5 interventions per top
 // frame origin per day. This prevents the intervention from being used as a
 // cross-origin side channel.
-class HeavyAdBlocklist : public blacklist::OptOutBlacklist {
+class HeavyAdBlocklist : public blocklist::OptOutBlocklist {
  public:
-  HeavyAdBlocklist(std::unique_ptr<blacklist::OptOutStore> opt_out_store,
+  HeavyAdBlocklist(std::unique_ptr<blocklist::OptOutStore> opt_out_store,
                    base::Clock* clock,
-                   blacklist::OptOutBlacklistDelegate* blacklist_delegate);
+                   blocklist::OptOutBlocklistDelegate* blocklist_delegate);
   ~HeavyAdBlocklist() override;
 
  protected:
-  // OptOutBlacklist:
+  // OptOutBlocklist:
   bool ShouldUseSessionPolicy(base::TimeDelta* duration,
                               size_t* history,
                               int* threshold) const override;
@@ -51,7 +51,7 @@
   bool ShouldUseTypePolicy(base::TimeDelta* duration,
                            size_t* history,
                            int* threshold) const override;
-  blacklist::BlacklistData::AllowedTypesAndVersions GetAllowedTypes()
+  blocklist::BlocklistData::AllowedTypesAndVersions GetAllowedTypes()
       const override;
 
  private:
diff --git a/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist_unittest.cc b/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist_unittest.cc
index 26a726a..f1c96986 100644
--- a/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist_unittest.cc
+++ b/chrome/browser/heavy_ad_intervention/heavy_ad_blocklist_unittest.cc
@@ -21,17 +21,17 @@
 namespace {
 
 // Empty mock class to test the HeavyAdBlocklist.
-class EmptyOptOutBlacklistDelegate : public blacklist::OptOutBlacklistDelegate {
+class EmptyOptOutBlocklistDelegate : public blocklist::OptOutBlocklistDelegate {
  public:
-  EmptyOptOutBlacklistDelegate() = default;
+  EmptyOptOutBlocklistDelegate() = default;
 };
 
 class TestHeavyAdBlocklist : public HeavyAdBlocklist {
  public:
-  TestHeavyAdBlocklist(std::unique_ptr<blacklist::OptOutStore> opt_out_store,
+  TestHeavyAdBlocklist(std::unique_ptr<blocklist::OptOutStore> opt_out_store,
                        base::Clock* clock,
-                       blacklist::OptOutBlacklistDelegate* blacklist_delegate)
-      : HeavyAdBlocklist(std::move(opt_out_store), clock, blacklist_delegate) {}
+                       blocklist::OptOutBlocklistDelegate* blocklist_delegate)
+      : HeavyAdBlocklist(std::move(opt_out_store), clock, blocklist_delegate) {}
   ~TestHeavyAdBlocklist() override = default;
 
   using HeavyAdBlocklist::GetAllowedTypes;
@@ -57,10 +57,10 @@
     scoped_feature_list_.InitAndEnableFeatureWithParameters(
         features::kHeavyAdPrivacyMitigations, params);
     blocklist_ = std::make_unique<TestHeavyAdBlocklist>(nullptr, &test_clock_,
-                                                        &blacklist_delegate_);
+                                                        &blocklist_delegate_);
   }
 
-  blacklist::BlacklistData::AllowedTypesAndVersions GetAllowedTypes() const {
+  blocklist::BlocklistData::AllowedTypesAndVersions GetAllowedTypes() const {
     return blocklist_->GetAllowedTypes();
   }
 
@@ -70,7 +70,7 @@
 
  private:
   // Observer to |blocklist_|.
-  EmptyOptOutBlacklistDelegate blacklist_delegate_;
+  EmptyOptOutBlocklistDelegate blocklist_delegate_;
 
   base::test::ScopedFeatureList scoped_feature_list_;
 
@@ -93,7 +93,7 @@
 
   EXPECT_FALSE(blocklist_->ShouldUseTypePolicy(nullptr, nullptr, nullptr));
 
-  blacklist::BlacklistData::AllowedTypesAndVersions types = GetAllowedTypes();
+  blocklist::BlocklistData::AllowedTypesAndVersions types = GetAllowedTypes();
   EXPECT_EQ(1u, types.size());
   const auto iter = types.begin();
   EXPECT_EQ(0, iter->first);
@@ -130,7 +130,7 @@
 TEST_F(HeavyAdBlocklistTest, TypeVersionParam) {
   int version = 17;
   ConfigBlocklistWithParams({{"type-version", base::NumberToString(version)}});
-  blacklist::BlacklistData::AllowedTypesAndVersions types = GetAllowedTypes();
+  blocklist::BlocklistData::AllowedTypesAndVersions types = GetAllowedTypes();
   EXPECT_EQ(1u, types.size());
   const auto iter = types.begin();
   EXPECT_EQ(0, iter->first);
diff --git a/chrome/browser/heavy_ad_intervention/heavy_ad_service.cc b/chrome/browser/heavy_ad_intervention/heavy_ad_service.cc
index d2bb64ee..01636f18 100644
--- a/chrome/browser/heavy_ad_intervention/heavy_ad_service.cc
+++ b/chrome/browser/heavy_ad_intervention/heavy_ad_service.cc
@@ -38,14 +38,14 @@
   if (!base::FeatureList::IsEnabled(features::kHeavyAdPrivacyMitigations))
     return;
 
-  std::unique_ptr<blacklist::OptOutStoreSQL> opt_out_store;
+  std::unique_ptr<blocklist::OptOutStoreSQL> opt_out_store;
   if (!HeavyAdOptOutStoreDisabled()) {
     // Get the background thread to run SQLite on.
     scoped_refptr<base::SequencedTaskRunner> background_task_runner =
         base::ThreadPool::CreateSequencedTaskRunner(
             {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
 
-    opt_out_store = std::make_unique<blacklist::OptOutStoreSQL>(
+    opt_out_store = std::make_unique<blocklist::OptOutStoreSQL>(
         content::GetUIThreadTaskRunner({}), background_task_runner,
         profile_path.Append(chrome::kHeavyAdInterventionOptOutDBFilename));
   }
diff --git a/chrome/browser/heavy_ad_intervention/heavy_ad_service.h b/chrome/browser/heavy_ad_intervention/heavy_ad_service.h
index 7c6e2e35..7a602be4 100644
--- a/chrome/browser/heavy_ad_intervention/heavy_ad_service.h
+++ b/chrome/browser/heavy_ad_intervention/heavy_ad_service.h
@@ -20,7 +20,7 @@
 
 // Keyed service that owns the heavy ad intervention blocklist.
 class HeavyAdService : public KeyedService,
-                       public blacklist::OptOutBlacklistDelegate {
+                       public blocklist::OptOutBlocklistDelegate {
  public:
   HeavyAdService();
   ~HeavyAdService() override;
diff --git a/chrome/browser/importer/external_process_importer_host.cc b/chrome/browser/importer/external_process_importer_host.cc
index 9087093..31f612d 100644
--- a/chrome/browser/importer/external_process_importer_host.cc
+++ b/chrome/browser/importer/external_process_importer_host.cc
@@ -23,13 +23,13 @@
 
 ExternalProcessImporterHost::ExternalProcessImporterHost()
     : headless_(false),
-      parent_window_(NULL),
-      observer_(NULL),
-      profile_(NULL),
+      parent_window_(nullptr),
+      observer_(nullptr),
+      profile_(nullptr),
       waiting_for_bookmarkbar_model_(false),
       installed_bookmark_observer_(false),
       is_source_readable_(true),
-      client_(NULL),
+      client_(nullptr),
       items_(0),
       cancelled_(false) {}
 
diff --git a/chrome/browser/interstitials/enterprise_util.cc b/chrome/browser/interstitials/enterprise_util.cc
index 63214fa..c8fb7af 100644
--- a/chrome/browser/interstitials/enterprise_util.cc
+++ b/chrome/browser/interstitials/enterprise_util.cc
@@ -64,13 +64,14 @@
   switch (threat_type) {
     case safe_browsing::SB_THREAT_TYPE_URL_PHISHING:
     case safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_PHISHING:
-      return "PHISHING";
+      return "SOCIAL_ENGINEERING";
     case safe_browsing::SB_THREAT_TYPE_URL_MALWARE:
     case safe_browsing::SB_THREAT_TYPE_URL_CLIENT_SIDE_MALWARE:
       return "MALWARE";
     case safe_browsing::SB_THREAT_TYPE_URL_UNWANTED:
+      return "UNWANTED_SOFTWARE";
     case safe_browsing::SB_THREAT_TYPE_BILLING:
-      return "HARMFUL";
+      return "THREAT_TYPE_UNSPECIFIED";
     case safe_browsing::SB_THREAT_TYPE_UNUSED:
     case safe_browsing::SB_THREAT_TYPE_SAFE:
     case safe_browsing::SB_THREAT_TYPE_URL_BINARY_MALWARE:
diff --git a/chrome/browser/lookalikes/lookalike_url_service.cc b/chrome/browser/lookalikes/lookalike_url_service.cc
index e68aab6..44749731d 100644
--- a/chrome/browser/lookalikes/lookalike_url_service.cc
+++ b/chrome/browser/lookalikes/lookalike_url_service.cc
@@ -30,7 +30,7 @@
 
 namespace {
 
-constexpr uint32_t kEngagedSiteUpdateIntervalInSeconds = 5 * 60;
+constexpr uint32_t kEngagedSiteUpdateIntervalInSeconds = 60;
 
 class LookalikeUrlServiceFactory : public BrowserContextKeyedServiceFactory {
  public:
diff --git a/chrome/browser/media/feeds/media_feeds_browsertest.cc b/chrome/browser/media/feeds/media_feeds_browsertest.cc
index 03c896a..ad187d23 100644
--- a/chrome/browser/media/feeds/media_feeds_browsertest.cc
+++ b/chrome/browser/media/feeds/media_feeds_browsertest.cc
@@ -182,8 +182,9 @@
     base::RunLoop run_loop;
     std::vector<media_feeds::mojom::MediaFeedItemPtr> out;
 
-    GetMediaHistoryService()->GetItemsForMediaFeedForDebug(
-        feed_id,
+    GetMediaHistoryService()->GetMediaFeedItems(
+        media_history::MediaHistoryKeyedService::GetMediaFeedItemsRequest::
+            CreateItemsForDebug(feed_id),
         base::BindLambdaForTesting(
             [&](std::vector<media_feeds::mojom::MediaFeedItemPtr> items) {
               out = std::move(items);
@@ -366,6 +367,7 @@
   // Check each feed item and all fields one-by-one.
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 1;
     expected_item->name =
         base::ASCIIToUTF16("Anatomy of a Web Media Experience");
     expected_item->type = mojom::MediaFeedItemType::kVideo;
@@ -406,6 +408,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 2;
     expected_item->name = base::ASCIIToUTF16(
         "Building Modern Web Media Experiences: Picture-in-Picture and AV1");
     expected_item->type = mojom::MediaFeedItemType::kVideo;
@@ -457,6 +460,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 3;
     expected_item->name = base::ASCIIToUTF16("Chrome Releases");
     expected_item->type = mojom::MediaFeedItemType::kTVSeries;
     ASSERT_TRUE(
@@ -527,6 +531,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 4;
     expected_item->name = base::ASCIIToUTF16("Chrome University");
     expected_item->type = mojom::MediaFeedItemType::kTVSeries;
     ASSERT_TRUE(
@@ -592,6 +597,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 5;
     expected_item->name = base::ASCIIToUTF16("JAM stack");
     expected_item->type = mojom::MediaFeedItemType::kTVSeries;
     ASSERT_TRUE(
@@ -624,6 +630,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 6;
     expected_item->name = base::ASCIIToUTF16("Ask Chrome");
     expected_item->type = mojom::MediaFeedItemType::kVideo;
     expected_item->author = mojom::Author::New();
@@ -664,6 +671,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 7;
     expected_item->name = base::ASCIIToUTF16("Big Buck Bunny");
     expected_item->type = mojom::MediaFeedItemType::kMovie;
     ASSERT_TRUE(
@@ -763,6 +771,7 @@
   // the correct fields are set. Don't assume or require any specific ordering.
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 1;
     expected_item->name =
         base::ASCIIToUTF16("Anatomy of a Web Media Experience");
     expected_item->type = mojom::MediaFeedItemType::kVideo;
@@ -796,6 +805,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 2;
     expected_item->name = base::ASCIIToUTF16("Chrome Releases");
     expected_item->type = mojom::MediaFeedItemType::kTVSeries;
     ASSERT_TRUE(
@@ -837,6 +847,7 @@
 
   {
     mojom::MediaFeedItemPtr expected_item = mojom::MediaFeedItem::New();
+    expected_item->id = 3;
     expected_item->name = base::ASCIIToUTF16("Big Buck Bunny");
     expected_item->type = mojom::MediaFeedItemType::kMovie;
     ASSERT_TRUE(
diff --git a/chrome/browser/media/feeds/media_feeds_service.cc b/chrome/browser/media/feeds/media_feeds_service.cc
index 81990a8..0ca7710 100644
--- a/chrome/browser/media/feeds/media_feeds_service.cc
+++ b/chrome/browser/media/feeds/media_feeds_service.cc
@@ -8,7 +8,6 @@
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/threading/thread_checker.h"
-#include "build/build_config.h"
 #include "chrome/browser/media/feeds/media_feeds_converter.h"
 #include "chrome/browser/media/feeds/media_feeds_fetcher.h"
 #include "chrome/browser/media/feeds/media_feeds_service_factory.h"
@@ -123,14 +122,10 @@
 
 MediaFeedsService::MediaFeedsService(Profile* profile)
     :
-#if defined(OS_ANDROID)
-      cookie_change_listener_(nullptr),
-#else
       cookie_change_listener_(std::make_unique<CookieChangeListener>(
           profile,
           base::BindRepeating(&MediaFeedsService::OnResetOriginFromCookie,
                               base::Unretained(this)))),
-#endif  // defined(OS_ANDROID)
       profile_(profile) {
   DCHECK(!profile->IsOffTheRecord());
 
diff --git a/chrome/browser/media/feeds/media_feeds_service_unittest.cc b/chrome/browser/media/feeds/media_feeds_service_unittest.cc
index b3e6565..dd392ad6 100644
--- a/chrome/browser/media/feeds/media_feeds_service_unittest.cc
+++ b/chrome/browser/media/feeds/media_feeds_service_unittest.cc
@@ -231,8 +231,9 @@
     base::RunLoop run_loop;
     std::vector<media_feeds::mojom::MediaFeedItemPtr> out;
 
-    GetMediaHistoryService()->GetItemsForMediaFeedForDebug(
-        feed_id,
+    GetMediaHistoryService()->GetMediaFeedItems(
+        media_history::MediaHistoryKeyedService::GetMediaFeedItemsRequest::
+            CreateItemsForDebug(feed_id),
         base::BindLambdaForTesting(
             [&](std::vector<media_feeds::mojom::MediaFeedItemPtr> rows) {
               out = std::move(rows);
@@ -298,8 +299,10 @@
     return media_history::MediaHistoryKeyedService::Get(profile());
   }
 
-  static media_feeds::mojom::MediaFeedItemPtr GetSingleExpectedItem() {
+  static media_feeds::mojom::MediaFeedItemPtr GetSingleExpectedItem(
+      int id_start = 0) {
     auto item = media_feeds::mojom::MediaFeedItem::New();
+    item->id = ++id_start;
     item->name = base::ASCIIToUTF16("The Movie");
     item->type = media_feeds::mojom::MediaFeedItemType::kMovie;
     item->date_published = base::Time::FromDeltaSinceWindowsEpoch(
@@ -315,12 +318,16 @@
     return item;
   }
 
-  static std::vector<media_feeds::mojom::MediaFeedItemPtr> GetExpectedItems() {
+  static std::vector<media_feeds::mojom::MediaFeedItemPtr> GetExpectedItems(
+      int id_start = 0) {
     std::vector<media_feeds::mojom::MediaFeedItemPtr> items;
-    items.push_back(GetSingleExpectedItem());
+
+    items.push_back(GetSingleExpectedItem(id_start));
+    id_start++;
 
     {
       auto item = media_feeds::mojom::MediaFeedItem::New();
+      item->id = ++id_start;
       item->type = media_feeds::mojom::MediaFeedItemType::kTVSeries;
       item->name = base::ASCIIToUTF16("The TV Series");
       item->action_status =
@@ -334,6 +341,7 @@
 
     {
       auto item = media_feeds::mojom::MediaFeedItem::New();
+      item->id = ++id_start;
       item->type = media_feeds::mojom::MediaFeedItemType::kTVSeries;
       item->name = base::ASCIIToUTF16("The Live TV Series");
       item->action_status =
diff --git a/chrome/browser/media/feeds/media_feeds_store.mojom b/chrome/browser/media/feeds/media_feeds_store.mojom
index 994fbd8..5f0af30 100644
--- a/chrome/browser/media/feeds/media_feeds_store.mojom
+++ b/chrome/browser/media/feeds/media_feeds_store.mojom
@@ -362,6 +362,9 @@
 // represents a single recommendation such as a video or TV show.
 // https://wicg.github.io/media-feeds/index.html#media-feed-item
 struct MediaFeedItem {
+  // The ID of the feed item in storage.
+  int64 id;
+
   // The type of this feed item such as a video or TV show.
   MediaFeedItemType type;
 
diff --git a/chrome/browser/media/history/media_history_feed_items_table.cc b/chrome/browser/media/history/media_history_feed_items_table.cc
index 6f27dc9a..f5a72dd1 100644
--- a/chrome/browser/media/history/media_history_feed_items_table.cc
+++ b/chrome/browser/media/history/media_history_feed_items_table.cc
@@ -207,6 +207,22 @@
         "mediaFeedItem (safe_search_result, feed_id)");
   }
 
+  if (success) {
+    success = DB()->Execute(
+        "CREATE INDEX IF NOT EXISTS "
+        "mediaFeedItem_continue_watching_index ON "
+        "mediaFeedItem (action_status, play_next_candidate, "
+        "safe_search_result)");
+  }
+
+  if (success) {
+    success = DB()->Execute(
+        "CREATE INDEX IF NOT EXISTS "
+        "mediaFeedItem_for_feed_index ON "
+        "mediaFeedItem (feed_id, action_status, play_next_candidate, "
+        "safe_search_result)");
+  }
+
   if (!success) {
     ResetDB();
     LOG(ERROR) << "Failed to create media history feed items table.";
@@ -408,20 +424,97 @@
 }
 
 std::vector<media_feeds::mojom::MediaFeedItemPtr>
-MediaHistoryFeedItemsTable::GetItemsForFeed(const int64_t feed_id) {
+MediaHistoryFeedItemsTable::GetItems(
+    const MediaHistoryKeyedService::GetMediaFeedItemsRequest& request) {
   std::vector<media_feeds::mojom::MediaFeedItemPtr> items;
   if (!CanAccessDatabase())
     return items;
 
-  sql::Statement statement(DB()->GetUniqueStatement(
+  std::vector<std::string> sql;
+  sql.push_back(
       "SELECT type, name, date_published_s, is_family_friendly, "
       "action_status, genre, duration_s, is_live, live_start_time_s, "
       "live_end_time_s, shown_count, clicked, author, action, "
       "interaction_counters, content_rating, identifiers, tv_episode, "
-      "play_next_candidate, images, safe_search_result FROM "
-      "mediaFeedItem WHERE feed_id = ?"));
+      "play_next_candidate, images, safe_search_result, id FROM mediaFeedItem");
 
-  statement.BindInt64(0, feed_id);
+  sql::Statement statement;
+
+  if (request.type ==
+      MediaHistoryKeyedService::GetMediaFeedItemsRequest::Type::kDebugAll) {
+    // Debug request should just return all feed items for a single feed.
+    sql.push_back("WHERE feed_id = ?");
+
+    statement.Assign(DB()->GetCachedStatement(
+        SQL_FROM_HERE, base::JoinString(sql, " ").c_str()));
+
+    statement.BindInt64(0, *request.feed_id);
+  } else if (request.type ==
+             MediaHistoryKeyedService::GetMediaFeedItemsRequest::Type::
+                 kItemsForFeed) {
+    // kItemsForFeed should return items for a feed. Ordered by clicked and
+    // shown count so items that have been clicked and shown a lot will be at
+    // the end. Items must not be continue watching items.
+    sql.push_back(
+        "WHERE feed_id = ? AND action_status != ? AND play_next_candidate IS "
+        "NULL");
+
+    if (request.fetched_items_should_be_safe)
+      sql.push_back("AND safe_search_result = ?");
+
+    sql.push_back("ORDER BY clicked ASC, shown_count ASC LIMIT ?");
+
+    if (request.fetched_items_should_be_safe) {
+      statement.Assign(DB()->GetCachedStatement(
+          SQL_FROM_HERE, base::JoinString(sql, " ").c_str()));
+
+      statement.BindInt64(
+          2, static_cast<int>(media_feeds::mojom::SafeSearchResult::kSafe));
+      statement.BindInt64(3, *request.limit);
+    } else {
+      statement.Assign(DB()->GetCachedStatement(
+          SQL_FROM_HERE, base::JoinString(sql, " ").c_str()));
+
+      statement.BindInt64(2, *request.limit);
+    }
+
+    // Bind common parameters.
+    statement.BindInt64(0, *request.feed_id);
+    statement.BindInt64(
+        1, static_cast<int>(
+               media_feeds::mojom::MediaFeedItemActionStatus::kActive));
+  } else if (request.type ==
+             MediaHistoryKeyedService::GetMediaFeedItemsRequest::Type::
+                 kContinueWatching) {
+    // kContinueWatching should return items across all feeds that either have
+    // an active action status or a play next candidate. Ordered by most recent
+    // first.
+    sql.push_back("WHERE action_status = ? OR play_next_candidate IS NOT NULL");
+
+    if (request.fetched_items_should_be_safe)
+      sql.push_back("AND safe_search_result = ?");
+
+    sql.push_back("ORDER BY id DESC LIMIT ?");
+
+    if (request.fetched_items_should_be_safe) {
+      statement.Assign(DB()->GetCachedStatement(
+          SQL_FROM_HERE, base::JoinString(sql, " ").c_str()));
+
+      statement.BindInt64(
+          1, static_cast<int>(media_feeds::mojom::SafeSearchResult::kSafe));
+      statement.BindInt64(2, *request.limit);
+    } else {
+      statement.Assign(DB()->GetCachedStatement(
+          SQL_FROM_HERE, base::JoinString(sql, " ").c_str()));
+
+      statement.BindInt64(1, *request.limit);
+    }
+
+    // Bind common parameters.
+    statement.BindInt64(
+        0, static_cast<int>(
+               media_feeds::mojom::MediaFeedItemActionStatus::kActive));
+  }
 
   DCHECK(statement.is_valid());
 
@@ -651,6 +744,7 @@
 
     item->shown_count = statement.ColumnInt64(10);
     item->clicked = statement.ColumnBool(11);
+    item->id = statement.ColumnInt64(21);
 
     items.push_back(std::move(item));
   }
diff --git a/chrome/browser/media/history/media_history_feed_items_table.h b/chrome/browser/media/history/media_history_feed_items_table.h
index fd8fee00..46c96e7 100644
--- a/chrome/browser/media/history/media_history_feed_items_table.h
+++ b/chrome/browser/media/history/media_history_feed_items_table.h
@@ -67,9 +67,9 @@
   // Deletes all items from a feed.
   bool DeleteItems(const int64_t feed_id);
 
-  // Gets all the items associated with |feed_id|.
-  std::vector<media_feeds::mojom::MediaFeedItemPtr> GetItemsForFeed(
-      const int64_t feed_id);
+  // Returns the feed rows in the database.
+  std::vector<media_feeds::mojom::MediaFeedItemPtr> GetItems(
+      const MediaHistoryKeyedService::GetMediaFeedItemsRequest& request);
 
   // Returns all the Media Feed Items that have an unknown safe search result.
   MediaHistoryKeyedService::PendingSafeSearchCheckList
diff --git a/chrome/browser/media/history/media_history_keyed_service.cc b/chrome/browser/media/history/media_history_keyed_service.cc
index 3e47f2d1..920da91 100644
--- a/chrome/browser/media/history/media_history_keyed_service.cc
+++ b/chrome/browser/media/history/media_history_keyed_service.cc
@@ -250,14 +250,53 @@
   }
 }
 
-void MediaHistoryKeyedService::GetItemsForMediaFeedForDebug(
-    const int64_t feed_id,
+MediaHistoryKeyedService::GetMediaFeedItemsRequest
+MediaHistoryKeyedService::GetMediaFeedItemsRequest::CreateItemsForDebug(
+    int64_t feed_id) {
+  GetMediaFeedItemsRequest request;
+  request.type = Type::kDebugAll;
+  request.feed_id = feed_id;
+  return request;
+}
+
+MediaHistoryKeyedService::GetMediaFeedItemsRequest
+MediaHistoryKeyedService::GetMediaFeedItemsRequest::CreateItemsForFeed(
+    int64_t feed_id,
+    unsigned limit,
+    bool fetched_items_should_be_safe) {
+  GetMediaFeedItemsRequest request;
+  request.type = Type::kItemsForFeed;
+  request.limit = limit;
+  request.feed_id = feed_id;
+  request.fetched_items_should_be_safe = fetched_items_should_be_safe;
+  return request;
+}
+
+MediaHistoryKeyedService::GetMediaFeedItemsRequest MediaHistoryKeyedService::
+    GetMediaFeedItemsRequest::CreateItemsForContinueWatching(
+        unsigned limit,
+        bool fetched_items_should_be_safe) {
+  GetMediaFeedItemsRequest request;
+  request.type = Type::kContinueWatching;
+  request.limit = limit;
+  request.fetched_items_should_be_safe = fetched_items_should_be_safe;
+  return request;
+}
+
+MediaHistoryKeyedService::GetMediaFeedItemsRequest::GetMediaFeedItemsRequest() =
+    default;
+
+MediaHistoryKeyedService::GetMediaFeedItemsRequest::GetMediaFeedItemsRequest(
+    const GetMediaFeedItemsRequest& t) = default;
+
+void MediaHistoryKeyedService::GetMediaFeedItems(
+    const GetMediaFeedItemsRequest& request,
     base::OnceCallback<void(std::vector<media_feeds::mojom::MediaFeedItemPtr>)>
         callback) {
   base::PostTaskAndReplyWithResult(
       store_->GetForRead()->db_task_runner_.get(), FROM_HERE,
-      base::BindOnce(&MediaHistoryStore::GetItemsForMediaFeedForDebug,
-                     store_->GetForRead(), feed_id),
+      base::BindOnce(&MediaHistoryStore::GetMediaFeedItems,
+                     store_->GetForRead(), request),
       std::move(callback));
 }
 
diff --git a/chrome/browser/media/history/media_history_keyed_service.h b/chrome/browser/media/history/media_history_keyed_service.h
index 3a46d97..235ceef5 100644
--- a/chrome/browser/media/history/media_history_keyed_service.h
+++ b/chrome/browser/media/history/media_history_keyed_service.h
@@ -88,9 +88,52 @@
       const base::Optional<media_session::MediaPosition>& position,
       const std::vector<media_session::MediaImage>& artwork);
 
-  // Gets the media items in |feed_id|.
-  void GetItemsForMediaFeedForDebug(
-      const int64_t feed_id,
+  // Returns Media Feeds items.
+  struct GetMediaFeedItemsRequest {
+    enum class Type {
+      // Return all the feed items for a feed for debugging.
+      kDebugAll,
+
+      // Returns items across all feeds that either have an active action status
+      // or a play next candidate. Ordered by most recent first.
+      kContinueWatching,
+
+      // Returns all the items for a single feed. Ordered by clicked and shown
+      // count so items that have been clicked and shown a lot will be at the
+      // end. Items must not be continue watching items.
+      kItemsForFeed
+    };
+
+    static GetMediaFeedItemsRequest CreateItemsForDebug(int64_t feed_id);
+
+    static GetMediaFeedItemsRequest CreateItemsForFeed(
+        int64_t feed_id,
+        unsigned limit,
+        bool fetched_items_should_be_safe);
+
+    static GetMediaFeedItemsRequest CreateItemsForContinueWatching(
+        unsigned limit,
+        bool fetched_items_should_be_safe);
+
+    GetMediaFeedItemsRequest();
+    GetMediaFeedItemsRequest(const GetMediaFeedItemsRequest& t);
+
+    Type type = Type::kDebugAll;
+
+    // The ID of the feed to retrieve items for. Only valid for |kDebugAll| and
+    // |kItemsForFeed|.
+    base::Optional<int64_t> feed_id;
+
+    // The maximum number of feeds to return. Only valid for |kContinueWatching|
+    // and |kItemsForFeed|.
+    base::Optional<unsigned> limit;
+
+    // True if the item should have passed Safe Search checks. Only valid for
+    // |kContinueWatching| and |kItemsForFeed|.
+    bool fetched_items_should_be_safe = false;
+  };
+  void GetMediaFeedItems(
+      const GetMediaFeedItemsRequest& request,
       base::OnceCallback<
           void(std::vector<media_feeds::mojom::MediaFeedItemPtr>)> callback);
 
diff --git a/chrome/browser/media/history/media_history_keyed_service_unittest.cc b/chrome/browser/media/history/media_history_keyed_service_unittest.cc
index 008350a8..5ff7be8b 100644
--- a/chrome/browser/media/history/media_history_keyed_service_unittest.cc
+++ b/chrome/browser/media/history/media_history_keyed_service_unittest.cc
@@ -16,8 +16,6 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "build/build_config.h"
 #include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/media/feeds/media_feeds_service.h"
-#include "chrome/browser/media/feeds/media_feeds_service_factory.h"
 #include "chrome/browser/media/feeds/media_feeds_store.mojom-shared.h"
 #include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
 #include "chrome/browser/media/history/media_history_feed_associated_origins_table.h"
@@ -44,6 +42,11 @@
 #include "services/media_session/public/cpp/media_position.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/media/feeds/media_feeds_service.h"
+#include "chrome/browser/media/feeds/media_feeds_service_factory.h"
+#endif
+
 namespace media_history {
 
 namespace {
@@ -244,10 +247,12 @@
     return result;
   }
 
+#if !defined(OS_ANDROID)
   media_feeds::MediaFeedsService* GetMediaFeedsService() {
     return media_feeds::MediaFeedsServiceFactory::GetInstance()->GetForProfile(
         profile());
   }
+#endif
 
   scoped_refptr<base::TestMockTimeTaskRunner> mock_time_task_runner_;
 
@@ -435,9 +440,11 @@
                                    CreateImageVector(shared_image));
   }
 
+#if !defined(OS_ANDROID)
   // Discover the media feeds.
   GetMediaFeedsService()->DiscoverMediaFeed(media_feed_1);
   GetMediaFeedsService()->DiscoverMediaFeed(media_feed_2);
+#endif
 
   // Wait until the playbacks have finished saving.
   WaitForDB();
@@ -456,11 +463,14 @@
     EXPECT_EQ(5,
               stats->table_row_counts[MediaHistoryPlaybackTable::kTableName]);
     EXPECT_EQ(5, stats->table_row_counts[MediaHistorySessionTable::kTableName]);
+
+#if !defined(OS_ANDROID)
     EXPECT_EQ(2, stats->table_row_counts[MediaHistoryFeedsTable::kTableName]);
     EXPECT_EQ(2,
               stats->table_row_counts[MediaHistoryFeedItemsTable::kTableName]);
     EXPECT_EQ(10, stats->table_row_counts
                       [MediaHistoryFeedAssociatedOriginsTable::kTableName]);
+#endif
 
     // There are 10 session images because each session has an image with two
     // sizes.
@@ -474,7 +484,10 @@
   EXPECT_EQ(all_urls, GetURLsInTable(MediaHistoryPlaybackTable::kTableName));
   EXPECT_EQ(all_urls, GetURLsInTable(MediaHistorySessionTable::kTableName));
   EXPECT_EQ(images, GetURLsInTable(MediaHistoryImagesTable::kTableName));
+
+#if !defined(OS_ANDROID)
   EXPECT_EQ(media_feeds, GetURLsInTable(MediaHistoryFeedsTable::kTableName));
+#endif
 
   MaybeSetSavingBrowsingHistoryDisabled();
 
@@ -503,11 +516,14 @@
     EXPECT_EQ(2,
               stats->table_row_counts[MediaHistoryPlaybackTable::kTableName]);
     EXPECT_EQ(2, stats->table_row_counts[MediaHistorySessionTable::kTableName]);
+
+#if !defined(OS_ANDROID)
     EXPECT_EQ(1, stats->table_row_counts[MediaHistoryFeedsTable::kTableName]);
     EXPECT_EQ(1,
               stats->table_row_counts[MediaHistoryFeedItemsTable::kTableName]);
     EXPECT_EQ(5, stats->table_row_counts
                      [MediaHistoryFeedAssociatedOriginsTable::kTableName]);
+#endif
 
     // There are 4 session images because each session has an image with two
     // sizes.
@@ -521,8 +537,11 @@
   EXPECT_EQ(remaining, GetURLsInTable(MediaHistorySessionTable::kTableName));
   EXPECT_EQ(remaining_images,
             GetURLsInTable(MediaHistoryImagesTable::kTableName));
+
+#if !defined(OS_ANDROID)
   EXPECT_EQ(remaining_media_feeds,
             GetURLsInTable(MediaHistoryFeedsTable::kTableName));
+#endif
 }
 
 TEST_P(MediaHistoryKeyedServiceTest,
@@ -656,9 +675,11 @@
   // Record a visit for |url3|.
   history->AddPage(url3, base::Time::Now(), history::SOURCE_BROWSED);
 
+#if !defined(OS_ANDROID)
   // Discover the media feeds.
   GetMediaFeedsService()->DiscoverMediaFeed(media_feed_1);
   GetMediaFeedsService()->DiscoverMediaFeed(media_feed_2);
+#endif
 
   // Wait until the playbacks have finished saving.
   WaitForDB();
@@ -677,11 +698,14 @@
     EXPECT_EQ(5,
               stats->table_row_counts[MediaHistoryPlaybackTable::kTableName]);
     EXPECT_EQ(5, stats->table_row_counts[MediaHistorySessionTable::kTableName]);
+
+#if !defined(OS_ANDROID)
     EXPECT_EQ(2, stats->table_row_counts[MediaHistoryFeedsTable::kTableName]);
     EXPECT_EQ(2,
               stats->table_row_counts[MediaHistoryFeedItemsTable::kTableName]);
     EXPECT_EQ(10, stats->table_row_counts
                       [MediaHistoryFeedAssociatedOriginsTable::kTableName]);
+#endif
 
     // There are 10 session images because each session has an image with two
     // sizes.
@@ -695,7 +719,10 @@
   EXPECT_EQ(all_urls, GetURLsInTable(MediaHistoryPlaybackTable::kTableName));
   EXPECT_EQ(all_urls, GetURLsInTable(MediaHistorySessionTable::kTableName));
   EXPECT_EQ(images, GetURLsInTable(MediaHistoryImagesTable::kTableName));
+
+#if !defined(OS_ANDROID)
   EXPECT_EQ(media_feeds, GetURLsInTable(MediaHistoryFeedsTable::kTableName));
+#endif
 
   MaybeSetSavingBrowsingHistoryDisabled();
 
@@ -724,11 +751,14 @@
     EXPECT_EQ(4,
               stats->table_row_counts[MediaHistoryPlaybackTable::kTableName]);
     EXPECT_EQ(4, stats->table_row_counts[MediaHistorySessionTable::kTableName]);
+
+#if !defined(OS_ANDROID)
     EXPECT_EQ(2, stats->table_row_counts[MediaHistoryFeedsTable::kTableName]);
     EXPECT_EQ(2,
               stats->table_row_counts[MediaHistoryFeedItemsTable::kTableName]);
     EXPECT_EQ(10, stats->table_row_counts
                       [MediaHistoryFeedAssociatedOriginsTable::kTableName]);
+#endif
 
     // There are 8 session images because each session has an image with two
     // sizes.
@@ -742,7 +772,10 @@
   EXPECT_EQ(remaining, GetURLsInTable(MediaHistorySessionTable::kTableName));
   EXPECT_EQ(remaining_images,
             GetURLsInTable(MediaHistoryImagesTable::kTableName));
+
+#if !defined(OS_ANDROID)
   EXPECT_EQ(media_feeds, GetURLsInTable(MediaHistoryFeedsTable::kTableName));
+#endif
 }
 
 TEST_P(MediaHistoryKeyedServiceTest, CleanUpDatabaseWhenURLIsDeleted) {
@@ -870,9 +903,11 @@
                                    CreateImageVector(shared_image));
   }
 
+#if !defined(OS_ANDROID)
   // Discover the media feeds.
   GetMediaFeedsService()->DiscoverMediaFeed(media_feed_1);
   GetMediaFeedsService()->DiscoverMediaFeed(media_feed_2);
+#endif
 
   // Wait until the playbacks have finished saving.
   WaitForDB();
@@ -891,11 +926,14 @@
     EXPECT_EQ(5,
               stats->table_row_counts[MediaHistoryPlaybackTable::kTableName]);
     EXPECT_EQ(5, stats->table_row_counts[MediaHistorySessionTable::kTableName]);
+
+#if !defined(OS_ANDROID)
     EXPECT_EQ(2, stats->table_row_counts[MediaHistoryFeedsTable::kTableName]);
     EXPECT_EQ(2,
               stats->table_row_counts[MediaHistoryFeedItemsTable::kTableName]);
     EXPECT_EQ(10, stats->table_row_counts
                       [MediaHistoryFeedAssociatedOriginsTable::kTableName]);
+#endif
 
     // There are 10 session images because each session has an image with two
     // sizes.
@@ -909,7 +947,10 @@
   EXPECT_EQ(all_urls, GetURLsInTable(MediaHistoryPlaybackTable::kTableName));
   EXPECT_EQ(all_urls, GetURLsInTable(MediaHistorySessionTable::kTableName));
   EXPECT_EQ(images, GetURLsInTable(MediaHistoryImagesTable::kTableName));
+
+#if !defined(OS_ANDROID)
   EXPECT_EQ(media_feeds, GetURLsInTable(MediaHistoryFeedsTable::kTableName));
+#endif
 
   // Check the origins have the correct aggregate watchtime.
   {
@@ -954,11 +995,14 @@
     EXPECT_EQ(3,
               stats->table_row_counts[MediaHistoryPlaybackTable::kTableName]);
     EXPECT_EQ(3, stats->table_row_counts[MediaHistorySessionTable::kTableName]);
+
+#if !defined(OS_ANDROID)
     EXPECT_EQ(2, stats->table_row_counts[MediaHistoryFeedsTable::kTableName]);
     EXPECT_EQ(2,
               stats->table_row_counts[MediaHistoryFeedItemsTable::kTableName]);
     EXPECT_EQ(10, stats->table_row_counts
                       [MediaHistoryFeedAssociatedOriginsTable::kTableName]);
+#endif
 
     // There are 6 session images because each session has an image with two
     // sizes.
@@ -972,7 +1016,10 @@
   EXPECT_EQ(remaining, GetURLsInTable(MediaHistorySessionTable::kTableName));
   EXPECT_EQ(remaining_images,
             GetURLsInTable(MediaHistoryImagesTable::kTableName));
+
+#if !defined(OS_ANDROID)
   EXPECT_EQ(media_feeds, GetURLsInTable(MediaHistoryFeedsTable::kTableName));
+#endif
 
   // Check the origins have the correct aggregate watchtime.
   {
diff --git a/chrome/browser/media/history/media_history_store.cc b/chrome/browser/media/history/media_history_store.cc
index 90182e9..50c35fb 100644
--- a/chrome/browser/media/history/media_history_store.cc
+++ b/chrome/browser/media/history/media_history_store.cc
@@ -10,7 +10,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/stringprintf.h"
 #include "base/task_runner_util.h"
-#include "chrome/browser/media/feeds/media_feeds_service.h"
+#include "build/build_config.h"
 #include "chrome/browser/media/history/media_history_feed_associated_origins_table.h"
 #include "chrome/browser/media/history/media_history_feed_items_table.h"
 #include "chrome/browser/media/history/media_history_feeds_table.h"
@@ -28,6 +28,10 @@
 #include "sql/transaction.h"
 #include "url/origin.h"
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/media/feeds/media_feeds_service.h"
+#endif  // !defined(OS_ANDROID)
+
 namespace {
 
 constexpr int kCurrentVersionNumber = 2;
@@ -97,6 +101,14 @@
          cause == net::CookieChangeCause::EVICTED;
 }
 
+bool IsMediaFeedsEnabled() {
+#if defined(OS_ANDROID)
+  return false;
+#else
+  return media_feeds::MediaFeedsService::IsEnabled();
+#endif  // defined(OS_ANDROID)
+}
+
 }  // namespace
 
 int GetCurrentVersion() {
@@ -128,14 +140,14 @@
       session_images_table_(
           new MediaHistorySessionImagesTable(db_task_runner_)),
       images_table_(new MediaHistoryImagesTable(db_task_runner_)),
-      feeds_table_(media_feeds::MediaFeedsService::IsEnabled()
+      feeds_table_(IsMediaFeedsEnabled()
                        ? new MediaHistoryFeedsTable(db_task_runner_)
                        : nullptr),
-      feed_items_table_(media_feeds::MediaFeedsService::IsEnabled()
+      feed_items_table_(IsMediaFeedsEnabled()
                             ? new MediaHistoryFeedItemsTable(db_task_runner_)
                             : nullptr),
       feed_origins_table_(
-          media_feeds::MediaFeedsService::IsEnabled()
+          IsMediaFeedsEnabled()
               ? new MediaHistoryFeedAssociatedOriginsTable(db_task_runner_)
               : nullptr),
       initialization_successful_(false) {}
@@ -462,6 +474,16 @@
   return playback_table_->GetPlaybackRows();
 }
 
+std::vector<media_feeds::mojom::MediaFeedItemPtr>
+MediaHistoryStore::GetMediaFeedItems(
+    const MediaHistoryKeyedService::GetMediaFeedItemsRequest& request) {
+  DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
+  if (!CanAccessDatabase() || !feed_items_table_)
+    return std::vector<media_feeds::mojom::MediaFeedItemPtr>();
+
+  return feed_items_table_->GetItems(request);
+}
+
 std::vector<media_feeds::mojom::MediaFeedPtr> MediaHistoryStore::GetMediaFeeds(
     const MediaHistoryKeyedService::GetMediaFeedsRequest& request) {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
@@ -817,16 +839,6 @@
   DB()->CommitTransaction();
 }
 
-std::vector<media_feeds::mojom::MediaFeedItemPtr>
-MediaHistoryStore::GetItemsForMediaFeedForDebug(const int64_t feed_id) {
-  DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
-
-  if (!CanAccessDatabase() || !feed_items_table_)
-    return std::vector<media_feeds::mojom::MediaFeedItemPtr>();
-
-  return feed_items_table_->GetItemsForFeed(feed_id);
-}
-
 MediaHistoryKeyedService::PendingSafeSearchCheckList
 MediaHistoryStore::GetPendingSafeSearchCheckMediaFeedItems() {
   DCHECK(db_task_runner_->RunsTasksInCurrentSequence());
diff --git a/chrome/browser/media/history/media_history_store.h b/chrome/browser/media/history/media_history_store.h
index ace0d2fd..c702d7ff 100644
--- a/chrome/browser/media/history/media_history_store.h
+++ b/chrome/browser/media/history/media_history_store.h
@@ -131,6 +131,9 @@
   std::vector<mojom::MediaHistoryPlaybackRowPtr>
   GetMediaHistoryPlaybackRowsForDebug();
 
+  std::vector<media_feeds::mojom::MediaFeedItemPtr> GetMediaFeedItems(
+      const MediaHistoryKeyedService::GetMediaFeedItemsRequest& request);
+
   std::vector<media_feeds::mojom::MediaFeedPtr> GetMediaFeeds(
       const MediaHistoryKeyedService::GetMediaFeedsRequest& request);
 
@@ -154,9 +157,6 @@
   void StoreMediaFeedFetchResult(
       MediaHistoryKeyedService::MediaFeedFetchResult result);
 
-  std::vector<media_feeds::mojom::MediaFeedItemPtr>
-  GetItemsForMediaFeedForDebug(const int64_t feed_id);
-
   MediaHistoryKeyedService::PendingSafeSearchCheckList
   GetPendingSafeSearchCheckMediaFeedItems();
 
diff --git a/chrome/browser/media/history/media_history_store_unittest.cc b/chrome/browser/media/history/media_history_store_unittest.cc
index 8ce98d02..f827eea 100644
--- a/chrome/browser/media/history/media_history_store_unittest.cc
+++ b/chrome/browser/media/history/media_history_store_unittest.cc
@@ -17,9 +17,8 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_timeouts.h"
+#include "build/build_config.h"
 #include "chrome/browser/history/history_service_factory.h"
-#include "chrome/browser/media/feeds/media_feeds_service.h"
-#include "chrome/browser/media/feeds/media_feeds_service_factory.h"
 #include "chrome/browser/media/feeds/media_feeds_store.mojom-forward.h"
 #include "chrome/browser/media/feeds/media_feeds_store.mojom.h"
 #include "chrome/browser/media/history/media_history_feed_items_table.h"
@@ -46,6 +45,11 @@
 #include "sql/statement.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/media/feeds/media_feeds_service.h"
+#include "chrome/browser/media/feeds/media_feeds_service_factory.h"
+#endif
+
 namespace media_history {
 
 namespace {
@@ -54,6 +58,8 @@
 // might be equal but it might be close too.
 const int kTimeErrorMargin = 10000;
 
+#if !defined(OS_ANDROID)
+
 // The expected display name for the fetched media feed.
 const char kExpectedDisplayName[] = "Test Feed";
 
@@ -70,6 +76,8 @@
 const int kExpectedAltFetchContentTypes =
     static_cast<int>(media_feeds::mojom::MediaFeedItemType::kVideo);
 
+#endif  // !defined(OS_ANDROID)
+
 base::FilePath g_temp_history_dir;
 
 std::unique_ptr<KeyedService> BuildTestHistoryService(
@@ -244,20 +252,6 @@
                            media_feeds::mojom::FetchResult::kSuccess);
   }
 
-  void DiscoverMediaFeed(const GURL& url) {
-    if (auto* service = GetMediaFeedsService())
-      service->DiscoverMediaFeed(url);
-  }
-
-  media_feeds::MediaFeedsService* GetMediaFeedsService() {
-    Profile* profile = profile_.get();
-    if (GetParam() == TestState::kIncognito)
-      profile = profile->GetOffTheRecordProfile();
-
-    return media_feeds::MediaFeedsServiceFactory::GetInstance()->GetForProfile(
-        profile);
-  }
-
   MediaHistoryKeyedService* service() const {
     // If the param is true then we use the OTR service to simulate being in
     // incognito.
@@ -271,6 +265,8 @@
 
   bool IsReadOnly() const { return GetParam() != TestState::kNormal; }
 
+  Profile* GetProfile() { return profile_.get(); }
+
  private:
   base::ScopedTempDir temp_dir_;
 
@@ -624,26 +620,7 @@
   EXPECT_EQ(origins, GetOriginRowsSync(otr_service()));
 }
 
-// TODO(crbug.com/1087974).
-#if defined(THREAD_SANITIZER)
-#define MAYBE_DiscoverMediaFeed_Noop DISABLED_DiscoverMediaFeed_Noop
-#else
-#define MAYBE_DiscoverMediaFeed_Noop DiscoverMediaFeed_Noop
-#endif
-TEST_P(MediaHistoryStoreUnitTest, MAYBE_DiscoverMediaFeed_Noop) {
-  DiscoverMediaFeed(GURL("https://www.google.com/feed"));
-  WaitForDB();
-
-  {
-    // Check the feeds were not recorded.
-    mojom::MediaHistoryStatsPtr stats = GetStatsSync(service());
-    EXPECT_FALSE(base::Contains(stats->table_row_counts,
-                                MediaHistoryFeedsTable::kTableName));
-
-    // The OTR service should have the same data.
-    EXPECT_EQ(stats, GetStatsSync(otr_service()));
-  }
-}
+#if !defined(OS_ANDROID)
 
 // Runs the tests with the media feeds feature enabled.
 class MediaHistoryStoreFeedsTest : public MediaHistoryStoreUnitTest {
@@ -653,14 +630,37 @@
     MediaHistoryStoreUnitTest::SetUp();
   }
 
+  void DiscoverMediaFeed(const GURL& url) {
+    if (auto* service = GetMediaFeedsService())
+      service->DiscoverMediaFeed(url);
+  }
+
+  media_feeds::MediaFeedsService* GetMediaFeedsService() {
+    Profile* profile = GetProfile();
+    if (GetParam() == TestState::kIncognito)
+      profile = profile->GetOffTheRecordProfile();
+
+    return media_feeds::MediaFeedsServiceFactory::GetInstance()->GetForProfile(
+        profile);
+  }
+
   std::vector<media_feeds::mojom::MediaFeedItemPtr> GetItemsForMediaFeedSync(
       MediaHistoryKeyedService* service,
       const int64_t feed_id) {
+    return GetItemsForMediaFeedSync(
+        service,
+        MediaHistoryKeyedService::GetMediaFeedItemsRequest::CreateItemsForDebug(
+            feed_id));
+  }
+
+  std::vector<media_feeds::mojom::MediaFeedItemPtr> GetItemsForMediaFeedSync(
+      MediaHistoryKeyedService* service,
+      MediaHistoryKeyedService::GetMediaFeedItemsRequest request) {
     base::RunLoop run_loop;
     std::vector<media_feeds::mojom::MediaFeedItemPtr> out;
 
-    service->GetItemsForMediaFeedForDebug(
-        feed_id,
+    service->GetMediaFeedItems(
+        request,
         base::BindLambdaForTesting(
             [&](std::vector<media_feeds::mojom::MediaFeedItemPtr> rows) {
               out = std::move(rows);
@@ -705,11 +705,13 @@
     return identifier;
   }
 
-  static std::vector<media_feeds::mojom::MediaFeedItemPtr> GetExpectedItems() {
+  static std::vector<media_feeds::mojom::MediaFeedItemPtr> GetExpectedItems(
+      int id_start = 0) {
     std::vector<media_feeds::mojom::MediaFeedItemPtr> items;
 
     {
       auto item = media_feeds::mojom::MediaFeedItem::New();
+      item->id = ++id_start;
       item->name = base::ASCIIToUTF16("The Movie");
       item->type = media_feeds::mojom::MediaFeedItemType::kMovie;
       item->date_published = base::Time::FromDeltaSinceWindowsEpoch(
@@ -803,6 +805,7 @@
 
     {
       auto item = media_feeds::mojom::MediaFeedItem::New();
+      item->id = ++id_start;
       item->type = media_feeds::mojom::MediaFeedItemType::kTVSeries;
       item->name = base::ASCIIToUTF16("The TV Series");
       item->action_status =
@@ -817,6 +820,7 @@
 
     {
       auto item = media_feeds::mojom::MediaFeedItem::New();
+      item->id = ++id_start;
       item->type = media_feeds::mojom::MediaFeedItemType::kTVSeries;
       item->name = base::ASCIIToUTF16("The Live TV Series");
       item->action_status =
@@ -831,12 +835,13 @@
     return items;
   }
 
-  static std::vector<media_feeds::mojom::MediaFeedItemPtr>
-  GetAltExpectedItems() {
+  static std::vector<media_feeds::mojom::MediaFeedItemPtr> GetAltExpectedItems(
+      int id_start = 0) {
     std::vector<media_feeds::mojom::MediaFeedItemPtr> items;
 
     {
       auto item = media_feeds::mojom::MediaFeedItem::New();
+      item->id = ++id_start;
       item->type = media_feeds::mojom::MediaFeedItemType::kVideo;
       item->name = base::ASCIIToUTF16("The Video");
       item->date_published = base::Time::FromDeltaSinceWindowsEpoch(
@@ -1040,6 +1045,7 @@
     result.associated_origins = GetExpectedAssociatedOrigins();
     result.user_identifier = GetExpectedUserIdentifier();
     result.cookie_name_filter = "test";
+    result.items[0]->id = 9;
     service()->StoreMediaFeedFetchResult(std::move(result), base::DoNothing());
     WaitForDB();
 
@@ -1112,7 +1118,7 @@
       EXPECT_EQ(ToSet(feed_url), ToSet(feeds[0]->associated_origins));
       EXPECT_TRUE(feeds[0]->cookie_name_filter.empty());
 
-      EXPECT_EQ(GetAltExpectedItems(), items);
+      EXPECT_EQ(GetAltExpectedItems(3), items);
 
       last_fetch_time_not_cache_hit = feeds[0]->last_fetch_time_not_cache_hit;
     }
@@ -1152,7 +1158,7 @@
       EXPECT_FALSE(feeds[0]->last_display_time.has_value());
       EXPECT_EQ(ToSet(feed_url), ToSet(feeds[0]->associated_origins));
 
-      EXPECT_EQ(GetAltExpectedItems(), items);
+      EXPECT_EQ(GetAltExpectedItems(4), items);
 
       EXPECT_EQ(last_fetch_time_not_cache_hit,
                 feeds[0]->last_fetch_time_not_cache_hit);
@@ -1316,7 +1322,7 @@
     if (IsReadOnly()) {
       EXPECT_TRUE(items.empty());
     } else {
-      EXPECT_EQ(GetAltExpectedItems(), items);
+      EXPECT_EQ(GetAltExpectedItems(3), items);
     }
 
     // The OTR service should have the same data.
@@ -2313,7 +2319,7 @@
       EXPECT_EQ(ToSet(feed_url_b), ToSet(feeds[1]->associated_origins));
 
       EXPECT_EQ(GetExpectedItems(), items_a);
-      EXPECT_EQ(GetAltExpectedItems(), items_b);
+      EXPECT_EQ(GetAltExpectedItems(3), items_b);
     }
 
     // The OTR service should have the same data.
@@ -2361,7 +2367,7 @@
       EXPECT_EQ(ToSet(feed_url_b), ToSet(feeds[1]->associated_origins));
 
       EXPECT_TRUE(items_a.empty());
-      EXPECT_EQ(GetAltExpectedItems(), items_b);
+      EXPECT_EQ(GetAltExpectedItems(3), items_b);
     }
 
     // The OTR service should have the same data.
@@ -2410,8 +2416,8 @@
       EXPECT_EQ(feed_id_b, feeds[1]->id);
       EXPECT_EQ(ToSet(feed_url_b), ToSet(feeds[1]->associated_origins));
 
-      EXPECT_EQ(GetExpectedItems(), items_a);
-      EXPECT_EQ(GetAltExpectedItems(), items_b);
+      EXPECT_EQ(GetExpectedItems(4), items_a);
+      EXPECT_EQ(GetAltExpectedItems(3), items_b);
     }
 
     // The OTR service should have the same data.
@@ -2496,7 +2502,7 @@
                 ToSet(feeds[1]->associated_origins));
 
       EXPECT_EQ(GetExpectedItems(), items_a);
-      EXPECT_EQ(GetAltExpectedItems(), items_b);
+      EXPECT_EQ(GetAltExpectedItems(3), items_b);
     }
 
     // The OTR service should have the same data.
@@ -2546,7 +2552,7 @@
                 ToSet(feeds[1]->associated_origins));
 
       EXPECT_EQ(GetExpectedItems(), items_a);
-      EXPECT_EQ(GetAltExpectedItems(), items_b);
+      EXPECT_EQ(GetAltExpectedItems(3), items_b);
     }
 
     // The OTR service should have the same data.
@@ -2643,7 +2649,7 @@
       EXPECT_EQ(feed_id_b, feeds[1]->id);
       EXPECT_EQ(ToSet(feed_url_b), ToSet(feeds[1]->associated_origins));
 
-      EXPECT_EQ(GetExpectedItems(), items_a);
+      EXPECT_EQ(GetExpectedItems(4), items_a);
       EXPECT_TRUE(items_b.empty());
     }
 
@@ -2692,7 +2698,7 @@
       EXPECT_EQ(feed_id_b, feeds[1]->id);
       EXPECT_EQ(ToSet(feed_url_b), ToSet(feeds[1]->associated_origins));
 
-      EXPECT_EQ(GetExpectedItems(), items_a);
+      EXPECT_EQ(GetExpectedItems(4), items_a);
       EXPECT_TRUE(items_b.empty());
     }
 
@@ -2873,4 +2879,122 @@
   }
 }
 
+TEST_P(MediaHistoryStoreFeedsTest, GetContinueWatching) {
+  const GURL feed_url("https://www.google.com/feed");
+
+  DiscoverMediaFeed(feed_url);
+  WaitForDB();
+
+  // If we are read only we should use -1 as a placeholder feed id because the
+  // feed will not have been stored. This is so we can run the rest of the test
+  // to ensure a no-op.
+  const int feed_id = IsReadOnly() ? -1 : GetMediaFeedsSync(service())[0]->id;
+
+  service()->StoreMediaFeedFetchResult(
+      SuccessfulResultWithItems(feed_id, GetExpectedItems()),
+      base::DoNothing());
+  WaitForDB();
+
+  {
+    auto items = GetItemsForMediaFeedSync(
+        service(), MediaHistoryKeyedService::GetMediaFeedItemsRequest::
+                       CreateItemsForContinueWatching(5, false));
+
+    if (IsReadOnly()) {
+      EXPECT_TRUE(items.empty());
+    } else {
+      // We should have the first item because it has play next details and the
+      // second item because it has an active action status.
+      ASSERT_EQ(2u, items.size());
+      EXPECT_EQ(2, items[0]->id);
+      EXPECT_EQ(1, items[1]->id);
+    }
+  }
+
+  {
+    auto items = GetItemsForMediaFeedSync(
+        service(), MediaHistoryKeyedService::GetMediaFeedItemsRequest::
+                       CreateItemsForContinueWatching(5, true));
+
+    if (IsReadOnly()) {
+      EXPECT_TRUE(items.empty());
+    } else {
+      // We should only return the second item because it is the only one that
+      // is safe.
+      ASSERT_EQ(1u, items.size());
+      EXPECT_EQ(2, items[0]->id);
+    }
+  }
+
+  {
+    auto items = GetItemsForMediaFeedSync(
+        service(), MediaHistoryKeyedService::GetMediaFeedItemsRequest::
+                       CreateItemsForContinueWatching(1, false));
+
+    if (IsReadOnly()) {
+      EXPECT_TRUE(items.empty());
+    } else {
+      // We should only return the second item because we are limiting to one
+      // item.
+      ASSERT_EQ(1u, items.size());
+      EXPECT_EQ(2, items[0]->id);
+    }
+  }
+}
+
+TEST_P(MediaHistoryStoreFeedsTest, GetItemsForFeed) {
+  const GURL feed_url("https://www.google.com/feed");
+
+  DiscoverMediaFeed(feed_url);
+  WaitForDB();
+
+  // If we are read only we should use -1 as a placeholder feed id because the
+  // feed will not have been stored. This is so we can run the rest of the test
+  // to ensure a no-op.
+  const int feed_id = IsReadOnly() ? -1 : GetMediaFeedsSync(service())[0]->id;
+
+  service()->StoreMediaFeedFetchResult(
+      SuccessfulResultWithItems(feed_id, GetExpectedItems()),
+      base::DoNothing());
+  WaitForDB();
+
+  {
+    auto items = GetItemsForMediaFeedSync(
+        service(),
+        MediaHistoryKeyedService::GetMediaFeedItemsRequest::CreateItemsForFeed(
+            1, 5, false));
+
+    if (IsReadOnly()) {
+      EXPECT_TRUE(items.empty());
+    } else {
+      // We should have the third item because the others have continue
+      // watching details are have been removed.
+      ASSERT_EQ(1u, items.size());
+      EXPECT_EQ(3, items[0]->id);
+    }
+  }
+
+  {
+    auto items = GetItemsForMediaFeedSync(
+        service(),
+        MediaHistoryKeyedService::GetMediaFeedItemsRequest::CreateItemsForFeed(
+            1, 5, true));
+
+    // Do not return anything since all the feed items are "unsafe".
+    EXPECT_TRUE(items.empty());
+  }
+
+  {
+    auto items = GetItemsForMediaFeedSync(
+        service(),
+        MediaHistoryKeyedService::GetMediaFeedItemsRequest::CreateItemsForFeed(
+            1, 0, false));
+
+    // Do not return anything since the limit is 0.
+    EXPECT_TRUE(items.empty());
+  }
+}
+
+#endif  // !defined(OS_ANDROID)
+
 }  // namespace media_history
diff --git a/chrome/browser/media/media_engagement_browsertest.cc b/chrome/browser/media/media_engagement_browsertest.cc
index 689e48b..be37ba1 100644
--- a/chrome/browser/media/media_engagement_browsertest.cc
+++ b/chrome/browser/media/media_engagement_browsertest.cc
@@ -35,7 +35,7 @@
 #include "components/component_updater/component_updater_service.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
-#include "components/prerender/prerender_final_status.h"
+#include "components/prerender/common/prerender_final_status.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
diff --git a/chrome/browser/media/media_engagement_contents_observer.cc b/chrome/browser/media/media_engagement_contents_observer.cc
index 775fe5824..0242117 100644
--- a/chrome/browser/media/media_engagement_contents_observer.cc
+++ b/chrome/browser/media/media_engagement_contents_observer.cc
@@ -605,7 +605,7 @@
 content::WebContents* MediaEngagementContentsObserver::GetOpener() const {
 #if !defined(OS_ANDROID)
   for (auto* browser : *BrowserList::GetInstance()) {
-    if (!browser->profile()->IsSameProfileAndType(service_->profile()))
+    if (browser->profile() != service_->profile())
       continue;
 
     int index =
diff --git a/chrome/browser/media/router/BUILD.gn b/chrome/browser/media/router/BUILD.gn
index 0a680d4..2ddc0fb 100644
--- a/chrome/browser/media/router/BUILD.gn
+++ b/chrome/browser/media/router/BUILD.gn
@@ -88,6 +88,8 @@
       "//ui/base:buildflags",
     ]
 
+    public_deps += [ "//chrome/common/media_router/mojom:logger" ]
+
     sources += [
       "data_decoder_util.cc",
       "data_decoder_util.h",
@@ -95,6 +97,8 @@
       "event_page_request_manager.h",
       "event_page_request_manager_factory.cc",
       "event_page_request_manager_factory.h",
+      "logger_impl.cc",
+      "logger_impl.h",
       "mojo/media_route_provider_util_win.cc",
       "mojo/media_route_provider_util_win.h",
       "mojo/media_router_desktop.cc",
@@ -248,6 +252,7 @@
       "discovery/mdns/dns_sd_registry_unittest.cc",
       "discovery/media_sink_discovery_metrics_unittest.cc",
       "event_page_request_manager_unittest.cc",
+      "logger_impl_unittest.cc",
       "media_router_feature_unittest.cc",
       "mojo/media_router_desktop_unittest.cc",
       "mojo/media_router_mojo_impl_unittest.cc",
diff --git a/chrome/browser/media/router/discovery/mdns/dns_sd_registry_unittest.cc b/chrome/browser/media/router/discovery/mdns/dns_sd_registry_unittest.cc
index bf0cba6..8a299f5 100644
--- a/chrome/browser/media/router/discovery/mdns/dns_sd_registry_unittest.cc
+++ b/chrome/browser/media/router/discovery/mdns/dns_sd_registry_unittest.cc
@@ -14,7 +14,7 @@
 
 class MockDnsSdDeviceLister : public DnsSdDeviceLister {
  public:
-  MockDnsSdDeviceLister() : DnsSdDeviceLister(NULL, NULL, "") {}
+  MockDnsSdDeviceLister() : DnsSdDeviceLister(nullptr, nullptr, "") {}
   ~MockDnsSdDeviceLister() override {}
 
   MOCK_METHOD0(Discover, void());
@@ -22,7 +22,7 @@
 
 class TestDnsSdRegistry : public DnsSdRegistry {
  public:
-  TestDnsSdRegistry() : DnsSdRegistry(NULL), delegate_(NULL) {}
+  TestDnsSdRegistry() : DnsSdRegistry(nullptr), delegate_(nullptr) {}
   ~TestDnsSdRegistry() override {}
 
   MockDnsSdDeviceLister* GetListerForService(const std::string& service_type) {
diff --git a/chrome/browser/media/router/logger_impl.cc b/chrome/browser/media/router/logger_impl.cc
new file mode 100644
index 0000000..ae318f0ad
--- /dev/null
+++ b/chrome/browser/media/router/logger_impl.cc
@@ -0,0 +1,182 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/router/logger_impl.h"
+
+#include "base/i18n/time_formatting.h"
+#include "base/json/json_string_value_serializer.h"
+#include "base/values.h"
+#include "chrome/common/media_router/media_source.h"
+#include "chrome/common/media_router/mojom/logger.mojom-shared.h"
+#include "url/gurl.h"
+
+namespace media_router {
+
+namespace {
+
+constexpr size_t kEntriesCapacity = 1000;
+
+constexpr size_t kComponentMaxLength = 64;
+constexpr size_t kMessageMaxLength = 256;
+constexpr size_t kSourceMaxLength = 64;
+
+const char* AsString(LoggerImpl::Severity severity) {
+  switch (severity) {
+    case LoggerImpl::Severity::kInfo:
+      return "Info";
+    case LoggerImpl::Severity::kWarning:
+      return "Warning";
+    case LoggerImpl::Severity::kError:
+      return "Error";
+  }
+}
+
+const char* AsString(mojom::LogCategory category) {
+  switch (category) {
+    case mojom::LogCategory::kDiscovery:
+      return "Discovery";
+    case mojom::LogCategory::kRoute:
+      return "Route";
+    case mojom::LogCategory::kMirroring:
+      return "Mirroring";
+    case mojom::LogCategory::kUi:
+      return "UI";
+  }
+}
+
+base::StringPiece TruncateComponent(base::StringPiece component) {
+  return component.substr(0, kComponentMaxLength);
+}
+
+base::StringPiece TruncateMessage(base::StringPiece message) {
+  return message.substr(0, kMessageMaxLength);
+}
+
+// Gets the last four characters of an ID string.
+base::StringPiece TruncateId(base::StringPiece id) {
+  if (id.size() <= 4)
+    return id;
+  return id.substr(id.size() - 4);
+}
+
+}  // namespace
+
+LoggerImpl::LoggerImpl() : capacity_(kEntriesCapacity) {}
+LoggerImpl::~LoggerImpl() = default;
+
+void LoggerImpl::LogInfo(mojom::LogCategory category,
+                         const std::string& component,
+                         const std::string& message,
+                         const std::string& sink_id,
+                         const std::string& media_source,
+                         const std::string& session_id) {
+  Log(Severity::kInfo, category, base::Time::Now(), component, message, sink_id,
+      media_source, session_id);
+}
+
+void LoggerImpl::LogWarning(mojom::LogCategory category,
+                            const std::string& component,
+                            const std::string& message,
+                            const std::string& sink_id,
+                            const std::string& media_source,
+                            const std::string& session_id) {
+  Log(Severity::kWarning, category, base::Time::Now(), component, message,
+      sink_id, media_source, session_id);
+}
+
+void LoggerImpl::LogError(mojom::LogCategory category,
+                          const std::string& component,
+                          const std::string& message,
+                          const std::string& sink_id,
+                          const std::string& media_source,
+                          const std::string& session_id) {
+  Log(Severity::kError, category, base::Time::Now(), component, message,
+      sink_id, media_source, session_id);
+}
+
+void LoggerImpl::Bind(mojo::PendingReceiver<mojom::Logger> receiver) {
+  receivers_.Add(this, std::move(receiver));
+}
+
+std::string LoggerImpl::GetLogsAsJson() const {
+  std::string json;
+  JSONStringValueSerializer serializer(&json);
+  serializer.set_pretty_print(true);
+  if (!serializer.Serialize(GetLogsAsValue())) {
+    DVLOG(1) << "Failed to serialize log to JSON.";
+    return "";
+  }
+  return json;
+}
+
+LoggerImpl::Entry::Entry(Severity severity,
+                         mojom::LogCategory category,
+                         base::Time time,
+                         base::StringPiece component,
+                         base::StringPiece message,
+                         base::StringPiece sink_id,
+                         std::string media_source,
+                         base::StringPiece session_id)
+    : severity(severity),
+      category(category),
+      time(time),
+      component(component.as_string()),
+      message(message.as_string()),
+      sink_id(sink_id.as_string()),
+      media_source(std::move(media_source)),
+      session_id(session_id.as_string()) {}
+
+LoggerImpl::Entry::Entry(Entry&& other)
+    : severity(other.severity),
+      category(other.category),
+      time(other.time),
+      component(std::move(other.component)),
+      message(std::move(other.message)),
+      sink_id(std::move(other.sink_id)),
+      media_source(std::move(other.media_source)),
+      session_id(std::move(other.session_id)) {}
+
+LoggerImpl::Entry::~Entry() = default;
+
+void LoggerImpl::Log(Severity severity,
+                     mojom::LogCategory category,
+                     base::Time time,
+                     const std::string& component,
+                     const std::string& message,
+                     const std::string& sink_id,
+                     const std::string& media_source,
+                     const std::string& session_id) {
+  entries_.emplace_back(
+      severity, category, time, TruncateComponent(component),
+      TruncateMessage(message), TruncateId(sink_id),
+      MediaSource(media_source).TruncateForLogging(kSourceMaxLength),
+      TruncateId(session_id));
+  if (entries_.size() > capacity_)
+    entries_.pop_front();
+}
+
+// static
+base::Value LoggerImpl::AsValue(const LoggerImpl::Entry& entry) {
+  base::Value entry_val(base::Value::Type::DICTIONARY);
+  entry_val.SetKey("severity", base::Value(AsString(entry.severity)));
+  entry_val.SetKey("category", base::Value(AsString(entry.category)));
+  entry_val.SetKey(
+      "time",
+      base::Value(base::TimeFormatTimeOfDayWithMilliseconds(entry.time)));
+  entry_val.SetKey("component", base::Value(entry.component));
+  entry_val.SetKey("message", base::Value(entry.message));
+  entry_val.SetKey("sinkId", base::Value(entry.sink_id));
+  entry_val.SetKey("mediaSource", base::Value(entry.media_source));
+  entry_val.SetKey("sessionId", base::Value(entry.session_id));
+  return entry_val;
+}
+
+base::Value LoggerImpl::GetLogsAsValue() const {
+  base::Value entries_val(base::Value::Type::LIST);
+  for (const auto& entry : entries_)
+    entries_val.Append(AsValue(entry));
+  return entries_val;
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/router/logger_impl.h b/chrome/browser/media/router/logger_impl.h
new file mode 100644
index 0000000..2fc94b7
--- /dev/null
+++ b/chrome/browser/media/router/logger_impl.h
@@ -0,0 +1,105 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_MEDIA_ROUTER_LOGGER_IMPL_H_
+#define CHROME_BROWSER_MEDIA_ROUTER_LOGGER_IMPL_H_
+
+#include "base/containers/circular_deque.h"
+#include "base/strings/string_piece_forward.h"
+#include "chrome/common/media_router/mojom/logger.mojom.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace base {
+class Value;
+}  // namespace base
+
+namespace media_router {
+
+class LoggerImpl : mojom::Logger {
+ public:
+  enum class Severity { kInfo, kWarning, kError };
+
+  LoggerImpl();
+  ~LoggerImpl() override;
+  LoggerImpl(const LoggerImpl&) = delete;
+  LoggerImpl& operator=(const LoggerImpl&) = delete;
+
+  // mojom::Logger overrides:
+  void LogInfo(mojom::LogCategory category,
+               const std::string& component,
+               const std::string& message,
+               const std::string& sink_id,
+               const std::string& media_source,
+               const std::string& session_id) override;
+  void LogWarning(mojom::LogCategory category,
+                  const std::string& component,
+                  const std::string& message,
+                  const std::string& sink_id,
+                  const std::string& media_source,
+                  const std::string& session_id) override;
+  void LogError(mojom::LogCategory category,
+                const std::string& component,
+                const std::string& message,
+                const std::string& sink_id,
+                const std::string& media_source,
+                const std::string& session_id) override;
+
+  void Bind(mojo::PendingReceiver<mojom::Logger> receiver);
+
+  std::string GetLogsAsJson() const;
+
+ private:
+  FRIEND_TEST_ALL_PREFIXES(LoggerImplTest, RecordAndGetLogs);
+
+  struct Entry {
+   public:
+    Entry(Severity severity,
+          mojom::LogCategory category,
+          base::Time time,
+          base::StringPiece component,
+          base::StringPiece message,
+          base::StringPiece sink_id,
+          std::string media_source,
+          base::StringPiece session_id);
+    Entry(Entry&& other);
+    Entry(const Entry&) = delete;
+    ~Entry();
+
+    Severity severity;
+    mojom::LogCategory category;
+    base::Time time;
+    // This is usually the name of the class that is emitting the log.
+    std::string component;
+    std::string message;
+    // May be empty if the entry is not associated with a sink.
+    std::string sink_id;
+    // May be empty if the entry is not associated with a media source.
+    std::string media_source;
+    // May be empty if the entry is not associated with a session.
+    std::string session_id;
+  };
+
+  // Called by tests that want to specify |time|.
+  void Log(Severity severity,
+           mojom::LogCategory category,
+           base::Time time,
+           const std::string& component,
+           const std::string& message,
+           const std::string& sink_id,
+           const std::string& media_source,
+           const std::string& session_id);
+
+  static base::Value AsValue(const Entry& entry);
+  base::Value GetLogsAsValue() const;
+
+  mojo::ReceiverSet<mojom::Logger> receivers_;
+  base::circular_deque<Entry> entries_;
+  size_t const capacity_;
+};
+
+}  // namespace media_router
+
+#endif  // CHROME_BROWSER_MEDIA_ROUTER_LOGGER_IMPL_H_
diff --git a/chrome/browser/media/router/logger_impl_unittest.cc b/chrome/browser/media/router/logger_impl_unittest.cc
new file mode 100644
index 0000000..2b7f3de
--- /dev/null
+++ b/chrome/browser/media/router/logger_impl_unittest.cc
@@ -0,0 +1,133 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser//media/router/logger_impl.h"
+
+#include "base/i18n/time_formatting.h"
+#include "base/json/json_reader.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/values.h"
+#include "chrome/common/media_router/mojom/logger.mojom-shared.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media_router {
+
+constexpr char kComponent[] = "MyComponent";
+constexpr char kMessage[] = "My message";
+constexpr char kSinkId[] = "sink-12345";
+constexpr char kMediaSource[] = "cast:ABCDEFGH";
+constexpr char kSessionId[] = "session-67890";
+
+class LoggerImplTest : public testing::Test {
+ protected:
+  void LogInfoWithSinkId(const std::string& sink_id) {
+    logger_.LogInfo(mojom::LogCategory::kRoute, kComponent, kMessage, sink_id,
+                    kMediaSource, kSessionId);
+  }
+  void LogWarningWithSessionId(const std::string& session_id) {
+    logger_.LogWarning(mojom::LogCategory::kRoute, kComponent, kMessage,
+                       kSinkId, kMediaSource, session_id);
+  }
+  void LogErrorWithSource(const std::string& media_source) {
+    logger_.LogError(mojom::LogCategory::kRoute, kComponent, kMessage, kSinkId,
+                     media_source, kSessionId);
+  }
+
+  std::string GetSinkId(const std::string& logs_json) {
+    return GetAttributeOfFirstEntry(logs_json, "sinkId");
+  }
+
+  std::string GetSessionId(const std::string& logs_json) {
+    return GetAttributeOfFirstEntry(logs_json, "sessionId");
+  }
+
+  std::string GetMediaSource(const std::string& logs_json) {
+    return GetAttributeOfFirstEntry(logs_json, "mediaSource");
+  }
+
+  LoggerImpl logger_;
+
+ private:
+  std::string GetAttributeOfFirstEntry(const std::string& logs_json,
+                                       const std::string& attribute) {
+    base::Value logs = base::JSONReader::Read(logs_json).value();
+    return *logs.GetList()[0].FindStringKey(attribute);
+  }
+};
+
+TEST_F(LoggerImplTest, RecordAndGetLogs) {
+  const base::Time time1 = base::Time::Now();
+  const base::Time time2 = time1 + base::TimeDelta::FromSeconds(20);
+  const std::string expected_logs =
+      R"([
+    {
+      "severity": "Error",
+      "category": "Route",
+      "time": ")" +
+      base::UTF16ToUTF8(base::TimeFormatTimeOfDayWithMilliseconds(time1)) +
+      R"(",
+      "component": "MyComponent",
+      "message": "My message",
+      "sinkId": "2345",
+      "mediaSource": "cast:ABCDEFGH",
+      "sessionId": "7890"
+    },
+    {
+      "severity": "Info",
+      "category": "UI",
+      "time": ")" +
+      base::UTF16ToUTF8(base::TimeFormatTimeOfDayWithMilliseconds(time2)) +
+      R"(",
+      "component": "Component 2",
+      "message": "Message 2",
+      "sinkId": "efgh",
+      "mediaSource": "cast:IJKLMNOP",
+      "sessionId": "wxyz"
+    }
+  ])";
+
+  logger_.Log(LoggerImpl::Severity::kError, mojom::LogCategory::kRoute, time1,
+              kComponent, kMessage, kSinkId, kMediaSource, kSessionId);
+  logger_.Log(LoggerImpl::Severity::kInfo, mojom::LogCategory::kUi, time2,
+              "Component 2", "Message 2", "sink-abcdefgh", "cast:IJKLMNOP",
+              "session-stuvwxyz");
+  const std::string logs = logger_.GetLogsAsJson();
+  EXPECT_EQ(base::JSONReader::Read(logs),
+            base::JSONReader::Read(expected_logs));
+}
+
+TEST_F(LoggerImplTest, TruncateSinkId) {
+  LogInfoWithSinkId(kSinkId);
+  const std::string logs = logger_.GetLogsAsJson();
+  EXPECT_EQ(GetSinkId(logs), "2345");
+}
+
+TEST_F(LoggerImplTest, TruncateSessionId) {
+  LogWarningWithSessionId(kSessionId);
+  const std::string logs = logger_.GetLogsAsJson();
+  EXPECT_EQ(GetSessionId(logs), "7890");
+}
+
+TEST_F(LoggerImplTest, HandleMirroringMediaSource) {
+  // A mirroring source should get logged as-is.
+  const std::string source = "urn:x-org.chromium.media:source:tab:*";
+  LogErrorWithSource(source);
+  const std::string logs = logger_.GetLogsAsJson();
+  EXPECT_EQ(GetMediaSource(logs), source);
+}
+
+TEST_F(LoggerImplTest, TrimCastMediaSource) {
+  LogErrorWithSource("cast:ABCDEFGH?a=b&c=d");
+  const std::string logs = logger_.GetLogsAsJson();
+  EXPECT_EQ(GetMediaSource(logs), "cast:ABCDEFGH");
+}
+
+TEST_F(LoggerImplTest, TrimPresentationMediaSource) {
+  LogErrorWithSource("https://presentation.example.com/receiver.html?a=b");
+  const std::string logs = logger_.GetLogsAsJson();
+  EXPECT_EQ(GetMediaSource(logs), "https://presentation.example.com/");
+}
+
+}  // namespace media_router
diff --git a/chrome/browser/media/webrtc/fake_desktop_media_list.cc b/chrome/browser/media/webrtc/fake_desktop_media_list.cc
index ee71126..3bc98e7 100644
--- a/chrome/browser/media/webrtc/fake_desktop_media_list.cc
+++ b/chrome/browser/media/webrtc/fake_desktop_media_list.cc
@@ -14,7 +14,7 @@
 using content::DesktopMediaID;
 
 FakeDesktopMediaList::FakeDesktopMediaList(DesktopMediaID::Type type)
-    : observer_(NULL), type_(type) {}
+    : observer_(nullptr), type_(type) {}
 FakeDesktopMediaList::~FakeDesktopMediaList() {}
 
 void FakeDesktopMediaList::AddSource(int id) {
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest.cc b/chrome/browser/media/webrtc/webrtc_browsertest.cc
index c30ac62..0165ea1 100644
--- a/chrome/browser/media/webrtc/webrtc_browsertest.cc
+++ b/chrome/browser/media/webrtc/webrtc_browsertest.cc
@@ -257,9 +257,8 @@
                                     kKeygenAlgorithmEcdsa, kKeygenAlgorithmRsa);
 }
 
-IN_PROC_BROWSER_TEST_F(
-    MAYBE_WebRtcBrowserTest,
-    DISABLED_RunsAudioVideoWebRTCCallInTwoTabsGetStatsCallback) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+                       RunsAudioVideoWebRTCCallInTwoTabsGetStatsCallback) {
   StartServerAndOpenTabs();
   SetupPeerconnectionWithLocalStream(left_tab_);
   SetupPeerconnectionWithLocalStream(right_tab_);
@@ -287,9 +286,8 @@
   EXPECT_EQ(0u, GetPeerToPeerConnectionsCountChangeFromNetworkService());
 }
 
-IN_PROC_BROWSER_TEST_F(
-    MAYBE_WebRtcBrowserTest,
-    DISABLED_RunsAudioVideoWebRTCCallInTwoTabsGetStatsPromise) {
+IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcBrowserTest,
+                       RunsAudioVideoWebRTCCallInTwoTabsGetStatsPromise) {
   StartServerAndOpenTabs();
   SetupPeerconnectionWithLocalStream(left_tab_);
   SetupPeerconnectionWithLocalStream(right_tab_);
diff --git a/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc b/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc
index 97ed2d5e..bcad334 100644
--- a/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc
+++ b/chrome/browser/media_galleries/gallery_watch_manager_unittest.cc
@@ -61,10 +61,10 @@
         test_user_manager_(std::make_unique<chromeos::ScopedTestUserManager>()),
 #endif
         profile_(new TestingProfile()),
-        gallery_prefs_(NULL),
+        gallery_prefs_(nullptr),
         expect_gallery_changed_(false),
         expect_gallery_watch_dropped_(false),
-        pending_loop_(NULL) {
+        pending_loop_(nullptr) {
   }
 
   ~GalleryWatchManagerTest() override {}
diff --git a/chrome/browser/media_galleries/media_galleries_permission_controller.cc b/chrome/browser/media_galleries/media_galleries_permission_controller.cc
index 8bc23e28..40c5f0d 100644
--- a/chrome/browser/media_galleries/media_galleries_permission_controller.cc
+++ b/chrome/browser/media_galleries/media_galleries_permission_controller.cc
@@ -100,7 +100,7 @@
     MediaGalleriesPreferences* preferences,
     const CreateDialogCallback& create_dialog_callback,
     const base::Closure& on_finish)
-    : web_contents_(NULL),
+    : web_contents_(nullptr),
       extension_(&extension),
       on_finish_(on_finish),
       preferences_(preferences),
diff --git a/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc b/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc
index f84be265..29f79c0 100644
--- a/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc
+++ b/chrome/browser/media_galleries/media_galleries_permission_controller_unittest.cc
@@ -44,9 +44,9 @@
 class MediaGalleriesPermissionControllerTest : public ::testing::Test {
  public:
   MediaGalleriesPermissionControllerTest()
-      : dialog_(NULL),
+      : dialog_(nullptr),
         dialog_update_count_at_destruction_(0),
-        controller_(NULL),
+        controller_(nullptr),
         profile_(new TestingProfile()) {}
 
   ~MediaGalleriesPermissionControllerTest() override {
diff --git a/chrome/browser/metrics/plugin_metrics_provider.cc b/chrome/browser/metrics/plugin_metrics_provider.cc
index f1398a2..5f4ef3b 100644
--- a/chrome/browser/metrics/plugin_metrics_provider.cc
+++ b/chrome/browser/metrics/plugin_metrics_provider.cc
@@ -164,7 +164,6 @@
     }
 
     if (!system_profile_plugin) {
-      NOTREACHED();
       continue;
     }
 
diff --git a/chrome/browser/net/dns_probe_browsertest.cc b/chrome/browser/net/dns_probe_browsertest.cc
index 0f31e7c3..c73735d 100644
--- a/chrome/browser/net/dns_probe_browsertest.cc
+++ b/chrome/browser/net/dns_probe_browsertest.cc
@@ -423,8 +423,8 @@
 
 DnsProbeBrowserTest::DnsProbeBrowserTest()
     : helper_(new DnsProbeBrowserTestIOThreadHelper()),
-      active_browser_(NULL),
-      monitored_tab_helper_(NULL) {
+      active_browser_(nullptr),
+      monitored_tab_helper_(nullptr) {
   NavigationCorrectionTabObserver::SetAllowEnableCorrectionsForTesting(true);
 }
 
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc
index 073acc8c..f40e582 100644
--- a/chrome/browser/net/network_context_configuration_browsertest.cc
+++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -633,8 +633,8 @@
         url, net::CookieOptions::MakeAllInclusive(),
         base::BindOnce(
             [](std::string* cookies_out, base::RunLoop* run_loop,
-               const net::CookieStatusList& cookies,
-               const net::CookieStatusList& excluded_cookies) {
+               const net::CookieAccessResultList& cookies,
+               const net::CookieAccessResultList& excluded_cookies) {
               *cookies_out = net::CanonicalCookie::BuildCookieLine(cookies);
               run_loop->Quit();
             },
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
index 2e7bbd4..adedc352 100644
--- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.cc
@@ -13,6 +13,7 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/histogram_macros_local.h"
+#include "base/notreached.h"
 #include "base/rand_util.h"
 #include "base/sequenced_task_runner.h"
 #include "base/task/post_task.h"
@@ -43,6 +44,7 @@
 #include "components/optimization_guide/optimization_guide_store.h"
 #include "components/optimization_guide/optimization_guide_switches.h"
 #include "components/optimization_guide/optimization_metadata.h"
+#include "components/optimization_guide/proto/models.pb.h"
 #include "components/optimization_guide/top_host_provider.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -1304,3 +1306,28 @@
   hint_cache_->AddHintForTesting(url, std::move(hint));
   PrepareToInvokeRegisteredCallbacks(url);
 }
+
+void OptimizationGuideHintsManager::OverrideTargetDecisionForTesting(
+    optimization_guide::proto::OptimizationTarget optimization_target,
+    optimization_guide::OptimizationGuideDecision optimization_guide_decision) {
+  if (optimization_target !=
+      optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD) {
+    return;
+  }
+
+  // Manipulate ECTs to effectively change the target decision.
+  switch (optimization_guide_decision) {
+    case optimization_guide::OptimizationGuideDecision::kTrue:
+      current_effective_connection_type_ =
+          net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G;
+      break;
+    case optimization_guide::OptimizationGuideDecision::kFalse:
+      current_effective_connection_type_ =
+          net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_4G;
+      break;
+    case optimization_guide::OptimizationGuideDecision::kUnknown:
+      // No way to override for |kUnknown|. Should not be used in tests.
+      NOTREACHED();
+      break;
+  }
+}
\ No newline at end of file
diff --git a/chrome/browser/optimization_guide/optimization_guide_hints_manager.h b/chrome/browser/optimization_guide/optimization_guide_hints_manager.h
index 2898559..18d4452 100644
--- a/chrome/browser/optimization_guide/optimization_guide_hints_manager.h
+++ b/chrome/browser/optimization_guide/optimization_guide_hints_manager.h
@@ -168,6 +168,13 @@
       optimization_guide::proto::OptimizationType optimization_type,
       const base::Optional<optimization_guide::OptimizationMetadata>& metadata);
 
+  // Override the decision returned by |ShouldTargetNavigation|
+  // for |optimization_target|. For testing purposes only.
+  void OverrideTargetDecisionForTesting(
+      optimization_guide::proto::OptimizationTarget optimization_target,
+      optimization_guide::OptimizationGuideDecision
+          optimization_guide_decision);
+
  private:
   FRIEND_TEST_ALL_PREFIXES(OptimizationGuideHintsManagerTest, IsGoogleURL);
   FRIEND_TEST_ALL_PREFIXES(OptimizationGuideHintsManagerFetchingTest,
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
index 65967cc6d..0dafe7d 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.cc
@@ -20,6 +20,7 @@
 #include "components/leveldb_proto/public/proto_database_provider.h"
 #include "components/optimization_guide/command_line_top_host_provider.h"
 #include "components/optimization_guide/hints_processing_util.h"
+#include "components/optimization_guide/optimization_guide_decider.h"
 #include "components/optimization_guide/optimization_guide_features.h"
 #include "components/optimization_guide/optimization_guide_service.h"
 #include "components/optimization_guide/top_host_provider.h"
@@ -276,3 +277,16 @@
   if (prediction_manager_)
     prediction_manager_->UpdateFCPSessionStatistics(fcp);
 }
+
+void OptimizationGuideKeyedService::OverrideTargetDecisionForTesting(
+    optimization_guide::proto::OptimizationTarget optimization_target,
+    optimization_guide::OptimizationGuideDecision optimization_guide_decision) {
+  if (prediction_manager_) {
+    prediction_manager_->OverrideTargetDecisionForTesting(
+        optimization_target, optimization_guide_decision);
+  } else {
+    DCHECK(hints_manager_);
+    hints_manager_->OverrideTargetDecisionForTesting(
+        optimization_target, optimization_guide_decision);
+  }
+}
diff --git a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
index 370bce0..a28bc259 100644
--- a/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
+++ b/chrome/browser/optimization_guide/optimization_guide_keyed_service.h
@@ -78,6 +78,13 @@
       optimization_guide::proto::OptimizationType optimization_type,
       const base::Optional<optimization_guide::OptimizationMetadata>& metadata);
 
+  // Override the decision returned by |ShouldTargetNavigation|
+  // for |optimization_target|. For testing purposes only.
+  void OverrideTargetDecisionForTesting(
+      optimization_guide::proto::OptimizationTarget optimization_target,
+      optimization_guide::OptimizationGuideDecision
+          optimization_guide_decision);
+
  private:
   friend class ChromeBrowsingDataRemoverDelegate;
   friend class HintsFetcherBrowserTest;
diff --git a/chrome/browser/optimization_guide/optimization_guide_test_util.cc b/chrome/browser/optimization_guide/optimization_guide_test_util.cc
new file mode 100644
index 0000000..42b102cd6
--- /dev/null
+++ b/chrome/browser/optimization_guide/optimization_guide_test_util.cc
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/optimization_guide/optimization_guide_test_util.h"
+
+std::unique_ptr<optimization_guide::proto::PredictionModel>
+GetMinimalDecisionTreePredictionModel(double threshold, double weight) {
+  auto prediction_model =
+      std::make_unique<optimization_guide::proto::PredictionModel>();
+  prediction_model->mutable_model()->mutable_threshold()->set_value(threshold);
+  optimization_guide::proto::DecisionTree decision_tree_model;
+  decision_tree_model.set_weight(weight);
+
+  optimization_guide::proto::TreeNode* tree_node =
+      decision_tree_model.add_nodes();
+  tree_node->mutable_node_id()->set_value(0);
+
+  *prediction_model->mutable_model()->mutable_decision_tree() =
+      decision_tree_model;
+
+  return prediction_model;
+}
+
+std::unique_ptr<optimization_guide::proto::PredictionModel>
+GetSingleLeafDecisionTreePredictionModel(double threshold,
+                                         double weight,
+                                         double leaf_value) {
+  auto prediction_model =
+      GetMinimalDecisionTreePredictionModel(threshold, weight);
+  prediction_model->mutable_model()
+      ->mutable_decision_tree()
+      ->mutable_nodes(0)
+      ->mutable_leaf()
+      ->mutable_vector()
+      ->add_value()
+      ->set_double_value(leaf_value);
+  return prediction_model;
+}
\ No newline at end of file
diff --git a/chrome/browser/optimization_guide/optimization_guide_test_util.h b/chrome/browser/optimization_guide/optimization_guide_test_util.h
new file mode 100644
index 0000000..07e9e53
--- /dev/null
+++ b/chrome/browser/optimization_guide/optimization_guide_test_util.h
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_TEST_UTIL_H_
+#define CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_TEST_UTIL_H_
+
+#include <memory>
+
+#include "components/optimization_guide/proto/models.pb.h"
+
+// Returns a decision tree model with |threshold|, |weight|, and a single
+// uninitialized node.
+std::unique_ptr<optimization_guide::proto::PredictionModel>
+GetMinimalDecisionTreePredictionModel(double threshold, double weight);
+
+// Returns a decision tree model with |threshold|, |weight|, and a single
+// leaf node with |leaf_value|.
+std::unique_ptr<optimization_guide::proto::PredictionModel>
+GetSingleLeafDecisionTreePredictionModel(double threshold,
+                                         double weight,
+                                         double leaf_value);
+
+#endif  // CHROME_BROWSER_OPTIMIZATION_GUIDE_OPTIMIZATION_GUIDE_TEST_UTIL_H_
\ No newline at end of file
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
index d0e01756..a180002 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/optimization_guide/prediction/prediction_manager.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/containers/flat_map.h"
@@ -22,6 +23,7 @@
 #include "chrome/browser/optimization_guide/optimization_guide_navigation_data.h"
 #include "chrome/browser/optimization_guide/optimization_guide_permissions_util.h"
 #include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h"
+#include "chrome/browser/optimization_guide/optimization_guide_test_util.h"
 #include "chrome/browser/optimization_guide/optimization_guide_util.h"
 #include "chrome/browser/optimization_guide/prediction/prediction_model.h"
 #include "chrome/browser/optimization_guide/prediction/prediction_model_fetcher.h"
@@ -887,4 +889,41 @@
   return it->second;
 }
 
+void PredictionManager::OverrideTargetDecisionForTesting(
+    proto::OptimizationTarget optimization_target,
+    OptimizationGuideDecision optimization_guide_decision) {
+  auto it = optimization_target_prediction_model_map_.find(optimization_target);
+  if (it != optimization_target_prediction_model_map_.end())
+    optimization_target_prediction_model_map_.erase(it);
+
+  // No model for |kUnknown|. This will make |ShouldTargetNavigation|
+  // return an |OptimizationTargetDecision::kModelNotAvailableOnClient|,
+  // which in turn yields an |OptimizationGuideDecision::kUnknown| in
+  // |OptimizationGuideKeyedService::ShouldTargetNavigation|.
+  if (optimization_guide_decision == OptimizationGuideDecision::kUnknown)
+    return;
+
+  // Construct a simple model that will return the provided
+  // |optimization_guide_decision|.
+  const double threshold = 5.0;
+  const double weight = 1.0;
+  double leaf_value =
+      (optimization_guide_decision == OptimizationGuideDecision::kTrue)
+          ? threshold + 1.0  // Value is greater than |threshold| to get |kTrue|
+          : threshold - 1.0;  // Value is less than |threshold| to get |kFalse|
+
+  std::unique_ptr<proto::PredictionModel> prediction_model =
+      GetSingleLeafDecisionTreePredictionModel(threshold, weight,
+                                               leaf_value / weight);
+
+  proto::ModelInfo* model_info = prediction_model->mutable_model_info();
+
+  model_info->set_version(1);
+  model_info->set_optimization_target(optimization_target);
+  model_info->add_supported_model_types(proto::MODEL_TYPE_DECISION_TREE);
+
+  optimization_target_prediction_model_map_.emplace(
+      optimization_target, CreatePredictionModel(*prediction_model));
+}
+
 }  // namespace optimization_guide
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.h b/chrome/browser/optimization_guide/prediction/prediction_manager.h
index ad8b47cc..a01d2b8 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager.h
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager.h
@@ -130,6 +130,12 @@
   // from the models and features store.
   void ClearHostModelFeatures();
 
+  // Override the decision returned by |ShouldTargetNavigation|
+  // for |optimization_target|. For testing purposes only.
+  void OverrideTargetDecisionForTesting(
+      proto::OptimizationTarget optimization_target,
+      OptimizationGuideDecision optimization_guide_decision);
+
  protected:
   // Return the prediction model for the optimization target used by this
   // PredictionManager for testing.
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
index 2cbc4ffc..7677e8a 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/optimization_guide/optimization_guide_session_statistic.h"
+#include "chrome/browser/optimization_guide/optimization_guide_test_util.h"
 #include "chrome/browser/optimization_guide/prediction/prediction_manager.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -71,16 +72,14 @@
 std::unique_ptr<optimization_guide::proto::PredictionModel>
 GetValidDecisionTreePredictionModel() {
   std::unique_ptr<optimization_guide::proto::PredictionModel> prediction_model =
-      std::make_unique<optimization_guide::proto::PredictionModel>();
-  prediction_model->mutable_model()->mutable_threshold()->set_value(5.0);
+      GetMinimalDecisionTreePredictionModel(/* threshold= */ 5.0,
+                                            /* weight= */ 2.0);
 
-  optimization_guide::proto::DecisionTree decision_tree_model =
-      optimization_guide::proto::DecisionTree();
-  decision_tree_model.set_weight(2.0);
+  optimization_guide::proto::DecisionTree* decision_tree_model =
+      prediction_model->mutable_model()->mutable_decision_tree();
 
   optimization_guide::proto::TreeNode* tree_node =
-      decision_tree_model.add_nodes();
-  tree_node->mutable_node_id()->set_value(0);
+      decision_tree_model->mutable_nodes(0);
   tree_node->mutable_binary_node()->mutable_left_child_id()->set_value(1);
   tree_node->mutable_binary_node()->mutable_right_child_id()->set_value(2);
   tree_node->mutable_binary_node()
@@ -96,18 +95,16 @@
       ->mutable_threshold()
       ->set_float_value(1.0);
 
-  tree_node = decision_tree_model.add_nodes();
+  tree_node = decision_tree_model->add_nodes();
   tree_node->mutable_node_id()->set_value(1);
   tree_node->mutable_leaf()->mutable_vector()->add_value()->set_double_value(
       2.);
 
-  tree_node = decision_tree_model.add_nodes();
+  tree_node = decision_tree_model->add_nodes();
   tree_node->mutable_node_id()->set_value(2);
   tree_node->mutable_leaf()->mutable_vector()->add_value()->set_double_value(
       4.);
 
-  *prediction_model->mutable_model()->mutable_decision_tree() =
-      decision_tree_model;
   return prediction_model;
 }
 
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
index d7f90e5..8b51115 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -1193,13 +1193,13 @@
     return true;
   }
 
-  std::vector<blacklist::BlacklistReason> passed_reasons;
+  std::vector<blocklist::BlocklistReason> passed_reasons;
   auto blocklist_reason = blocklist->IsLoadedAndAllowed(
       GetDelegate().GetWebContents()->GetLastCommittedURL().host(),
       static_cast<int>(HeavyAdBlocklistType::kHeavyAdOnlyType),
       false /* opt_out */, &passed_reasons);
   heavy_ads_blocklist_blocklisted_ =
-      (blocklist_reason != blacklist::BlacklistReason::kAllowed);
+      (blocklist_reason != blocklist::BlocklistReason::kAllowed);
 
   // Record whether this intervention hit the blocklist.
   RecordHeavyAdInterventionDisallowedByBlocklist(
diff --git a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
index 54276549..6811d9d 100644
--- a/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -389,7 +389,7 @@
 
 class AdsPageLoadMetricsObserverTest
     : public SubresourceFilterTestHarness,
-      public blacklist::OptOutBlacklistDelegate {
+      public blocklist::OptOutBlocklistDelegate {
  public:
   AdsPageLoadMetricsObserverTest()
       : test_blocklist_(std::make_unique<HeavyAdBlocklist>(
diff --git a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
index 40b10771..e2de0a9 100644
--- a/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc
@@ -124,7 +124,7 @@
   void SetUpCommandLine(base::CommandLine* command_line) override {
     command_line->AppendSwitch(
         data_reduction_proxy::switches::kEnableDataReductionProxy);
-    command_line->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
+    command_line->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist);
   }
 };
 
diff --git a/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.cc
index 28c3024..37f7569 100644
--- a/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.cc
@@ -182,8 +182,8 @@
 
 void IsolatedPrerenderPageLoadMetricsObserver::OnCookieResult(
     base::Time query_start_time,
-    const net::CookieStatusList& cookies,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies,
+    const net::CookieAccessResultList& excluded_cookies) {
   cookie_query_times_.push_back(base::Time::Now() - query_start_time);
   mainframe_had_cookies_ =
       mainframe_had_cookies_.value_or(false) || !cookies.empty();
diff --git a/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.h
index 1bb61fd1..d08b8edb 100644
--- a/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/isolated_prerender_page_load_metrics_observer.h
@@ -52,8 +52,8 @@
 
   // Used as a callback for the cookie manager query.
   void OnCookieResult(base::Time query_start_time,
-                      const net::CookieStatusList& cookies,
-                      const net::CookieStatusList& excluded_cookies);
+                      const net::CookieAccessResultList& cookies,
+                      const net::CookieAccessResultList& excluded_cookies);
 
   // Sets |prefetch_metrics_| for this page load. Done in a separate method so
   // that this can be done in an event notification.
diff --git a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
index 0b5636c..96115eb 100644
--- a/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
+++ b/chrome/browser/page_load_metrics/observers/previews_ukm_observer_unittest.cc
@@ -519,9 +519,9 @@
           false /* origin_opt_out */, true /* save_data_enabled */,
 
           {{PreviewsType::OFFLINE,
-            PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+            PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE},
            {PreviewsType::LITE_PAGE,
-            PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+            PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE},
            // ALLOWED is equal to zero and should not be recorded.
            {PreviewsType::NOSCRIPT,
             PreviewsEligibilityReason::ALLOWED}} /* eligibility_reasons */);
@@ -533,10 +533,10 @@
                       true /* save_data_enabled_expected */,
                       false /* previews_likely */,
                       {{PreviewsType::OFFLINE,
-                        PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+                        PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE},
                        {PreviewsType::LITE_PAGE,
                         PreviewsEligibilityReason::
-                            BLACKLIST_UNAVAILABLE}} /* eligibility_reasons */);
+                            BLOCKLIST_UNAVAILABLE}} /* eligibility_reasons */);
 }
 
 TEST_F(PreviewsUKMObserverTest, LogPreviewsEligibilityReason_NoneAllowed) {
@@ -545,12 +545,12 @@
           false /* origin_opt_out */, true /* save_data_enabled */,
 
           {{PreviewsType::OFFLINE,
-            PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+            PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE},
            {PreviewsType::LITE_PAGE,
-            PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+            PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE},
            {PreviewsType::NOSCRIPT,
             PreviewsEligibilityReason::
-                BLACKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */);
+                BLOCKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */);
 
   tester()->NavigateToUntrackedUrl();
 
@@ -559,12 +559,12 @@
       false /* origin_opt_out_expected */,
       true /* save_data_enabled_expected */, false /* previews_likely */,
       {{PreviewsType::OFFLINE,
-        PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+        PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE},
        {PreviewsType::LITE_PAGE,
-        PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE},
+        PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE},
        {PreviewsType::NOSCRIPT,
         PreviewsEligibilityReason::
-            BLACKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */);
+            BLOCKLIST_DATA_NOT_LOADED}} /* eligibility_reasons */);
 }
 
 TEST_F(PreviewsUKMObserverTest, CheckReportingForHidden) {
diff --git a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
index 83eb2c3..a315264 100644
--- a/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ukm_page_load_metrics_observer.cc
@@ -27,8 +27,8 @@
 #include "components/page_load_metrics/browser/page_load_metrics_util.h"
 #include "components/page_load_metrics/browser/protocol_util.h"
 #include "components/prefs/pref_service.h"
-#include "components/prerender/prerender_final_status.h"
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_origin.h"
 #include "components/search_engines/template_url_service.h"
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
index f74a930..4e89ead 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -61,7 +61,7 @@
 #include "components/page_load_metrics/browser/page_load_metrics_test_waiter.h"
 #include "components/page_load_metrics/browser/page_load_tracker.h"
 #include "components/prefs/pref_service.h"
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_origin.h"
 #include "components/sessions/content/content_test_helper.h"
 #include "components/sessions/core/serialized_navigation_entry.h"
 #include "components/sessions/core/serialized_navigation_entry_test_helper.h"
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index a066ecd9..88d6592 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -107,6 +107,7 @@
 #endif
 
 #if defined(OS_ANDROID)
+#include "base/feature_list.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/autofill/manual_filling_controller.h"
 #include "chrome/browser/infobars/infobar_service.h"
@@ -134,11 +135,7 @@
 #endif
 
 #if defined(OS_ANDROID)
-#if defined(ENABLE_PASSWORD_CHANGE)
-#include "chrome/browser/password_manager/credential_leak_password_change_controller_android.h"
-#else
 #include "chrome/browser/password_manager/android/credential_leak_controller_android.h"
-#endif
 using password_manager::CredentialCache;
 #endif
 
@@ -547,17 +544,14 @@
     const GURL& origin,
     const base::string16& username) {
 #if defined(OS_ANDROID)
+  if (base::FeatureList::IsEnabled(
+          password_manager::features::kPasswordChange)) {
+    was_leak_dialog_shown_ = true;
+  }
   HideSavePasswordInfobar(web_contents());
-#if defined(ENABLE_PASSWORD_CHANGE)
-  was_leak_dialog_shown_ = true;
-  (new CredentialLeakPasswordChangeControllerAndroid(
-       leak_type, origin, username, web_contents()->GetTopLevelNativeWindow()))
-      ->ShowDialog();
-#else
   (new CredentialLeakControllerAndroid(
        leak_type, origin, web_contents()->GetTopLevelNativeWindow()))
       ->ShowDialog();
-#endif
 #else   // !defined(OS_ANDROID)
   PasswordsClientUIDelegate* manage_passwords_ui_controller =
       PasswordsClientUIDelegateFromWebContents(web_contents());
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h
index 606fcf7..6e2a140 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.h
+++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -354,7 +354,7 @@
   base::string16 last_composing_text_;
 
   // Whether a leak warning was shown. Used only for tests or when
-  // ENABLE_PASSWORD_CHANGE is defined.
+  // kPasswordChange feature is enabled.
   bool was_leak_dialog_shown_ = false;
 #endif
 
diff --git a/chrome/browser/password_manager/credential_leak_password_change_controller_android.cc b/chrome/browser/password_manager/credential_leak_password_change_controller_android.cc
deleted file mode 100644
index bc117eca..0000000
--- a/chrome/browser/password_manager/credential_leak_password_change_controller_android.cc
+++ /dev/null
@@ -1,106 +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 "chrome/browser/password_manager/credential_leak_password_change_controller_android.h"
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "chrome/android/chrome_jni_headers/PasswordChangeLauncher_jni.h"
-#include "chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.h"
-#include "chrome/common/url_constants.h"
-#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
-#include "components/strings/grit/components_strings.h"
-#include "ui/android/window_android.h"
-#include "ui/base/l10n/l10n_util.h"
-
-using password_manager::metrics_util::LeakDialogDismissalReason;
-using password_manager::metrics_util::LogLeakDialogTypeAndDismissalReason;
-
-CredentialLeakPasswordChangeControllerAndroid::
-    CredentialLeakPasswordChangeControllerAndroid(
-        password_manager::CredentialLeakType leak_type,
-        const GURL& origin,
-        const base::string16& username,
-        ui::WindowAndroid* window_android)
-    : leak_type_(leak_type),
-      origin_(origin),
-      username_(username),
-      window_android_(window_android) {}
-
-CredentialLeakPasswordChangeControllerAndroid::
-    ~CredentialLeakPasswordChangeControllerAndroid() = default;
-
-void CredentialLeakPasswordChangeControllerAndroid::ShowDialog() {
-  dialog_view_.reset(new CredentialLeakDialogPasswordChangeViewAndroid(this));
-  dialog_view_->Show(window_android_);
-}
-
-void CredentialLeakPasswordChangeControllerAndroid::OnCancelDialog() {
-  LogLeakDialogTypeAndDismissalReason(
-      password_manager::GetLeakDialogType(leak_type_),
-      LeakDialogDismissalReason::kClickedClose);
-  delete this;
-}
-
-void CredentialLeakPasswordChangeControllerAndroid::OnAcceptDialog() {
-  LogLeakDialogTypeAndDismissalReason(
-      password_manager::GetLeakDialogType(leak_type_),
-      ShouldCheckPasswords() ? LeakDialogDismissalReason::kClickedCheckPasswords
-                             : LeakDialogDismissalReason::kClickedOk);
-  if (window_android_) {
-    JNIEnv* env = base::android::AttachCurrentThread();
-    Java_PasswordChangeLauncher_start(
-        env, window_android_->GetJavaObject(),
-        base::android::ConvertUTF8ToJavaString(env, origin_.spec()),
-        base::android::ConvertUTF16ToJavaString(env, username_));
-  }
-  delete this;
-}
-
-void CredentialLeakPasswordChangeControllerAndroid::OnCloseDialog() {
-  LogLeakDialogTypeAndDismissalReason(
-      password_manager::GetLeakDialogType(leak_type_),
-      LeakDialogDismissalReason::kNoDirectInteraction);
-  delete this;
-}
-
-base::string16
-CredentialLeakPasswordChangeControllerAndroid::GetAcceptButtonLabel() const {
-  if (ShouldShowChangePasswordButton()) {
-    return l10n_util::GetStringUTF16(IDS_PASSWORD_CHANGE);
-  }
-  return password_manager::GetAcceptButtonLabel(leak_type_);
-}
-
-base::string16
-CredentialLeakPasswordChangeControllerAndroid::GetCancelButtonLabel() const {
-  return password_manager::GetCancelButtonLabel();
-}
-
-base::string16 CredentialLeakPasswordChangeControllerAndroid::GetDescription()
-    const {
-  return password_manager::GetDescription(leak_type_, origin_);
-}
-
-base::string16 CredentialLeakPasswordChangeControllerAndroid::GetTitle() const {
-  return password_manager::GetTitle(leak_type_);
-}
-
-bool CredentialLeakPasswordChangeControllerAndroid::ShouldCheckPasswords()
-    const {
-  return password_manager::ShouldCheckPasswords(leak_type_);
-}
-
-bool CredentialLeakPasswordChangeControllerAndroid::ShouldShowCancelButton()
-    const {
-  return password_manager::ShouldShowCancelButton(leak_type_) ||
-         ShouldShowChangePasswordButton();
-}
-
-bool CredentialLeakPasswordChangeControllerAndroid::
-    ShouldShowChangePasswordButton() const {
-  return password_manager::IsPasswordSaved(leak_type_) &&
-         !password_manager::IsPasswordUsedOnOtherSites(leak_type_) &&
-         password_manager::IsSyncingPasswordsNormally(leak_type_);
-}
diff --git a/chrome/browser/password_manager/credential_leak_password_change_controller_android.h b/chrome/browser/password_manager/credential_leak_password_change_controller_android.h
deleted file mode 100644
index a1e32aa..0000000
--- a/chrome/browser/password_manager/credential_leak_password_change_controller_android.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PASSWORD_MANAGER_CREDENTIAL_LEAK_PASSWORD_CHANGE_CONTROLLER_ANDROID_H_
-#define CHROME_BROWSER_PASSWORD_MANAGER_CREDENTIAL_LEAK_PASSWORD_CHANGE_CONTROLLER_ANDROID_H_
-
-#include <memory>
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
-#include "ui/gfx/range/range.h"
-#include "url/gurl.h"
-
-namespace ui {
-class WindowAndroid;
-}
-
-class CredentialLeakDialogPasswordChangeViewAndroid;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when
-// prototype is done.
-
-// Class which manages the dialog displayed when a credential leak was
-// detected. It is self-owned and it owns the dialog view.
-class CredentialLeakPasswordChangeControllerAndroid {
- public:
-  CredentialLeakPasswordChangeControllerAndroid(
-      password_manager::CredentialLeakType leak_type,
-      const GURL& origin,
-      const base::string16& username,
-      ui::WindowAndroid* window_android);
-  ~CredentialLeakPasswordChangeControllerAndroid();
-
-  // Called when a leaked credential was detected.
-  void ShowDialog();
-
-  // Called from the UI when the "Close" button was pressed.
-  // Will destroy the controller.
-  void OnCancelDialog();
-
-  // Called from the UI when the okay or password check button was pressed.
-  // Will destroy the controller.
-  void OnAcceptDialog();
-
-  // Called from the UI when the dialog was dismissed by other means (e.g. back
-  // button).
-  // Will destroy the controller.
-  void OnCloseDialog();
-
-  // The label of the accept button. Varies by leak type.
-  base::string16 GetAcceptButtonLabel() const;
-
-  // The label of the cancel button. Varies by leak type.
-  base::string16 GetCancelButtonLabel() const;
-
-  // Text explaining the leak details. Varies by leak type.
-  base::string16 GetDescription() const;
-
-  // The title of the dialog displaying the leak warning.
-  base::string16 GetTitle() const;
-
-  // Checks whether the dialog should show the option to check passwords.
-  bool ShouldCheckPasswords() const;
-
-  // Checks whether the cancel button should be shown.
-  bool ShouldShowCancelButton() const;
-
- private:
-  bool ShouldShowChangePasswordButton() const;
-
-  // Used to customize the UI.
-  const password_manager::CredentialLeakType leak_type_;
-
-  const GURL origin_;
-
-  const base::string16 username_;
-
-  ui::WindowAndroid* window_android_;
-
-  std::unique_ptr<CredentialLeakDialogPasswordChangeViewAndroid> dialog_view_;
-
-  DISALLOW_COPY_AND_ASSIGN(CredentialLeakPasswordChangeControllerAndroid);
-};
-
-#endif  // CHROME_BROWSER_PASSWORD_MANAGER_CREDENTIAL_LEAK_PASSWORD_CHANGE_CONTROLLER_ANDROID_H_
diff --git a/chrome/browser/password_manager/credential_leak_password_change_controller_android_unittest.cc b/chrome/browser/password_manager/credential_leak_password_change_controller_android_unittest.cc
deleted file mode 100644
index c19ca05..0000000
--- a/chrome/browser/password_manager/credential_leak_password_change_controller_android_unittest.cc
+++ /dev/null
@@ -1,93 +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 "chrome/browser/password_manager/credential_leak_password_change_controller_android.h"
-
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
-#include "components/password_manager/core/browser/password_manager_metrics_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "url/gurl.h"
-
-using password_manager::CreateLeakType;
-using password_manager::IsReused;
-using password_manager::IsSaved;
-using password_manager::IsSyncing;
-using password_manager::metrics_util::LeakDialogDismissalReason;
-
-namespace {
-
-// The On*Dialog() methods used by the tests below all invoke `delete this;`,
-// thus there is no memory leak here.
-CredentialLeakPasswordChangeControllerAndroid*
-MakeController(IsSaved is_saved, IsReused is_reused, IsSyncing is_syncing) {
-  return new CredentialLeakPasswordChangeControllerAndroid(
-      CreateLeakType(is_saved, is_reused, is_syncing),
-      GURL("https://example.com"), base::ASCIIToUTF16("test_username"),
-      nullptr);
-}
-
-}  // namespace
-
-TEST(CredentialLeakPasswordChangeControllerAndroidTest, ClickedCancel) {
-  base::HistogramTester histogram_tester;
-
-  MakeController(IsSaved(false), IsReused(true), IsSyncing(true))
-      ->OnCancelDialog();
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason",
-      LeakDialogDismissalReason::kClickedClose, 1);
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason.CheckupAndChange",
-      LeakDialogDismissalReason::kClickedClose, 1);
-}
-
-TEST(CredentialLeakPasswordChangeControllerAndroidTest, ClickedOk) {
-  base::HistogramTester histogram_tester;
-
-  MakeController(IsSaved(false), IsReused(false), IsSyncing(false))
-      ->OnAcceptDialog();
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason",
-      LeakDialogDismissalReason::kClickedOk, 1);
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason.Change",
-      LeakDialogDismissalReason::kClickedOk, 1);
-}
-
-TEST(CredentialLeakPasswordChangeControllerAndroidTest, ClickedCheckPasswords) {
-  base::HistogramTester histogram_tester;
-
-  MakeController(IsSaved(true), IsReused(true), IsSyncing(true))
-      ->OnAcceptDialog();
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason",
-      LeakDialogDismissalReason::kClickedCheckPasswords, 1);
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason.Checkup",
-      LeakDialogDismissalReason::kClickedCheckPasswords, 1);
-}
-
-TEST(CredentialLeakPasswordChangeControllerAndroidTest, NoDirectInteraction) {
-  base::HistogramTester histogram_tester;
-
-  MakeController(IsSaved(false), IsReused(false), IsSyncing(false))
-      ->OnCloseDialog();
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason",
-      LeakDialogDismissalReason::kNoDirectInteraction, 1);
-
-  histogram_tester.ExpectUniqueSample(
-      "PasswordManager.LeakDetection.DialogDismissalReason.Change",
-      LeakDialogDismissalReason::kNoDirectInteraction, 1);
-}
diff --git a/chrome/browser/pdf/pdf_extension_util.cc b/chrome/browser/pdf/pdf_extension_util.cc
index 877d0ba..73a46d0 100644
--- a/chrome/browser/pdf/pdf_extension_util.cc
+++ b/chrome/browser/pdf/pdf_extension_util.cc
@@ -5,9 +5,19 @@
 #include "chrome/browser/pdf/pdf_extension_util.h"
 
 #include "base/strings/string_util.h"
+#include "base/values.h"
 #include "chrome/common/chrome_content_client.h"
 #include "chrome/grit/browser_resources.h"
+#include "components/strings/grit/components_strings.h"
+#include "components/zoom/page_zoom_constants.h"
+#include "pdf/pdf_features.h"
+#include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/web_ui_util.h"
+
+#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/ui/login_display_host.h"
+#endif  // defined(OS_CHROMEOS)
 
 namespace pdf_extension_util {
 
@@ -30,4 +40,106 @@
   return manifest_contents;
 }
 
+void AddStrings(base::Value* dict) {
+  static constexpr webui::LocalizedString kPdfResources[] = {
+    {"passwordDialogTitle", IDS_PDF_PASSWORD_DIALOG_TITLE},
+    {"passwordPrompt", IDS_PDF_NEED_PASSWORD},
+    {"passwordSubmit", IDS_PDF_PASSWORD_SUBMIT},
+    {"passwordInvalid", IDS_PDF_PASSWORD_INVALID},
+    {"pageLoading", IDS_PDF_PAGE_LOADING},
+    {"pageLoadFailed", IDS_PDF_PAGE_LOAD_FAILED},
+    {"errorDialogTitle", IDS_PDF_ERROR_DIALOG_TITLE},
+    {"pageReload", IDS_PDF_PAGE_RELOAD_BUTTON},
+    {"bookmarks", IDS_PDF_BOOKMARKS},
+    {"labelPageNumber", IDS_PDF_LABEL_PAGE_NUMBER},
+    {"tooltipRotateCW", IDS_PDF_TOOLTIP_ROTATE_CW},
+    {"tooltipDownload", IDS_PDF_TOOLTIP_DOWNLOAD},
+    {"tooltipPrint", IDS_PDF_TOOLTIP_PRINT},
+    {"tooltipFitToPage", IDS_PDF_TOOLTIP_FIT_PAGE},
+    {"tooltipFitToWidth", IDS_PDF_TOOLTIP_FIT_WIDTH},
+    {"tooltipTwoUpViewEnable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_ENABLE},
+    {"tooltipTwoUpViewDisable", IDS_PDF_TOOLTIP_TWO_UP_VIEW_DISABLE},
+    {"tooltipZoomIn", IDS_PDF_TOOLTIP_ZOOM_IN},
+    {"tooltipZoomOut", IDS_PDF_TOOLTIP_ZOOM_OUT},
+#if defined(OS_CHROMEOS)
+    {"tooltipAnnotate", IDS_PDF_ANNOTATION_ANNOTATE},
+    {"annotationDocumentTooLarge", IDS_PDF_ANNOTATION_DOCUMENT_TOO_LARGE},
+    {"annotationDocumentProtected", IDS_PDF_ANNOTATION_DOCUMENT_PROTECTED},
+    {"annotationDocumentRotated", IDS_PDF_ANNOTATION_DOCUMENT_ROTATED},
+    {"annotationPen", IDS_PDF_ANNOTATION_PEN},
+    {"annotationHighlighter", IDS_PDF_ANNOTATION_HIGHLIGHTER},
+    {"annotationEraser", IDS_PDF_ANNOTATION_ERASER},
+    {"annotationUndo", IDS_PDF_ANNOTATION_UNDO},
+    {"annotationRedo", IDS_PDF_ANNOTATION_REDO},
+    {"annotationExpand", IDS_PDF_ANNOTATION_EXPAND},
+    {"annotationColorBlack", IDS_PDF_ANNOTATION_COLOR_BLACK},
+    {"annotationColorRed", IDS_PDF_ANNOTATION_COLOR_RED},
+    {"annotationColorYellow", IDS_PDF_ANNOTATION_COLOR_YELLOW},
+    {"annotationColorGreen", IDS_PDF_ANNOTATION_COLOR_GREEN},
+    {"annotationColorCyan", IDS_PDF_ANNOTATION_COLOR_CYAN},
+    {"annotationColorPurple", IDS_PDF_ANNOTATION_COLOR_PURPLE},
+    {"annotationColorBrown", IDS_PDF_ANNOTATION_COLOR_BROWN},
+    {"annotationColorWhite", IDS_PDF_ANNOTATION_COLOR_WHITE},
+    {"annotationColorCrimson", IDS_PDF_ANNOTATION_COLOR_CRIMSON},
+    {"annotationColorAmber", IDS_PDF_ANNOTATION_COLOR_AMBER},
+    {"annotationColorAvocadoGreen", IDS_PDF_ANNOTATION_COLOR_AVOCADO_GREEN},
+    {"annotationColorCobaltBlue", IDS_PDF_ANNOTATION_COLOR_COBALT_BLUE},
+    {"annotationColorDeepPurple", IDS_PDF_ANNOTATION_COLOR_DEEP_PURPLE},
+    {"annotationColorDarkBrown", IDS_PDF_ANNOTATION_COLOR_DARK_BROWN},
+    {"annotationColorDarkGrey", IDS_PDF_ANNOTATION_COLOR_DARK_GREY},
+    {"annotationColorHotPink", IDS_PDF_ANNOTATION_COLOR_HOT_PINK},
+    {"annotationColorOrange", IDS_PDF_ANNOTATION_COLOR_ORANGE},
+    {"annotationColorLime", IDS_PDF_ANNOTATION_COLOR_LIME},
+    {"annotationColorBlue", IDS_PDF_ANNOTATION_COLOR_BLUE},
+    {"annotationColorViolet", IDS_PDF_ANNOTATION_COLOR_VIOLET},
+    {"annotationColorTeal", IDS_PDF_ANNOTATION_COLOR_TEAL},
+    {"annotationColorLightGrey", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREY},
+    {"annotationColorLightPink", IDS_PDF_ANNOTATION_COLOR_LIGHT_PINK},
+    {"annotationColorLightOrange", IDS_PDF_ANNOTATION_COLOR_LIGHT_ORANGE},
+    {"annotationColorLightGreen", IDS_PDF_ANNOTATION_COLOR_LIGHT_GREEN},
+    {"annotationColorLightBlue", IDS_PDF_ANNOTATION_COLOR_LIGHT_BLUE},
+    {"annotationColorLavender", IDS_PDF_ANNOTATION_COLOR_LAVENDER},
+    {"annotationColorLightTeal", IDS_PDF_ANNOTATION_COLOR_LIGHT_TEAL},
+    {"annotationSize1", IDS_PDF_ANNOTATION_SIZE1},
+    {"annotationSize2", IDS_PDF_ANNOTATION_SIZE2},
+    {"annotationSize3", IDS_PDF_ANNOTATION_SIZE3},
+    {"annotationSize4", IDS_PDF_ANNOTATION_SIZE4},
+    {"annotationSize8", IDS_PDF_ANNOTATION_SIZE8},
+    {"annotationSize12", IDS_PDF_ANNOTATION_SIZE12},
+    {"annotationSize16", IDS_PDF_ANNOTATION_SIZE16},
+    {"annotationSize20", IDS_PDF_ANNOTATION_SIZE20},
+    {"annotationFormWarningTitle", IDS_PDF_DISCARD_FORM_CHANGES},
+    {"annotationFormWarningDetail", IDS_PDF_DISCARD_FORM_CHANGES_DETAIL},
+    {"annotationFormWarningKeepEditing", IDS_PDF_KEEP_EDITING},
+    {"annotationFormWarningDiscard", IDS_PDF_DISCARD},
+#endif  // defined(OS_CHROMEOS)
+  };
+  for (const auto& resource : kPdfResources)
+    dict->SetStringKey(resource.name, l10n_util::GetStringUTF16(resource.id));
+
+  dict->SetStringKey("presetZoomFactors", zoom::GetPresetZoomFactorsAsJSON());
+}
+
+void AddAdditionalData(base::Value* dict) {
+  dict->SetKey("pdfFormSaveEnabled",
+               base::Value(base::FeatureList::IsEnabled(
+                   chrome_pdf::features::kSaveEditedPDFForm)));
+  dict->SetKey("pdfTwoUpViewEnabled",
+               base::Value(base::FeatureList::IsEnabled(
+                   chrome_pdf::features::kPDFTwoUpView)));
+  dict->SetKey("pdfViewerUpdateEnabled",
+               base::Value(base::FeatureList::IsEnabled(
+                   chrome_pdf::features::kPDFViewerUpdate)));
+
+  bool enable_printing = true;
+  bool enable_annotations = false;
+#if defined(OS_CHROMEOS)
+  // For Chrome OS, enable printing only if we are not at OOBE.
+  enable_printing = !chromeos::LoginDisplayHost::default_host();
+  enable_annotations = true;
+#endif  // defined(OS_CHROMEOS)
+  dict->SetKey("printingEnabled", base::Value(enable_printing));
+  dict->SetKey("pdfAnnotationsEnabled", base::Value(enable_annotations));
+}
+
 }  // namespace pdf_extension_util
diff --git a/chrome/browser/pdf/pdf_extension_util.h b/chrome/browser/pdf/pdf_extension_util.h
index 8bc101eb..de7488f 100644
--- a/chrome/browser/pdf/pdf_extension_util.h
+++ b/chrome/browser/pdf/pdf_extension_util.h
@@ -13,6 +13,10 @@
 #error "PDF must be enabled"
 #endif
 
+namespace base {
+class Value;
+}
+
 namespace pdf_extension_util {
 
 // Return the extensions manifest for PDF. The manifest is loaded from
@@ -20,6 +24,13 @@
 // flags are enabled.
 std::string GetManifest();
 
+// Adds all strings used by the PDF Viewer UI in |dict|.
+void AddStrings(base::Value* dict);
+
+// Adds additional data used by the PDF Viewer UI in |dict|, for example
+// whether certain features are enabled/disabled.
+void AddAdditionalData(base::Value* dict);
+
 }  // namespace pdf_extension_util
 
 #endif  // CHROME_BROWSER_PDF_PDF_EXTENSION_UTIL_H_
diff --git a/chrome/browser/performance_hints/performance_hints_observer.cc b/chrome/browser/performance_hints/performance_hints_observer.cc
index 82eb0cbe..88a83067 100644
--- a/chrome/browser/performance_hints/performance_hints_observer.cc
+++ b/chrome/browser/performance_hints/performance_hints_observer.cc
@@ -4,7 +4,12 @@
 
 #include "chrome/browser/performance_hints/performance_hints_observer.h"
 
+#include <string>
+
+#include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/strcat.h"
 #include "build/build_config.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
@@ -55,6 +60,20 @@
   }
 }
 
+enum class HintLookupSource {
+  kLinkHint = 0,
+  kPageHint = 1,
+  kMaxValue = kPageHint,
+};
+
+const char* ToString(HintLookupSource source) {
+  switch (source) {
+    case HintLookupSource::kLinkHint:
+      return "LinkHint";
+    case HintLookupSource::kPageHint:
+      return "PageHint";
+  }
+}
 }  // namespace
 
 #if defined(OS_ANDROID)
@@ -64,7 +83,7 @@
     const base::android::JavaParamRef<jstring>& url) {
   content::WebContents* web_contents =
       content::WebContents::FromJavaWebContents(java_web_contents);
-  return PerformanceHintsObserver::PerformanceClassForURLInternal(
+  return PerformanceHintsObserver::PerformanceClassForURL(
       web_contents, GURL(base::android::ConvertJavaStringToUTF8(url)),
       /*record_metrics=*/false);
 }
@@ -74,6 +93,11 @@
     "PerformanceHintsObserver", base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kPerformanceHintsTreatUnknownAsFast{
     "PerformanceHintsTreatUnknownAsFast", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kPerformanceHintsHandleRewrites{
+    "PerformanceHintsHandleRewrites", base::FEATURE_ENABLED_BY_DEFAULT};
+constexpr base::FeatureParam<std::string> kRewriteConfig{
+    &kPerformanceHintsHandleRewrites, "rewrite_config",
+    "www.google.com/url?url"};
 
 PerformanceHintsObserver::PerformanceHintsObserver(
     content::WebContents* web_contents)
@@ -85,6 +109,9 @@
     optimization_guide_decider_->RegisterOptimizationTypesAndTargets(
         {optimization_guide::proto::PERFORMANCE_HINTS}, {});
   }
+
+  rewrite_handler_ =
+      PerformanceHintsRewriteHandler::FromConfigString(kRewriteConfig.Get());
 }
 
 PerformanceHintsObserver::~PerformanceHintsObserver() {
@@ -94,14 +121,6 @@
 // static
 PerformanceClass PerformanceHintsObserver::PerformanceClassForURL(
     content::WebContents* web_contents,
-    const GURL& url) {
-  return PerformanceClassForURLInternal(web_contents, url,
-                                        /*record_metrics=*/true);
-}
-
-// static
-PerformanceClass PerformanceHintsObserver::PerformanceClassForURLInternal(
-    content::WebContents* web_contents,
     const GURL& url,
     bool record_metrics) {
   if (web_contents == nullptr) {
@@ -121,32 +140,37 @@
     return PerformanceClass::PERFORMANCE_UNKNOWN;
   }
 
-  HintForURLResult hint_result;
-  base::Optional<PerformanceHint> hint;
-  std::tie(hint_result, hint) = performance_hints_observer->HintForURL(url);
+  HintForURLResult result =
+      performance_hints_observer->HintForURL(url, record_metrics);
   if (record_metrics) {
-    base::UmaHistogramEnumeration("PerformanceHints.Observer.HintForURLResult",
-                                  hint_result);
+    if (result.rewritten) {
+      UMA_HISTOGRAM_ENUMERATION(
+          "PerformanceHints.Observer.HintForURLResult.Rewritten",
+          result.status);
+    }
+    UMA_HISTOGRAM_ENUMERATION("PerformanceHints.Observer.HintForURLResult",
+                              result.status);
   }
 
   PerformanceClass performance_class;
-  switch (hint_result) {
-    case HintForURLResult::kHintFound:
-    case HintForURLResult::kHintNotFound:
-    case HintForURLResult::kHintNotReady:
-      performance_class = hint ? hint->performance_class()
-                               : PerformanceClass::PERFORMANCE_UNKNOWN;
+  switch (result.status) {
+    case HintForURLStatus::kHintFound:
+      performance_class = result.hint ? result.hint->performance_class()
+                                      : PerformanceClass::PERFORMANCE_UNKNOWN;
       break;
-    case HintForURLResult::kInvalidURL:
-    default:
-      // Error or unknown case. Don't allow the override.
+    case HintForURLStatus::kHintNotFound:
+    case HintForURLStatus::kHintNotReady:
+      performance_class = PerformanceClass::PERFORMANCE_UNKNOWN;
+      break;
+    case HintForURLStatus::kInvalidURL:
+      // Error case. Don't allow the override.
       return PerformanceClass::PERFORMANCE_UNKNOWN;
   }
 
   if (record_metrics) {
     // Log to UMA before the override logic so we can determine how often the
     // override is happening.
-    base::UmaHistogramEnumeration(
+    UMA_HISTOGRAM_ENUMERATION(
         "PerformanceHints.Observer.PerformanceClassForURL",
         ToUmaPerformanceClass(performance_class));
   }
@@ -165,33 +189,138 @@
 void PerformanceHintsObserver::RecordPerformanceUMAForURL(
     content::WebContents* web_contents,
     const GURL& url) {
-  PerformanceClassForURLInternal(web_contents, url,
-                                 /*record_metrics=*/true);
+  PerformanceClassForURL(web_contents, url, /*record_metrics=*/true);
 }
 
-std::tuple<PerformanceHintsObserver::HintForURLResult,
-           base::Optional<PerformanceHint>>
-PerformanceHintsObserver::HintForURL(const GURL& url) const {
+PerformanceHintsObserver::HintForURLResult::HintForURLResult() = default;
+PerformanceHintsObserver::HintForURLResult::HintForURLResult(
+    const HintForURLResult&) = default;
+PerformanceHintsObserver::HintForURLResult::~HintForURLResult() = default;
+
+PerformanceHintsObserver::HintForURLResult PerformanceHintsObserver::HintForURL(
+    const GURL& url,
+    bool record_metrics) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  base::Optional<PerformanceHint> hint;
-  HintForURLResult hint_result = HintForURLResult::kHintNotFound;
+  HintForURLResult result;
 
-  if (!hint_processed_) {
-    hint_result = HintForURLResult::kHintNotReady;
-  } else if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
-    hint_result = HintForURLResult::kInvalidURL;
-  } else {
-    for (const auto& pattern_hint : hints_) {
-      if (pattern_hint.first.Matches(url.spec())) {
-        hint_result = HintForURLResult::kHintFound;
-        hint = pattern_hint.second;
-        break;
-      }
+  if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
+    result.status = HintForURLStatus::kInvalidURL;
+    return result;
+  }
+
+  base::Optional<GURL> maybe_rewritten;
+  if (base::FeatureList::IsEnabled(kPerformanceHintsHandleRewrites)) {
+    maybe_rewritten = rewrite_handler_.HandleRewriteIfNecessary(url);
+    result.rewritten = maybe_rewritten.has_value();
+    if (maybe_rewritten && (!maybe_rewritten->is_valid() ||
+                            !maybe_rewritten->SchemeIsHTTPOrHTTPS())) {
+      result.status = HintForURLStatus::kInvalidURL;
+      return result;
     }
   }
 
-  return {hint_result, hint};
+  GURL hint_url = maybe_rewritten.value_or(url);
+
+  // At this point we know the URL is valid. Individual source lookups will
+  // override this if they have more detailed status (found or not ready).
+  result.status = HintForURLStatus::kHintNotFound;
+
+  using LookupFn = base::OnceCallback<std::tuple<
+      SourceLookupStatus,
+      base::Optional<optimization_guide::proto::PerformanceHint>>(const GURL&)>;
+
+  std::vector<std::tuple<HintLookupSource, LookupFn>> sources;
+  sources.emplace_back(HintLookupSource::kLinkHint,
+                       base::BindOnce(&PerformanceHintsObserver::LinkHintForURL,
+                                      base::Unretained(this)));
+  sources.emplace_back(HintLookupSource::kPageHint,
+                       base::BindOnce(&PerformanceHintsObserver::PageHintForURL,
+                                      base::Unretained(this)));
+
+  for (std::tuple<HintLookupSource, LookupFn>& source : sources) {
+    SourceLookupStatus lookup_status = SourceLookupStatus::kNotQueried;
+    // Only query sources until a hint has been found.
+    if (!result.hint.has_value()) {
+      std::tie(lookup_status, result.hint) =
+          std::move(std::get<LookupFn>(source)).Run(hint_url);
+    }
+    if (record_metrics) {
+      // UMA is recorded for each source, even if it wasn't queried. This is
+      // done so all source histograms have the same total.
+      base::UmaHistogramEnumeration(
+          base::StrCat({"PerformanceHints.Observer.SourceLookupStatus.",
+                        ToString(std::get<HintLookupSource>(source))}),
+          lookup_status);
+    }
+    switch (lookup_status) {
+      case SourceLookupStatus::kNotReady:
+        // If no hints are found and any of the sources returned kNotReady, we
+        // should also return kNotReady.
+        result.status = HintForURLStatus::kHintNotReady;
+        break;
+      case SourceLookupStatus::kHintFound:
+        DCHECK(result.hint.has_value());
+        result.status = HintForURLStatus::kHintFound;
+        break;
+      case SourceLookupStatus::kNotQueried:
+      case SourceLookupStatus::kNoMatch:
+        break;
+    }
+  }
+
+  return result;
+}
+
+std::tuple<PerformanceHintsObserver::SourceLookupStatus,
+           base::Optional<optimization_guide::proto::PerformanceHint>>
+PerformanceHintsObserver::LinkHintForURL(const GURL& url) const {
+  if (!hint_processed_) {
+    return {SourceLookupStatus::kNotReady, base::nullopt};
+  } else {
+    // Link hints only contain scheme, host, and path, so remove other
+    // components.
+    url::Replacements<char> replacements;
+    replacements.ClearUsername();
+    replacements.ClearPassword();
+    replacements.ClearQuery();
+    replacements.ClearPort();
+    replacements.ClearRef();
+    GURL scheme_host_path = url.ReplaceComponents(replacements);
+
+    for (const auto& pattern_hint : hints_) {
+      if (pattern_hint.first.Matches(scheme_host_path.spec())) {
+        return {SourceLookupStatus::kHintFound, pattern_hint.second};
+      }
+    }
+    return {SourceLookupStatus::kNoMatch, base::nullopt};
+  }
+}
+
+std::tuple<PerformanceHintsObserver::SourceLookupStatus,
+           base::Optional<optimization_guide::proto::PerformanceHint>>
+PerformanceHintsObserver::PageHintForURL(const GURL& url) const {
+  if (!optimization_guide_decider_) {
+    return {SourceLookupStatus::kNoMatch, base::nullopt};
+  }
+
+  // Check to see if there happens to be a cached hint for the site that this
+  // URL belongs to. This should be the case for links on the SRP since the
+  // OptimizationGuideService proactively fetches hints for them.
+  optimization_guide::OptimizationMetadata metadata;
+  OptimizationGuideDecision decision =
+      optimization_guide_decider_->CanApplyOptimization(
+          url, optimization_guide::proto::PERFORMANCE_HINTS, &metadata);
+  if (decision == OptimizationGuideDecision::kUnknown) {
+    return {SourceLookupStatus::kNotReady, base::nullopt};
+  } else if (decision == OptimizationGuideDecision::kTrue &&
+             metadata.performance_hints_metadata() &&
+             metadata.performance_hints_metadata()->has_page_hint()) {
+    return {SourceLookupStatus::kHintFound,
+            metadata.performance_hints_metadata()->page_hint()};
+  }
+
+  return {SourceLookupStatus::kNoMatch, base::nullopt};
 }
 
 void PerformanceHintsObserver::DidFinishNavigation(
@@ -218,6 +347,9 @@
     return;
   }
 
+  // TODO(jds): Because calls to HintForURL are not asynchronous, we don't
+  // actually need to use the Async version and can instead call
+  // CanApplyOptimization directly from HintForURL to remove this complexity.
   optimization_guide_decider_->CanApplyOptimizationAsync(
       navigation_handle, optimization_guide::proto::PERFORMANCE_HINTS,
       base::BindOnce(&PerformanceHintsObserver::ProcessPerformanceHint,
diff --git a/chrome/browser/performance_hints/performance_hints_observer.h b/chrome/browser/performance_hints/performance_hints_observer.h
index eea75ca..99eaccb 100644
--- a/chrome/browser/performance_hints/performance_hints_observer.h
+++ b/chrome/browser/performance_hints/performance_hints_observer.h
@@ -14,6 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/sequence_checker.h"
+#include "chrome/browser/performance_hints/performance_hints_rewrite_handler.h"
 #include "components/optimization_guide/optimization_guide_decider.h"
 #include "components/optimization_guide/proto/hints.pb.h"
 #include "components/optimization_guide/proto/performance_hints_metadata.pb.h"
@@ -40,6 +41,10 @@
 // If enabled, hints of PERFORMANCE_UNKNOWN will be overridden to
 // PERFORMANCE_FAST. This does not affect the value that is recorded via UMA.
 extern const base::Feature kPerformanceHintsTreatUnknownAsFast;
+// If enabled, PerformanceHintsRewriteHandler will be used to detect rewritten
+// URLs (specified by the rewrite_config param) and revert them to their
+// original form.
+extern const base::Feature kPerformanceHintsHandleRewrites;
 
 // Provides an interface to access PerformanceHints for the associated
 // WebContents and links within it.
@@ -53,21 +58,21 @@
 
   // Returns the PerformanceClass for |url|, or PERFORMANCE_UNKNOWN if could not
   // be determined.
+  //
+  // UMA metrics are only recorded when |record_metrics| is true. Callers should
+  // record metrics only once per badging decision, e.g. once per context menu
+  // shown. If the same PerformanceClass is needed again, |record_metrics|
+  // should be set to false.
   static optimization_guide::proto::PerformanceClass PerformanceClassForURL(
       content::WebContents* web_contents,
-      const GURL& url);
+      const GURL& url,
+      bool record_metrics);
 
   // Used only on Android since the java API can be called repeatedly and is
   // not appropriate to record metrics.
   static void RecordPerformanceUMAForURL(content::WebContents* web_contents,
                                          const GURL& url);
 
-  // Public so is accessible by Android JNI.
-  static optimization_guide::proto::PerformanceClass
-  PerformanceClassForURLInternal(content::WebContents* web_contents,
-                                 const GURL& url,
-                                 bool record_metrics);
-
  private:
   explicit PerformanceHintsObserver(content::WebContents* web_contents);
   friend class content::WebContentsUserData<PerformanceHintsObserver>;
@@ -84,15 +89,53 @@
       optimization_guide::OptimizationGuideDecision decision,
       const optimization_guide::OptimizationMetadata& optimization_metadata);
 
+  // SourceLookupStatus represents the result of a querying a single source
+  // (page hints or link hints) for performance information. Tracking this
+  // separately from the overall HintForURLStatus (below) allows us to determine
+  // individual source coverage and how often each source is ready to respond.
+  //
+  // These values are logged to UMA. Entries should not be renumbered and
+  // numeric values should never be reused. Please keep in sync with
+  // "PerformanceHintsObserverSourceLookupStatus" in
+  // src/tools/metrics/histograms/enums.xml.
+  enum class SourceLookupStatus {
+    // The source was not queried for a given URL lookup (i.e. a hint was found
+    // in a preceding source).
+    kNotQueried = 0,
+    // The source didn't have an answer in time.
+    kNotReady = 1,
+    // The source was ready but no matching hint was found.
+    kNoMatch = 2,
+    // A matching hint was found for the URL.
+    kHintFound = 3,
+    kMaxValue = kHintFound,
+  };
+
+  // Attempts to retrieve a PerformanceHint for |url| from the link hints of the
+  // current page.
+  std::tuple<SourceLookupStatus,
+             base::Optional<optimization_guide::proto::PerformanceHint>>
+  LinkHintForURL(const GURL& url) const;
+
+  // Attempts to retrieve a PerformanceHint for |url| from the OptimizationGuide
+  // metadata for that URL.
+  std::tuple<SourceLookupStatus,
+             base::Optional<optimization_guide::proto::PerformanceHint>>
+  PageHintForURL(const GURL& url) const;
+
+  // HintForURLStatus represents the overall lookup result for a given URL.
+  // Exactly one sample will be recorded for each call to HintForURL.
+  //
   // These values are logged to UMA. Entries should not be renumbered and
   // numeric values should never be reused. Please keep in sync with
   // "PerformanceHintsObserverHintForURLResult" in
   // src/tools/metrics/histograms/enums.xml.
-  enum class HintForURLResult {
+  enum class HintForURLStatus {
     // Hints for the current page have been processed and no hint for the URL
     // was found.
     kHintNotFound = 0,
-    // Hints have not yet been processed. The call may be attempted again.
+    // One or more sources could not answer in time. The call may be attempted
+    // again.
     kHintNotReady = 1,
     // An invalid URL was passed.
     kInvalidURL = 2,
@@ -101,13 +144,32 @@
     kMaxValue = kHintFound,
   };
 
+  struct HintForURLResult {
+    HintForURLResult();
+    HintForURLResult(const HintForURLResult&);
+    ~HintForURLResult();
+
+    // Describes the fetch outcome. See HintForURLStatus for details.
+    HintForURLStatus status = HintForURLStatus::kHintNotFound;
+    // True if the URL was rewritten before lookups were done. False otherwise.
+    bool rewritten = false;
+    // If status == kHintFound, this will contain the matching hint.
+    base::Optional<optimization_guide::proto::PerformanceHint> hint =
+        base::nullopt;
+  };
+
   // Fetches a PerformanceHint for the given |url|.
   //
-  // Returns an enum describing the fetch outcome and, if that outcome is
-  // kHintFound, the matching PerformanceHint. See HintForURLResult, above.
-  std::tuple<HintForURLResult,
-             base::Optional<optimization_guide::proto::PerformanceHint>>
-  HintForURL(const GURL& url) const;
+  // See HintForURLResult for details on the return value.
+  HintForURLResult HintForURL(const GURL& url, bool record_metrics) const;
+
+  // If kPerformanceHintsHandleRewrites is enabled, URLs that match one of the
+  // configured rewrite patterns will have the inner URL extracted and used for
+  // hint matching.
+  //
+  // Configuration is controlled by kRewriteConfig in
+  // performance_hints_observer.cc.
+  PerformanceHintsRewriteHandler rewrite_handler_;
 
   // Initialized in constructor. It may be null if !IsOptimizationHintsEnabled.
   optimization_guide::OptimizationGuideDecider* optimization_guide_decider_ =
diff --git a/chrome/browser/performance_hints/performance_hints_observer_unittest.cc b/chrome/browser/performance_hints/performance_hints_observer_unittest.cc
index ab02bade..8764410 100644
--- a/chrome/browser/performance_hints/performance_hints_observer_unittest.cc
+++ b/chrome/browser/performance_hints/performance_hints_observer_unittest.cc
@@ -45,20 +45,26 @@
                void(content::NavigationHandle*,
                     optimization_guide::proto::OptimizationType,
                     optimization_guide::OptimizationGuideDecisionCallback));
+  MOCK_METHOD3(CanApplyOptimization,
+               optimization_guide::OptimizationGuideDecision(
+                   const GURL& gurl,
+                   optimization_guide::proto::OptimizationType,
+                   optimization_guide::OptimizationMetadata* metadata));
 };
 
 class PerformanceHintsObserverTest : public ChromeRenderViewHostTestHarness {
  public:
-  PerformanceHintsObserverTest() = default;
-  ~PerformanceHintsObserverTest() override = default;
-
-  void SetUp() override {
+  PerformanceHintsObserverTest() {
     scoped_feature_list_.InitWithFeatures(
         {kPerformanceHintsObserver,
          // Need to enable kOptimizationHints or GetForProfile will return
          // nullptr.
          optimization_guide::features::kOptimizationHints},
         {});
+  }
+  ~PerformanceHintsObserverTest() override = default;
+
+  void SetUp() override {
     base::CommandLine::ForCurrentProcess()->AppendSwitch(
         optimization_guide::switches::
             kDisableCheckingUserPermissionsForTesting);
@@ -77,6 +83,12 @@
                       return std::make_unique<
                           MockOptimizationGuideKeyedService>(context);
                     })));
+    ON_CALL(*mock_optimization_guide_keyed_service_,
+            CanApplyOptimization(testing::_,
+                                 optimization_guide::proto::PERFORMANCE_HINTS,
+                                 testing::_))
+        .WillByDefault(testing::Return(
+            optimization_guide::OptimizationGuideDecision::kFalse));
 
     test_handle_ = std::make_unique<content::MockNavigationHandle>(
         GURL(kTestUrl), main_rfh());
@@ -102,13 +114,17 @@
   DISALLOW_COPY_AND_ASSIGN(PerformanceHintsObserverTest);
 };
 
-TEST_F(PerformanceHintsObserverTest, HasPerformanceHints) {
+TEST_F(PerformanceHintsObserverTest, RegisterPerformanceHints) {
   EXPECT_CALL(*mock_optimization_guide_keyed_service_,
               RegisterOptimizationTypesAndTargets(
                   testing::UnorderedElementsAre(
                       optimization_guide::proto::PERFORMANCE_HINTS),
                   testing::IsEmpty()));
 
+  PerformanceHintsObserver::CreateForWebContents(web_contents());
+}
+
+TEST_F(PerformanceHintsObserverTest, HasPerformanceHints) {
   optimization_guide::proto::PerformanceHintsMetadata hints_metadata;
   auto* hint = hints_metadata.add_performance_hints();
   hint->set_wildcard_pattern("test.com");
@@ -132,21 +148,24 @@
   base::HistogramTester histogram_tester;
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("http://www.test.com")),
+                  web_contents(), GURL("http://www.test.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_SLOW));
   histogram_tester.ExpectUniqueSample(
       "PerformanceHints.Observer.HintForURLResult", /*kHintFound*/ 3, 1);
   histogram_tester.ExpectUniqueSample(
       "PerformanceHints.Observer.PerformanceClassForURL", /*kSlow*/ 1, 1);
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("https://www.othersite.net/this/link")),
+                  web_contents(), GURL("https://www.othersite.net/this/link"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_FAST));
   histogram_tester.ExpectUniqueSample(
       "PerformanceHints.Observer.HintForURLResult", /*kHintFound*/ 3, 2);
   histogram_tester.ExpectBucketCount(
       "PerformanceHints.Observer.PerformanceClassForURL", /*kFast*/ 2, 1);
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("https://www.nohint.com")),
+                  web_contents(), GURL("https://www.nohint.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
   histogram_tester.ExpectBucketCount(
       "PerformanceHints.Observer.HintForURLResult", /*kHintNotFound*/ 0, 1);
@@ -154,6 +173,259 @@
       "PerformanceHints.Observer.PerformanceClassForURL", /*kUnknown*/ 0, 1);
 }
 
+TEST_F(PerformanceHintsObserverTest, FallbackToPageHint) {
+  optimization_guide::proto::PerformanceHintsMetadata hints_metadata;
+  auto* hint = hints_metadata.add_performance_hints();
+  hint->set_wildcard_pattern("linkhint.com");
+  hint->set_performance_class(optimization_guide::proto::PERFORMANCE_SLOW);
+  optimization_guide::OptimizationMetadata metadata;
+  metadata.set_performance_hints_metadata(hints_metadata);
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimizationAsync(
+                  testing::_, optimization_guide::proto::PERFORMANCE_HINTS,
+                  base::test::IsNotNullCallback()))
+      .WillOnce(base::test::RunOnceCallback<2>(
+          optimization_guide::OptimizationGuideDecision::kTrue,
+          testing::ByRef(metadata)));
+
+  PerformanceHintsObserver::CreateForWebContents(web_contents());
+  CallDidFinishNavigation(web_contents());
+
+  base::HistogramTester histogram_tester;
+
+  EXPECT_CALL(
+      *mock_optimization_guide_keyed_service_,
+      CanApplyOptimization(
+          testing::_, optimization_guide::proto::PERFORMANCE_HINTS, testing::_))
+      .Times(0);
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(), GURL("http://www.linkhint.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_SLOW));
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.HintForURLResult", /*kHintFound*/ 3, 1);
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.SourceLookupStatus.LinkHint", /*kHintFound*/ 3,
+      1);
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.SourceLookupStatus.PageHint",
+      /*kNotQueried*/ 0, 1);
+
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimization(GURL("https://www.nohint.com"),
+                                   optimization_guide::proto::PERFORMANCE_HINTS,
+                                   testing::_))
+      .WillOnce(testing::Return(
+          optimization_guide::OptimizationGuideDecision::kFalse));
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(), GURL("https://www.nohint.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.HintForURLResult", /*kHintNotFound*/ 0, 1);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.SourceLookupStatus.LinkHint", /*kNoMatch*/ 2,
+      1);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.SourceLookupStatus.PageHint", /*kNoMatch*/ 2,
+      1);
+
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimization(GURL("https://www.notready.com"),
+                                   optimization_guide::proto::PERFORMANCE_HINTS,
+                                   testing::_))
+      .WillOnce(testing::Return(
+          optimization_guide::OptimizationGuideDecision::kUnknown));
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(), GURL("https://www.notready.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.HintForURLResult", /*kHintNotReady*/ 1, 1);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.SourceLookupStatus.LinkHint", /*kNoMatch*/ 2,
+      2);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.SourceLookupStatus.PageHint", /*kNotReady*/ 1,
+      1);
+
+  optimization_guide::proto::PerformanceHintsMetadata pagehint_metadata;
+  pagehint_metadata.mutable_page_hint()->set_performance_class(
+      optimization_guide::proto::PERFORMANCE_FAST);
+  metadata.set_performance_hints_metadata(pagehint_metadata);
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimization(GURL("https://www.pagehint.com"),
+                                   optimization_guide::proto::PERFORMANCE_HINTS,
+                                   testing::NotNull()))
+      .WillOnce(testing::DoAll(
+          testing::SetArgPointee<2>(metadata),
+          testing::Return(
+              optimization_guide::OptimizationGuideDecision::kTrue)));
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(), GURL("https://www.pagehint.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_FAST));
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.HintForURLResult", /*kHintFound*/ 3, 2);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.SourceLookupStatus.LinkHint", /*kNoMatch*/ 2,
+      3);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.SourceLookupStatus.PageHint", /*kHintFound*/ 3,
+      1);
+}
+
+// If any sources are NotReady and the rest are NotFound, NotReady should be
+// returned.
+TEST_F(PerformanceHintsObserverTest, SomeSourcesNotReady) {
+  // Link hints callback will not be called, so kNotReady.
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimizationAsync(
+                  testing::_, optimization_guide::proto::PERFORMANCE_HINTS,
+                  base::test::IsNotNullCallback()));
+
+  PerformanceHintsObserver::CreateForWebContents(web_contents());
+  CallDidFinishNavigation(web_contents());
+
+  // No page hint for URL.
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimization(GURL("https://www.nohint.com"),
+                                   optimization_guide::proto::PERFORMANCE_HINTS,
+                                   testing::_))
+      .WillOnce(testing::Return(
+          optimization_guide::OptimizationGuideDecision::kFalse));
+
+  base::HistogramTester histogram_tester;
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(), GURL("https://www.nohint.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.HintForURLResult", /*kHintNotReady*/ 1, 1);
+}
+
+TEST_F(PerformanceHintsObserverTest, RewrittenUrl) {
+  optimization_guide::proto::PerformanceHintsMetadata hints_metadata;
+  auto* hint = hints_metadata.add_performance_hints();
+  hint->set_wildcard_pattern("www.google.com");
+  hint->set_performance_class(optimization_guide::proto::PERFORMANCE_FAST);
+  hint = hints_metadata.add_performance_hints();
+  hint->set_wildcard_pattern("www.test.com");
+  hint->set_performance_class(optimization_guide::proto::PERFORMANCE_SLOW);
+  optimization_guide::OptimizationMetadata metadata;
+  metadata.set_performance_hints_metadata(hints_metadata);
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimizationAsync(
+                  testing::_, optimization_guide::proto::PERFORMANCE_HINTS,
+                  base::test::IsNotNullCallback()))
+      .WillOnce(base::test::RunOnceCallback<2>(
+          optimization_guide::OptimizationGuideDecision::kTrue,
+          testing::ByRef(metadata)));
+
+  PerformanceHintsObserver::CreateForWebContents(web_contents());
+  CallDidFinishNavigation(web_contents());
+
+  base::HistogramTester histogram_tester;
+
+  // There is a FAST hint that should match all www.google.com URLs, but not
+  // those that fit the redirect pattern.
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(),
+                  GURL("https://www.google.com/url?url=http://www.test.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_SLOW));
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.HintForURLResult",
+      /*kHintFound*/ 3, 1);
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.HintForURLResult.Rewritten",
+      /*kHintFound*/ 3, 1);
+
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(), GURL("https://www.google.com/other/link"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_FAST));
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.HintForURLResult",
+      /*kHintFound*/ 3, 2);
+  // Still only one sample in .Rewritten.
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.HintForURLResult.Rewritten",
+      /*kHintFound*/ 3, 1);
+
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(),
+                  GURL("https://www.google.com/url?url=https://www.nohint.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.HintForURLResult",
+      /*kHintNotFound*/ 0, 1);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.HintForURLResult.Rewritten",
+      /*kHintNotFound*/ 0, 1);
+
+  EXPECT_THAT(
+      PerformanceHintsObserver::PerformanceClassForURL(
+          web_contents(), GURL("https://www.google.com/url?url=notaurl"),
+          /*record_metrics=*/true),
+      Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.HintForURLResult", /*kInvalidURL*/ 2, 1);
+  histogram_tester.ExpectBucketCount(
+      "PerformanceHints.Observer.HintForURLResult.Rewritten", /*kInvalidURL*/ 2,
+      1);
+}
+
+class RewritesDisabledPerformanceHintsObserverTest
+    : public PerformanceHintsObserverTest {
+ public:
+  RewritesDisabledPerformanceHintsObserverTest() {
+    scoped_feature_list_.InitWithFeatures(
+        {kPerformanceHintsObserver,
+         // Need to enable kOptimizationHints or GetForProfile will return
+         // nullptr.
+         optimization_guide::features::kOptimizationHints},
+        {kPerformanceHintsHandleRewrites});
+  }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(RewritesDisabledPerformanceHintsObserverTest, RewritesDisabled) {
+  optimization_guide::proto::PerformanceHintsMetadata hints_metadata;
+  auto* hint = hints_metadata.add_performance_hints();
+  hint->set_wildcard_pattern("www.google.com");
+  hint->set_performance_class(optimization_guide::proto::PERFORMANCE_FAST);
+  hint = hints_metadata.add_performance_hints();
+  hint->set_wildcard_pattern("www.test.com");
+  hint->set_performance_class(optimization_guide::proto::PERFORMANCE_SLOW);
+  optimization_guide::OptimizationMetadata metadata;
+  metadata.set_performance_hints_metadata(hints_metadata);
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimizationAsync(
+                  testing::_, optimization_guide::proto::PERFORMANCE_HINTS,
+                  base::test::IsNotNullCallback()))
+      .WillOnce(base::test::RunOnceCallback<2>(
+          optimization_guide::OptimizationGuideDecision::kTrue,
+          testing::ByRef(metadata)));
+
+  PerformanceHintsObserver::CreateForWebContents(web_contents());
+  CallDidFinishNavigation(web_contents());
+
+  base::HistogramTester histogram_tester;
+
+  // The rewrite handling should not happen here and the link should be badged
+  // as though it were google.com.
+  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
+                  web_contents(),
+                  GURL("https://www.google.com/url?url=http://www.test.com"),
+                  /*record_metrics=*/true),
+              Eq(optimization_guide::proto::PERFORMANCE_FAST));
+  histogram_tester.ExpectTotalCount(
+      "PerformanceHints.Observer.HintForURLResult.Rewritten", 0);
+}
+
 TEST_F(PerformanceHintsObserverTest, PerformanceHintsMetadataNotPresent) {
   optimization_guide::OptimizationMetadata metadata;
   EXPECT_CALL(*mock_optimization_guide_keyed_service_,
@@ -170,7 +442,8 @@
   base::HistogramTester histogram_tester;
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("https://www.nohint.com")),
+                  web_contents(), GURL("https://www.nohint.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 
   histogram_tester.ExpectUniqueSample(
@@ -192,11 +465,13 @@
 
   base::HistogramTester histogram_tester;
 
-  EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(web_contents(),
-                                                               GURL("")),
-              Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
+  EXPECT_THAT(
+      PerformanceHintsObserver::PerformanceClassForURL(web_contents(), GURL(""),
+                                                       /*record_metrics=*/true),
+      Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("ftp://notsupported.com")),
+                  web_contents(), GURL("ftp://notsupported.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 
   histogram_tester.ExpectUniqueSample(
@@ -221,13 +496,50 @@
   base::HistogramTester histogram_tester;
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("https://www.nohint.com")),
+                  web_contents(), GURL("https://www.nohint.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 
   histogram_tester.ExpectUniqueSample(
       "PerformanceHints.Observer.HintForURLResult", /*kHintNotFound*/ 0, 1);
 }
 
+TEST_F(PerformanceHintsObserverTest, DontMatchQueryParams) {
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              RegisterOptimizationTypesAndTargets(
+                  testing::UnorderedElementsAre(
+                      optimization_guide::proto::PERFORMANCE_HINTS),
+                  testing::IsEmpty()));
+
+  optimization_guide::proto::PerformanceHintsMetadata hints_metadata;
+  auto* hint = hints_metadata.add_performance_hints();
+  hint->set_wildcard_pattern("www.test.com");
+  hint->set_performance_class(optimization_guide::proto::PERFORMANCE_SLOW);
+  hint = hints_metadata.add_performance_hints();
+  hint->set_wildcard_pattern("www.google.com");
+  hint->set_performance_class(optimization_guide::proto::PERFORMANCE_FAST);
+  optimization_guide::OptimizationMetadata metadata;
+  metadata.set_performance_hints_metadata(hints_metadata);
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
+              CanApplyOptimizationAsync(
+                  testing::_, optimization_guide::proto::PERFORMANCE_HINTS,
+                  base::test::IsNotNullCallback()))
+      .WillOnce(base::test::RunOnceCallback<2>(
+          optimization_guide::OptimizationGuideDecision::kTrue,
+          testing::ByRef(metadata)));
+
+  PerformanceHintsObserver::CreateForWebContents(web_contents());
+  CallDidFinishNavigation(web_contents());
+
+  base::HistogramTester histogram_tester;
+
+  EXPECT_THAT(
+      PerformanceHintsObserver::PerformanceClassForURL(
+          web_contents(), GURL("http://www.google.com/search?q=www.test.com"),
+          /*record_metrics=*/true),
+      Eq(optimization_guide::proto::PERFORMANCE_FAST));
+}
+
 TEST_F(PerformanceHintsObserverTest, PerformanceInfoRequestedBeforeCallback) {
   EXPECT_CALL(*mock_optimization_guide_keyed_service_,
               CanApplyOptimizationAsync(
@@ -240,11 +552,15 @@
   base::HistogramTester histogram_tester;
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("https://www.nohint.com")),
+                  web_contents(), GURL("https://www.nohint.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 
   histogram_tester.ExpectUniqueSample(
       "PerformanceHints.Observer.HintForURLResult", /*kHintNotReady*/ 1, 1);
+  histogram_tester.ExpectUniqueSample(
+      "PerformanceHints.Observer.SourceLookupStatus.LinkHint", /*kNotReady*/ 1,
+      1);
 }
 
 TEST_F(PerformanceHintsObserverTest, OptimizationGuideDisabled) {
@@ -256,7 +572,8 @@
   CallDidFinishNavigation(web_contents());
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("http://www.test.com")),
+                  web_contents(), GURL("http://www.test.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 }
 
@@ -271,7 +588,8 @@
   CallDidFinishNavigation(web_contents());
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("http://www.test.com")),
+                  web_contents(), GURL("http://www.test.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 }
 
@@ -294,25 +612,28 @@
   CallDidFinishNavigation(web_contents());
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("http://www.test.com")),
+                  web_contents(), GURL("http://www.test.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 }
 
-TEST_F(PerformanceHintsObserverTest, OverrideUnknownPerformanceToFast) {
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      {kPerformanceHintsObserver, kPerformanceHintsTreatUnknownAsFast,
-       // Need to enable kOptimizationHints or GetForProfile will return
-       // nullptr.
-       optimization_guide::features::kOptimizationHints},
-      {});
+class OverrideUnknownPerformanceHintsObserverTest
+    : public PerformanceHintsObserverTest {
+ public:
+  OverrideUnknownPerformanceHintsObserverTest() {
+    scoped_feature_list_.InitWithFeatures(
+        {kPerformanceHintsObserver, kPerformanceHintsTreatUnknownAsFast,
+         // Need to enable kOptimizationHints or GetForProfile will return
+         // nullptr.
+         optimization_guide::features::kOptimizationHints},
+        {});
+  }
 
-  EXPECT_CALL(*mock_optimization_guide_keyed_service_,
-              RegisterOptimizationTypesAndTargets(
-                  testing::UnorderedElementsAre(
-                      optimization_guide::proto::PERFORMANCE_HINTS),
-                  testing::IsEmpty()));
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
 
+TEST_F(OverrideUnknownPerformanceHintsObserverTest,
+       OverrideUnknownPerformanceToFast) {
   optimization_guide::proto::PerformanceHintsMetadata hints_metadata;
   auto* hint = hints_metadata.add_performance_hints();
   hint->set_wildcard_pattern("test.com");
@@ -339,40 +660,37 @@
   base::HistogramTester histogram_tester;
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("http://www.test.com")),
+                  web_contents(), GURL("http://www.test.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_SLOW));
   histogram_tester.ExpectBucketCount(
       "PerformanceHints.Observer.PerformanceClassForURL", /*kSlow*/ 1, 1);
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("http://www.fastsite.org")),
+                  web_contents(), GURL("http://www.fastsite.org"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_FAST));
   histogram_tester.ExpectBucketCount(
       "PerformanceHints.Observer.PerformanceClassForURL", /*kFast*/ 2, 1);
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("https://www.othersite.net/this/link")),
+                  web_contents(), GURL("https://www.othersite.net/this/link"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_FAST));
   histogram_tester.ExpectBucketCount(
       "PerformanceHints.Observer.PerformanceClassForURL", /*kUnknown*/ 0, 1);
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("https://www.nohint.com")),
+                  web_contents(), GURL("https://www.nohint.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_FAST));
   histogram_tester.ExpectBucketCount(
       "PerformanceHints.Observer.PerformanceClassForURL", /*kUnknown*/ 0, 2);
 }
 
-TEST_F(PerformanceHintsObserverTest, HintFetchingNotEnabled) {
+// Uses OverrideUnknownPerformanceHintsObserverTest to ensure
+// PERFORMANCE_UNKNOWN is not overridden to FAST when fetching is disabled.
+TEST_F(OverrideUnknownPerformanceHintsObserverTest, HintFetchingNotEnabled) {
   base::CommandLine::ForCurrentProcess()->RemoveSwitch(
       optimization_guide::switches::kDisableCheckingUserPermissionsForTesting);
 
-  base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitWithFeatures(
-      {kPerformanceHintsObserver,
-       optimization_guide::features::kOptimizationHints,
-       // Ensure PERFORMANCE_UNKNOWN is not overridden to FAST when fetching is
-       // disabled.
-       kPerformanceHintsTreatUnknownAsFast},
-      {});
-
   ON_CALL(*mock_optimization_guide_keyed_service_,
           CanApplyOptimizationAsync(testing::_, testing::_, testing::_))
       .WillByDefault(base::test::RunOnceCallback<2>(
@@ -383,7 +701,8 @@
   CallDidFinishNavigation(web_contents());
 
   EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                  web_contents(), GURL("http://www.test.com")),
+                  web_contents(), GURL("http://www.test.com"),
+                  /*record_metrics=*/true),
               Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 }
 
@@ -407,7 +726,8 @@
   {
     base::HistogramTester histogram_tester;
     EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                    web_contents(), GURL("https://www.nohint.com")),
+                    web_contents(), GURL("https://www.nohint.com"),
+                    /*record_metrics=*/true),
                 Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 
     histogram_tester.ExpectUniqueSample(
@@ -420,7 +740,8 @@
     std::move(finished_callback)
         .Run(optimization_guide::OptimizationGuideDecision::kTrue, {});
     EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                    web_contents(), GURL("https://www.nohint.com")),
+                    web_contents(), GURL("https://www.nohint.com"),
+                    /*record_metrics=*/true),
                 Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 
     histogram_tester.ExpectUniqueSample(
@@ -434,7 +755,8 @@
     CallDidFinishNavigation(web_contents());
 
     EXPECT_THAT(PerformanceHintsObserver::PerformanceClassForURL(
-                    web_contents(), GURL("https://www.nohint.com")),
+                    web_contents(), GURL("https://www.nohint.com"),
+                    /*record_metrics=*/true),
                 Eq(optimization_guide::proto::PERFORMANCE_UNKNOWN));
 
     histogram_tester.ExpectUniqueSample(
diff --git a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
index 1a09ff6..0add839 100644
--- a/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
+++ b/chrome/browser/picture_in_picture/picture_in_picture_window_controller_browsertest.cc
@@ -84,7 +84,6 @@
   MOCK_METHOD0(GetWebContents, content::WebContents*());
   MOCK_METHOD2(UpdatePlaybackState, void(bool, bool));
   MOCK_METHOD0(TogglePlayPause, bool());
-  MOCK_METHOD1(SetAlwaysHidePlayPauseButton, void(bool));
   MOCK_METHOD0(SkipAd, void());
   MOCK_METHOD0(NextTrack, void());
   MOCK_METHOD0(PreviousTrack, void());
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
index 235c7909..fb65b9e1 100644
--- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc
+++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/values.h"
@@ -37,6 +38,7 @@
 #include "chrome/browser/spellchecker/spellcheck_language_policy_handler.h"
 #include "chrome/browser/ssl/secure_origin_policy_handler.h"
 #include "chrome/common/buildflags.h"
+#include "chrome/common/channel_info.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/pref_names.h"
 #include "chromeos/services/assistant/public/cpp/assistant_prefs.h"
@@ -83,6 +85,8 @@
 #include "components/unified_consent/pref_names.h"
 #include "components/variations/pref_names.h"
 #include "components/variations/service/variations_service.h"
+#include "components/version_info/channel.h"
+#include "content/public/common/content_switches.h"
 #include "extensions/buildflags/buildflags.h"
 #include "media/media_buildflags.h"
 #include "ppapi/buildflags/buildflags.h"
@@ -1311,6 +1315,16 @@
   // re-enable them.
 }
 
+// Future policies are not supported on Stable and Beta by default.
+bool AreFuturePoliciesSupported() {
+  // Enable future policies for branded browser tests.
+  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestType))
+    return true;
+  version_info::Channel channel = chrome::GetChannel();
+  return channel != version_info::Channel::STABLE &&
+         channel != version_info::Channel::BETA;
+}
+
 }  // namespace
 
 void PopulatePolicyHandlerParameters(PolicyHandlerParameters* parameters) {
@@ -1329,7 +1343,7 @@
   std::unique_ptr<ConfigurationPolicyHandlerList> handlers(
       new ConfigurationPolicyHandlerList(
           base::Bind(&PopulatePolicyHandlerParameters),
-          base::Bind(&GetChromePolicyDetails)));
+          base::Bind(&GetChromePolicyDetails), AreFuturePoliciesSupported()));
   for (size_t i = 0; i < base::size(kSimplePolicyMap); ++i) {
     handlers->AddHandler(std::make_unique<SimplePolicyHandler>(
         kSimplePolicyMap[i].policy_name, kSimplePolicyMap[i].preference_path,
diff --git a/chrome/browser/policy/messaging_layer/proto/test.proto b/chrome/browser/policy/messaging_layer/proto/test.proto
index d960e1f9..fda55d91 100644
--- a/chrome/browser/policy/messaging_layer/proto/test.proto
+++ b/chrome/browser/policy/messaging_layer/proto/test.proto
@@ -6,7 +6,7 @@
 
 option optimize_for = LITE_RUNTIME;
 
-package reporting_messaging_layer.test;
+package reporting.test;
 
 // A simple test proto with a string in it.
 message TestMessage {
diff --git a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
index c5fd1b9..616db2b 100644
--- a/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_client_unittest.cc
@@ -18,8 +18,8 @@
 namespace {
 
 using policy::DMToken;
-using reporting_messaging_layer::Destination;
-using reporting_messaging_layer::Priority;
+using reporting::Destination;
+using reporting::Priority;
 
 class ReportingClientTest : public testing::Test {
  protected:
diff --git a/chrome/browser/policy/messaging_layer/public/report_queue.cc b/chrome/browser/policy/messaging_layer/public/report_queue.cc
index c1c5ac3..6f2212f 100644
--- a/chrome/browser/policy/messaging_layer/public/report_queue.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_queue.cc
@@ -18,21 +18,21 @@
 #include "base/task/thread_pool.h"
 #include "base/values.h"
 #include "chrome/browser/policy/messaging_layer/encryption/encryption_module.h"
-#include "chrome/browser/policy/messaging_layer/proto/record.pb.h"
 #include "chrome/browser/policy/messaging_layer/public/report_queue_configuration.h"
 #include "chrome/browser/policy/messaging_layer/storage/storage_module.h"
 #include "chrome/browser/policy/messaging_layer/util/status.h"
 #include "chrome/browser/policy/messaging_layer/util/status_macros.h"
 #include "chrome/browser/policy/messaging_layer/util/statusor.h"
 #include "components/policy/core/common/cloud/dm_token.h"
+#include "components/policy/proto/record.pb.h"
 #include "components/policy/proto/record_constants.pb.h"
 #include "crypto/sha2.h"
 
 namespace reporting {
 
-using reporting_messaging_layer::EncryptedRecord;
-using reporting_messaging_layer::Record;
-using reporting_messaging_layer::WrappedRecord;
+using reporting::EncryptedRecord;
+using reporting::Record;
+using reporting::WrappedRecord;
 
 std::unique_ptr<ReportQueue> ReportQueue::Create(
     std::unique_ptr<ReportQueueConfiguration> config,
diff --git a/chrome/browser/policy/messaging_layer/public/report_queue.h b/chrome/browser/policy/messaging_layer/public/report_queue.h
index 41782d65..b346b0a 100644
--- a/chrome/browser/policy/messaging_layer/public/report_queue.h
+++ b/chrome/browser/policy/messaging_layer/public/report_queue.h
@@ -15,11 +15,11 @@
 #include "base/sequenced_task_runner.h"
 #include "base/values.h"
 #include "chrome/browser/policy/messaging_layer/encryption/encryption_module.h"
-#include "chrome/browser/policy/messaging_layer/proto/record.pb.h"
 #include "chrome/browser/policy/messaging_layer/public/report_queue_configuration.h"
 #include "chrome/browser/policy/messaging_layer/storage/storage_module.h"
 #include "chrome/browser/policy/messaging_layer/util/status.h"
 #include "chrome/browser/policy/messaging_layer/util/statusor.h"
+#include "components/policy/proto/record.pb.h"
 #include "components/policy/proto/record_constants.pb.h"
 #include "third_party/protobuf/src/google/protobuf/message_lite.h"
 
@@ -80,11 +80,10 @@
   Status AddRecord(base::StringPiece record, EnqueueCallback callback);
   void SendRecordToStorage(std::string record, EnqueueCallback callback);
 
-  StatusOr<reporting_messaging_layer::WrappedRecord> WrapRecord(
-      base::StringPiece record_data);
+  StatusOr<reporting::WrappedRecord> WrapRecord(base::StringPiece record_data);
   StatusOr<std::string> GetLastRecordDigest();
-  StatusOr<reporting_messaging_layer::EncryptedRecord> EncryptRecord(
-      reporting_messaging_layer::WrappedRecord wrapped_record);
+  StatusOr<reporting::EncryptedRecord> EncryptRecord(
+      reporting::WrappedRecord wrapped_record);
 
   std::unique_ptr<ReportQueueConfiguration> config_;
   scoped_refptr<StorageModule> storage_;
diff --git a/chrome/browser/policy/messaging_layer/public/report_queue_configuration.cc b/chrome/browser/policy/messaging_layer/public/report_queue_configuration.cc
index 9416af4..5f2f0d7 100644
--- a/chrome/browser/policy/messaging_layer/public/report_queue_configuration.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_queue_configuration.cc
@@ -14,8 +14,8 @@
 namespace reporting {
 
 using policy::DMToken;
-using reporting_messaging_layer::Destination;
-using reporting_messaging_layer::Priority;
+using reporting::Destination;
+using reporting::Priority;
 
 StatusOr<std::unique_ptr<ReportQueueConfiguration>>
 ReportQueueConfiguration::Create(const policy::DMToken& dm_token,
diff --git a/chrome/browser/policy/messaging_layer/public/report_queue_configuration.h b/chrome/browser/policy/messaging_layer/public/report_queue_configuration.h
index e9dea51..bb5e114 100644
--- a/chrome/browser/policy/messaging_layer/public/report_queue_configuration.h
+++ b/chrome/browser/policy/messaging_layer/public/report_queue_configuration.h
@@ -35,14 +35,12 @@
   // Priority::UNDEFINED_PRIORITY.
   static StatusOr<std::unique_ptr<ReportQueueConfiguration>> Create(
       const policy::DMToken& dm_token,
-      reporting_messaging_layer::Destination destination,
-      reporting_messaging_layer::Priority priority);
+      reporting::Destination destination,
+      reporting::Priority priority);
 
-  reporting_messaging_layer::Destination destination() const {
-    return destination_;
-  }
+  reporting::Destination destination() const { return destination_; }
 
-  reporting_messaging_layer::Priority priority() const { return priority_; }
+  reporting::Priority priority() const { return priority_; }
 
   policy::DMToken dm_token() const { return dm_token_; }
 
@@ -50,12 +48,12 @@
   ReportQueueConfiguration() = default;
 
   Status SetDMToken(const policy::DMToken& dm_token);
-  Status SetDestination(reporting_messaging_layer::Destination destination);
-  Status SetPriority(reporting_messaging_layer::Priority priority);
+  Status SetDestination(reporting::Destination destination);
+  Status SetPriority(reporting::Priority priority);
 
   policy::DMToken dm_token_;
-  reporting_messaging_layer::Destination destination_;
-  reporting_messaging_layer::Priority priority_;
+  reporting::Destination destination_;
+  reporting::Priority priority_;
 };
 
 }  // namespace reporting
diff --git a/chrome/browser/policy/messaging_layer/public/report_queue_configuration_unittest.cc b/chrome/browser/policy/messaging_layer/public/report_queue_configuration_unittest.cc
index 4053e5d..8f02d486 100644
--- a/chrome/browser/policy/messaging_layer/public/report_queue_configuration_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_queue_configuration_unittest.cc
@@ -15,8 +15,8 @@
 namespace {
 
 using policy::DMToken;
-using reporting_messaging_layer::Destination;
-using reporting_messaging_layer::Priority;
+using reporting::Destination;
+using reporting::Priority;
 
 // Tests to ensure that only valid parameters are used to generate a
 // ReportQueueConfiguration.
diff --git a/chrome/browser/policy/messaging_layer/public/report_queue_unittest.cc b/chrome/browser/policy/messaging_layer/public/report_queue_unittest.cc
index 7aaf3ea..63bdd77 100644
--- a/chrome/browser/policy/messaging_layer/public/report_queue_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/public/report_queue_unittest.cc
@@ -31,10 +31,10 @@
 
 using base::MakeRefCounted;
 using policy::DMToken;
-using reporting_messaging_layer::Destination;
-using reporting_messaging_layer::EncryptedRecord;
-using reporting_messaging_layer::Priority;
-using reporting_messaging_layer::WrappedRecord;
+using reporting::Destination;
+using reporting::EncryptedRecord;
+using reporting::Priority;
+using reporting::WrappedRecord;
 
 // A |StorageModule| that stores the wrapped record and priority and calls the
 // callback with an OK status.
@@ -197,7 +197,7 @@
 // Enqueues a |TestMessage| and ensures that it arrives unaltered in the
 // |StorageModule|.
 TEST_F(ReportQueueTest, SuccessfulProtoRecord) {
-  reporting_messaging_layer::test::TestMessage test_message;
+  reporting::test::TestMessage test_message;
   test_message.set_test("TEST_MESSAGE");
   Status status = report_queue_->Enqueue(&test_message, std::move(callback_));
   ASSERT_TRUE(status.ok());
@@ -208,7 +208,7 @@
 
   EXPECT_EQ(storage_module_->priority(), priority_);
 
-  reporting_messaging_layer::test::TestMessage result_message;
+  reporting::test::TestMessage result_message;
   ASSERT_TRUE(result_message.ParseFromString(
       storage_module_->wrapped_record().record().data()));
   ASSERT_EQ(result_message.test(), test_message.test());
@@ -240,7 +240,7 @@
 // been scheduled. The callback should fail, indicating that storage was
 // unsuccessful.
 TEST_F(StorageFailsReportQueueTest, CallSuccessCallbackFailure) {
-  reporting_messaging_layer::test::TestMessage test_message;
+  reporting::test::TestMessage test_message;
   test_message.set_test("TEST_MESSAGE");
   Status status = report_queue_->Enqueue(&test_message, std::move(callback_));
   ASSERT_TRUE(status.ok());
@@ -275,7 +275,7 @@
 // has been scheduled. The callback should fail, indicating that encryption was
 // unsuccessful.
 TEST_F(EncryptionFailsReportQueueTest, CallSuccessCallFailure) {
-  reporting_messaging_layer::test::TestMessage test_message;
+  reporting::test::TestMessage test_message;
   test_message.set_test("TEST_MESSAGE");
   Status status = report_queue_->Enqueue(&test_message, std::move(callback_));
   ASSERT_TRUE(status.ok());
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_module.cc b/chrome/browser/policy/messaging_layer/storage/storage_module.cc
index 292222c0..7a64412d 100644
--- a/chrome/browser/policy/messaging_layer/storage/storage_module.cc
+++ b/chrome/browser/policy/messaging_layer/storage/storage_module.cc
@@ -5,15 +5,15 @@
 #include <utility>
 
 #include "base/callback.h"
-#include "chrome/browser/policy/messaging_layer/proto/record.pb.h"
 #include "chrome/browser/policy/messaging_layer/storage/storage_module.h"
 #include "chrome/browser/policy/messaging_layer/util/status.h"
+#include "components/policy/proto/record.pb.h"
 #include "components/policy/proto/record_constants.pb.h"
 
 namespace reporting {
 
-void StorageModule::AddRecord(reporting_messaging_layer::EncryptedRecord record,
-                              reporting_messaging_layer::Priority priority,
+void StorageModule::AddRecord(reporting::EncryptedRecord record,
+                              reporting::Priority priority,
                               base::OnceCallback<void(Status)> callback) {
   std::move(callback).Run(
       Status(error::UNIMPLEMENTED, "AddRecord isn't implemented"));
diff --git a/chrome/browser/policy/messaging_layer/storage/storage_module.h b/chrome/browser/policy/messaging_layer/storage/storage_module.h
index 9c89417..7f7a5a1 100644
--- a/chrome/browser/policy/messaging_layer/storage/storage_module.h
+++ b/chrome/browser/policy/messaging_layer/storage/storage_module.h
@@ -9,8 +9,8 @@
 
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
-#include "chrome/browser/policy/messaging_layer/proto/record.pb.h"
 #include "chrome/browser/policy/messaging_layer/util/status.h"
+#include "components/policy/proto/record.pb.h"
 #include "components/policy/proto/record_constants.pb.h"
 
 namespace reporting {
@@ -25,8 +25,8 @@
 
   // AddRecord will add |record| to the |StorageModule| according to the
   // provided |priority|. On completion, |callback| will be called.
-  virtual void AddRecord(reporting_messaging_layer::EncryptedRecord record,
-                         reporting_messaging_layer::Priority priority,
+  virtual void AddRecord(reporting::EncryptedRecord record,
+                         reporting::Priority priority,
                          base::OnceCallback<void(Status)> callback);
 
  protected:
diff --git a/chrome/browser/policy/messaging_layer/storage/test_storage_module.cc b/chrome/browser/policy/messaging_layer/storage/test_storage_module.cc
index e43a0f06..9c78788 100644
--- a/chrome/browser/policy/messaging_layer/storage/test_storage_module.cc
+++ b/chrome/browser/policy/messaging_layer/storage/test_storage_module.cc
@@ -7,16 +7,16 @@
 #include <utility>
 
 #include "base/callback.h"
-#include "chrome/browser/policy/messaging_layer/proto/record.pb.h"
 #include "chrome/browser/policy/messaging_layer/public/report_queue.h"
+#include "components/policy/proto/record.pb.h"
 #include "components/policy/proto/record_constants.pb.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace reporting {
 namespace test {
 
-using reporting_messaging_layer::EncryptedRecord;
-using reporting_messaging_layer::Priority;
+using reporting::EncryptedRecord;
+using reporting::Priority;
 
 void TestStorageModule::AddRecord(EncryptedRecord record,
                                   Priority priority,
diff --git a/chrome/browser/policy/messaging_layer/storage/test_storage_module.h b/chrome/browser/policy/messaging_layer/storage/test_storage_module.h
index 65d41d62..9e8ade1 100644
--- a/chrome/browser/policy/messaging_layer/storage/test_storage_module.h
+++ b/chrome/browser/policy/messaging_layer/storage/test_storage_module.h
@@ -8,8 +8,8 @@
 #include <utility>
 
 #include "base/callback.h"
-#include "chrome/browser/policy/messaging_layer/proto/record.pb.h"
 #include "chrome/browser/policy/messaging_layer/public/report_queue.h"
+#include "components/policy/proto/record.pb.h"
 #include "components/policy/proto/record_constants.pb.h"
 
 namespace reporting {
@@ -21,22 +21,20 @@
  public:
   TestStorageModule() = default;
 
-  void AddRecord(reporting_messaging_layer::EncryptedRecord record,
-                 reporting_messaging_layer::Priority priority,
+  void AddRecord(reporting::EncryptedRecord record,
+                 reporting::Priority priority,
                  base::OnceCallback<void(Status)> callback) override;
 
-  reporting_messaging_layer::WrappedRecord wrapped_record() {
-    return wrapped_record_;
-  }
+  reporting::WrappedRecord wrapped_record() { return wrapped_record_; }
 
-  reporting_messaging_layer::Priority priority() { return priority_; }
+  reporting::Priority priority() { return priority_; }
 
  protected:
   ~TestStorageModule() override = default;
 
  private:
-  reporting_messaging_layer::WrappedRecord wrapped_record_;
-  reporting_messaging_layer::Priority priority_;
+  reporting::WrappedRecord wrapped_record_;
+  reporting::Priority priority_;
 };
 
 // A |TestStorageModule| that always fails on |AddRecord| calls.
@@ -44,8 +42,8 @@
  public:
   AlwaysFailsStorageModule() = default;
 
-  void AddRecord(reporting_messaging_layer::EncryptedRecord record,
-                 reporting_messaging_layer::Priority priority,
+  void AddRecord(reporting::EncryptedRecord record,
+                 reporting::Priority priority,
                  base::OnceCallback<void(Status)> callback) override;
 
  protected:
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 0c49b7b..bd82e11c 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -403,7 +403,7 @@
 
 TestAddAppWindowObserver::TestAddAppWindowObserver(
     extensions::AppWindowRegistry* registry)
-    : registry_(registry), window_(NULL) {
+    : registry_(registry), window_(nullptr) {
   registry_->AddObserver(this);
 }
 
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 6abde35..e5f9fd62 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -30,7 +30,6 @@
 #include "chrome/browser/gpu/gpu_mode_manager.h"
 #include "chrome/browser/intranet_redirect_detector.h"
 #include "chrome/browser/lifetime/browser_shutdown.h"
-#include "chrome/browser/media/feeds/media_feeds_service.h"
 #include "chrome/browser/media/media_device_id_salt.h"
 #include "chrome/browser/media/media_engagement_service.h"
 #include "chrome/browser/media/media_storage_id_salt.h"
@@ -397,6 +396,10 @@
 #include "chrome/browser/ui/browser_view_prefs.h"
 #endif
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/media/feeds/media_feeds_service.h"
+#endif
+
 namespace {
 
 #if defined(OS_ANDROID)
@@ -1084,7 +1087,9 @@
   RegisterBrowserViewProfilePrefs(registry);
 #endif
 
+#if !defined(OS_ANDROID)
   media_feeds::MediaFeedsService::RegisterProfilePrefs(registry);
+#endif
 
   RegisterProfilePrefsForMigration(registry);
 }
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_browsertest.cc b/chrome/browser/prerender/isolated/isolated_prerender_browsertest.cc
index 824db5f..16347f0 100644
--- a/chrome/browser/prerender/isolated/isolated_prerender_browsertest.cc
+++ b/chrome/browser/prerender/isolated/isolated_prerender_browsertest.cc
@@ -46,7 +46,7 @@
 #include "components/data_reduction_proxy/proto/client_config.pb.h"
 #include "components/language/core/browser/pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "components/prerender/prerender_final_status.h"
+#include "components/prerender/common/prerender_final_status.h"
 #include "components/ukm/test_ukm_recorder.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc
index 704dc94..e004b64 100644
--- a/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc
+++ b/chrome/browser/prerender/isolated/isolated_prerender_tab_helper.cc
@@ -99,9 +99,9 @@
 void OnGotCookieList(
     const GURL& url,
     IsolatedPrerenderTabHelper::OnEligibilityResultCallback result_callback,
-    const net::CookieStatusList& cookie_with_status_list,
-    const net::CookieStatusList& excluded_cookies) {
-  if (!cookie_with_status_list.empty()) {
+    const net::CookieAccessResultList& cookie_list,
+    const net::CookieAccessResultList& excluded_cookies) {
+  if (!cookie_list.empty()) {
     std::move(result_callback)
         .Run(url, false,
              IsolatedPrerenderTabHelper::PrefetchStatus::
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc
index 7e31b447..557dd52 100644
--- a/chrome/browser/prerender/prerender_contents.cc
+++ b/chrome/browser/prerender/prerender_contents.cc
@@ -26,11 +26,11 @@
 #include "chrome/browser/task_manager/web_contents_tags.h"
 #include "chrome/browser/ui/tab_helpers.h"
 #include "chrome/browser/ui/web_contents_sizer.h"
-#include "chrome/common/prerender_messages.h"
 #include "chrome/common/prerender_util.h"
 #include "components/history/core/browser/history_types.h"
-#include "components/prerender/prerender_final_status.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_messages.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
@@ -644,7 +644,8 @@
 }
 
 void PrerenderContents::AddPrerenderCancelerReceiver(
-    mojo::PendingReceiver<chrome::mojom::PrerenderCanceler> receiver) {
+    mojo::PendingReceiver<
+        components::prerender::common::mojom::PrerenderCanceler> receiver) {
   prerender_canceler_receiver_set_.Add(this, std::move(receiver));
 }
 
diff --git a/chrome/browser/prerender/prerender_contents.h b/chrome/browser/prerender/prerender_contents.h
index 7aeb5d6..800f82c 100644
--- a/chrome/browser/prerender/prerender_contents.h
+++ b/chrome/browser/prerender/prerender_contents.h
@@ -18,10 +18,10 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "base/values.h"
-#include "chrome/common/prerender_canceler.mojom.h"
-#include "components/prerender/prerender_final_status.h"
-#include "components/prerender/prerender_origin.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_canceler.mojom.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_origin.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/browser/notification_observer.h"
 #include "content/public/browser/notification_registrar.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -54,9 +54,10 @@
 
 class PrerenderManager;
 
-class PrerenderContents : public content::NotificationObserver,
-                          public content::WebContentsObserver,
-                          public chrome::mojom::PrerenderCanceler {
+class PrerenderContents
+    : public content::NotificationObserver,
+      public content::WebContentsObserver,
+      public components::prerender::common::mojom::PrerenderCanceler {
  public:
   // PrerenderContents::Create uses the currently registered Factory to create
   // the PrerenderContents. Factory is intended for testing.
@@ -233,7 +234,8 @@
   int64_t network_bytes() { return network_bytes_; }
 
   void AddPrerenderCancelerReceiver(
-      mojo::PendingReceiver<chrome::mojom::PrerenderCanceler> receiver);
+      mojo::PendingReceiver<
+          components::prerender::common::mojom::PrerenderCanceler> receiver);
 
  protected:
   PrerenderContents(PrerenderManager* prerender_manager,
@@ -290,10 +292,10 @@
       bool success,
       std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump);
 
-  // chrome::mojom::PrerenderCanceler:
+  // components::prerender::common::mojom::PrerenderCanceler:
   void CancelPrerenderForUnsupportedScheme(const GURL& url) override;
 
-  mojo::ReceiverSet<chrome::mojom::PrerenderCanceler>
+  mojo::ReceiverSet<components::prerender::common::mojom::PrerenderCanceler>
       prerender_canceler_receiver_set_;
 
   base::ObserverList<Observer>::Unchecked observer_list_;
diff --git a/chrome/browser/prerender/prerender_histograms.h b/chrome/browser/prerender/prerender_histograms.h
index dc36aa74..9c085cf 100644
--- a/chrome/browser/prerender/prerender_histograms.h
+++ b/chrome/browser/prerender/prerender_histograms.h
@@ -14,8 +14,8 @@
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "chrome/browser/prerender/prerender_contents.h"
-#include "components/prerender/prerender_final_status.h"
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_origin.h"
 #include "url/gurl.h"
 
 namespace prerender {
diff --git a/chrome/browser/prerender/prerender_history.h b/chrome/browser/prerender/prerender_history.h
index d6b922a2..6d533220 100644
--- a/chrome/browser/prerender/prerender_history.h
+++ b/chrome/browser/prerender/prerender_history.h
@@ -12,8 +12,8 @@
 #include "base/macros.h"
 #include "base/sequence_checker.h"
 #include "base/time/time.h"
-#include "components/prerender/prerender_final_status.h"
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_origin.h"
 #include "url/gurl.h"
 
 namespace base {
diff --git a/chrome/browser/prerender/prerender_link_manager.cc b/chrome/browser/prerender/prerender_link_manager.cc
index bda27ad9..a6d8990 100644
--- a/chrome/browser/prerender/prerender_link_manager.cc
+++ b/chrome/browser/prerender/prerender_link_manager.cc
@@ -17,7 +17,7 @@
 #include "chrome/browser/prerender/prerender_handle.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/session_storage_namespace.h"
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc
index eb59205..43386901 100644
--- a/chrome/browser/prerender/prerender_manager.cc
+++ b/chrome/browser/prerender/prerender_manager.cc
@@ -49,8 +49,8 @@
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 #include "chrome/common/chrome_features.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
-#include "components/prerender/prerender_final_status.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/render_frame_host.h"
diff --git a/chrome/browser/prerender/prerender_manager.h b/chrome/browser/prerender/prerender_manager.h
index 5aae844..9f48fa5 100644
--- a/chrome/browser/prerender/prerender_manager.h
+++ b/chrome/browser/prerender/prerender_manager.h
@@ -22,8 +22,8 @@
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_histograms.h"
 #include "components/keyed_service/core/keyed_service.h"
-#include "components/prerender/prerender_final_status.h"
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_origin.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "url/gurl.h"
 #include "url/origin.h"
diff --git a/chrome/browser/prerender/prerender_message_filter.cc b/chrome/browser/prerender/prerender_message_filter.cc
index 69eb226..33faf9e 100644
--- a/chrome/browser/prerender/prerender_message_filter.cc
+++ b/chrome/browser/prerender/prerender_message_filter.cc
@@ -7,8 +7,8 @@
 #include "chrome/browser/prerender/prerender_contents.h"
 #include "chrome/browser/prerender/prerender_manager.h"
 #include "chrome/browser/prerender/prerender_manager_factory.h"
-#include "chrome/common/prerender_messages.h"
-#include "components/prerender/prerender_final_status.h"
+#include "components/prerender/common/prerender_final_status.h"
+#include "components/prerender/common/prerender_messages.h"
 #include "content/public/browser/render_process_host.h"
 
 namespace prerender {
diff --git a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
index 6b91379c..76782c0 100644
--- a/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
+++ b/chrome/browser/prerender/prerender_nostate_prefetch_browsertest.cc
@@ -571,11 +571,11 @@
 }
 
 void GetCookieCallback(base::RepeatingClosure callback,
-                       const net::CookieStatusList& cookie_with_status_list,
-                       const net::CookieStatusList& excluded_cookies) {
+                       const net::CookieAccessResultList& cookie_list,
+                       const net::CookieAccessResultList& excluded_cookies) {
   bool found_chocolate = false;
   bool found_oatmeal = false;
-  for (const auto& c : cookie_with_status_list) {
+  for (const auto& c : cookie_list) {
     if (c.cookie.Name() == "chocolate-chip") {
       EXPECT_EQ("the-best", c.cookie.Value());
       found_chocolate = true;
diff --git a/chrome/browser/prerender/prerender_tab_helper.h b/chrome/browser/prerender/prerender_tab_helper.h
index 46c19d3..fd0ac0dd 100644
--- a/chrome/browser/prerender/prerender_tab_helper.h
+++ b/chrome/browser/prerender/prerender_tab_helper.h
@@ -11,7 +11,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
 #include "chrome/browser/prerender/prerender_histograms.h"
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_origin.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "url/gurl.h"
diff --git a/chrome/browser/prerender/prerender_unittest.cc b/chrome/browser/prerender/prerender_unittest.cc
index a47c8c8d..d6b8863a 100644
--- a/chrome/browser/prerender/prerender_unittest.cc
+++ b/chrome/browser/prerender/prerender_unittest.cc
@@ -41,8 +41,8 @@
 #include "chrome/test/base/testing_profile.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
-#include "components/prerender/prerender_origin.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_origin.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
diff --git a/chrome/browser/previews/defer_all_script_browsertest.cc b/chrome/browser/previews/defer_all_script_browsertest.cc
index 8c97b103..cd4d1d8 100644
--- a/chrome/browser/previews/defer_all_script_browsertest.cc
+++ b/chrome/browser/previews/defer_all_script_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include <map>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -14,6 +15,8 @@
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/previews/previews_service.h"
 #include "chrome/browser/previews/previews_service_factory.h"
 #include "chrome/browser/previews/previews_test_util.h"
@@ -53,6 +56,10 @@
         {previews::features::kPreviews,
          previews::features::kDeferAllScriptPreviews,
          optimization_guide::features::kOptimizationHints,
+         // TODO(crbug/1021364): Remove the following two features after the
+         // model rollout
+         optimization_guide::features::kRemoteOptimizationGuideFetching,
+         optimization_guide::features::kOptimizationTargetPrediction,
          features::kBackForwardCache},
         {});
   }
@@ -61,11 +68,12 @@
 
   void SetUpOnMainThread() override {
     host_resolver()->AddRule("*", "127.0.0.1");
-    g_browser_process->network_quality_tracker()
-        ->ReportEffectiveConnectionTypeForTesting(
-            net::EFFECTIVE_CONNECTION_TYPE_2G);
-    https_server_.reset(
-        new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS));
+    OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+        ->OverrideTargetDecisionForTesting(
+            optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+            optimization_guide::OptimizationGuideDecision::kTrue);
+    https_server_ = std::make_unique<net::EmbeddedTestServer>(
+        net::EmbeddedTestServer::TYPE_HTTPS);
     https_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews");
     ASSERT_TRUE(https_server_->Start());
 
@@ -99,10 +107,10 @@
     cmd->AppendSwitch("optimization-guide-disable-installer");
     cmd->AppendSwitch("purge_hint_cache_store");
 
-    // Due to race conditions, it's possible that blacklist data is not loaded
+    // Due to race conditions, it's possible that blocklist data is not loaded
     // at the time of first navigation. That may prevent Preview from
     // triggering, and causing the test to flake.
-    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
+    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist);
 
     InProcessBrowserTest::SetUpCommandLine(cmd);
   }
@@ -556,11 +564,12 @@
   histogram_tester.ExpectBucketCount("Previews.PreviewShown.DeferAllScript",
                                      true, 1);
 
-  // Now adjust the network triggering condition to not choose preview for a
+  // Override the target decision to |kFalse| to not trigger a preview for the
   // new decision.
-  g_browser_process->network_quality_tracker()
-      ->ReportEffectiveConnectionTypeForTesting(
-          net::EFFECTIVE_CONNECTION_TYPE_4G);
+  OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+      ->OverrideTargetDecisionForTesting(
+          optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+          optimization_guide::OptimizationGuideDecision::kFalse);
 
   // Navigate to another host on same tab (to cause previous navigation
   // to be saved in BackForward cache).
@@ -620,11 +629,12 @@
   // Wait for initial page load to complete.
   content::WaitForLoadStop(web_contents());
 
-  // Adjust the network triggering condition to not choose preview for this
-  // navigation.
-  g_browser_process->network_quality_tracker()
-      ->ReportEffectiveConnectionTypeForTesting(
-          net::EFFECTIVE_CONNECTION_TYPE_4G);
+  // Override the target decision to |kFalse| to choose not to trigger a
+  // preview this navigation.
+  OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+      ->OverrideTargetDecisionForTesting(
+          optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+          optimization_guide::OptimizationGuideDecision::kFalse);
 
   // Navigate to DeferAllScript url.
   ui_test_utils::NavigateToURL(browser(), url);
@@ -637,11 +647,12 @@
       "Previews.EligibilityReason.DeferAllScript",
       static_cast<int>(previews::PreviewsEligibilityReason::COMMITTED), 0);
 
-  // Now adjust the network triggering condition to allow a preview for a
+  // Now override the model decision to |kTrue| to allow a preview for a
   // new decision.
-  g_browser_process->network_quality_tracker()
-      ->ReportEffectiveConnectionTypeForTesting(
-          net::EFFECTIVE_CONNECTION_TYPE_2G);
+  OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+      ->OverrideTargetDecisionForTesting(
+          optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+          optimization_guide::OptimizationGuideDecision::kTrue);
 
   // Navigate to another host on same tab (to cause previous navigation
   // to be saved in BackForward cache).
diff --git a/chrome/browser/previews/defer_all_script_priority_browsertest.cc b/chrome/browser/previews/defer_all_script_priority_browsertest.cc
index 7c69e05..846f95e1 100644
--- a/chrome/browser/previews/defer_all_script_priority_browsertest.cc
+++ b/chrome/browser/previews/defer_all_script_priority_browsertest.cc
@@ -103,10 +103,10 @@
     cmd->AppendSwitch("optimization-guide-disable-installer");
     cmd->AppendSwitch("purge_hint_cache_store");
 
-    // Due to race conditions, it's possible that blacklist data is not loaded
+    // Due to race conditions, it's possible that blocklist data is not loaded
     // at the time of first navigation. That may prevent Preview from
     // triggering, and causing the test to flake.
-    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
+    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist);
   }
 
   // Returns a unique script for each request, to test service worker update.
diff --git a/chrome/browser/previews/lazyload_browsertest.cc b/chrome/browser/previews/lazyload_browsertest.cc
index c5df6a6..638f675 100644
--- a/chrome/browser/previews/lazyload_browsertest.cc
+++ b/chrome/browser/previews/lazyload_browsertest.cc
@@ -19,7 +19,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/data_use_measurement/core/data_use_user_data.h"
-#include "components/prerender/prerender_final_status.h"
+#include "components/prerender/common/prerender_final_status.h"
 #include "content/public/browser/content_browser_client.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
diff --git a/chrome/browser/previews/previews_browsertest.cc b/chrome/browser/previews/previews_browsertest.cc
index 74221460..852ab22 100644
--- a/chrome/browser/previews/previews_browsertest.cc
+++ b/chrome/browser/previews/previews_browsertest.cc
@@ -12,6 +12,8 @@
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/metrics/subprocess_metrics_provider.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
+#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/previews/previews_service_factory.h"
 #include "chrome/browser/previews/previews_test_util.h"
 #include "chrome/browser/previews/previews_ui_tab_helper.h"
@@ -26,6 +28,7 @@
 #include "components/optimization_guide/optimization_guide_features.h"
 #include "components/optimization_guide/optimization_guide_service.h"
 #include "components/optimization_guide/proto/hints.pb.h"
+#include "components/optimization_guide/proto/models.pb.h"
 #include "components/optimization_guide/test_hints_component_creator.h"
 #include "components/previews/core/previews_features.h"
 #include "components/previews/core/previews_switches.h"
@@ -46,10 +49,6 @@
   ~PreviewsBrowserTest() override = default;
 
   void SetUpOnMainThread() override {
-    g_browser_process->network_quality_tracker()
-        ->ReportEffectiveConnectionTypeForTesting(
-            net::EFFECTIVE_CONNECTION_TYPE_2G);
-
     // Set up https server with resource monitor.
     https_server_.reset(
         new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTPS));
@@ -70,8 +69,8 @@
     ASSERT_EQ(https_hint_setup_url_.host(), https_url_.host());
 
     // Set up http server with resource monitor and redirect handler.
-    http_server_.reset(
-        new net::EmbeddedTestServer(net::EmbeddedTestServer::TYPE_HTTP));
+    http_server_ = std::make_unique<net::EmbeddedTestServer>(
+        net::EmbeddedTestServer::TYPE_HTTP);
     http_server_->ServeFilesFromSourceDirectory("chrome/test/data/previews");
     http_server_->RegisterRequestMonitor(base::BindRepeating(
         &PreviewsBrowserTest::MonitorResourceRequest, base::Unretained(this)));
@@ -92,10 +91,10 @@
 
   void SetUpCommandLine(base::CommandLine* cmd) override {
     cmd->AppendSwitch("enable-spdy-proxy-auth");
-    // Due to race conditions, it's possible that blacklist data is not loaded
+    // Due to race conditions, it's possible that blocklist data is not loaded
     // at the time of first navigation. That may prevent Preview from
     // triggering, and causing the test to flake.
-    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
+    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist);
   }
 
   const GURL& https_url() const { return https_url_; }
@@ -207,11 +206,19 @@
     PreviewsBrowserTest::SetUp();
   }
 
+  void SetUpOnMainThread() override {
+    OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+        ->OverrideTargetDecisionForTesting(
+            optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+            optimization_guide::OptimizationGuideDecision::kTrue);
+    PreviewsBrowserTest::SetUpOnMainThread();
+  }
+
   void SetUpCommandLine(base::CommandLine* cmd) override {
     cmd->AppendSwitch("enable-spdy-proxy-auth");
     cmd->AppendSwitch("optimization-guide-disable-installer");
     cmd->AppendSwitch("purge_hint_cache_store");
-    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
+    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist);
   }
 
   // Creates hint data for the |hint_setup_url|'s host and then performs a
@@ -412,10 +419,12 @@
 IN_PROC_BROWSER_TEST_P(PreviewsNoScriptBrowserTest,
                        DISABLE_ON_WIN_MAC_CHROMEOS(
                            NoScriptPreviewsEnabledShouldSkipPreviewCheck)) {
-  // Set ECT to 4G so that the Preview should not be shown in the regular case.
-  g_browser_process->network_quality_tracker()
-      ->ReportEffectiveConnectionTypeForTesting(
-          net::EFFECTIVE_CONNECTION_TYPE_4G);
+  // Override the decision to |kFalse| so that the Preview should not be shown
+  // in the regular case.
+  OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile())
+      ->OverrideTargetDecisionForTesting(
+          optimization_guide::proto::OPTIMIZATION_TARGET_PAINFUL_PAGE_LOAD,
+          optimization_guide::OptimizationGuideDecision::kFalse);
 
   GURL url = https_url();
 
diff --git a/chrome/browser/previews/previews_service.cc b/chrome/browser/previews/previews_service.cc
index eefff0eb..e754023 100644
--- a/chrome/browser/previews/previews_service.cc
+++ b/chrome/browser/previews/previews_service.cc
@@ -140,9 +140,9 @@
 }
 
 // static
-blacklist::BlacklistData::AllowedTypesAndVersions
+blocklist::BlocklistData::AllowedTypesAndVersions
 PreviewsService::GetAllowedPreviews() {
-  blacklist::BlacklistData::AllowedTypesAndVersions enabled_previews;
+  blocklist::BlocklistData::AllowedTypesAndVersions enabled_previews;
 
   // Loop across all previews types (relies on sequential enum values).
   for (int i = static_cast<int>(previews::PreviewsType::NONE) + 1;
@@ -203,7 +203,7 @@
 
   previews_ui_service_ = std::make_unique<previews::PreviewsUIService>(
       std::move(previews_decider_impl),
-      std::make_unique<blacklist::OptOutStoreSQL>(
+      std::make_unique<blocklist::OptOutStoreSQL>(
           ui_task_runner, background_task_runner,
           profile_path.Append(chrome::kPreviewsOptOutDBFilename)),
       std::move(previews_opt_guide), base::Bind(&IsPreviewsTypeEnabled),
@@ -219,10 +219,10 @@
     previews_offline_helper_->Shutdown();
 }
 
-void PreviewsService::ClearBlackList(base::Time begin_time,
+void PreviewsService::ClearBlockList(base::Time begin_time,
                                      base::Time end_time) {
   if (previews_ui_service_)
-    previews_ui_service_->ClearBlackList(begin_time, end_time);
+    previews_ui_service_->ClearBlockList(begin_time, end_time);
 }
 
 void PreviewsService::ReportObservedRedirectWithDeferAllScriptPreview(
diff --git a/chrome/browser/previews/previews_service.h b/chrome/browser/previews/previews_service.h
index 85021ed..aab5cf7 100644
--- a/chrome/browser/previews/previews_service.h
+++ b/chrome/browser/previews/previews_service.h
@@ -50,9 +50,9 @@
   // Allows members to remove themselves from observed classes.
   void Shutdown() override;
 
-  // Clears the history of the black lists in |previews_ui_service_| and between
+  // Clears the history of the block lists in |previews_ui_service_| and between
   // |begin_time| and |end_time|.
-  void ClearBlackList(base::Time begin_time, base::Time end_time);
+  void ClearBlockList(base::Time begin_time, base::Time end_time);
 
   // The previews UI thread service.
   previews::PreviewsUIService* previews_ui_service() {
@@ -70,7 +70,7 @@
   }
 
   // Returns the enabled PreviewsTypes with their version.
-  static blacklist::BlacklistData::AllowedTypesAndVersions GetAllowedPreviews();
+  static blocklist::BlocklistData::AllowedTypesAndVersions GetAllowedPreviews();
 
   // Called when that there is a redirect from |start_url| to |end_url|. Called
   // only when DeferAllScript preview feature is enabled.
diff --git a/chrome/browser/previews/previews_service_unittest.cc b/chrome/browser/previews/previews_service_unittest.cc
index a88ed7a5..8db3cf8 100644
--- a/chrome/browser/previews/previews_service_unittest.cc
+++ b/chrome/browser/previews/previews_service_unittest.cc
@@ -34,7 +34,7 @@
 }  // namespace
 
 TEST_F(PreviewsServiceTest, TestOfflineFieldTrialNotSet) {
-  blacklist::BlacklistData::AllowedTypesAndVersions allowed_types_and_versions =
+  blocklist::BlocklistData::AllowedTypesAndVersions allowed_types_and_versions =
       PreviewsService::GetAllowedPreviews();
   EXPECT_EQ(allowed_types_and_versions.find(
                 static_cast<int>(previews::PreviewsType::OFFLINE)),
@@ -42,7 +42,7 @@
 }
 
 TEST_F(PreviewsServiceTest, TestOfflineFeatureDisabled) {
-  blacklist::BlacklistData::AllowedTypesAndVersions allowed_types_and_versions =
+  blocklist::BlocklistData::AllowedTypesAndVersions allowed_types_and_versions =
       PreviewsService::GetAllowedPreviews();
   EXPECT_EQ(allowed_types_and_versions.find(
                 static_cast<int>(previews::PreviewsType::OFFLINE)),
@@ -54,7 +54,7 @@
   scoped_feature_list.InitWithFeatures(
       {previews::features::kPreviews} /* enabled features */,
       {} /* disabled features */);
-  blacklist::BlacklistData::AllowedTypesAndVersions allowed_types_and_versions =
+  blocklist::BlocklistData::AllowedTypesAndVersions allowed_types_and_versions =
       PreviewsService::GetAllowedPreviews();
   EXPECT_EQ(allowed_types_and_versions.find(
                 static_cast<int>(previews::PreviewsType::LITE_PAGE)),
@@ -64,7 +64,7 @@
 TEST_F(PreviewsServiceTest, TestNoScriptPreviewsEnabledByFeature) {
 #if !defined(OS_ANDROID)
   // For non-android, default is disabled.
-  blacklist::BlacklistData::AllowedTypesAndVersions allowed_types_and_versions =
+  blocklist::BlocklistData::AllowedTypesAndVersions allowed_types_and_versions =
       PreviewsService::GetAllowedPreviews();
   EXPECT_EQ(allowed_types_and_versions.find(
                 static_cast<int>(previews::PreviewsType::NOSCRIPT)),
@@ -74,7 +74,7 @@
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
       previews::features::kNoScriptPreviews);
-  blacklist::BlacklistData::AllowedTypesAndVersions
+  blocklist::BlocklistData::AllowedTypesAndVersions
       allowed_types_and_versions2 = PreviewsService::GetAllowedPreviews();
   EXPECT_NE(allowed_types_and_versions2.find(
                 static_cast<int>(previews::PreviewsType::NOSCRIPT)),
@@ -84,7 +84,7 @@
 TEST_F(PreviewsServiceTest, TestDeferAllScriptPreviewsEnabledByFeature) {
 #if !defined(OS_ANDROID)
   // For non-android, default is disabled.
-  blacklist::BlacklistData::AllowedTypesAndVersions allowed_types_and_versions =
+  blocklist::BlocklistData::AllowedTypesAndVersions allowed_types_and_versions =
       PreviewsService::GetAllowedPreviews();
   EXPECT_EQ(allowed_types_and_versions.find(
                 static_cast<int>(previews::PreviewsType::DEFER_ALL_SCRIPT)),
@@ -94,7 +94,7 @@
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndEnableFeature(
       previews::features::kDeferAllScriptPreviews);
-  blacklist::BlacklistData::AllowedTypesAndVersions
+  blocklist::BlocklistData::AllowedTypesAndVersions
       allowed_types_and_versions2 = PreviewsService::GetAllowedPreviews();
   EXPECT_NE(allowed_types_and_versions2.find(
                 static_cast<int>(previews::PreviewsType::DEFER_ALL_SCRIPT)),
diff --git a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
index c174288..89ba688 100644
--- a/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
+++ b/chrome/browser/previews/resource_loading_hints/resource_loading_hints_browsertest.cc
@@ -134,10 +134,10 @@
 
     cmd->AppendSwitch("purge_hint_cache_store");
 
-    // Due to race conditions, it's possible that blacklist data is not loaded
+    // Due to race conditions, it's possible that blocklist data is not loaded
     // at the time of first navigation. That may prevent Preview from
     // triggering, and causing the test to flake.
-    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
+    cmd->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist);
   }
 
   // Creates hint data from the |component_info| and waits for it to be fully
diff --git a/chrome/browser/process_singleton_posix_unittest.cc b/chrome/browser/process_singleton_posix_unittest.cc
index 3a653ce4..74db167 100644
--- a/chrome/browser/process_singleton_posix_unittest.cc
+++ b/chrome/browser/process_singleton_posix_unittest.cc
@@ -74,7 +74,7 @@
                     base::WaitableEvent::InitialState::NOT_SIGNALED),
         signal_event_(base::WaitableEvent::ResetPolicy::MANUAL,
                       base::WaitableEvent::InitialState::NOT_SIGNALED),
-        process_singleton_on_thread_(NULL) {}
+        process_singleton_on_thread_(nullptr) {}
 
   void SetUp() override {
     testing::Test::SetUp();
diff --git a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
index 8ebf716..0e564ebf 100644
--- a/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
+++ b/chrome/browser/profile_resetter/profile_resetter_browsertest.cc
@@ -41,8 +41,9 @@
                  const std::string& value);
 
  private:
-  void GetCookieListCallback(const net::CookieStatusList& cookies,
-                             const net::CookieStatusList& excluded_cookies);
+  void GetCookieListCallback(
+      const net::CookieAccessResultList& cookies,
+      const net::CookieAccessResultList& excluded_cookies);
   void SetCanonicalCookieCallback(net::CookieInclusionStatus result);
 
   void BlockUntilNotified();
@@ -108,9 +109,9 @@
 }
 
 void RemoveCookieTester::GetCookieListCallback(
-    const net::CookieStatusList& cookies,
-    const net::CookieStatusList& excluded_cookies) {
-  last_cookies_ = net::cookie_util::StripStatuses(cookies);
+    const net::CookieAccessResultList& cookies,
+    const net::CookieAccessResultList& excluded_cookies) {
+  last_cookies_ = net::cookie_util::StripAccessResults(cookies);
   Notify();
 }
 
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index b35064b7..b359e44e 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/history/top_sites_factory.h"
 #include "chrome/browser/language/language_model_manager_factory.h"
 #include "chrome/browser/language/url_language_histogram_factory.h"
-#include "chrome/browser/media/feeds/media_feeds_service_factory.h"
 #include "chrome/browser/media/history/media_history_keyed_service_factory.h"
 #include "chrome/browser/media/media_engagement_service.h"
 #include "chrome/browser/media/media_engagement_service_factory.h"
@@ -108,6 +107,7 @@
 #else
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/feedback/feedback_uploader_factory_chrome.h"
+#include "chrome/browser/media/feeds/media_feeds_service_factory.h"
 #include "chrome/browser/metrics/desktop_session_duration/desktop_profile_session_durations_service_factory.h"
 #include "chrome/browser/resource_coordinator/local_site_characteristics_data_store_factory.h"
 #include "chrome/browser/search/instant_service_factory.h"
@@ -290,8 +290,8 @@
 #endif
   if (MediaEngagementService::IsEnabled())
     MediaEngagementServiceFactory::GetInstance();
-  media_feeds::MediaFeedsServiceFactory::GetInstance();
 #if !defined(OS_ANDROID)
+  media_feeds::MediaFeedsServiceFactory::GetInstance();
   MediaGalleriesPreferencesFactory::GetInstance();
 #endif
   if (base::FeatureList::IsEnabled(media::kUseMediaHistoryStore))
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h
index 642ce0c5..85b3d9aa 100644
--- a/chrome/browser/profiles/profile.h
+++ b/chrome/browser/profiles/profile.h
@@ -319,11 +319,6 @@
   // versa).
   virtual bool IsSameProfile(Profile* profile) = 0;
 
-  // Returns whether two profiles are the same and of the same type.
-  bool IsSameProfileAndType(Profile* profile) {
-    return profile == static_cast<Profile*>(this);
-  }
-
   // Returns the time the profile was started. This is not the time the profile
   // was created, rather it is the time the user started chrome and logged into
   // this profile. For the single profile case, this corresponds to the time
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index a47df10e..eddcff1 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -1347,9 +1347,6 @@
 }
 
 bool ProfileImpl::IsSameProfile(Profile* profile) {
-  if (IsSameProfileAndType(profile))
-    return true;
-
   return profile && profile->GetOriginalProfile() == this;
 }
 
diff --git a/chrome/browser/profiles/profile_manager.cc b/chrome/browser/profiles/profile_manager.cc
index 35936c3..c58139c 100644
--- a/chrome/browser/profiles/profile_manager.cc
+++ b/chrome/browser/profiles/profile_manager.cc
@@ -29,7 +29,7 @@
 #include "base/task/thread_pool.h"
 #include "base/threading/scoped_blocking_call.h"
 #include "base/trace_event/trace_event.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "build/build_config.h"
 #include "chrome/browser/accessibility/accessibility_labels_service.h"
 #include "chrome/browser/accessibility/accessibility_labels_service_factory.h"
@@ -259,7 +259,7 @@
   // on shutdown. In case of a crash remaining files are removed on next start.
   ListPrefUpdate deleted_profiles(g_browser_process->local_state(),
                                   prefs::kProfilesDeleted);
-  deleted_profiles->Append(CreateFilePathValue(path));
+  deleted_profiles->Append(util::FilePathToValue(path));
 }
 
 // Cancel a scheduling deletion, so ScheduleProfileDirectoryForDeletion can be
@@ -947,21 +947,18 @@
   DCHECK(deleted_profiles);
 
   for (const base::Value& value : *deleted_profiles) {
-    base::FilePath profile_path;
-    bool is_valid_profile_path =
-        base::GetValueAsFilePath(value, &profile_path) &&
-        IsAllowedProfilePath(profile_path);
+    base::Optional<base::FilePath> profile_path = util::ValueToFilePath(value);
     // Although it should never happen, make sure this is a valid path in the
-    // user_data_dir, so we don't accidentially delete something else.
-    if (is_valid_profile_path) {
-      if (base::PathExists(profile_path)) {
+    // user_data_dir, so we don't accidentally delete something else.
+    if (profile_path && IsAllowedProfilePath(*profile_path)) {
+      if (base::PathExists(*profile_path)) {
         LOG(WARNING) << "Files of a deleted profile still exist after restart. "
                         "Cleaning up now.";
         base::ThreadPool::PostTaskAndReply(
             FROM_HERE,
             {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
              base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-            base::BindOnce(&NukeProfileFromDisk, profile_path),
+            base::BindOnce(&NukeProfileFromDisk, *profile_path),
             base::BindOnce(&ProfileCleanedUp, &value));
       } else {
         // Everything is fine, the profile was removed on shutdown.
@@ -970,7 +967,7 @@
       }
     } else {
       LOG(ERROR) << "Found invalid profile path in deleted_profiles: "
-                 << profile_path.AsUTF8Unsafe();
+                 << profile_path->AsUTF8Unsafe();
       NOTREACHED();
     }
   }
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
index b1cc8208..5e4feb3f 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu_browsertest.cc
@@ -69,6 +69,7 @@
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/test_utils.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
@@ -936,22 +937,28 @@
               testing::Not(testing::Contains(IDC_CONTENT_CONTEXT_RELOADFRAME)));
 }
 
-#if defined(OS_MACOSX)
-// TODO(lukasza): https://crbug.com/1090891: Subframe behavior is unexpected on
-// some Mac bots.
-#define MAYBE_MenuContentsVerification_Subframe \
-  DISABLED_MenuContentsVerification_Subframe
-#else
-#define MAYBE_MenuContentsVerification_Subframe \
-  MenuContentsVerification_Subframe
-#endif
 // Check which commands are present after opening the context menu for a
 // subframe.
 IN_PROC_BROWSER_TEST_F(ContextMenuBrowserTest,
-                       MAYBE_MenuContentsVerification_Subframe) {
+                       MenuContentsVerification_Subframe) {
   ASSERT_TRUE(embedded_test_server()->Start());
   GURL url(embedded_test_server()->GetURL("/iframe.html"));
   ui_test_utils::NavigateToURL(browser(), url);
+  content::WebContents* tab =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Make sure the subframe doesn't contain any text, because the context menu
+  // may behave differently when opened over text selection.  See also
+  // https://crbug.com/1090891.
+  {
+    content::TestNavigationObserver nav_observer(tab, 1);
+    const char kScript[] = R"(
+        var frame = document.getElementsByTagName('iframe')[0];
+        frame.src = 'data:text/html;charset=utf-8,%3Cbody%3E%3C%2Fbody%3E';
+    )";
+    ASSERT_TRUE(content::ExecJs(tab, kScript));
+    nav_observer.Wait();
+  }
 
   // Open a context menu.
   ContextMenuWaiter menu_observer;
@@ -961,8 +968,6 @@
       blink::WebInputEvent::GetStaticTimeStampForTests());
   mouse_event.button = blink::WebMouseEvent::Button::kRight;
   mouse_event.SetPositionInWidget(25, 25);  // This is over the subframe.
-  content::WebContents* tab =
-      browser()->tab_strip_model()->GetActiveWebContents();
   tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
   mouse_event.SetType(blink::WebInputEvent::Type::kMouseUp);
   tab->GetRenderViewHost()->GetWidget()->ForwardMouseEvent(mouse_event);
diff --git a/chrome/browser/renderer_host/chrome_navigation_ui_data.h b/chrome/browser/renderer_host/chrome_navigation_ui_data.h
index 3a21d237..d011f81 100644
--- a/chrome/browser/renderer_host/chrome_navigation_ui_data.h
+++ b/chrome/browser/renderer_host/chrome_navigation_ui_data.h
@@ -10,7 +10,7 @@
 #include "base/macros.h"
 #include "components/offline_pages/buildflags/buildflags.h"
 #include "components/offline_pages/core/request_header/offline_page_navigation_ui_data.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/browser/navigation_ui_data.h"
 #include "extensions/browser/extension_navigation_ui_data.h"
 #include "extensions/buildflags/buildflags.h"
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index fdf73de0..d6942f66 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -289,7 +289,10 @@
       enable_input_discovery_for_gn_analyze = false
       source = "settings/os_settings_resources_vulcanized.grd"
 
-      deps += [ "//chrome/browser/resources/settings/chromeos:build" ]
+      deps += [
+        "//chrome/browser/resources/settings/chromeos:build",
+        "//chrome/browser/resources/settings/chromeos:build_polymer3",
+      ]
     } else {
       source = "settings/os_settings_resources.grd"
       deps += [
diff --git a/chrome/browser/resources/chromeos/BUILD.gn b/chrome/browser/resources/chromeos/BUILD.gn
index 32e0561ad..e7537c8 100644
--- a/chrome/browser/resources/chromeos/BUILD.gn
+++ b/chrome/browser/resources/chromeos/BUILD.gn
@@ -54,6 +54,29 @@
   ]
 }
 
+grit("camera_resources") {
+  source = "camera/camera_resources.grd"
+
+  defines = chrome_grit_defines
+  outputs = [
+    "grit/camera_resources.h",
+    "grit/camera_resources_map.cc",
+    "grit/camera_resources_map.h",
+    "camera_resources.pak",
+  ]
+  output_dir = "$root_gen_dir/chrome"
+
+  deps = [
+    "//components/arc/mojom:camera_intent_js",
+    "//media/capture/video/chromeos/mojom:cros_camera_js",
+  ]
+
+  grit_flags = [
+    "-E",
+    "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
+  ]
+}
+
 group("closure_compile") {
   deps = [
     "accessibility/braille_ime:closure_compile",
@@ -61,6 +84,7 @@
     "accessibility/switch_access:closure_compile",
     "add_supervision:closure_compile",
     "bluetooth_pairing_dialog:closure_compile",
+    "camera/src/js:closure_compile",
     "crostini_installer:closure_compile",
     "edu_login:closure_compile",
     "emulator:closure_compile",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
index 1c1a77e..4b6d1057 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -10,6 +10,9 @@
 import("//testing/test.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 
+# Prevent Chromium source assignment filters from being inherited.
+set_sources_assignment_filter([])
+
 declare_args() {
   # Whether to compress the main Chromevox javascript files or load the
   # modules individually from source files.
@@ -136,12 +139,17 @@
 closure_library_modules =
     rebase_path(relative_closure_library_modules, ".", closure_library_dir)
 
+chromevox_gen_dir =
+    "$root_gen_dir/chrome/browser/resources/chromeos/accessibility/chromevox"
+
 chromevox_out_dir = "$root_out_dir/resources/chromeos/accessibility/chromevox"
 
 group("build") {
   deps = [
     ":chromevox_copied_files",
     ":chromevox_phonetic_dictionaries_js",
+    ":lesson_component",
+    ":tutorial_component",
     "//chrome/browser/resources/chromeos/accessibility/braille_ime:braille_ime_manifest",
     "//third_party/chromevox:chromevox_third_party_resources",
     "//third_party/liblouis",
@@ -183,6 +191,11 @@
     "background/keymaps/default_keymap.json",
     "background/logging/log.css",
     "background/logging/log.html",
+    "i_tutorial/components/i_tutorial.js",
+    "i_tutorial/components/tutorial_lesson.js",
+    "i_tutorial/lessons/basic_navigation.html",
+    "i_tutorial/lessons/jump_commands.html",
+    "i_tutorial/lessons/text_fields.html",
     "images/chromevox-128.png",
     "images/chromevox-16.png",
     "images/chromevox-19.png",
@@ -444,3 +457,22 @@
     defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
   }
 }
+
+copy("lesson_component") {
+  sources = [ "$chromevox_gen_dir/i_tutorial/components/tutorial_lesson.js" ]
+  outputs = [ "$chromevox_out_dir/i_tutorial/tutorial_lesson.js" ]
+  deps = [
+    "i_tutorial/components:closure_compile",
+    "i_tutorial/components:components",
+  ]
+}
+
+copy("tutorial_component") {
+  sources = [ "$chromevox_gen_dir/i_tutorial/components/i_tutorial.js" ]
+  outputs = [ "$chromevox_out_dir/i_tutorial/i_tutorial.js" ]
+
+  deps = [
+    "i_tutorial/components:closure_compile",
+    "i_tutorial/components:components",
+  ]
+}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel_command.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel_command.js
index c8bc1a85..651f192 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel_command.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/panel_command.js
@@ -25,15 +25,42 @@
   }
 
   /**
-   * Send this command to the ChromeVox Panel window.
+   * @return {Window}
    */
-  send() {
+  getPanelWindow() {
     const views = chrome.extension.getViews();
     for (let i = 0; i < views.length; i++) {
       if (views[i].location.href.indexOf('panel/panel.html') > 0) {
-        views[i].postMessage(JSON.stringify(this), window.location.origin);
+        return views[i];
       }
     }
+    throw new Error('Could not find the panel window');
+  }
+
+  waitForPanel() {
+    return new Promise(resolve => {
+      const panelWindow = this.getPanelWindow();
+      if (panelWindow.document.readyState === 'complete') {
+        // The panel may already have loaded. In this case, resolve() and
+        // do not wait for a load event that has already fired.
+        resolve();
+      }
+      panelWindow.addEventListener('load', () => {
+        resolve();
+      });
+    });
+  }
+
+  /**
+   * Send this command to the ChromeVox Panel window.
+   * @return {!Promise}
+   */
+  async send() {
+    // Do not send commands to the ChromeVox Panel window until it has finished
+    // loading and is ready to receive commands.
+    await this.waitForPanel();
+    const panelWindow = this.getPanelWindow();
+    panelWindow.postMessage(JSON.stringify(this), window.location.origin);
   }
 };
 
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/BUILD.gn
new file mode 100644
index 0000000..679a3871
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/BUILD.gn
@@ -0,0 +1,33 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/closure_compiler/compile_js.gni")
+import("//tools/polymer/html_to_js.gni")
+
+html_to_js("components") {
+  js_files = [
+    "tutorial_lesson.js",
+    "i_tutorial.js",
+  ]
+}
+
+js_type_check("closure_compile") {
+  is_polymer3 = true
+  deps = [
+    ":i_tutorial",
+    ":tutorial_lesson",
+  ]
+}
+
+js_library("tutorial_lesson") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
+
+js_library("i_tutorial") {
+  deps = [
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+  ]
+}
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.html b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.html
new file mode 100644
index 0000000..447e7220
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.html
@@ -0,0 +1,111 @@
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<style>
+	
+#tutorialContainer {
+	background: linear-gradient(to bottom,rgba(255, 255, 255, 1) 40%,
+    	rgba(215, 215, 215, 1) 100%);
+	bottom: 0;
+	left: 0;
+	position: fixed;
+	right: 0;
+	top: 0;
+}
+
+#routingPageContainer {
+	margin: auto;
+	text-align: center;
+	width: 50%;
+}
+
+#mainMenuContainer {
+	margin: auto;
+	text-align: center;
+	width: 50%;
+}
+
+#lessonContainer {
+	margin: auto;
+	text-align: center;
+	width: 50%;
+}
+
+#navigationContainer {
+	margin: auto;
+	text-align: center;
+	width: 50%;
+}
+
+</style>
+
+<div id="tutorialContainer">
+
+<div id="routingPageContainer"
+		hidden$="[[ shouldHideRoutingContainer_(activeContainer) ]]">
+	<h1 id="welcomeRoutingPage" tabindex="-1">[[ routingPageWelcome ]]</h1>
+	<h2>[[ chooseYourExperience ]]</h2>
+	<cr-button id="newUserButton" on-click="chooseCurriculum_">
+		[[ newUser ]]
+	</cr-button>
+	<cr-button id="experiencedUserButton" on-click="chooseCurriculum_">
+		[[ experiencedUser ]]
+	</cr-button>
+	<cr-button id="developerButton" on-click="chooseCurriculum_">
+		[[ developer ]]
+	</cr-button>
+</div>
+
+<div id="mainMenuContainer"
+		hidden$="[[ shouldHideMainMenuContainer_(activeContainer) ]]">
+	<h1 id="welcomeMainMenu"
+			tabindex="-1">[[ computeMainMenuHeader_(curriculum, medium) ]]</h1>
+	<div id="lessonShortcuts"></div>
+</div>
+
+<div id="lessonContainer"
+		hidden$="[[ shouldHideLessonContainer_(activeContainer) ]]">
+
+	<!-- Use lessonData object to create all lessons -->
+	<template is="dom-repeat" items="[[ lessonData ]]" as="lesson" 
+			index-as="index">
+		<tutorial-lesson
+		lesson-num="[[ index ]]"
+		title="[[ lesson.title ]]"
+		content="[[ lesson.content ]]"
+		medium="[[ lesson.medium ]]"
+		curriculums="[[ lesson.curriculums ]]"
+		test-area-title="[[ lesson.testAreaTitle ]]"
+		test-area-instructions="[[ lesson.testAreaInstructions ]]"
+		test-area-file="[[ lesson.testAreaFile ]]"
+		test-area-state="[[ lesson.testAreaState ]]"
+		hints="[[ lesson.hints ]]"
+		events="[[ lesson.events ]]"
+		active-lesson-num="[[ activeLessonNum ]]">
+		</tutorial-lesson>
+	</template>
+</div>
+
+<div id="navigationContainer">
+	<cr-button id="previousLesson" on-click="previousLesson_"
+		hidden$="[[
+		shouldHidePreviousLessonButton_(activeLessonIndex, activeContainer) ]]">
+		[[ previousLesson ]]
+	</cr-button>
+	<cr-button id="nextLesson" on-click="nextLesson_"
+		hidden$="[[
+		shouldHideNextLessonButton_(activeLessonIndex, activeContainer) ]]">
+		[[ nextLesson ]]
+	</cr-button>
+	<cr-button id="showRoutingPage" on-click="showRoutingContainer_"
+			hidden$="[[ !shouldHideRoutingContainer_(activeContainer) ]]">
+		[[ showRoutingPage ]]
+	</cr-button>
+	<cr-button id="showMainMenu" on-click="showMainMenuContainer_"
+			hidden$="[[ !shouldHideMainMenuContainer_(activeContainer) ]]">
+		[[ showMainMenu ]]
+	</cr-button>
+	<cr-button id="quit" on-click="quit_">[[ quitTutorial ]]</cr-button>
+</div>
+
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.js b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.js
new file mode 100644
index 0000000..cffdf74
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/i_tutorial.js
@@ -0,0 +1,430 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+import {TutorialLesson} from './tutorial_lesson.js';
+
+/** @enum {string} */
+const Curriculum = {
+  OOBE: 'oobe',
+  NEW_USER: 'new_user',
+  EXPERIENCED_USER: 'experienced_user',
+  DEVELOPER: 'developer'
+};
+
+/**
+ * The user’s interaction medium. Influences tutorial content.
+ * @enum {string}
+ */
+const InteractionMedium = {
+  KEYBOARD: 'keyboard',
+  TOUCH: 'touch',
+  BRAILLE: 'braille',
+};
+
+/**
+ * The various containers within the tutorial.
+ * @enum {string}
+ */
+const Container = {
+  ROUTING: 'routing',
+  MAIN_MENU: 'main_menu',
+  LESSON: 'lesson',
+  NAVIGATION: 'navigation',
+};
+
+Polymer({
+  is: 'i-tutorial',
+
+  _template: html`{__html_template__}`,
+
+  properties: {
+    curriculum: {type: String, observer: '_updateIncludedLessons'},
+
+    medium: {
+      type: String,
+      value: InteractionMedium.KEYBOARD,
+      observer: '_updateIncludedLessons'
+    },
+
+    // Bookkeeping variables.
+
+    // Not all lessons are included, some are filtered out based on the chosen
+    // medium and curriculum.
+    includedLessons: {type: Array},
+
+    // An index into |includedLessons|.
+    activeLessonIndex: {type: Number, value: -1},
+
+    activeLessonNum: {type: Number, value: -1},
+
+    numLessons: {type: Number, value: 0},
+
+    activeContainer: {type: String},
+
+    // Labels and text content.
+
+    routingPageWelcome:
+        {type: String, value: 'Welcome to the ChromeVox Tutorial'},
+
+    chooseYourExperience: {
+      type: String,
+      value: 'Choose your tutorial experience',
+    },
+
+    newUser: {type: String, value: 'New user'},
+
+    experiencedUser: {type: String, value: 'Experienced user'},
+
+    developer: {type: String, value: 'Developer'},
+
+    continue: {type: String, value: 'Continue where I left off'},
+
+    previousLesson: {type: String, value: 'Previous lesson'},
+
+    nextLesson: {type: String, value: 'Next lesson'},
+
+    showRoutingPage: {type: String, value: 'Show routing page'},
+
+    showMainMenu: {type: String, value: 'Show main menu'},
+
+    quitTutorial: {type: String, value: 'Quit tutorial'},
+
+    lessonData: {
+      type: Array,
+      value: [
+        {
+          'title': 'On, Off, and Stop',
+          'content': [
+            'To temporarily stop ChromeVox from speaking, press the Control ' +
+                'key.',
+            'To turn ChromeVox on or off, use Control+Alt+Z.',
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.OOBE, Curriculum.NEW_USER],
+        },
+
+        {
+          'title': 'The ChromeVox Modifier Key',
+          'content': [
+            'In ChromeVox, the Search key is the modifier key. ' +
+                'Most ChromeVox shortcuts start with the Search key. ' +
+                'You’ll also use the arrow keys for navigation.',
+            'On the Chromebook, the Search key is immediately above the ' +
+                'left Shift key.',
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.OOBE, Curriculum.NEW_USER],
+        },
+
+        {
+          'title': 'Basic Navigation',
+          'content': [
+            'To move forward between items on a page, press Search + Right ' +
+                'Arrow, or Search + Left Arrow to jump back.',
+            'To go to the next line, press Search + Down Arrow. ' +
+                'To get to the previous line, use Search + Up Arrow.',
+            'If you reach an item you want to click, press Search + Space.',
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.OOBE, Curriculum.NEW_USER],
+          'testAreaTitle': 'Basic Navigation Test Area',
+          'testAreaInstructions':
+              'Try using basic navigation to navigate through the items ' +
+              'below. Find the button titled "Click me" and use Search ' +
+              '+ Space to click it. Then move to the next lesson.',
+          'testAreaFile': 'basic_navigation',
+          'testAreaState': {
+            'goal': {'click': false},
+          },
+          'events': ['click'],
+          'hints': [
+            'Try pressing Search + left/right arrow. The search key directly ' +
+                ' above the shift key',
+            'Use search + space to click an item'
+          ],
+        },
+
+        {
+          'title': 'Jump Commands',
+          'content': [
+            'Use jump commands to skip to specific types of elements.',
+            'To jump forward between headings, press Search + H, or to ' +
+                'jump backward, press Search + Shift + H.',
+            'To jump forward between buttons, press Search + B, or to ' +
+                'jump backward, press Search + Shift + B',
+            'To jump foorward beetween links, press Search + L, or to ' +
+                'jump backward, press Search + Shift + L'
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.NEW_USER],
+          'testAreaTitle': 'Jump Commands Test Area',
+          'testAreaInstructions':
+              'Try using what you have learned to navigate by element type. ' +
+              'Notice that navigation wraps if you are on the first or ' +
+              'last element and press previous element or next element, ' +
+              'respectively.',
+          'testAreaFile': 'jump_commands',
+          'testAreaState': {
+            'first-heading': {'focus': false},
+            'first-link': {'focus': false},
+            'first-button': {'focus': false},
+            'second-heading': {'focus': false},
+            'second-link': {'focus': false},
+            'second-button': {'focus': false},
+            'last-heading': {'focus': false},
+            'last-link': {'focus': false},
+            'last-button': {'focus': false},
+          },
+          'events': ['focus'],
+          'hints': [
+            'Try using search + h to move by header',
+            'Try using search + b to move by button',
+            'Try using search + l to move by link'
+          ],
+        },
+
+        {
+          'title': 'The ChromeVox Menu',
+          'content': [
+            'To explore all ChromeVox commands and shortcuts, press ' +
+                'Search + Period, then use the Arrow keys to navigate the ' +
+                'menus, and Enter to activate a command. Return here by ' +
+                'pressing Search+o then t.',
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.NEW_USER]
+        },
+
+        {
+          'title': 'Helpful Chrome Shortcuts',
+          'content': [
+            'The next few shortcuts aren’t ChromeVox commands, but they are ' +
+                'still very useful for getting the most out of Chrome.',
+            'To navigate forward through actionable items like buttons and ' +
+                'links, press the Tab key. To navigate backwards, press ' +
+                'Shift+Tab.',
+            'To enter the Chrome browser address box, also called the ' +
+                'omnibox, press Control + L.',
+            'To open and go to a new tab automatically, press Control+T. ' +
+                'Your cursor will be in the omnibox.',
+            ' To close a tab, press Control+W.',
+            'To move forward between open tabs, use Control+Tab.',
+            'To open the Chrome browser menu, press Alt+F.',
+            'To open the full list of keyboard shortcuts, press ' +
+                'Control + Alt + /'
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.NEW_USER]
+        },
+
+        {
+          'title': 'Sounds',
+          'content': [
+            'ChromeVox uses sounds to give you essential and additional ' +
+                'information. You can use these sounds to navigate more ' +
+                'quickly by learning what each sound means. Once you get ' +
+                'more comfortable, you can turn off verbose descriptions in ' +
+                'speech and rely on them for essential information about the ' +
+                'page. Here is a complete list of sounds and what they mean',
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.NEW_USER]
+        },
+
+        {
+          'title': 'Text fields',
+          'content': ['Text content for text fields lesson'],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [Curriculum.EXPERIENCED_USER],
+          'testAreaTitle': 'Edit fields Test Area',
+          'testAreaInstructions':
+              'Try using what you have learned about text fields and edit ' +
+              'the text fields below.',
+          'testAreaFile': 'text_fields',
+          'testAreaState': {
+            'input': {'focus': false, 'input': false},
+            'editable': {'focus': false, 'input': false}
+          },
+          'events': ['focus', 'input'],
+          'hints': [
+            'Once you find an editable element, you can type normally.',
+            'Try editing the content you entered'
+          ]
+        },
+
+        {
+          'title': 'Congratulations',
+          'content': [
+            'You’ve learned the essentials to use ChromeVox successfully.  ' +
+                'Remember that you can open the ChromeVox command menu at ' +
+                'any time by pressing Search+Period. To learn even more ' +
+                'about ChromeVox and Chrome OS, visit the following articles.',
+            'If you are done with the tutorial, use ChromeVox to navigate ' +
+                'to the Quit button and click it.'
+          ],
+          'medium': InteractionMedium.KEYBOARD,
+          'curriculums': [
+            Curriculum.OOBE, Curriculum.NEW_USER, Curriculum.DEVELOPER,
+            Curriculum.EXPERIENCED_USER
+          ],
+        }
+      ]
+    }
+  },
+
+  /** @override */
+  ready() {
+    this.showRoutingContainer_();
+  },
+
+  chooseCurriculum_(evt) {
+    const id = evt.target.id;
+    if (id === 'newUserButton') {
+      this.curriculum = Curriculum.NEW_USER;
+    } else if (id === 'experiencedUserButton') {
+      this.curriculum = Curriculum.EXPERIENCED_USER;
+    } else if (id === 'developerButton') {
+      this.curriculum = Curriculum.DEVELOPER;
+    } else {
+      throw new Error('Invalid target for chooseCurriculum_: ' + evt.target.id);
+    }
+    this.showMainMenuContainer_();
+  },
+
+  nextLesson_() {
+    this.showLesson_(this.activeLessonIndex + 1);
+  },
+
+  previousLesson_() {
+    this.showLesson_(this.activeLessonIndex - 1);
+  },
+
+  /**
+   * @param {number} index
+   */
+  showLesson_(index) {
+    this.showLessonContainer();
+    if (index < 0 || index >= this.numLessons) {
+      return;
+    }
+
+    this.activeLessonIndex = index;
+
+    // Lessons observe activeLessonNum. When updated, lessons automatically
+    // update their visibility.
+    this.activeLessonNum = this.includedLessons[index].lessonNum;
+  },
+
+
+  // Methods for hiding and showing containers.
+
+
+  showRoutingContainer_() {
+    this.activeContainer = Container.ROUTING;
+    this.$.welcomeRoutingPage.focus();
+  },
+
+  showMainMenuContainer_() {
+    this.activeContainer = Container.MAIN_MENU;
+    this.createLessonShortcuts();
+    this.$.welcomeMainMenu.focus();
+  },
+
+  showLessonContainer() {
+    this.activeContainer = Container.LESSON;
+  },
+
+  _updateIncludedLessons() {
+    this.includedLessons = [];
+    this.activeLessonNum = -1;
+    this.activeLessonIndex = -1;
+    this.numLessons = 0;
+    const lessons = this.$.lessonContainer.children;
+    for (let i = 0; i < lessons.length; ++i) {
+      const element = lessons[i];
+      if (element.is !== 'tutorial-lesson') {
+        continue;
+      }
+
+      const lesson = element;
+      if (lesson.shouldInclude(this.medium, this.curriculum)) {
+        this.includedLessons.push(lesson);
+      }
+    }
+    this.numLessons = this.includedLessons.length;
+    this.createLessonShortcuts();
+  },
+
+  createLessonShortcuts() {
+    // Clear previous lesson shortcuts, as the user may have chosen a new
+    // curriculum or medium for the tutorial.
+    this.$.lessonShortcuts.innerHTML = '';
+
+    // Create shortcuts for each included lesson.
+    let count = 1;
+    for (const lesson of this.includedLessons) {
+      const button = document.createElement('cr-button');
+      button.addEventListener('click', this.showLesson_.bind(this, count - 1));
+      button.textContent = count + ': ' + lesson.title;
+      this.$.lessonShortcuts.appendChild(button);
+      count += 1;
+    }
+  },
+
+
+  // Methods for computing attributes and properties.
+
+
+  shouldHideNextLessonButton_(activeLessonIndex, activeContainer) {
+    if (activeLessonIndex === this.numLessons - 1 ||
+        activeContainer !== Container.LESSON) {
+      return true;
+    }
+
+    return false;
+  },
+
+  shouldHidePreviousLessonButton_(activeLessonIndex, activeContainer) {
+    if (activeLessonIndex === 0 || activeContainer !== Container.LESSON) {
+      return true;
+    }
+
+    return false;
+  },
+
+  shouldHideRoutingContainer_(activeContainer) {
+    if (activeContainer === Container.ROUTING) {
+      return false;
+    }
+
+    return true;
+  },
+
+  shouldHideLessonContainer_(activeContainer) {
+    if (activeContainer === Container.LESSON) {
+      return false;
+    }
+
+    return true;
+  },
+
+  shouldHideMainMenuContainer_(activeContainer) {
+    if (activeContainer === Container.MAIN_MENU) {
+      return false;
+    }
+
+    return true;
+  },
+
+  computeMainMenuHeader_(curriculum, medium) {
+    return 'Lessons for the ' + curriculum + ' ' + medium + ' experience';
+  },
+
+  quit_() {
+    this.dispatchEvent(new CustomEvent('tutorial-close', {}));
+  },
+});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.html b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.html
new file mode 100644
index 0000000..a0a4c39b
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.html
@@ -0,0 +1,39 @@
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<style>
+
+#lessonTitle {
+	font-family: 'Roboto', sans-serif;
+	font-size: 30pt;
+	font-weight: bold;
+}
+
+#lessonContent {
+	display: block;
+	font-family: 'Roboto', sans-serif;
+	font-size: 16pt;
+	line-height: 150%;
+}
+
+</style>
+
+<div id="lessonContainer" hidden>
+	<h1 id="lessonTitle" tabindex="-1">[[title]]</h1>
+	<div id="lessonContent">
+		<template is="dom-repeat" items="[[ content ]]" as="text">
+			<p>[[ text ]]</p>
+		</template>
+	</div>
+	<cr-dialog id="testAreaContainer" close-text="Exit test area" 
+			on-close="closeTestArea" show-close-button>
+		<div id="testAreaTitle" class="title" 
+			slot="title">[[testAreaTitle]]</div>
+		<div class="body" slot="body">
+			<p id="testAreaInstructions">[[testAreaInstructions]]</p>
+			<div id="testArea"></div>
+		</div>
+	</cr-dialog>
+	<cr-button id="showTestArea" on-click="showTestArea" 
+		hidden$="[[ shouldHideTestAreaButton_() ]]">Show test area</cr-button>
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.js b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.js
new file mode 100644
index 0000000..58f04265e
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/components/tutorial_lesson.js
@@ -0,0 +1,220 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
+
+import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+
+export const TutorialLesson = Polymer({
+  is: 'tutorial-lesson',
+
+  _template: html`{__html_template__}`,
+
+  properties: {
+    lessonNum: {type: Number},
+
+    title: {type: String},
+
+    content: {type: Array},
+
+    medium: {type: String},
+
+    curriculums: {type: Array},
+
+    testAreaTitle: {type: String},
+
+    testAreaInstructions: {type: String},
+
+    testAreaFile: {type: String},
+
+    testAreaState: {type: Object},
+
+    events: {type: Array},
+
+    hints: {type: Array},
+
+    hintCounter: {type: Number, value: 0},
+
+    hintIntervalId: {type: Number},
+
+    goalStateReached: {type: Boolean, value: false},
+
+    // Observed properties.
+
+    activeLessonNum: {type: Number, observer: '_setVisibility'},
+  },
+
+  /** @override */
+  ready() {
+    if (this.testAreaFile) {
+      this.populateTestArea_();
+      for (const evt of this.events) {
+        this.$.testArea.addEventListener(
+            evt, this.onTestAreaEvent.bind(this), true);
+      }
+    }
+  },
+
+  /**
+   * Updates this lessons visibility whenever the active lesson of the tutorial
+   * changes.
+   */
+  _setVisibility() {
+    if (this.lessonNum === this.activeLessonNum) {
+      this.show();
+    } else {
+      this.hide();
+    }
+  },
+
+  show() {
+    this.$.lessonContainer.hidden = false;
+    this.$.lessonTitle.focus();
+  },
+
+  hide() {
+    this.$.lessonContainer.hidden = true;
+  },
+
+
+  // Methods for managing the test area.
+
+
+  /**
+   * Asynchronously populates test area.
+   * @private
+   */
+  populateTestArea_() {
+    const path = '../i_tutorial/lessons/' + this.testAreaFile + '.html';
+    const xhr = new XMLHttpRequest();
+    xhr.open('GET', path, true);
+    xhr.onload = (evt) => {
+      if (xhr.readyState === 4 && xhr.status === 200) {
+        this.$.testArea.innerHTML = xhr.responseText;
+      } else {
+        console.error(xhr.statusText);
+      }
+    };
+    xhr.onerror = function(evt) {
+      console.error('Failed to open test area file: ' + path);
+      console.error(xhr.statusText);
+    };
+    xhr.send(null);
+  },
+
+  showTestArea() {
+    this.$.testAreaContainer.showModal();
+    this.startHints();
+  },
+
+  closeTestArea() {
+    this.stopHints();
+    this.$.showTestArea.focus();
+  },
+
+
+  // Methods for tracking the state of the test area.
+
+
+  /** @param {Event} event */
+  onTestAreaEvent(event) {
+    const elt = event.target.id;
+    const type = event.type;
+    // Maybe update goal state.
+    if (elt in this.testAreaState) {
+      if (type in this.testAreaState[elt]) {
+        this.testAreaState[elt][type] = true;
+      }
+    }
+
+    if (this.isGoalStateReached()) {
+      this.onGoalStateReached();
+    }
+  },
+
+  /** @return {boolean} */
+  isGoalStateReached() {
+    if (this.goalStateReached === true) {
+      return true;
+    }
+
+    for (const [elt, state] of Object.entries(this.testAreaState)) {
+      for (const [evt, performed] of Object.entries(state)) {
+        if (performed == false) {
+          return false;
+        }
+      }
+    }
+    return true;
+  },
+
+  onGoalStateReached() {
+    const previousState = this.goalStateReached;
+    this.goalStateReached = true;
+    if (previousState === false) {
+      // Only perform when crossing the threshold from not reached to reached.
+      this.stopHints();
+      this.requestSpeech(
+          'You have passed this tutorial lesson. Find and press the close ' +
+          'test area button to continue');
+    }
+  },
+
+
+  // Methods for managing hints.
+
+
+  startHints() {
+    this.hintCounter = 0;
+    this.hintIntervalId = setInterval(() => {
+      if (this.hintCounter >= this.hints.length) {
+        this.stopHints();
+        return;
+      }
+      this.requestSpeech(this.hints[this.hintCounter]);
+      this.hintCounter += 1;
+    }, 20000);
+  },
+
+  stopHints() {
+    if (this.hintIntervalId) {
+      clearInterval(this.hintIntervalId);
+    }
+  },
+
+
+  // Miscellaneous methods.
+
+  /**
+   * @param {string} medium
+   * @param {string} curriculum
+   * @return {boolean}
+   */
+  shouldInclude(medium, curriculum) {
+    if (this.medium === medium && this.curriculums.includes(curriculum)) {
+      return true;
+    }
+
+    return false;
+  },
+
+  /**
+   * Requests speech from the Panel.
+   * @param {string} text
+   */
+  requestSpeech(text) {
+    this.dispatchEvent(
+        new CustomEvent('request-speech', {composed: true, detail: {text}}));
+  },
+
+  /** @return {boolean} */
+  shouldHideTestAreaButton_() {
+    if (!this.testAreaFile) {
+      return true;
+    }
+
+    return false;
+  },
+});
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/basic_navigation.html b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/basic_navigation.html
new file mode 100644
index 0000000..9e6f12ed
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/basic_navigation.html
@@ -0,0 +1,12 @@
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<h1>This is a heading</h1>
+<button>This is a button</button>
+<p>You're almost there</p>
+<p>You're very close to the button</p>
+<button id="goal">Click me</button>
+<p>You're very close to the button</p>
+<p>You're almost there</p>
+<button>This is another button</button>
+<h1>This is another heading</h1>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/jump_commands.html b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/jump_commands.html
new file mode 100644
index 0000000..6ab5e69
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/jump_commands.html
@@ -0,0 +1,12 @@
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<h1 id="first-heading" tabindex="-1">This is the first heading</h1>
+<a id="first-link" href="#first-link">This is the first link</a>
+<button id="first-button">This is the first button</button>
+<h1 id="second-heading" tabindex="-1">This is the middle heading</h1>
+<button id="second-button">This is the second button</button>
+<a id="second-link" href="#second-link">This is the second link</a>
+<button id="last-button">This is the last button</button>
+<h1 id="last-heading" tabindex="-1">This is the last heading</h1>
+<a id="last-link"href="#last-link">This is the last link</a>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/text_fields.html b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/text_fields.html
new file mode 100644
index 0000000..a8454e4
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/i_tutorial/lessons/text_fields.html
@@ -0,0 +1,8 @@
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+<p>There is an input below</p>
+<input id="input" aria-lable="Edit me">
+<p>There is a rich multiline text fields below, which appears in Gmail.</p>
+<div id="editable" role="textbox" contenteditable="true" aria-label="Edit me">
+</div>
\ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html
index 61fdaea..a05884c 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html
@@ -12,9 +12,7 @@
 <script type="text/javascript" src="../closure/base.js"></script>
 <script type="text/javascript" src="../deps.js"></script>
 <script type="text/javascript" src="panel_loader.js"></script>
-<script type="text/javascript" src="../chromeVoxPanelScript.js">
-</script>
-
+<script type="text/javascript" src="../chromeVoxPanelScript.js"></script>
 </head>
 
 <body>
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
index a2fd57c..3093017a 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.js
@@ -149,10 +149,7 @@
     /** @type {Window} */
     Panel.ownerWindow = window;
 
-    /**
-     * @type {boolean}
-     * @private
-     */
+    /** @private {boolean} */
     Panel.menuSearchEnabled_ = true;
 
     chrome.commandLinePrivate.hasSwitch(
@@ -160,6 +157,14 @@
         (enabled) => {
           Panel.menuSearchEnabled_ = !enabled;
         });
+
+    /** @private {boolean} */
+    Panel.iTutorialEnabled_ = false;
+
+    chrome.commandLinePrivate.hasSwitch(
+        'enable-experimental-accessibility-chromevox-tutorial', (enabled) => {
+          Panel.iTutorialEnabled_ = enabled;
+        });
   }
 
   /**
@@ -279,9 +284,17 @@
         chrome.extension.getURL('chromevox/panel/panel.html') +
         Panel.ModeInfo[Panel.mode_].location;
 
-    $('main').hidden = (Panel.mode_ == Panel.Mode.FULLSCREEN_TUTORIAL);
+    $('main').hidden =
+        (Panel.mode_ == Panel.Mode.FULLSCREEN_TUTORIAL ||
+         Panel.mode_ == Panel.Mode.FULLSCREEN_I_TUTORIAL);
     $('menus_background').hidden = (Panel.mode_ != Panel.Mode.FULLSCREEN_MENUS);
     $('tutorial').hidden = (Panel.mode_ != Panel.Mode.FULLSCREEN_TUTORIAL);
+    // Interactive tutorial elements may not have been loaded yet.
+    const iTutorialContainer = $('i-tutorial-container');
+    if (iTutorialContainer) {
+      iTutorialContainer.hidden =
+          (Panel.mode_ != Panel.Mode.FULLSCREEN_I_TUTORIAL);
+    }
 
     Panel.updateFromPrefs();
 
@@ -1076,6 +1089,43 @@
   static onTutorial(opt_page) {
     // Change the url fragment to 'fullscreen', which signals the native
     // host code to make the window fullscreen, revealing the menus.
+    if (Panel.iTutorialEnabled_) {
+      if ($('i-tutorial') === null) {
+        // Load resources if this is the first time opening the tutorial.
+        const tutorialScript = document.createElement('script');
+        tutorialScript.src = '../i_tutorial/i_tutorial.js';
+        tutorialScript.setAttribute('type', 'module');
+        const lessonScript = document.createElement('script');
+        lessonScript.src = '../i_tutorial/tutorial_lesson.js';
+        lessonScript.setAttribute('type', 'module');
+        document.body.appendChild(tutorialScript);
+        document.body.appendChild(lessonScript);
+
+        // Create tutorial container and element.
+        const tutorialContainer = document.createElement('div');
+        tutorialContainer.setAttribute('id', 'i-tutorial-container');
+        tutorialContainer.hidden = true;
+        const tutorialElement = document.createElement('i-tutorial');
+        tutorialElement.setAttribute('id', 'i-tutorial');
+        tutorialContainer.appendChild(tutorialElement);
+        document.body.appendChild(tutorialContainer);
+
+        // Add listeners. These are custom events fired from custom components.
+        $('i-tutorial')
+            .addEventListener('tutorial-close', Panel.onCloseTutorial);
+        $('i-tutorial').addEventListener('request-speech', (evt) => {
+          const text = evt.detail.text;
+          const background = chrome.extension.getBackgroundPage();
+          const cvox = background['ChromeVox'];
+          cvox.tts.speak(
+              text, background.QueueMode.FLUSH, {'doNotInterrupt': true});
+        });
+      }
+
+      Panel.setMode(Panel.Mode.FULLSCREEN_I_TUTORIAL);
+      return;
+    }
+
     Panel.setMode(Panel.Mode.FULLSCREEN_TUTORIAL);
 
     switch (opt_page) {
@@ -1181,8 +1231,9 @@
   COLLAPSED: 'collapsed',
   FOCUSED: 'focused',
   FULLSCREEN_MENUS: 'menus',
+  FULLSCREEN_I_TUTORIAL: 'i_tutorial',
   FULLSCREEN_TUTORIAL: 'tutorial',
-  SEARCH: 'search'
+  SEARCH: 'search',
 };
 
 /**
@@ -1192,9 +1243,10 @@
   annotation: {title: 'panel_title', location: '#focus'},
   collapsed: {title: 'panel_title', location: '#'},
   focused: {title: 'panel_title', location: '#focus'},
+  i_tutorial: {title: 'panel_tutorial_title', location: '#fullscreen'},
   menus: {title: 'panel_menus_title', location: '#fullscreen'},
   tutorial: {title: 'panel_tutorial_title', location: '#fullscreen'},
-  search: {title: 'panel_title', location: '#focus'}
+  search: {title: 'panel_title', location: '#focus'},
 };
 
 Panel.ACTION_TO_MSG_ID = {
@@ -1212,7 +1264,6 @@
  */
 Panel.lastMenu_ = '';
 
-
 window.addEventListener('load', function() {
   Panel.init();
 
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js
index 73c205c..1b2326e 100644
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel_test.js
@@ -96,6 +96,13 @@
     assertEquals(menuItemTitle, menuItem.menuItemTitle);
   }
 
+  assertActiveSearchMenuItem(menuItemTitle) {
+    const searchMenu = this.getPanel().searchMenu;
+    const activeIndex = searchMenu.activeIndex_;
+    const activeItem = searchMenu.items_[activeIndex];
+    assertEquals(menuItemTitle, activeItem.menuItemTitle);
+  }
+
   get linksDoc() {
     return `
       <p>start</p>
@@ -145,26 +152,18 @@
 
 TEST_F('ChromeVoxPanelTest', 'SearchMenu', function() {
   const mockFeedback = this.createMockFeedback();
-  this.runWithLoadedTree(this.linksDoc, function(root) {
-    const openMenus = new PanelCommand(PanelCommandType.OPEN_MENUS);
-    mockFeedback.call(openMenus.send.bind(openMenus))
-        .expectSpeech(
-            'Search the menus', 'Search',
-            'Type to search the menus. Use the up and down arrows to cycle' +
-                ' through results. Use the left and right arrows to adjust' +
-                ' the text caret, and to move between menus.');
-    // Enter query into search box. ChromeVox should announce the first result.
-    mockFeedback.call(this.fireMockQuery('announce'))
-        .expectSpeech(/announce/i, 'Menu item', /1 of [0-9]+/);
-    // Using ArrowUp and ArrowDown should navigate through results.
-    mockFeedback.call(this.fireMockEvent('ArrowDown'))
-        .expectSpeech(/announce/i, 'Menu item', /2 of [0-9]+/);
-    mockFeedback.call(this.fireMockEvent('ArrowDown'))
-        .expectSpeech(/announce/i, 'Menu item', /3 of [0-9]+/);
-    mockFeedback.call(this.fireMockEvent('ArrowUp'))
-        .expectSpeech(/announce/i, 'Menu item', /2 of [0-9]+/);
-    mockFeedback.replay();
-  });
+  this.runWithLoadedTree(this.linksDoc, async function(root) {
+    new PanelCommand(PanelCommandType.OPEN_MENUS).send();
+    await this.waitForMenu('panel_search_menu');
+    this.fireMockQuery('jump')();
+    this.assertActiveSearchMenuItem('Jump To Details');
+    this.fireMockEvent('ArrowDown')();
+    this.assertActiveSearchMenuItem('Jump To The Bottom Of The Page');
+    this.fireMockEvent('ArrowDown')();
+    this.assertActiveSearchMenuItem('Jump To The Top Of The Page');
+    this.fireMockEvent('ArrowDown')();
+    this.assertActiveSearchMenuItem('Jump To Details');
+  }, {isAsync: true});
 });
 
 // TODO(crbug.com/1088438): flaky crashes.
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/tools/jscompilerwrapper.py b/chrome/browser/resources/chromeos/accessibility/chromevox/tools/jscompilerwrapper.py
index f404ebf..af098d31 100755
--- a/chrome/browser/resources/chromeos/accessibility/chromevox/tools/jscompilerwrapper.py
+++ b/chrome/browser/resources/chromeos/accessibility/chromevox/tools/jscompilerwrapper.py
@@ -68,7 +68,7 @@
   args.extend(['--compilation_level', 'SIMPLE_OPTIMIZATIONS'])
   args.extend(['--jscomp_error=%s' % error for error in _JSCOMP_ERRORS])
   args.extend(['--jscomp_off=%s' % off for off in _JSCOMP_OFF])
-  args.extend(['--language_in', 'ECMASCRIPT6'])
+  args.extend(['--language_in', 'ECMASCRIPT_NEXT'])
   args.extend(['--externs=%s' % extern for extern in externs])
   args.extend(['--js=%s' % js for js in js_files])
   args.extend(['--js_output_file', '/dev/null'])
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
index 7862beb..9881e57 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/BUILD.gn
@@ -65,11 +65,13 @@
     "metrics.js",
     "navigation_manager.js",
     "nodes/back_button_node.js",
+    "nodes/combo_box_node.js",
     "nodes/desktop_node.js",
     "nodes/editable_text_node.js",
     "nodes/group_node.js",
     "nodes/keyboard_node.js",
     "nodes/node_wrapper.js",
+    "nodes/slider_node.js",
     "nodes/switch_access_node.js",
     "nodes/system_menu_node.js",
     "nodes/tab_node.js",
@@ -134,6 +136,7 @@
     ":auto_scan_manager",
     ":back_button_node",
     ":background",
+    ":combo_box_node",
     ":commands",
     ":desktop_node",
     ":editable_text_node",
@@ -150,6 +153,7 @@
     ":node_wrapper",
     ":preferences",
     ":rect_helper",
+    ":slider_node",
     ":switch_access",
     ":switch_access_constants",
     ":switch_access_node",
@@ -157,6 +161,7 @@
     ":system_menu_node",
     ":tab_node",
     ":text_navigation_manager",
+    "../common:automation_predicate",
     "../common:closure_shim",
     "../common:constants",
     "../common:tree_walker",
@@ -185,6 +190,16 @@
   ]
 }
 
+js_library("combo_box_node") {
+  sources = [ "nodes/combo_box_node.js" ]
+  deps = [
+    ":event_helper",
+    ":node_wrapper",
+    ":switch_access_constants",
+  ]
+  externs_list = []
+}
+
 js_library("commands") {
   deps = [
     ":auto_scan_manager",
@@ -327,6 +342,7 @@
     ":switch_access_constants",
     ":switch_access_node",
     ":switch_access_predicate",
+    "../common:automation_predicate",
     "../common:constants",
     "../common:tree_walker",
   ]
@@ -345,6 +361,16 @@
   externs_list = [ "$externs_path/accessibility_private.js" ]
 }
 
+js_library("slider_node") {
+  sources = [ "nodes/slider_node.js" ]
+  deps = [
+    ":event_helper",
+    ":node_wrapper",
+    ":switch_access_constants",
+  ]
+  externs_list = [ "$externs_path/automation.js" ]
+}
+
 js_library("switch_access") {
   deps = [
     ":auto_scan_manager",
@@ -381,6 +407,7 @@
   deps = [
     ":switch_access_constants",
     ":switch_access_node",
+    "../common:automation_predicate",
   ]
   externs_list = [ "$externs_path/automation.js" ]
 }
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
index fbd2f34..2e96f8a 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/navigation_manager.js
@@ -109,7 +109,9 @@
    */
   static forceFocusedNode(node) {
     const navigator = NavigationManager.instance;
-    navigator.setNode_(node);
+    if (!navigator.node_.equals(node)) {
+      navigator.setNode_(node);
+    }
   }
 
   /**
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/combo_box_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/combo_box_node.js
new file mode 100644
index 0000000..f5ef97a
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/combo_box_node.js
@@ -0,0 +1,42 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * This class handles interactions with combo boxes.
+ * TODO(anastasi): Add a test for this class.
+ */
+class ComboBoxNode extends NodeWrapper {
+  /** @override */
+  get actions() {
+    return [SwitchAccessMenuAction.INCREMENT, SwitchAccessMenuAction.DECREMENT];
+  }
+
+  /** @override */
+  doDefaultAction() {
+    this.performAction(SwitchAccessMenuAction.INCREMENT);
+  }
+
+  /** @override */
+  onFocus() {
+    super.onFocus();
+    this.automationNode.focus();
+  }
+
+  /** @override */
+  performAction(action) {
+    // The box of options that typically pops up with combo boxes is not
+    // currently represented in the automation tree, so we work around that by
+    // selecting a value without opening the pop-up, using the up and down
+    // arrows.
+    switch (action) {
+      case SwitchAccessMenuAction.DECREMENT:
+        EventHelper.simulateKeyPress(EventHelper.KeyCode.UP_ARROW);
+        return SAConstants.ActionResponse.REMAIN_OPEN;
+      case SwitchAccessMenuAction.INCREMENT:
+        EventHelper.simulateKeyPress(EventHelper.KeyCode.DOWN_ARROW);
+        return SAConstants.ActionResponse.REMAIN_OPEN;
+    }
+    return SAConstants.ActionResponse.NO_ACTION_TAKEN;
+  }
+}
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
index dcd2aac0..70ea786f 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/node_wrapper.js
@@ -199,11 +199,16 @@
    * @return {!NodeWrapper}
    */
   static create(baseNode, parent) {
+    if (AutomationPredicate.comboBox(baseNode)) {
+      return new ComboBoxNode(baseNode, parent);
+    }
     if (SwitchAccessPredicate.isTextInput(baseNode)) {
       return new EditableTextNode(baseNode, parent);
     }
 
     switch (baseNode.role) {
+      case chrome.automation.RoleType.SLIDER:
+        return new SliderNode(baseNode, parent);
       case chrome.automation.RoleType.TAB:
         return TabNode.create(baseNode, parent);
       default:
@@ -335,9 +340,8 @@
       }
     }
 
-    // If the previously focused node no longer exists, focus the first node in
-    // the group.
-    NavigationManager.forceFocusedNode(this.children[0]);
+    // If we didn't find a match, fall back and reset.
+    NavigationManager.moveToValidNode();
   }
 
   // ================= Static methods =================
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/slider_node.js b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/slider_node.js
new file mode 100644
index 0000000..12e947c5
--- /dev/null
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/nodes/slider_node.js
@@ -0,0 +1,39 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/** This class handles interactions with sliders. */
+class SliderNode extends NodeWrapper {
+  /**
+   * @param {!AutomationNode} baseNode
+   * @param {?SARootNode} parent
+   */
+  constructor(baseNode, parent) {
+    super(baseNode, parent);
+    this.isCustomSlider_ = !!baseNode.htmlAttributes.role;
+  }
+
+  /** @override */
+  onFocus() {
+    super.onFocus();
+    this.automationNode.focus();
+  }
+
+  /** @override */
+  performAction(action) {
+    // Currently, custom sliders have no way to support increment/decrement via
+    // the automation API. We handle this case by simulating left/right arrow
+    // presses.
+    if (this.isCustomSlider_) {
+      if (action === SwitchAccessMenuAction.INCREMENT) {
+        EventHelper.simulateKeyPress(EventHelper.KeyCode.RIGHT_ARROW);
+        return SAConstants.ActionResponse.REMAIN_OPEN;
+      } else if (action === SwitchAccessMenuAction.DECREMENT) {
+        EventHelper.simulateKeyPress(EventHelper.KeyCode.LEFT_ARROW);
+        return SAConstants.ActionResponse.REMAIN_OPEN;
+      }
+    }
+
+    return super.performAction(action);
+  }
+}
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js
index 1619033..5938b70 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access/switch_access_predicate.js
@@ -68,7 +68,8 @@
       return true;
     }
 
-    if (SwitchAccessPredicate.isTextInput(node)) {
+    if (AutomationPredicate.comboBox(node) ||
+        SwitchAccessPredicate.isTextInput(node)) {
       return true;
     }
 
@@ -120,6 +121,9 @@
     if (node.state[StateType.INVISIBLE]) {
       return false;
     }
+    if (AutomationPredicate.comboBox(node)) {
+      return false;
+    }
 
     let interestingBranchesCount =
         SwitchAccessPredicate.isActionable(node) ? 1 : 0;
diff --git a/chrome/browser/resources/chromeos/accessibility/switch_access_manifest.json.jinja2 b/chrome/browser/resources/chromeos/accessibility/switch_access_manifest.json.jinja2
index 6dfe2037..5af0cb1 100644
--- a/chrome/browser/resources/chromeos/accessibility/switch_access_manifest.json.jinja2
+++ b/chrome/browser/resources/chromeos/accessibility/switch_access_manifest.json.jinja2
@@ -12,10 +12,10 @@
   "background": {
     "scripts": [
       "common/array_util.js",
-      "switch_access/auto_scan_manager.js",
       "common/closure_shim.js",
-      "switch_access/commands.js",
       "common/constants.js",
+      "switch_access/auto_scan_manager.js",
+      "switch_access/commands.js",
       "switch_access/event_helper.js",
       "switch_access/focus_ring_manager.js",
       "switch_access/history.js",
@@ -25,10 +25,12 @@
       "switch_access/nodes/switch_access_node.js",
       "switch_access/nodes/node_wrapper.js",
       "switch_access/nodes/back_button_node.js",
+      "switch_access/nodes/combo_box_node.js",
       "switch_access/nodes/desktop_node.js",
       "switch_access/nodes/editable_text_node.js",
       "switch_access/nodes/group_node.js",
       "switch_access/nodes/keyboard_node.js",
+      "switch_access/nodes/slider_node.js",
       "switch_access/nodes/system_menu_node.js",
       "switch_access/nodes/tab_node.js",
       "switch_access/preferences.js",
@@ -37,6 +39,7 @@
       "switch_access/switch_access_constants.js",
       "switch_access/switch_access_predicate.js",
       "switch_access/text_navigation_manager.js",
+      "common/automation_predicate.js",
       "common/tree_walker.js",
       "switch_access/background.js"
     ]
diff --git a/chromeos/components/camera_app_ui/resources/.clang-format b/chrome/browser/resources/chromeos/camera/.clang-format
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/.clang-format
rename to chrome/browser/resources/chromeos/camera/.clang-format
diff --git a/chromeos/components/camera_app_ui/resources/.eslintignore b/chrome/browser/resources/chromeos/camera/.eslintignore
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/.eslintignore
rename to chrome/browser/resources/chromeos/camera/.eslintignore
diff --git a/chromeos/components/camera_app_ui/resources/.eslintrc.js b/chrome/browser/resources/chromeos/camera/.eslintrc.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/.eslintrc.js
rename to chrome/browser/resources/chromeos/camera/.eslintrc.js
diff --git a/chromeos/components/camera_app_ui/resources/.style.yapf b/chrome/browser/resources/chromeos/camera/.style.yapf
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/.style.yapf
rename to chrome/browser/resources/chromeos/camera/.style.yapf
diff --git a/chromeos/components/camera_app_ui/resources/BUILD.gn b/chrome/browser/resources/chromeos/camera/BUILD.gn
similarity index 94%
rename from chromeos/components/camera_app_ui/resources/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/BUILD.gn
index 1c1d921..2931d06 100644
--- a/chromeos/components/camera_app_ui/resources/BUILD.gn
+++ b/chrome/browser/resources/chromeos/camera/BUILD.gn
@@ -13,7 +13,7 @@
   # rather than list only the folders to avoid potential building issue and ease
   # the difficulty to diagnose.
   deps = [
-    "src/strings:camera_strings",
+    "//chrome/browser/resources/chromeos/camera/src/strings:camera_strings",
   ]
 
   data_deps = [
@@ -222,8 +222,8 @@
 
 copy("chrome_camera_app_mojo_generated") {
   sources = [
-    "$root_gen_dir/chromeos/components/camera_app_ui/camera_app_helper.mojom-lite.js",
     "$root_gen_dir/components/arc/mojom/camera_intent.mojom-lite.js",
+    "$root_gen_dir/components/chromeos_camera/common/camera_app_helper.mojom-lite.js",
     "$root_gen_dir/media/capture/mojom/image_capture.mojom-lite.js",
     "$root_gen_dir/media/capture/video/chromeos/mojom/camera_app.mojom-lite.js",
     "$root_gen_dir/media/capture/video/chromeos/mojom/camera_common.mojom-lite.js",
@@ -237,10 +237,15 @@
   ]
 
   deps = [
-    "//chromeos/components/camera_app_ui:mojo_bindings_js",
+    "//components/arc/mojom:camera_intent_js",
+    "//components/arc/mojom:mojom_js",
+    "//components/chromeos_camera/common:camera_app_helper_js",
+    "//media/capture/mojom:image_capture_js",
     "//media/capture/video/chromeos/mojom:cros_camera_js",
     "//mojo/public/js:bindings_lite",
     "//third_party/blink/public/mojom:mojom_platform_js",
+    "//ui/gfx/geometry/mojom:mojom_js",
+    "//ui/gfx/range/mojom:mojom_js",
   ]
 
   outputs = [ "$chrome_camera_app_dir/js/mojo/{{source_file_part}}" ]
diff --git a/chrome/browser/resources/chromeos/camera/OWNERS b/chrome/browser/resources/chromeos/camera/OWNERS
new file mode 100644
index 0000000..a879800
--- /dev/null
+++ b/chrome/browser/resources/chromeos/camera/OWNERS
@@ -0,0 +1,6 @@
+henryhsu@chromium.org
+inker@chromium.org
+jcliang@chromium.org
+shik@chromium.org
+wtlee@chromium.org
+yuli@chromium.org
diff --git a/chromeos/components/camera_app_ui/resources/PRESUBMIT.cfg b/chrome/browser/resources/chromeos/camera/PRESUBMIT.cfg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/PRESUBMIT.cfg
rename to chrome/browser/resources/chromeos/camera/PRESUBMIT.cfg
diff --git a/chromeos/components/camera_app_ui/resources/README.md b/chrome/browser/resources/chromeos/camera/README.md
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/README.md
rename to chrome/browser/resources/chromeos/camera/README.md
diff --git a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd b/chrome/browser/resources/chromeos/camera/camera_resources.grd
similarity index 96%
rename from chromeos/components/camera_app_ui/resources/camera_app_resources.grd
rename to chrome/browser/resources/chromeos/camera/camera_resources.grd
index 486eebc..66dd27b0 100644
--- a/chromeos/components/camera_app_ui/resources/camera_app_resources.grd
+++ b/chrome/browser/resources/chromeos/camera/camera_resources.grd
@@ -1,14 +1,14 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <grit latest_public_release="0" current_release="1" output_all_resource_defines="false">
   <outputs>
-    <output filename="grit/chromeos_camera_app_resources.h" type="rc_header">
+    <output filename="grit/camera_resources.h" type="rc_header">
       <emit emit_type='prepend'></emit>
     </output>
-    <output filename="grit/chromeos_camera_app_resources_map.cc"
+    <output filename="grit/camera_resources_map.cc"
             type="resource_file_map_source" />
-    <output filename="grit/chromeos_camera_app_resources_map.h"
+    <output filename="grit/camera_resources_map.h"
             type="resource_map_header" />
-    <output filename="chromeos_camera_app_resources.pak" type="data_package" />
+    <output filename="camera_resources.pak" type="data_package" />
   </outputs>
   <release seq="1">
     <structures>
@@ -46,7 +46,6 @@
       <structure name="IDR_CAMERA_OPTIONS_JS" file="src/js/views/camera/options.js" type="chrome_html" />
       <structure name="IDR_CAMERA_PERF_JS" file="src/js/perf.js" type="chrome_html" />
       <structure name="IDR_CAMERA_PREVIEW_JS" file="src/js/views/camera/preview.js" type="chrome_html" />
-      <structure name="IDR_CAMERA_PWA_HTML" file="pwa.html" type="chrome_html" />
       <structure name="IDR_CAMERA_RECORDTIME_JS" file="src/js/views/camera/recordtime.js" type="chrome_html" />
       <structure name="IDR_CAMERA_RESULT_SAVER_JS" file="src/js/models/result_saver.js" type="chrome_html" />
       <structure name="IDR_CAMERA_REVIEW_RESULT_JS" file="src/js/views/camera/review_result.js" type="chrome_html" />
diff --git a/chromeos/components/camera_app_ui/resources/cca b/chrome/browser/resources/chromeos/camera/cca
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/cca
rename to chrome/browser/resources/chromeos/camera/cca
diff --git a/chromeos/components/camera_app_ui/resources/manifest.json b/chrome/browser/resources/chromeos/camera/manifest.json
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/manifest.json
rename to chrome/browser/resources/chromeos/camera/manifest.json
diff --git a/chromeos/components/camera_app_ui/resources/pylintrc b/chrome/browser/resources/chromeos/camera/pylintrc
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/pylintrc
rename to chrome/browser/resources/chromeos/camera/pylintrc
diff --git a/chromeos/components/camera_app_ui/resources/src/LICENSE b/chrome/browser/resources/chromeos/camera/src/LICENSE
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/LICENSE
rename to chrome/browser/resources/chromeos/camera/src/LICENSE
diff --git a/chromeos/components/camera_app_ui/resources/src/css/main.css b/chrome/browser/resources/chromeos/camera/src/css/main.css
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/css/main.css
rename to chrome/browser/resources/chromeos/camera/src/css/main.css
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_app_icons_128.png b/chrome/browser/resources/chromeos/camera/src/images/camera_app_icons_128.png
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_app_icons_128.png
rename to chrome/browser/resources/chromeos/camera/src/images/camera_app_icons_128.png
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_app_icons_192.png b/chrome/browser/resources/chromeos/camera/src/images/camera_app_icons_192.png
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_app_icons_192.png
rename to chrome/browser/resources/chromeos/camera/src/images/camera_app_icons_192.png
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_app_icons_48.png b/chrome/browser/resources/chromeos/camera/src/images/camera_app_icons_48.png
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_app_icons_48.png
rename to chrome/browser/resources/chromeos/camera/src/images/camera_app_icons_48.png
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_fps_30.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_fps_30.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_fps_30.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_fps_30.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_fps_60.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_fps_60.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_fps_60.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_fps_60.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_grid_off.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_grid_off.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_grid_off.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_grid_off.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_grid_on.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_grid_on.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_grid_on.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_grid_on.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_mic_off.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_mic_off.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_mic_off.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_mic_off.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_mic_on.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_mic_on.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_mic_on.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_mic_on.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_mirror_off.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_mirror_off.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_mirror_off.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_mirror_off.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_mirror_on.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_mirror_on.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_mirror_on.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_mirror_on.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_settings.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_settings.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_settings.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_settings.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_switch_device.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_switch_device.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_switch_device.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_switch_device.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_switch_photo.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_switch_photo.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_switch_photo.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_switch_photo.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_switch_video.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_switch_video.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_switch_video.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_switch_video.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_timer_off.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_timer_off.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_timer_off.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_timer_off.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_timer_on_10s.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_timer_on_10s.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_timer_on_10s.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_timer_on_10s.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_button_timer_on_3s.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_button_timer_on_3s.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_button_timer_on_3s.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_button_timer_on_3s.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_focus_aim.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_focus_aim.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_focus_aim.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_focus_aim.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_intent_play_video.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_intent_play_video.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_intent_play_video.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_intent_play_video.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_intent_result_cancel.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_intent_result_cancel.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_intent_result_cancel.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_intent_result_cancel.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_intent_result_confirm.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_intent_result_confirm.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_intent_result_confirm.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_intent_result_confirm.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_mode_photo.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_photo.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_mode_photo.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_mode_photo.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_mode_portrait.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_portrait.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_mode_portrait.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_mode_portrait.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_mode_square.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_square.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_mode_square.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_mode_square.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_mode_video.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_mode_video.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_mode_video.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_mode_video.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_start.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_start.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_start.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_start.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_start_active.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_start_active.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_start_active.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_start_active.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_start_hover.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_start_hover.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_start_hover.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_start_hover.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_stop.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_stop.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_stop.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_stop.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_stop_hover.svg b/chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_stop_hover.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/camera_shutter_photo_stop_hover.svg
rename to chrome/browser/resources/chromeos/camera/src/images/camera_shutter_photo_stop_hover.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/settings_button_back.svg b/chrome/browser/resources/chromeos/camera/src/images/settings_button_back.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/settings_button_back.svg
rename to chrome/browser/resources/chromeos/camera/src/images/settings_button_back.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/settings_button_expand.svg b/chrome/browser/resources/chromeos/camera/src/images/settings_button_expand.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/settings_button_expand.svg
rename to chrome/browser/resources/chromeos/camera/src/images/settings_button_expand.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/settings_feedback.svg b/chrome/browser/resources/chromeos/camera/src/images/settings_feedback.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/settings_feedback.svg
rename to chrome/browser/resources/chromeos/camera/src/images/settings_feedback.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/settings_grid_type.svg b/chrome/browser/resources/chromeos/camera/src/images/settings_grid_type.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/settings_grid_type.svg
rename to chrome/browser/resources/chromeos/camera/src/images/settings_grid_type.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/settings_help.svg b/chrome/browser/resources/chromeos/camera/src/images/settings_help.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/settings_help.svg
rename to chrome/browser/resources/chromeos/camera/src/images/settings_help.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/settings_resolution.svg b/chrome/browser/resources/chromeos/camera/src/images/settings_resolution.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/settings_resolution.svg
rename to chrome/browser/resources/chromeos/camera/src/images/settings_resolution.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/settings_timer_duration.svg b/chrome/browser/resources/chromeos/camera/src/images/settings_timer_duration.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/settings_timer_duration.svg
rename to chrome/browser/resources/chromeos/camera/src/images/settings_timer_duration.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/images/spinner.svg b/chrome/browser/resources/chromeos/camera/src/images/spinner.svg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/images/spinner.svg
rename to chrome/browser/resources/chromeos/camera/src/images/spinner.svg
diff --git a/chromeos/components/camera_app_ui/resources/src/js/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/js/background.js b/chrome/browser/resources/chromeos/camera/src/js/background.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/background.js
rename to chrome/browser/resources/chromeos/camera/src/js/background.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/background_ops.js b/chrome/browser/resources/chromeos/camera/src/js/background_ops.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/background_ops.js
rename to chrome/browser/resources/chromeos/camera/src/js/background_ops.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/browser_proxy/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/browser_proxy/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/browser_proxy/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/js/browser_proxy/browser_proxy.js b/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/browser_proxy.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/browser_proxy/browser_proxy.js
rename to chrome/browser/resources/chromeos/camera/src/js/browser_proxy/browser_proxy.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/browser_proxy/browser_proxy_interface.js b/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/browser_proxy_interface.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/browser_proxy/browser_proxy_interface.js
rename to chrome/browser/resources/chromeos/camera/src/js/browser_proxy/browser_proxy_interface.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/browser_proxy/webui_browser_proxy.js b/chrome/browser/resources/chromeos/camera/src/js/browser_proxy/webui_browser_proxy.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/browser_proxy/webui_browser_proxy.js
rename to chrome/browser/resources/chromeos/camera/src/js/browser_proxy/webui_browser_proxy.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/chrome_util.js b/chrome/browser/resources/chromeos/camera/src/js/chrome_util.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/chrome_util.js
rename to chrome/browser/resources/chromeos/camera/src/js/chrome_util.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/device/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/device/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/device/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/js/device/camera3_device_info.js b/chrome/browser/resources/chromeos/camera/src/js/device/camera3_device_info.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/device/camera3_device_info.js
rename to chrome/browser/resources/chromeos/camera/src/js/device/camera3_device_info.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/device/constraints_preferrer.js b/chrome/browser/resources/chromeos/camera/src/js/device/constraints_preferrer.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/device/constraints_preferrer.js
rename to chrome/browser/resources/chromeos/camera/src/js/device/constraints_preferrer.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/device/device_info_updater.js b/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/device/device_info_updater.js
rename to chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/device/error.js b/chrome/browser/resources/chromeos/camera/src/js/device/error.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/device/error.js
rename to chrome/browser/resources/chromeos/camera/src/js/device/error.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/error.js b/chrome/browser/resources/chromeos/camera/src/js/error.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/error.js
rename to chrome/browser/resources/chromeos/camera/src/js/error.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/externs/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/externs/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/externs/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/js/externs/chrome.js b/chrome/browser/resources/chromeos/camera/src/js/externs/chrome.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/externs/chrome.js
rename to chrome/browser/resources/chromeos/camera/src/js/externs/chrome.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/externs/universal_analytics_api.js b/chrome/browser/resources/chromeos/camera/src/js/externs/universal_analytics_api.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/externs/universal_analytics_api.js
rename to chrome/browser/resources/chromeos/camera/src/js/externs/universal_analytics_api.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/externs/w3c_api.js b/chrome/browser/resources/chromeos/camera/src/js/externs/w3c_api.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/externs/w3c_api.js
rename to chrome/browser/resources/chromeos/camera/src/js/externs/w3c_api.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/gallerybutton.js b/chrome/browser/resources/chromeos/camera/src/js/gallerybutton.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/gallerybutton.js
rename to chrome/browser/resources/chromeos/camera/src/js/gallerybutton.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/intent.js b/chrome/browser/resources/chromeos/camera/src/js/intent.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/intent.js
rename to chrome/browser/resources/chromeos/camera/src/js/intent.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/.clang-format b/chrome/browser/resources/chromeos/camera/src/js/lib/.clang-format
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/.clang-format
rename to chrome/browser/resources/chromeos/camera/src/js/lib/.clang-format
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/lib/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/README.md b/chrome/browser/resources/chromeos/camera/src/js/lib/README.md
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/README.md
rename to chrome/browser/resources/chromeos/camera/src/js/lib/README.md
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/analytics.js b/chrome/browser/resources/chromeos/camera/src/js/lib/analytics.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/analytics.js
rename to chrome/browser/resources/chromeos/camera/src/js/lib/analytics.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/build_ffmpeg.sh b/chrome/browser/resources/chromeos/camera/src/js/lib/build_ffmpeg.sh
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/build_ffmpeg.sh
rename to chrome/browser/resources/chromeos/camera/src/js/lib/build_ffmpeg.sh
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/comlink.js b/chrome/browser/resources/chromeos/camera/src/js/lib/comlink.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/comlink.js
rename to chrome/browser/resources/chromeos/camera/src/js/lib/comlink.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/ffmpeg.js b/chrome/browser/resources/chromeos/camera/src/js/lib/ffmpeg.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/ffmpeg.js
rename to chrome/browser/resources/chromeos/camera/src/js/lib/ffmpeg.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/ffmpeg.patch b/chrome/browser/resources/chromeos/camera/src/js/lib/ffmpeg.patch
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/ffmpeg.patch
rename to chrome/browser/resources/chromeos/camera/src/js/lib/ffmpeg.patch
diff --git a/chromeos/components/camera_app_ui/resources/src/js/lib/ffmpeg.wasm b/chrome/browser/resources/chromeos/camera/src/js/lib/ffmpeg.wasm
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/lib/ffmpeg.wasm
rename to chrome/browser/resources/chromeos/camera/src/js/lib/ffmpeg.wasm
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/js/main.js b/chrome/browser/resources/chromeos/camera/src/js/main.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/main.js
rename to chrome/browser/resources/chromeos/camera/src/js/main.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/metrics.js b/chrome/browser/resources/chromeos/camera/src/js/metrics.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/metrics.js
rename to chrome/browser/resources/chromeos/camera/src/js/metrics.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/async_writer.js b/chrome/browser/resources/chromeos/camera/src/js/models/async_writer.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/async_writer.js
rename to chrome/browser/resources/chromeos/camera/src/js/models/async_writer.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/filenamer.js b/chrome/browser/resources/chromeos/camera/src/js/models/filenamer.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/filenamer.js
rename to chrome/browser/resources/chromeos/camera/src/js/models/filenamer.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/filesystem.js b/chrome/browser/resources/chromeos/camera/src/js/models/filesystem.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/filesystem.js
rename to chrome/browser/resources/chromeos/camera/src/js/models/filesystem.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/mp4_video_processor.js b/chrome/browser/resources/chromeos/camera/src/js/models/mp4_video_processor.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/mp4_video_processor.js
rename to chrome/browser/resources/chromeos/camera/src/js/models/mp4_video_processor.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/nop_video_processor.js b/chrome/browser/resources/chromeos/camera/src/js/models/nop_video_processor.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/nop_video_processor.js
rename to chrome/browser/resources/chromeos/camera/src/js/models/nop_video_processor.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/result_saver.js b/chrome/browser/resources/chromeos/camera/src/js/models/result_saver.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/result_saver.js
rename to chrome/browser/resources/chromeos/camera/src/js/models/result_saver.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/models/video_saver.js b/chrome/browser/resources/chromeos/camera/src/js/models/video_saver.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/models/video_saver.js
rename to chrome/browser/resources/chromeos/camera/src/js/models/video_saver.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/mojo/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn
similarity index 91%
rename from chromeos/components/camera_app_ui/resources/src/js/mojo/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn
index 39e91ba7..b1bdcd32 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/mojo/BUILD.gn
+++ b/chrome/browser/resources/chromeos/camera/src/js/mojo/BUILD.gn
@@ -14,8 +14,8 @@
 
 js_library("chrome_helper") {
   deps = [
-    "//chromeos/components/camera_app_ui:mojo_bindings_js_library_for_compile",
     "//components/arc/mojom:camera_intent_js_library_for_compile",
+    "//components/chromeos_camera/common:camera_app_helper_js_library_for_compile",
     "//third_party/blink/public/mojom:mojom_platform_js_library_for_compile",
   ]
   externs_list = [ "$externs_path/pending.js" ]
diff --git a/chromeos/components/camera_app_ui/resources/src/js/mojo/chrome_helper.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/chrome_helper.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/mojo/chrome_helper.js
rename to chrome/browser/resources/chromeos/camera/src/js/mojo/chrome_helper.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/mojo/device_operator.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/device_operator.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/mojo/device_operator.js
rename to chrome/browser/resources/chromeos/camera/src/js/mojo/device_operator.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/mojo/image_capture.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/mojo/image_capture.js
rename to chrome/browser/resources/chromeos/camera/src/js/mojo/image_capture.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/nav.js b/chrome/browser/resources/chromeos/camera/src/js/nav.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/nav.js
rename to chrome/browser/resources/chromeos/camera/src/js/nav.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/perf.js b/chrome/browser/resources/chromeos/camera/src/js/perf.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/perf.js
rename to chrome/browser/resources/chromeos/camera/src/js/perf.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/sound.js b/chrome/browser/resources/chromeos/camera/src/js/sound.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/sound.js
rename to chrome/browser/resources/chromeos/camera/src/js/sound.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/state.js b/chrome/browser/resources/chromeos/camera/src/js/state.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/state.js
rename to chrome/browser/resources/chromeos/camera/src/js/state.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/toast.js b/chrome/browser/resources/chromeos/camera/src/js/toast.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/toast.js
rename to chrome/browser/resources/chromeos/camera/src/js/toast.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/tooltip.js b/chrome/browser/resources/chromeos/camera/src/js/tooltip.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/tooltip.js
rename to chrome/browser/resources/chromeos/camera/src/js/tooltip.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/type.js b/chrome/browser/resources/chromeos/camera/src/js/type.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/type.js
rename to chrome/browser/resources/chromeos/camera/src/js/type.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/util.js b/chrome/browser/resources/chromeos/camera/src/js/util.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/util.js
rename to chrome/browser/resources/chromeos/camera/src/js/util.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/views/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn
similarity index 94%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn
index d898340d..97fdd2d 100644
--- a/chromeos/components/camera_app_ui/resources/src/js/views/camera/BUILD.gn
+++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera/BUILD.gn
@@ -50,6 +50,7 @@
     "../..:type",
     "../..:util",
     "../../device:device_info_updater",
+    "//components/chromeos_camera/common:camera_app_helper_js_library_for_compile",
   ]
 }
 
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/layout.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/layout.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/layout.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/layout.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/modes.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/modes.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/modes.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/options.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/options.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/options.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/preview.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/preview.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/preview.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/preview.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/recordtime.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/recordtime.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/recordtime.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/recordtime.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/review_result.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/review_result.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/review_result.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/review_result.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera/timertick.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera/timertick.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera/timertick.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera/timertick.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/camera_intent.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera_intent.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/camera_intent.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/camera_intent.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/dialog.js b/chrome/browser/resources/chromeos/camera/src/js/views/dialog.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/dialog.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/dialog.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/settings.js b/chrome/browser/resources/chromeos/camera/src/js/views/settings.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/settings.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/settings.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/view.js b/chrome/browser/resources/chromeos/camera/src/js/views/view.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/view.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/view.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/views/warning.js b/chrome/browser/resources/chromeos/camera/src/js/views/warning.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/views/warning.js
rename to chrome/browser/resources/chromeos/camera/src/js/views/warning.js
diff --git a/chromeos/components/camera_app_ui/resources/src/js/waitable_event.js b/chrome/browser/resources/chromeos/camera/src/js/waitable_event.js
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/js/waitable_event.js
rename to chrome/browser/resources/chromeos/camera/src/js/waitable_event.js
diff --git a/chromeos/components/camera_app_ui/resources/src/manifest.json b/chrome/browser/resources/chromeos/camera/src/manifest.json
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/manifest.json
rename to chrome/browser/resources/chromeos/camera/src/manifest.json
diff --git a/chromeos/components/camera_app_ui/resources/src/sounds/record_end.ogg b/chrome/browser/resources/chromeos/camera/src/sounds/record_end.ogg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/sounds/record_end.ogg
rename to chrome/browser/resources/chromeos/camera/src/sounds/record_end.ogg
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/sounds/record_start.ogg b/chrome/browser/resources/chromeos/camera/src/sounds/record_start.ogg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/sounds/record_start.ogg
rename to chrome/browser/resources/chromeos/camera/src/sounds/record_start.ogg
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/sounds/shutter.ogg b/chrome/browser/resources/chromeos/camera/src/sounds/shutter.ogg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/sounds/shutter.ogg
rename to chrome/browser/resources/chromeos/camera/src/sounds/shutter.ogg
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/sounds/tick_final.ogg b/chrome/browser/resources/chromeos/camera/src/sounds/tick_final.ogg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/sounds/tick_final.ogg
rename to chrome/browser/resources/chromeos/camera/src/sounds/tick_final.ogg
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/sounds/tick_inc.ogg b/chrome/browser/resources/chromeos/camera/src/sounds/tick_inc.ogg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/sounds/tick_inc.ogg
rename to chrome/browser/resources/chromeos/camera/src/sounds/tick_inc.ogg
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/sounds/tick_start.ogg b/chrome/browser/resources/chromeos/camera/src/sounds/tick_start.ogg
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/sounds/tick_start.ogg
rename to chrome/browser/resources/chromeos/camera/src/sounds/tick_start.ogg
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/BUILD.gn
rename to chrome/browser/resources/chromeos/camera/src/strings/BUILD.gn
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings.grd b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings.grd
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_af.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_af.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_af.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_af.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_am.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_am.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_am.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_am.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ar.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ar.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ar.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ar.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_as.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_as.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_as.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_as.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_az.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_az.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_az.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_az.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_be.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_be.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_be.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_be.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_bg.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_bg.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_bg.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_bg.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_bn.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_bn.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_bn.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_bn.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_bs.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_bs.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_bs.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_bs.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ca.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ca.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ca.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ca.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_cs.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_cs.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_cs.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_cs.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_da.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_da.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_da.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_da.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_de.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_de.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_de.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_de.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_el.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_el.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_el.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_el.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_en-GB.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_en-GB.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_en-GB.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_en-GB.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_es-419.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_es-419.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_es-419.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_es-419.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_es.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_es.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_es.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_es.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_et.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_et.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_et.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_et.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_eu.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_eu.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_eu.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_eu.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fa.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fa.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fa.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fa.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fi.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fi.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fi.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fi.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fil.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fil.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fil.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fil.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fr-CA.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr-CA.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fr-CA.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr-CA.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fr.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_fr.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_fr.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_gl.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_gl.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_gl.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_gl.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_CAMERA_RESOLUTION_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_CAMERA_RESOLUTION_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_CAMERA_RESOLUTION_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_CAMERA_RESOLUTION_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_ERROR_MSG_EXPERT_MODE_NOT_SUPPORTED.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_ERROR_MSG_TAKE_PORTRAIT_PHOTO_FAILED.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_EXPERT_MODE_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_EXPERT_MODE_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_EXPERT_MODE_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_EXPERT_MODE_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_EXPERT_PREVIEW_METADATA.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_EXPERT_PREVIEW_METADATA.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_EXPERT_PREVIEW_METADATA.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_EXPERT_PREVIEW_METADATA.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_EXPERT_SAVE_METADATA.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_EXPERT_SAVE_METADATA.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_EXPERT_SAVE_METADATA.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_EXPERT_SAVE_METADATA.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_BACK_CAMERA.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_BACK_CAMERA.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_BACK_CAMERA.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_BACK_CAMERA.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_EXTERNAL_CAMERA.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_EXTERNAL_CAMERA.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_EXTERNAL_CAMERA.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_EXTERNAL_CAMERA.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_FRONT_CAMERA.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_FRONT_CAMERA.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_FRONT_CAMERA.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_FRONT_CAMERA.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_RECORD_VIDEO_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PHOTO_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_PORTRAIT_PHOTO_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_SWITCH_TAKE_SQUARE_PHOTO_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_LABEL_VIDEO_RESOLUTION.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_PHOTO_RESOLUTION_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_PHOTO_RESOLUTION_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_PHOTO_RESOLUTION_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_PHOTO_RESOLUTION_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_TOGGLE_60FPS_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_TOGGLE_60FPS_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_TOGGLE_60FPS_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_TOGGLE_60FPS_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_VIDEO_RESOLUTION_BUTTON.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_VIDEO_RESOLUTION_BUTTON.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/IDS_VIDEO_RESOLUTION_BUTTON.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/IDS_VIDEO_RESOLUTION_BUTTON.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_30FPS.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_30FPS.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_30FPS.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_30FPS.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_60FPS.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_60FPS.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_60FPS.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_60FPS.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_DETAIL_PHOTO_RESOLUTION.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_DETAIL_PHOTO_RESOLUTION.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_DETAIL_PHOTO_RESOLUTION.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_DETAIL_PHOTO_RESOLUTION.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_PHOTO_RESOLUTION.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_PHOTO_RESOLUTION.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_PHOTO_RESOLUTION.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_PHOTO_RESOLUTION.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_VIDEO_RESOLUTION.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_VIDEO_RESOLUTION.png.sha1
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_grd/ID_LABEL_VIDEO_RESOLUTION.png.sha1
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_VIDEO_RESOLUTION.png.sha1
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_gu.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_gu.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_gu.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_gu.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hi.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hi.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hi.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hi.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hr.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hr.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hr.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hr.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hu.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hu.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hu.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hu.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hy.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hy.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_hy.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_hy.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_id.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_id.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_id.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_id.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_is.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_is.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_is.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_is.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_it.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_it.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_it.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_it.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_iw.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_iw.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_iw.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_iw.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ja.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ja.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ja.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ja.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ka.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ka.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ka.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ka.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_kk.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_kk.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_kk.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_kk.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_km.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_km.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_km.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_km.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_kn.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_kn.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_kn.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_kn.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ko.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ko.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ko.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ko.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ky.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ky.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ky.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ky.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_lo.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_lo.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_lo.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_lo.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_lt.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_lt.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_lt.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_lt.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_lv.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_lv.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_lv.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_lv.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_mk.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_mk.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_mk.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_mk.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ml.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ml.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ml.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ml.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_mn.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_mn.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_mn.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_mn.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_mr.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_mr.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_mr.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_mr.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ms.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ms.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ms.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ms.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_my.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_my.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_my.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_my.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ne.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ne.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ne.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ne.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_nl.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_nl.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_nl.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_nl.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_no.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_no.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_no.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_no.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_or.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_or.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_or.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_or.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pa.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pa.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pa.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pa.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pl.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pl.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pl.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pl.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pt-BR.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pt-BR.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pt-BR.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pt-BR.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pt-PT.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pt-PT.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_pt-PT.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_pt-PT.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ro.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ro.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ro.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ro.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ru.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ru.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ru.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ru.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_si.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_si.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_si.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_si.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sk.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sk.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sk.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sk.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sl.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sl.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sl.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sl.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sq.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sq.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sq.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sq.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sr-Latn.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sr-Latn.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sr-Latn.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sr-Latn.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sr.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sr.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sr.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sr.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sv.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sv.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sv.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sv.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sw.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sw.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_sw.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_sw.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ta.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ta.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ta.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ta.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_te.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_te.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_te.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_te.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_th.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_th.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_th.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_th.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_tr.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_tr.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_tr.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_tr.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_uk.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_uk.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_uk.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_uk.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ur.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ur.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_ur.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_ur.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_uz.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_uz.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_uz.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_uz.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_vi.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_vi.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_vi.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_vi.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zh-CN.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zh-CN.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zh-CN.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zh-CN.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zh-HK.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zh-HK.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zh-HK.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zh-HK.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zh-TW.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zh-TW.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zh-TW.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zh-TW.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zu.xtb b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zu.xtb
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/strings/camera_strings_zu.xtb
rename to chrome/browser/resources/chromeos/camera/src/strings/camera_strings_zu.xtb
diff --git a/chromeos/components/camera_app_ui/resources/src/views/background.html b/chrome/browser/resources/chromeos/camera/src/views/background.html
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/views/background.html
rename to chrome/browser/resources/chromeos/camera/src/views/background.html
diff --git a/chromeos/components/camera_app_ui/resources/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/src/views/main.html
rename to chrome/browser/resources/chromeos/camera/src/views/main.html
diff --git a/chromeos/components/camera_app_ui/resources/utils/cca.py b/chrome/browser/resources/chromeos/camera/utils/cca.py
similarity index 98%
rename from chromeos/components/camera_app_ui/resources/utils/cca.py
rename to chrome/browser/resources/chromeos/camera/utils/cca.py
index fa4d888..1dc305a 100755
--- a/chromeos/components/camera_app_ui/resources/utils/cca.py
+++ b/chrome/browser/resources/chromeos/camera/utils/cca.py
@@ -19,7 +19,7 @@
 
 @functools.lru_cache(1)
 def get_chromium_root():
-    path = os.path.realpath('../../../../')
+    path = os.path.realpath('../../../../../')
     assert os.path.basename(path) == 'src'
     return path
 
@@ -284,7 +284,7 @@
 
 def main(args):
     cca_root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-    assert os.path.basename(cca_root) == 'resources'
+    assert os.path.basename(cca_root) == 'camera'
     os.chdir(cca_root)
 
     args = parse_args(args)
diff --git a/chromeos/components/camera_app_ui/resources/utils/dev/images/camera_app_icons_128.png b/chrome/browser/resources/chromeos/camera/utils/dev/images/camera_app_icons_128.png
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/utils/dev/images/camera_app_icons_128.png
rename to chrome/browser/resources/chromeos/camera/utils/dev/images/camera_app_icons_128.png
Binary files differ
diff --git a/chromeos/components/camera_app_ui/resources/utils/dev/images/camera_app_icons_48.png b/chrome/browser/resources/chromeos/camera/utils/dev/images/camera_app_icons_48.png
similarity index 100%
rename from chromeos/components/camera_app_ui/resources/utils/dev/images/camera_app_icons_48.png
rename to chrome/browser/resources/chromeos/camera/utils/dev/images/camera_app_icons_48.png
Binary files differ
diff --git a/chrome/browser/resources/chromeos/crostini_installer/app.html b/chrome/browser/resources/chromeos/crostini_installer/app.html
index 475fb7f..0dfed207 100644
--- a/chrome/browser/resources/chromeos/crostini_installer/app.html
+++ b/chrome/browser/resources/chromeos/crostini_installer/app.html
@@ -88,6 +88,11 @@
     color: var(--cr-link-color);
     text-decoration: none;
   }
+
+  #low-free-space-warning {
+    --iron-icon-fill-color: var(--google-yellow-500);
+    display: flex;
+  }
 </style>
 
 <div id="main">
@@ -133,7 +138,7 @@
           </cr-radio-group>
         </template>
         <div id='low-free-space-warning' hidden="[[!isLowSpaceAvailable_]]">
-          <iron-icon icon="cr:warning"></iron-icon>
+          <iron-icon icon="cr:warning" class="warning"></iron-icon>
           $i18n{lowSpaceAvailableWarning}
         </div>
         <template is="dom-if" if="[[showDiskSlider_]]">
diff --git a/chrome/browser/resources/chromeos/keyboard/keyboard_utils.js b/chrome/browser/resources/chromeos/keyboard/keyboard_utils.js
index 08582d5c..fb28578 100644
--- a/chrome/browser/resources/chromeos/keyboard/keyboard_utils.js
+++ b/chrome/browser/resources/chromeos/keyboard/keyboard_utils.js
@@ -90,8 +90,12 @@
   // The networks list in the Chrome OOBE has an iron-list which uses arrow
   // keys to navigate elements. Tab events will remove focus from the list.
   //
+  // $ is defined differently depending on how this file gets executed; we have
+  // to use document.getElementById to get consistent behavior.
+  //
   // See crbug.com/1083145
-  if (document.activeElement === document.$('oobe-network-md') &&
+  // eslint-disable-next-line no-restricted-properties
+  if (document.activeElement === document.getElementById('oobe-network-md') &&
       document.activeElement.shadowRoot.activeElement.tagName ==
       'NETWORK-SELECT-LOGIN') {
     return;
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn
index 94ffb8137..9117dd7 100644
--- a/chrome/browser/resources/chromeos/login/BUILD.gn
+++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -238,6 +238,7 @@
 
 js_library("oobe_update") {
   deps = [
+    "components:login_screen_behavior",
     "components:oobe_dialog_host_behavior",
     "components:oobe_i18n_behavior",
   ]
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_dialog.js b/chrome/browser/resources/chromeos/login/components/oobe_dialog.js
index 0bc8dcc..62fc37c3 100644
--- a/chrome/browser/resources/chromeos/login/components/oobe_dialog.js
+++ b/chrome/browser/resources/chromeos/login/components/oobe_dialog.js
@@ -127,6 +127,20 @@
   },
 
   /**
+   * @private
+   * Focuses the element. As cr-input uses focusInput() instead of focus() due
+   * to bug, we have to handle this separately.
+   * TODO(crbug.com/882612): Replace this with focus() in show().
+   */
+  focusElement_(element) {
+    if (element.focusInput) {
+      element.focusInput();
+      return;
+    }
+    element.focus();
+  },
+
+  /**
    * This is called from oobe_welcome when this dialog is shown.
    */
   show() {
@@ -137,11 +151,11 @@
         continue;
 
       focused = true;
-      focusedElements[i].focus();
+      this.focusElement_(focusedElements[i]);
       break;
     }
     if (!focused && focusedElements.length > 0)
-      focusedElements[0].focus();
+      this.focusElement_(focusedElements[0]);
 
     this.fire('show-dialog');
     this.updateScroll();
diff --git a/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior.js b/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior.js
index be4dab5..37214e8 100644
--- a/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior.js
+++ b/chrome/browser/resources/chromeos/login/components/oobe_dialog_host_behavior.js
@@ -60,6 +60,18 @@
           .updateLocalizedContent();
     }
   },
+
+  addSubmitListener(element, id) {
+    element.addEventListener('keydown', (function(id, e) {
+                                          if (e.keyCode != 13)
+                                            return;
+                                          this.onFieldSubmit(id);
+                                        }).bind(this, id));
+  },
+
+  onFieldSubmit(id) {
+    console.error('Override this method in your element.');
+  },
 };
 
 /**
diff --git a/chrome/browser/resources/chromeos/login/cr_ui.js b/chrome/browser/resources/chromeos/login/cr_ui.js
index b91ebc1..32b987c 100644
--- a/chrome/browser/resources/chromeos/login/cr_ui.js
+++ b/chrome/browser/resources/chromeos/login/cr_ui.js
@@ -437,6 +437,9 @@
     return;
   document.removeEventListener('DOMContentLoaded', initializeOobe);
 
+  // TODO(crbug.com/1082670): Remove excessive logging after investigation.
+  console.warn('1082670 : initializing OOBE');
+
   try {
     Oobe.initialize();
   } finally {
@@ -456,6 +459,9 @@
     console.error(error.stack);
 };
 
+// TODO(crbug.com/1082670): Remove excessive logging after investigation.
+console.warn('1082670 : cr_ui loaded');
+
 /**
  * Final initialization performed after DOM and all scripts have loaded.
  */
diff --git a/chrome/browser/resources/chromeos/login/debug/debug.js b/chrome/browser/resources/chromeos/login/debug/debug.js
index 77583f5..e5e5896e 100644
--- a/chrome/browser/resources/chromeos/login/debug/debug.js
+++ b/chrome/browser/resources/chromeos/login/debug/debug.js
@@ -134,8 +134,22 @@
       suffix: 'demo',
     },
     {
-      id: 'update',
+      id: 'oobe-update',
       kind: ScreenKind.NORMAL,
+      states: [
+        {
+          // Checking for update
+          id: 'check-update',
+        },
+        {
+          // Ask for permission to update over celluar
+          id: 'require-permission-celluar',
+          trigger: (screen) => {
+            screen.onBeforeShow();
+            screen.setRequiresPermissionForCellular(true);
+          },
+        },
+      ]
     },
     {
       id: 'auto-enrollment-check',
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js
index de3961f..2e5e88c 100644
--- a/chrome/browser/resources/chromeos/login/oobe.js
+++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -43,7 +43,6 @@
 // <include src="oobe_screen_eula.js">
 // <include src="oobe_screen_network.js">
 // <include src="oobe_screen_oauth_enrollment.js">
-// <include src="oobe_screen_update.js">
 // <include src="multi_tap_detector.js">
 // <include src="web_view_helper.js">
 
@@ -58,7 +57,6 @@
       login.WrongHWIDScreen.register();
       login.NetworkScreen.register();
       login.EulaScreen.register();
-      login.UpdateScreen.register();
       login.AutoEnrollmentCheckScreen.register();
       login.EnableDebuggingScreen.register();
       login.AutolaunchScreen.register();
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_update.html b/chrome/browser/resources/chromeos/login/oobe_screen_update.html
deleted file mode 100644
index b4eeb3d1..0000000
--- a/chrome/browser/resources/chromeos/login/oobe_screen_update.html
+++ /dev/null
@@ -1,4 +0,0 @@
-<div class="step right hidden animated" id="update" role="group"
-     i18n-values="aria-label:updateScreenAccessibleTitle" hidden>
-  <oobe-update-md id="oobe-update-md"></oobe-update-md>
-</div>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_update.js b/chrome/browser/resources/chromeos/login/oobe_screen_update.js
deleted file mode 100644
index db3fea75..0000000
--- a/chrome/browser/resources/chromeos/login/oobe_screen_update.js
+++ /dev/null
@@ -1,101 +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.
-
-/**
- * @fileoverview Oobe update screen implementation.
- */
-
-login.createScreen('UpdateScreen', 'update', function() {
-  var USER_ACTION_CANCEL_UPDATE_SHORTCUT = 'cancel-update';
-
-  return {
-    EXTERNAL_API: [
-      'setEstimatedTimeLeft',
-      'showEstimatedTimeLeft',
-      'setUpdateCompleted',
-      'showUpdateCurtain',
-      'setProgressMessage',
-      'setUpdateProgress',
-      'setRequiresPermissionForCellular',
-      'setCancelUpdateShortcutEnabled',
-    ],
-
-    /** @param {boolean} enabled */
-    setCancelUpdateShortcutEnabled(enabled) {
-      $('oobe-update-md').cancelAllowed = enabled;
-    },
-
-    /**
-     * Returns default event target element.
-     * @type {Object}
-     */
-    get defaultControl() {
-      return $('oobe-update-md');
-    },
-
-    /**
-     * Cancels the screen.
-     */
-    cancel() {
-      $('oobe-update-md').cancelHint = 'cancelledUpdateMessage';
-      this.send(
-          login.Screen.CALLBACK_USER_ACTED, USER_ACTION_CANCEL_UPDATE_SHORTCUT);
-    },
-
-    /**
-     * Sets update's progress bar value.
-     * @param {number} progress Percentage of the progress bar.
-     */
-    setUpdateProgress(progress) {
-      $('oobe-update-md').progressValue = progress;
-    },
-
-    setRequiresPermissionForCellular(requiresPermission) {
-      $('oobe-update-md').requiresPermissionForCellular = requiresPermission;
-    },
-
-    /**
-     * Shows or hides downloading ETA message.
-     * @param {boolean} visible Are ETA message visible?
-     */
-    showEstimatedTimeLeft(visible) {
-      $('oobe-update-md').estimatedTimeLeftShown = visible;
-    },
-
-    /**
-     * Sets estimated time left until download will complete.
-     * @param {number} seconds Time left in seconds.
-     */
-    setEstimatedTimeLeft(seconds) {
-      $('oobe-update-md').estimatedTimeLeft = seconds;
-    },
-
-    /**
-     * Sets message below progress bar. Hide the message by setting an empty
-     * string.
-     * @param {string} message Message that should be shown.
-     */
-    setProgressMessage(message) {
-      var visible = !!message;
-      $('oobe-update-md').progressMessage = message;
-      $('oobe-update-md').estimatedTimeLeftShown = !visible;
-    },
-
-    /**
-     * Marks update completed. Shows "update completed" message.
-     * @param {boolean} is_completed True if update process is completed.
-     */
-    setUpdateCompleted(is_completed) {
-      $('oobe-update-md').updateCompleted = is_completed;
-    },
-
-    /**
-     * Shows or hides update curtain.
-     * @param {boolean} visible Are curtains visible?
-     */
-    showUpdateCurtain(visible) {
-      $('oobe-update-md').checkingForUpdate = visible;
-    },
-  };
-});
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.html b/chrome/browser/resources/chromeos/login/oobe_update.html
index 6417998..5763f79 100644
--- a/chrome/browser/resources/chromeos/login/oobe_update.html
+++ b/chrome/browser/resources/chromeos/login/oobe_update.html
@@ -6,12 +6,13 @@
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html">
 
-<dom-module id="oobe-update-md">
+<dom-module id="oobe-update">
   <template>
     <style include="oobe-dialog-host"></style>
     <link rel="stylesheet" href="oobe_update.css">
     <checking-downloading-update id="checking-downloading-update"
         full-screen-dialog
+        aria-label$="[[i18nDynamic(locale, 'updateScreenAccessibleTitle')]]"
         hidden="[[requiresPermissionForCellular]]"
         checking-for-update="[[checkingForUpdate]]"
         cancel-allowed="[[cancelAllowed]]"
diff --git a/chrome/browser/resources/chromeos/login/oobe_update.js b/chrome/browser/resources/chromeos/login/oobe_update.js
index 248db28..e597d3f9 100644
--- a/chrome/browser/resources/chromeos/login/oobe_update.js
+++ b/chrome/browser/resources/chromeos/login/oobe_update.js
@@ -6,10 +6,29 @@
  * @fileoverview Polymer element for displaying material design Update screen.
  */
 
-Polymer({
-  is: 'oobe-update-md',
+'use strict';
 
-  behaviors: [OobeI18nBehavior, OobeDialogHostBehavior],
+(function() {
+
+const USER_ACTION_ACCEPT_UPDATE_OVER_CELLUAR = 'update-accept-cellular';
+const USER_ACTION_REJECT_UPDATE_OVER_CELLUAR = 'update-reject-cellular';
+const USER_ACTION_CANCEL_UPDATE_SHORTCUT = 'cancel-update';
+
+Polymer({
+  is: 'oobe-update',
+
+  behaviors: [OobeI18nBehavior, OobeDialogHostBehavior, LoginScreenBehavior],
+
+  EXTERNAL_API: [
+    'setEstimatedTimeLeft',
+    'showEstimatedTimeLeft',
+    'setUpdateCompleted',
+    'showUpdateCurtain',
+    'setProgressMessage',
+    'setUpdateProgress',
+    'setRequiresPermissionForCellular',
+    'setCancelUpdateShortcutEnabled',
+  ],
 
   properties: {
     /**
@@ -85,16 +104,97 @@
     },
   },
 
+  ready() {
+    this.initializeLoginScreen('UpdateScreen', {
+      resetAllowed: true,
+    });
+  },
+
+  /**
+   * Cancels the screen.
+   */
+  cancel() {
+    this.cancelHint = 'cancelledUpdateMessage';
+    this.userActed(USER_ACTION_CANCEL_UPDATE_SHORTCUT);
+  },
+
   onBeforeShow() {
     cr.ui.login.invokePolymerMethod(
         this.$['checking-downloading-update'], 'onBeforeShow');
   },
 
   onBackClicked_() {
-    chrome.send('login.UpdateScreen.userActed', ['update-reject-cellular']);
+    this.userActed(USER_ACTION_REJECT_UPDATE_OVER_CELLUAR);
   },
 
   onNextClicked_() {
-    chrome.send('login.UpdateScreen.userActed', ['update-accept-cellular']);
+    this.userActed(USER_ACTION_ACCEPT_UPDATE_OVER_CELLUAR);
   },
+
+  /** @param {boolean} enabled */
+  setCancelUpdateShortcutEnabled(enabled) {
+    this.cancelAllowed = enabled;
+  },
+
+  /**
+   * Sets update's progress bar value.
+   * @param {number} progress Percentage of the progress bar.
+   */
+  setUpdateProgress(progress) {
+    this.progressValue = progress;
+  },
+
+  /**
+   * Shows or hides the warning that asks the user for permission to update
+   * over celluar.
+   * @param {boolean} requiresPermission Are the warning visible?
+   */
+  setRequiresPermissionForCellular(requiresPermission) {
+    this.requiresPermissionForCellular = requiresPermission;
+  },
+
+  /**
+   * Shows or hides downloading ETA message.
+   * @param {boolean} visible Are ETA message visible?
+   */
+  showEstimatedTimeLeft(visible) {
+    this.estimatedTimeLeftShown = visible;
+  },
+
+  /**
+   * Sets estimated time left until download will complete.
+   * @param {number} seconds Time left in seconds.
+   */
+  setEstimatedTimeLeft(seconds) {
+    this.estimatedTimeLeft = seconds;
+  },
+
+  /**
+   * Sets message below progress bar. Hide the message by setting an empty
+   * string.
+   * @param {string} message Message that should be shown.
+   */
+  setProgressMessage(message) {
+    let visible = !!message;
+    this.progressMessage = message;
+    this.estimatedTimeLeftShown = !visible;
+  },
+
+  /**
+   * Marks update completed. Shows "update completed" message.
+   * @param {boolean} is_completed True if update process is completed.
+   */
+  setUpdateCompleted(is_completed) {
+    this.updateCompleted = is_completed;
+  },
+
+  /**
+   * Shows or hides update curtain.
+   * @param {boolean} visible Are curtains visible?
+   */
+  showUpdateCurtain(visible) {
+    this.checkingForUpdate = visible;
+  },
+
 });
+})();
diff --git a/chrome/browser/resources/chromeos/login/structure/screens_oobe.html b/chrome/browser/resources/chromeos/login/structure/screens_oobe.html
index 4f51390..0315a90 100644
--- a/chrome/browser/resources/chromeos/login/structure/screens_oobe.html
+++ b/chrome/browser/resources/chromeos/login/structure/screens_oobe.html
@@ -14,7 +14,8 @@
 <include src="../oobe_screen_demo_setup.html">
 <include src="../oobe_screen_network.html">
 <include src="../oobe_screen_eula.html">
-<include src="../oobe_screen_update.html">
+<oobe-update id="oobe-update" class="step right hidden animated" hidden>
+</oobe-update>
 <include src="../oobe_screen_auto_enrollment_check.html">
 <include src="../oobe_screen_demo_preferences.html">
 <include src="../oobe_screen_oauth_enrollment.html">
diff --git a/chrome/browser/resources/component_extension_resources.grd b/chrome/browser/resources/component_extension_resources.grd
index cf1d5e9e..deeffbd 100644
--- a/chrome/browser/resources/component_extension_resources.grd
+++ b/chrome/browser/resources/component_extension_resources.grd
@@ -103,6 +103,7 @@
         <include name="IDR_PDF_MAIN_JS" file="pdf/main.js" type="BINDATA" preprocess="true" />
         <include name="IDR_PDF_MAIN_UTIL_JS" file="pdf/main_util.js" type="BINDATA" />
         <include name="IDR_PDF_PDF_VIEWER_JS" file="pdf/pdf_viewer.js" type="BINDATA" />
+        <include name="IDR_PDF_PDF_VIEWER_UTILS_JS" file="pdf/pdf_viewer_utils.js" type="BINDATA" />
         <include name="IDR_PDF_BOOKMARK_TYPE_JS" file="pdf/bookmark_type.js" type="BINDATA" />
         <include name="IDR_PDF_CONSTANTS_JS" file="pdf/constants.js" type="BINDATA" />
         <include name="IDR_PDF_CONTROLLER_JS" file="pdf/controller.js" type="BINDATA" />
diff --git a/chrome/browser/resources/extensions/detail_view.html b/chrome/browser/resources/extensions/detail_view.html
index 2e64721..04c47db 100644
--- a/chrome/browser/resources/extensions/detail_view.html
+++ b/chrome/browser/resources/extensions/detail_view.html
@@ -401,7 +401,7 @@
       </div>
     </div>
     <cr-link-row class="hr" id="remove-extension"
-        hidden="[[isControlled_(data.controlledInfo)]]"
+        hidden="[[data.mustRemainInstalled]]"
         label="$i18n{itemRemoveExtension}" on-click="onRemoveTap_">
     </cr-link-row>
   </div>
diff --git a/chrome/browser/resources/extensions/detail_view.js b/chrome/browser/resources/extensions/detail_view.js
index a45ebd87..fc461db1 100644
--- a/chrome/browser/resources/extensions/detail_view.js
+++ b/chrome/browser/resources/extensions/detail_view.js
@@ -31,7 +31,7 @@
 
 import {ItemDelegate} from './item.js';
 import {ItemBehavior} from './item_behavior.js';
-import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, userCanChangeEnablement} from './item_util.js';
+import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isEnabled, userCanChangeEnablement} from './item_util.js';
 import {navigation, Page} from './navigation_helper.js';
 
 Polymer({
@@ -132,14 +132,6 @@
    * @return {boolean}
    * @private
    */
-  isControlled_() {
-    return isControlled(this.data);
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
   isEnabled_() {
     return isEnabled(this.data.state);
   },
diff --git a/chrome/browser/resources/extensions/item.html b/chrome/browser/resources/extensions/item.html
index 712997e..fb2f6d20 100644
--- a/chrome/browser/resources/extensions/item.html
+++ b/chrome/browser/resources/extensions/item.html
@@ -279,7 +279,7 @@
       </cr-button>
       <cr-button id="remove-button" on-click="onRemoveTap_"
           aria-describedby="a11yAssociation"
-          hidden="[[isControlled_(data.controlledInfo)]]">
+          hidden="[[data.mustRemainInstalled]]">
         $i18n{remove}
       </cr-button>
       <template is="dom-if" if="[[shouldShowErrorsButton_(data.*)]]">
diff --git a/chrome/browser/resources/extensions/item.js b/chrome/browser/resources/extensions/item.js
index fb88800..51eb6417 100644
--- a/chrome/browser/resources/extensions/item.js
+++ b/chrome/browser/resources/extensions/item.js
@@ -27,7 +27,7 @@
 import {flush, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {ItemBehavior} from './item_behavior.js';
-import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isControlled, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js';
+import {computeInspectableViewLabel, EnableControl, getEnableControl, getItemSource, getItemSourceString, isEnabled, SourceType, userCanChangeEnablement} from './item_util.js';
 import {navigation, Page} from './navigation_helper.js';
 
 /** @interface */
@@ -276,14 +276,6 @@
    * @return {boolean}
    * @private
    */
-  isControlled_() {
-    return isControlled(this.data);
-  },
-
-  /**
-   * @return {boolean}
-   * @private
-   */
   isEnabled_() {
     return isEnabled(this.data.state);
   },
diff --git a/chrome/browser/resources/extensions/item_util.js b/chrome/browser/resources/extensions/item_util.js
index a1f91b5..83e727c 100644
--- a/chrome/browser/resources/extensions/item_util.js
+++ b/chrome/browser/resources/extensions/item_util.js
@@ -44,14 +44,6 @@
 }
 
 /**
- * @param {!chrome.developerPrivate.ExtensionInfo} extensionInfo
- * @return {boolean} Whether the extension is controlled.
- */
-export function isControlled(extensionInfo) {
-  return !!extensionInfo.controlledInfo;
-}
-
-/**
  * Returns true if the user can change whether or not the extension is
  * enabled.
  * @param {!chrome.developerPrivate.ExtensionInfo} item
diff --git a/chrome/browser/resources/interventions_internals/index.css b/chrome/browser/resources/interventions_internals/index.css
index 1af46cd..dec8560 100644
--- a/chrome/browser/resources/interventions_internals/index.css
+++ b/chrome/browser/resources/interventions_internals/index.css
@@ -26,7 +26,7 @@
 }
 
 .previews-flag-value {
-  margin-left: 10px;
+  margin-inline-start: 10px;
 }
 
 button {
@@ -138,7 +138,7 @@
 td {
   border: 0;
   padding: 10px;
-  text-align: left;
+  text-align: start;
   vertical-align: middle;
 }
 
@@ -205,14 +205,14 @@
   bottom: 100%;
   content: ' ';
   left: 50%;
-  margin-left: -5px;
+  margin-inline-start: -5px;
   position: absolute;
 }
 
 .expansion-row {
   background: transparent;
   border: 0;
-  margin-left: 20px;
+  margin-inline-start: 20px;
   padding: 0 0 0 15px;
   width: 80%;
 }
@@ -268,7 +268,7 @@
     width: 60%;
   }
 
-  #blacklisted-hosts-table {
+  #blocklisted-hosts-table {
     width: 60%;
   }
 
@@ -354,7 +354,7 @@
   font-style: italic;
 }
 
-#blacklist-ignored-status {
+#blocklist-ignored-status {
   color: red;
   font-style: italic;
   font-weight: bold;
diff --git a/chrome/browser/resources/interventions_internals/index.html b/chrome/browser/resources/interventions_internals/index.html
index 4f17156..dd5f3ad 100644
--- a/chrome/browser/resources/interventions_internals/index.html
+++ b/chrome/browser/resources/interventions_internals/index.html
@@ -26,8 +26,8 @@
         <span>Logs</span>
       </label>
       <label class="inactive-tab">
-        <input type="radio" id="blacklist-tab" name="tabs"
-            value="blacklist-status">
+        <input type="radio" id="blocklist-tab" name="tabs"
+            value="blocklist-status">
         <span>Blocklist Status</span>
       </label>
       <label class="inactive-tab">
@@ -74,26 +74,26 @@
       </table>
     </div>
 
-    <div class="tab-content" id="blacklist-status">
-      <div id="blacklist-ignored-status"></div>
-      <button id="ignore-blacklist-button" type="button">
+    <div class="tab-content" id="blocklist-status">
+      <div id="blocklist-ignored-status"></div>
+      <button id="ignore-blocklist-button" type="button">
         Ignore Blocklist
       </button>
-      <div id="user-blacklisted-status">
+      <div id="user-blocklisted-status">
         User blocklisted status:
-        <span id="user-blacklisted-status-value">N/A</span>
+        <span id="user-blocklisted-status-value">N/A</span>
       </div>
-      <div id="blacklist-cleared-status">
+      <div id="blocklist-cleared-status">
         Last blocklist cleared:
-        <span id="blacklist-last-cleared-time">N/A</span>
+        <span id="blocklist-last-cleared-time">N/A</span>
       </div>
 
-      <div id="blacklisted-hosts">
+      <div id="blocklisted-hosts">
         <div class="table-name">Blocklisted hosts</div>
-        <table id="blacklisted-hosts-table">
+        <table id="blocklisted-hosts-table">
           <tr>
-            <th id="blacklisted-host-header">Host</th>
-            <th id="blacklisted-time-header">Time</th>
+            <th id="blocklisted-host-header">Host</th>
+            <th id="blocklisted-time-header">Time</th>
           </tr>
         </table>
       </div>
diff --git a/chrome/browser/resources/interventions_internals/index.js b/chrome/browser/resources/interventions_internals/index.js
index 752d3913..d88edff 100644
--- a/chrome/browser/resources/interventions_internals/index.js
+++ b/chrome/browser/resources/interventions_internals/index.js
@@ -3,9 +3,9 @@
 // found in the LICENSE file.
 
 /** The columns that are used to find rows that contain the keyword. */
-const ENABLE_BLACKLIST_BUTTON = 'Enable Blacklist';
-const IGNORE_BLACKLIST_BUTTON = 'Ignore Blacklist';
-const IGNORE_BLACKLIST_MESSAGE = 'Blacklist decisions are ignored.';
+const ENABLE_BLOCKLIST_BUTTON = 'Enable Blocklist';
+const IGNORE_BLOCKLIST_BUTTON = 'Ignore Blocklist';
+const IGNORE_BLOCKLIST_MESSAGE = 'Blocklist decisions are ignored.';
 const URL_THRESHOLD = 40;  // Maximum URL length
 
 window.logTableMap = {};
@@ -469,59 +469,59 @@
   },
 
   /**
-   * Update new blacklisted host to the web page.
+   * Update new blocklisted host to the web page.
    *
    * @override
-   * @param {!string} host The blacklisted host.
-   * @param {number} time The time when the host was blacklisted in milliseconds
+   * @param {!string} host The blocklisted host.
+   * @param {number} time The time when the host was blocklisted in milliseconds
    * since Unix epoch.
    */
-  onBlacklistedHost(host, time) {
+  onBlocklistedHost(host, time) {
     const row = document.createElement('tr');
-    row.setAttribute('class', 'blacklisted-host-row');
+    row.setAttribute('class', 'blocklisted-host-row');
 
     const hostTd = document.createElement('td');
-    hostTd.setAttribute('class', 'host-blacklisted');
+    hostTd.setAttribute('class', 'host-blocklisted');
     hostTd.textContent = host;
     row.appendChild(hostTd);
 
     const timeTd = document.createElement('td');
-    timeTd.setAttribute('class', 'host-blacklisted-time');
+    timeTd.setAttribute('class', 'host-blocklisted-time');
     timeTd.textContent = getTimeFormat(time);
     row.appendChild(timeTd);
 
     // TODO(thanhdle): Insert row at correct index. crbug.com/776105.
-    $('blacklisted-hosts-table').appendChild(row);
+    $('blocklisted-hosts-table').appendChild(row);
   },
 
   /**
-   * Update to the page that the user blacklisted status has changed.
+   * Update to the page that the user blocklisted status has changed.
    *
    * @override
-   * @param {boolean} blacklisted The time of the event in milliseconds since
+   * @param {boolean} blocklisted The time of the event in milliseconds since
    * Unix epoch.
    */
-  onUserBlacklistedStatusChange(blacklisted) {
-    const userBlacklistedStatus = $('user-blacklisted-status-value');
-    userBlacklistedStatus.textContent =
-        (blacklisted ? 'Blacklisted' : 'Not blacklisted');
+  onUserBlocklistedStatusChange(blocklisted) {
+    const userBlocklistedStatus = $('user-blocklisted-status-value');
+    userBlocklistedStatus.textContent =
+        (blocklisted ? 'Blocklisted' : 'Not blocklisted');
   },
 
   /**
-   * Update the blacklist cleared status on the page.
+   * Update the blocklist cleared status on the page.
    *
    * @override
    * @param {number} time The time of the event in milliseconds since Unix
    * epoch.
    */
-  onBlacklistCleared(time) {
-    const blacklistClearedStatus = $('blacklist-last-cleared-time');
-    blacklistClearedStatus.textContent = getTimeFormat(time);
+  onBlocklistCleared(time) {
+    const blocklistClearedStatus = $('blocklist-last-cleared-time');
+    blocklistClearedStatus.textContent = getTimeFormat(time);
 
     // Remove hosts from table.
-    const blacklistedHostsTable = $('blacklisted-hosts-table');
-    for (let row = blacklistedHostsTable.rows.length - 1; row > 0; row--) {
-      blacklistedHostsTable.deleteRow(row);
+    const blocklistedHostsTable = $('blocklisted-hosts-table');
+    for (let row = blocklistedHostsTable.rows.length - 1; row > 0; row--) {
+      blocklistedHostsTable.deleteRow(row);
     }
 
     // Remove log message from logs table.
@@ -529,24 +529,24 @@
 
     // Log event message.
     insertMessageRowToMessageLogTable(
-        time, 'Blacklist', 'Blacklist Cleared', '' /* URL */, 0 /* pageId */);
+        time, 'Blocklist', 'Blocklist Cleared', '' /* URL */, 0 /* pageId */);
   },
 
   /**
-   * Update the page with the new value of ignored blacklist decision status.
+   * Update the page with the new value of ignored blocklist decision status.
    *
    * @override
-   * @param {boolean} ignored The new status of whether the previews blacklist
-   * decisions is blacklisted or not.
+   * @param {boolean} ignored The new status of whether the previews blocklist
+   * decisions is blocklisted or not.
    */
-  onIgnoreBlacklistDecisionStatusChanged(ignored) {
-    const ignoreButton = $('ignore-blacklist-button');
+  onIgnoreBlocklistDecisionStatusChanged(ignored) {
+    const ignoreButton = $('ignore-blocklist-button');
     ignoreButton.textContent =
-        ignored ? ENABLE_BLACKLIST_BUTTON : IGNORE_BLACKLIST_BUTTON;
+        ignored ? ENABLE_BLOCKLIST_BUTTON : IGNORE_BLOCKLIST_BUTTON;
 
-    // Update the status of blacklist ignored on the page.
-    $('blacklist-ignored-status').textContent =
-        ignored ? IGNORE_BLACKLIST_MESSAGE : '';
+    // Update the status of blocklist ignored on the page.
+    $('blocklist-ignored-status').textContent =
+        ignored ? IGNORE_BLOCKLIST_MESSAGE : '';
   },
 
   /**
@@ -601,12 +601,12 @@
     getPreviewsEnabled();
     getPreviewsFlagsDetails();
 
-    const ignoreButton = $('ignore-blacklist-button');
+    const ignoreButton = $('ignore-blocklist-button');
     ignoreButton.addEventListener('click', () => {
-      // Whether the blacklist is currently ignored.
-      const ignored = (ignoreButton.textContent == ENABLE_BLACKLIST_BUTTON);
+      // Whether the blocklist is currently ignored.
+      const ignored = (ignoreButton.textContent == ENABLE_BLOCKLIST_BUTTON);
       // Try to reverse the ignore status.
-      pageHandler.setIgnorePreviewsBlacklistDecision(!ignored);
+      pageHandler.setIgnorePreviewsBlocklistDecision(!ignored);
     });
   }
 
diff --git a/chrome/browser/resources/net_internals/domain_security_policy_view.html b/chrome/browser/resources/net_internals/domain_security_policy_view.html
index aaac84b..746c4c63 100644
--- a/chrome/browser/resources/net_internals/domain_security_policy_view.html
+++ b/chrome/browser/resources/net_internals/domain_security_policy_view.html
@@ -45,6 +45,13 @@
     Transparency information. See
     <a href="https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct" target=_blank>https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct</a>.</div>
 
+    <p>To protect against cross-site tracking, Expect-CT data will soon be keyed
+        on the site of the main frame and innermost frame when an Expect-CT
+        header is encountered. When that behavior is enabled, both adding and
+        querying an Expect-CT domain use the eTLD+1 of the provided domain as
+        the site for both frames. Deleting policies affects information stored
+        for that domain in the context of all sites, however.</p>
+
   <h4>Add Expect-CT domain</h4>
 
   <p>Input a domain name to add it to the Expect-CT set. Leave Enforce unchecked
diff --git a/chrome/browser/resources/new_tab_page/app.js b/chrome/browser/resources/new_tab_page/app.js
index ce15678..77501b0 100644
--- a/chrome/browser/resources/new_tab_page/app.js
+++ b/chrome/browser/resources/new_tab_page/app.js
@@ -231,6 +231,7 @@
         }
       }
     });
+    this.eventTracker_.add(window, 'keydown', e => this.onWindowKeydown_(e));
     if (this.shouldPrintPerformance_) {
       // It is possible that the background image has already loaded by now.
       // If it has, we request it to re-send the load time so that we can
@@ -456,6 +457,21 @@
   }
 
   /**
+   * @param {KeyboardEvent} e
+   * @private
+   */
+  onWindowKeydown_(e) {
+    // Open voice search with <CTRL> + <SHIFT> + <.> (also <CMD> + <SHIFT> + <.>
+    // on mac) keyboard shortcut.
+    let ctrlKeyPressed = e.ctrlKey;
+    // <if expr="is_macosx">
+    ctrlKeyPressed = ctrlKeyPressed || e.metaKey;
+    // </if>
+    this.showVoiceSearchOverlay_ =
+        ctrlKeyPressed && e.code === 'Period' && e.shiftKey;
+  }
+
+  /**
    * @param {skia.mojom.SkColor} skColor
    * @return {string}
    * @private
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd b/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd
index 35e62f6..d7f9cc2 100644
--- a/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd
+++ b/chrome/browser/resources/new_tab_page/new_tab_page_resources.grd
@@ -16,7 +16,8 @@
           file="new_tab_page.js" type="BINDATA" compress="false" />
       <include name="IDR_NEW_TAB_PAGE_APP_JS"
           file="${root_gen_dir}/chrome/browser/resources/new_tab_page/app.js"
-          use_base_dir="false" type="BINDATA" compress="false" />
+          use_base_dir="false" type="BINDATA" compress="false"
+          preprocess="true" />
       <include name="IDR_NEW_TAB_PAGE_MOST_VISITED_JS"
           file="${root_gen_dir}/chrome/browser/resources/new_tab_page/most_visited.js"
           use_base_dir="false" type="BINDATA" compress="false" />
diff --git a/chrome/browser/resources/optimize_webui.py b/chrome/browser/resources/optimize_webui.py
index 388cb64..e5ce0b5 100755
--- a/chrome/browser/resources/optimize_webui.py
+++ b/chrome/browser/resources/optimize_webui.py
@@ -210,9 +210,10 @@
   # arbitrary names?
   bundled_paths = []
   for index, js_file in enumerate(args.js_module_in_files):
-    expected_name = '%s.rollup.js' % js_file[:-len('.js')]
+    base_file_name = os.path.basename(js_file)
+    expected_name = '%s.rollup.js' % base_file_name[:-len('.js')]
     assert args.js_out_files[index] == expected_name, \
-           'Output file corresponding to %s should be named %s.rollup.js' % \
+           'Output file corresponding to %s should be named %s' % \
            (js_file, expected_name)
     bundled_paths.append(os.path.join(tmp_out_dir, expected_name))
 
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn
index c975fd59..919644e 100644
--- a/chrome/browser/resources/pdf/BUILD.gn
+++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -99,11 +99,13 @@
 js_library("pdf_viewer") {
   deps = [
     ":bookmark_type",
+    ":browser_api",
     ":constants",
     ":controller",
     ":metrics",
     ":navigator",
     ":pdf_scripting_api",
+    ":pdf_viewer_utils",
     ":toolbar_manager",
     ":viewport",
     ":viewport_scroller",
@@ -121,6 +123,15 @@
   externs_list = [ "$externs_path/resources_private.js" ]
 }
 
+js_library("pdf_viewer_utils") {
+  deps = [
+    ":browser_api",
+    ":controller",
+    ":navigator",
+    ":viewport",
+  ]
+}
+
 js_library("main_util") {
   deps = [
     ":browser_api",
@@ -152,6 +163,7 @@
     ":open_pdf_params_parser",
     ":pdf_scripting_api",
     ":pdf_viewer",
+    ":pdf_viewer_utils",
     ":toolbar_manager",
     ":viewport",
     ":viewport_scroller",
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html
index fbf3d1e..09e611c 100644
--- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html
+++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.html
@@ -176,25 +176,27 @@
         </div>
 
         <div id="buttons" class="invisible">
+<if expr="chromeos">
           <template is="dom-if" if="[[pdfAnnotationsEnabled_]]">
             <cr-icon-button id="annotate" iron-icon="pdf:create"
                 disabled="[[!annotationAvailable]]" on-click="toggleAnnotation"
-                aria-label$="[[strings.tooltipAnnotate]]"
-                title="[[strings.tooltipAnnotate]]"></cr-icon-button>
+                aria-label$="$i18n{tooltipAnnotate}"
+                title="$i18n{tooltipAnnotate}"></cr-icon-button>
           </template>
+</if>
 
           <cr-icon-button id="rotate-right" iron-icon="pdf:rotate-right"
               disabled="[[annotationMode]]" on-click="rotateRight"
-              aria-label$="[[strings.tooltipRotateCW]]"
-              title="[[strings.tooltipRotateCW]]"></cr-icon-button>
+              aria-label$="$i18n{tooltipRotateCW}"
+              title="$i18n{tooltipRotateCW}"></cr-icon-button>
 
           <cr-icon-button id="download" iron-icon="cr:file-download"
-              on-click="download" aria-label$="[[strings.tooltipDownload]]"
-              title="[[strings.tooltipDownload]]"></cr-icon-button>
+              on-click="download" aria-label$="$i18n{tooltipDownload}"
+              title="$i18n{tooltipDownload}"></cr-icon-button>
 
           <cr-icon-button id="print" iron-icon="cr:print" on-click="print"
-              hidden="[[!printingEnabled_]]" title="[[strings.tooltipPrint]]"
-              aria-label$="[[strings.tooltipPrint]]"></cr-icon-button>
+              hidden="[[!printingEnabled_]]" title="$i18n{tooltipPrint}"
+              aria-label$="$i18n{tooltipPrint}"></cr-icon-button>
 
           <viewer-toolbar-dropdown id="bookmarks"
                                    selected
@@ -202,7 +204,7 @@
                                    hidden$="[[!bookmarks.length]]"
                                    open-icon="pdf:bookmark"
                                    closed-icon="pdf:bookmark-border"
-                                   header="[[strings.bookmarks]]">
+                                   header="$i18n{bookmarks}">
             <template is="dom-repeat" items="[[bookmarks]]">
               <viewer-bookmark bookmark="[[item]]" depth="0"></viewer-bookmark>
             </template>
@@ -216,6 +218,7 @@
       </div>
     </div>
 
+<if expr="chromeos">
     <div id="annotations-bar" hidden>
       <viewer-toolbar-dropdown id="pen"
           selected$="[[isAnnotationTool_('pen', annotationTool.tool)]]"
@@ -225,7 +228,7 @@
           closed-icon="pdf:marker"
           dropdown-centered
           hide-header
-          header="[[strings.annotationPen]]"
+          header="$i18n{annotationPen}"
           style="--pen-tip-fill: #000000">
         <viewer-pen-options
           selected-color="#000000"
@@ -244,7 +247,7 @@
           closed-icon="pdf:highlighter"
           dropdown-centered
           hide-header
-          header="[[strings.annotationHighlighter]]"
+          header="$i18n{annotationHighlighter}"
           style="--pen-tip-fill: #ffbc00">
         <viewer-pen-options
           selected-color="#ffbc00"
@@ -258,18 +261,19 @@
       <cr-icon-button id="eraser"
           selected$="[[isAnnotationTool_('eraser', annotationTool.tool)]]"
           on-click="annotationToolClicked_" iron-icon="pdf:eraser"
-          aria-label$="[[strings.annotationEraser]]"
-          title="[[strings.annotationEraser]]"></cr-icon-button>
+          aria-label$="$i18n{annotationEraser}"
+          title="$i18n{annotationEraser}"></cr-icon-button>
 
       <div id="annotation-separator"></div>
 
       <cr-icon-button id="undo" disabled="[[!canUndoAnnotation]]"
           iron-icon="pdf:undo" on-click="undo"
-          aria-label$="[[strings.annotationUndo]]"
-          title="[[strings.annotationUndo]]"></cr-icon-button>
+          aria-label$="$i18n{annotationUndo}"
+          title="$i18n{annotationUndo}"></cr-icon-button>
 
       <cr-icon-button id="redo" disabled="[[!canRedoAnnotation]]"
           iron-icon="pdf:redo" on-click="redo"
-          aria-label$="[[strings.annotationRedo]]"
-          title="[[strings.annotationRedo]]"></cr-icon-button>
+          aria-label$="$i18n{annotationRedo}"
+          title="$i18n{annotationRedo}"></cr-icon-button>
     </div>
+</if>
diff --git a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
index e61fbb0..06bffb5 100644
--- a/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
+++ b/chrome/browser/resources/pdf/elements/viewer-pdf-toolbar.js
@@ -130,7 +130,9 @@
       this.$.pageselector.classList.toggle('invisible', !loaded);
       this.$.buttons.classList.toggle('invisible', !loaded);
       this.$.progress.style.opacity = loaded ? 0 : 1;
+      // <if expr="chromeos">
       this.$['annotations-bar'].hidden = !loaded || !this.annotationMode;
+      // </if>
     }
   },
 
@@ -189,6 +191,7 @@
       this.$.bookmarks.toggleDropdown();
       result = true;
     }
+    // <if expr="chromeos">
     if (this.$.pen.dropdownOpen) {
       this.$.pen.toggleDropdown();
       result = true;
@@ -197,6 +200,7 @@
       this.$.highlighter.toggleDropdown();
       result = true;
     }
+    // </if>
     return result;
   },
 
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
index 985afc4..ee77d88 100644
--- a/chrome/browser/resources/pdf/pdf_viewer.js
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
@@ -18,6 +18,7 @@
 import {NavigatorDelegate, PdfNavigator} from './navigator.js';
 import {OpenPdfParamsParser} from './open_pdf_params_parser.js';
 import {DeserializeKeyEvent, LoadState, SerializeKeyEvent} from './pdf_scripting_api.js';
+import {createPlugin, DestinationMessageData, DocumentDimensionsMessageData, getFilenameFromURL, getScrollbarWidth, MessageObject, NavigateMessageData, shouldIgnoreKeyEvents} from './pdf_viewer_utils.js';
 import {ToolbarManager} from './toolbar_manager.js';
 import {LayoutOptions, Point, Viewport} from './viewport.js';
 import {ViewportScroller} from './viewport_scroller.js';
@@ -25,46 +26,6 @@
 
 /**
  * @typedef {{
- *   source: Object,
- *   origin: string,
- *   data: !MessageData,
- * }}
- */
-let MessageObject;
-
-/**
- * @typedef {{
- *   type: string,
- *   height: number,
- *   width: number,
- *   layoutOptions: (!LayoutOptions|undefined),
- *   pageDimensions: Array
- * }}
- */
-let DocumentDimensionsMessageData;
-
-/**
- * @typedef {{
- *   type: string,
- *   url: string,
- *   disposition: !PdfNavigator.WindowOpenDisposition,
- * }}
- */
-let NavigateMessageData;
-
-/**
- * @typedef {{
- *   type: string,
- *   page: number,
- *   x: number,
- *   y: number,
- *   zoom: number
- * }}
- */
-let DestinationMessageData;
-
-/**
- * @typedef {{
  *   type: string,
  *   title: string,
  *   bookmarks: !Array<!Bookmark>,
@@ -82,58 +43,6 @@
  */
 let RequiredSaveResult;
 
-/** @return {number} Width of a scrollbar in pixels */
-function getScrollbarWidth() {
-  const div = document.createElement('div');
-  div.style.visibility = 'hidden';
-  div.style.overflow = 'scroll';
-  div.style.width = '50px';
-  div.style.height = '50px';
-  div.style.position = 'absolute';
-  document.body.appendChild(div);
-  const result = div.offsetWidth - div.clientWidth;
-  div.parentNode.removeChild(div);
-  return result;
-}
-
-/**
- * Return the filename component of a URL, percent decoded if possible.
- * @param {string} url The URL to get the filename from.
- * @return {string} The filename component.
- */
-export function getFilenameFromURL(url) {
-  // Ignore the query and fragment.
-  const mainUrl = url.split(/#|\?/)[0];
-  const components = mainUrl.split(/\/|\\/);
-  const filename = components[components.length - 1];
-  try {
-    return decodeURIComponent(filename);
-  } catch (e) {
-    if (e instanceof URIError) {
-      return filename;
-    }
-    throw e;
-  }
-}
-
-/**
- * Whether keydown events should currently be ignored. Events are ignored when
- * an editable element has focus, to allow for proper editing controls.
- * @param {Element} activeElement The currently selected DOM node.
- * @return {boolean} True if keydown events should be ignored.
- */
-export function shouldIgnoreKeyEvents(activeElement) {
-  while (activeElement.shadowRoot != null &&
-         activeElement.shadowRoot.activeElement != null) {
-    activeElement = activeElement.shadowRoot.activeElement;
-  }
-
-  return (
-      activeElement.isContentEditable ||
-      (activeElement.tagName === 'INPUT' && activeElement.type !== 'radio') ||
-      activeElement.tagName === 'TEXTAREA');
-}
-
 // There should only be one of these objects per document.
 export class PDFViewer {
   /**
@@ -259,20 +168,6 @@
         userInitiated => this.setUserInitiated_(userInitiated));
     window.addEventListener('beforeunload', () => this.resetTrackers_());
 
-    // Create the plugin object dynamically so we can set its src. The plugin
-    // element is sized to fill the entire window and is set to be fixed
-    // positioning, acting as a viewport. The plugin renders into this viewport
-    // according to the scroll position of the window.
-    /** @private {!HTMLEmbedElement} */
-    this.plugin_ =
-        /** @type {!HTMLEmbedElement} */ (document.createElement('embed'));
-
-    // NOTE: The plugin's 'id' field must be set to 'plugin' since
-    // chrome/renderer/printing/print_render_frame_helper.cc actually
-    // references it.
-    this.plugin_.id = 'plugin';
-    this.plugin_.type = 'application/x-google-chrome-pdf';
-
     // Handle scripting messages from outside the extension that wish to
     // interact with it. We also send a message indicating that extension has
     // loaded and is ready to receive messages.
@@ -280,27 +175,14 @@
       this.handleScriptingMessage(/** @type {!MessageObject} */ (message));
     }, false);
 
-    this.plugin_.setAttribute('src', this.originalUrl_);
-    this.plugin_.setAttribute(
-        'stream-url', this.browserApi_.getStreamInfo().streamUrl);
-    let headers = '';
-    for (const header in this.browserApi_.getStreamInfo().responseHeaders) {
-      headers += header + ': ' +
-          this.browserApi_.getStreamInfo().responseHeaders[header] + '\n';
-    }
-    this.plugin_.setAttribute('headers', headers);
-
-    this.plugin_.setAttribute('background-color', PDFViewer.BACKGROUND_COLOR);
-    this.plugin_.setAttribute('top-toolbar-height', topToolbarHeight);
-    this.plugin_.setAttribute('javascript', this.javascript_);
-
-    if (this.browserApi_.getStreamInfo().embedded) {
-      this.plugin_.setAttribute(
-          'top-level-url', this.browserApi_.getStreamInfo().tabUrl);
-    } else {
-      this.plugin_.setAttribute('full-frame', '');
-    }
-
+    // Create the plugin object dynamically so we can set its src. The plugin
+    // element is sized to fill the entire window and is set to be fixed
+    // positioning, acting as a viewport. The plugin renders into this viewport
+    // according to the scroll position of the window.
+    /** @private {!HTMLEmbedElement} */
+    this.plugin_ = createPlugin(
+        this.browserApi_, topToolbarHeight, PDFViewer.BACKGROUND_COLOR,
+        this.originalUrl_);
     $('content').appendChild(this.plugin_);
 
     /** @private {!PluginController} */
diff --git a/chrome/browser/resources/pdf/pdf_viewer_utils.js b/chrome/browser/resources/pdf/pdf_viewer_utils.js
new file mode 100644
index 0000000..ea050eaa
--- /dev/null
+++ b/chrome/browser/resources/pdf/pdf_viewer_utils.js
@@ -0,0 +1,151 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {BrowserApi} from './browser_api.js';
+import {MessageData} from './controller.js';
+import {PdfNavigator} from './navigator.js';
+import {LayoutOptions} from './viewport.js';
+
+/**
+ * @typedef {{
+ *   source: Object,
+ *   origin: string,
+ *   data: !MessageData,
+ * }}
+ */
+export let MessageObject;
+
+/**
+ * @typedef {{
+ *   type: string,
+ *   height: number,
+ *   width: number,
+ *   layoutOptions: (!LayoutOptions|undefined),
+ *   pageDimensions: Array
+ * }}
+ */
+export let DocumentDimensionsMessageData;
+
+/**
+ * @typedef {{
+ *   type: string,
+ *   url: string,
+ *   disposition: !PdfNavigator.WindowOpenDisposition,
+ * }}
+ */
+export let NavigateMessageData;
+
+/**
+ * @typedef {{
+ *   type: string,
+ *   page: number,
+ *   x: number,
+ *   y: number,
+ *   zoom: number
+ * }}
+ */
+export let DestinationMessageData;
+
+/**
+ * @typedef {{
+ *   hasUnsavedChanges: (boolean|undefined),
+ *   fileName: string,
+ *   dataToSave: !ArrayBuffer
+ * }}
+ */
+export let RequiredSaveResult;
+
+/** @return {number} Width of a scrollbar in pixels */
+export function getScrollbarWidth() {
+  const div = document.createElement('div');
+  div.style.visibility = 'hidden';
+  div.style.overflow = 'scroll';
+  div.style.width = '50px';
+  div.style.height = '50px';
+  div.style.position = 'absolute';
+  document.body.appendChild(div);
+  const result = div.offsetWidth - div.clientWidth;
+  div.parentNode.removeChild(div);
+  return result;
+}
+
+/**
+ * Return the filename component of a URL, percent decoded if possible.
+ * @param {string} url The URL to get the filename from.
+ * @return {string} The filename component.
+ */
+export function getFilenameFromURL(url) {
+  // Ignore the query and fragment.
+  const mainUrl = url.split(/#|\?/)[0];
+  const components = mainUrl.split(/\/|\\/);
+  const filename = components[components.length - 1];
+  try {
+    return decodeURIComponent(filename);
+  } catch (e) {
+    if (e instanceof URIError) {
+      return filename;
+    }
+    throw e;
+  }
+}
+
+/**
+ * Whether keydown events should currently be ignored. Events are ignored when
+ * an editable element has focus, to allow for proper editing controls.
+ * @param {Element} activeElement The currently selected DOM node.
+ * @return {boolean} True if keydown events should be ignored.
+ */
+export function shouldIgnoreKeyEvents(activeElement) {
+  while (activeElement.shadowRoot != null &&
+         activeElement.shadowRoot.activeElement != null) {
+    activeElement = activeElement.shadowRoot.activeElement;
+  }
+
+  return (
+      activeElement.isContentEditable ||
+      (activeElement.tagName === 'INPUT' && activeElement.type !== 'radio') ||
+      activeElement.tagName === 'TEXTAREA');
+}
+
+/**
+ * @param {!BrowserApi} browserApi
+ * @param {number} topToolbarHeight
+ * @param {string} backgroundColor
+ * @param {string} originalUrl
+ * @return {!HTMLEmbedElement} The plugin
+ */
+export function createPlugin(
+    browserApi, topToolbarHeight, backgroundColor, originalUrl) {
+  const plugin =
+      /** @type {!HTMLEmbedElement} */ (document.createElement('embed'));
+
+  // NOTE: The plugin's 'id' field must be set to 'plugin' since
+  // chrome/renderer/printing/print_render_frame_helper.cc actually
+  // references it.
+  plugin.id = 'plugin';
+  plugin.type = 'application/x-google-chrome-pdf';
+
+  plugin.setAttribute('src', originalUrl);
+  plugin.setAttribute('stream-url', browserApi.getStreamInfo().streamUrl);
+  let headers = '';
+  for (const header in browserApi.getStreamInfo().responseHeaders) {
+    headers += header + ': ' +
+        browserApi.getStreamInfo().responseHeaders[header] + '\n';
+  }
+  plugin.setAttribute('headers', headers);
+
+  plugin.setAttribute('background-color', backgroundColor);
+  plugin.setAttribute('top-toolbar-height', topToolbarHeight);
+
+  const javascript = browserApi.getStreamInfo().javascript || 'block';
+  plugin.setAttribute('javascript', javascript);
+
+  if (browserApi.getStreamInfo().embedded) {
+    plugin.setAttribute('top-level-url', browserApi.getStreamInfo().tabUrl);
+  } else {
+    plugin.setAttribute('full-frame', '');
+  }
+
+  return plugin;
+}
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index 9cd5818..058f3a1 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -4,6 +4,7 @@
 
 import './ui/app.js';
 
+export {PluralStringProxyImpl as PrintPreviewPluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
 export {CloudPrintInterface, CloudPrintInterfaceEventType} from './cloud_print_interface.js';
 export {CloudPrintInterfaceImpl} from './cloud_print_interface_impl.js';
 export {ColorMode, createDestinationKey, Destination, DestinationCertificateStatus, DestinationConnectionStatus, DestinationOrigin, DestinationType, makeRecentDestination, RecentDestination} from './data/destination.js';
diff --git a/chrome/browser/resources/print_preview/ui/BUILD.gn b/chrome/browser/resources/print_preview/ui/BUILD.gn
index f0deaa20..30aa908 100644
--- a/chrome/browser/resources/print_preview/ui/BUILD.gn
+++ b/chrome/browser/resources/print_preview/ui/BUILD.gn
@@ -118,6 +118,7 @@
     "../data:destination",
     "../data:state",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:plural_string_proxy",
   ]
 
   if (is_chromeos) {
@@ -132,6 +133,7 @@
     "../data:state",
     "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
     "//ui/webui/resources/js:load_time_data.m",
+    "//ui/webui/resources/js:plural_string_proxy",
   ]
 }
 
diff --git a/chrome/browser/resources/print_preview/ui/button_strip.js b/chrome/browser/resources/print_preview/ui/button_strip.js
index 28ea8d62..46244702 100644
--- a/chrome/browser/resources/print_preview/ui/button_strip.js
+++ b/chrome/browser/resources/print_preview/ui/button_strip.js
@@ -8,6 +8,7 @@
 import '../strings.m.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
 import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
@@ -50,7 +51,6 @@
     /** @private */
     errorMessage_: {
       type: String,
-      computed: 'computeErrorMessage_(destination.id, maxSheets, sheetCount)',
       observer: 'errorMessageChanged_',
     },
     // </if>
@@ -59,6 +59,9 @@
   observers: [
     'updatePrintButtonLabel_(destination.id)',
     'updatePrintButtonEnabled_(state, destination.id, maxSheets, sheetCount)',
+    // <if expr="chromeos">
+    'updateErrorMessage_(state, destination.id, maxSheets, sheetCount)',
+    // </if>
   ],
 
   /** @private {!State} */
@@ -140,19 +143,17 @@
     return this.sheetCount > 0 && this.printButtonDisabled_();
   },
 
-  /**
-   * @return {string} Localized message to show as an error.
-   * @private
-   */
-  computeErrorMessage_() {
+  /** @private */
+  updateErrorMessage_() {
     if (!this.showSheetsError_()) {
-      return '';
+      this.errorMessage_ = '';
+      return;
     }
-
-    const singularOrPlural = this.maxSheets > 1 ? 'Plural' : 'Singular';
-    const label = loadTimeData.getString(`sheetsLimitLabel${singularOrPlural}`);
-    return loadTimeData.getStringF(
-        'sheetsLimitErrorMessage', this.maxSheets.toLocaleString(), label);
+    PluralStringProxyImpl.getInstance()
+        .getPluralString('sheetsLimitErrorMessage', this.maxSheets)
+        .then(label => {
+          this.errorMessage_ = label;
+        });
   },
 
   /**
diff --git a/chrome/browser/resources/print_preview/ui/header.js b/chrome/browser/resources/print_preview/ui/header.js
index 3848934..e441b037 100644
--- a/chrome/browser/resources/print_preview/ui/header.js
+++ b/chrome/browser/resources/print_preview/ui/header.js
@@ -9,6 +9,7 @@
 import '../strings.m.js';
 
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {PluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import {Destination} from '../data/destination.js';
@@ -40,12 +41,13 @@
     sheetCount: Number,
 
     /** @private {?string} */
-    summary_: {
-      type: String,
-      computed: 'computeSummary_(sheetCount, state, destination.id)',
-    },
+    summary_: String,
   },
 
+  observers: [
+    'updateSummary_(sheetCount, state, destination.id)',
+  ],
+
   /**
    * @return {boolean}
    * @private
@@ -56,21 +58,22 @@
          this.destination.id === Destination.GooglePromotedId.DOCS);
   },
 
-  /**
-   * @return {?string}
-   * @private
-   */
-  computeSummary_() {
+  /** @private */
+  updateSummary_() {
     switch (this.state) {
       case (State.PRINTING):
-        return loadTimeData.getString(
+        this.summary_ = loadTimeData.getString(
             this.isPdfOrDrive_() ? 'saving' : 'printing');
+        break;
       case (State.READY):
-        return this.getSheetsSummary_();
+        this.updateSheetsSummary_();
+        break;
       case (State.FATAL_ERROR):
-        return this.getErrorMessage_();
+        this.summary_ = this.getErrorMessage_();
+        break;
       default:
-        return null;
+        this.summary_ = null;
+        break;
     }
   },
 
@@ -89,21 +92,19 @@
     }
   },
 
-  /**
-   * @return {string}
-   * @private
-   */
-  getSheetsSummary_() {
+  /** @private */
+  updateSheetsSummary_() {
     if (this.sheetCount === 0) {
-      return '';
+      this.summary_ = '';
+      return;
     }
 
-    const pageOrSheets = this.isPdfOrDrive_() ? 'Page' : 'Sheets';
-    const singularOrPlural = this.sheetCount > 1 ? 'Plural' : 'Singular';
-    const label = loadTimeData.getString(
-        `printPreview${pageOrSheets}Label${singularOrPlural}`);
-    return loadTimeData.getStringF(
-        'printPreviewSummaryFormatShort', this.sheetCount.toLocaleString(),
-        label);
+    const pageOrSheet = this.isPdfOrDrive_() ? 'Page' : 'Sheet';
+    PluralStringProxyImpl.getInstance()
+        .getPluralString(
+            `printPreview${pageOrSheet}SummaryLabel`, this.sheetCount)
+        .then(label => {
+          this.summary_ = label;
+        });
   },
 });
diff --git a/chrome/browser/resources/print_preview/ui/print_preview_search_box.html b/chrome/browser/resources/print_preview/ui/print_preview_search_box.html
index 816b959..6ecd94c 100644
--- a/chrome/browser/resources/print_preview/ui/print_preview_search_box.html
+++ b/chrome/browser/resources/print_preview/ui/print_preview_search_box.html
@@ -50,7 +50,7 @@
     on-search="onSearchTermSearch" on-input="onSearchTermInput"
     aria-label$="[[label]]" placeholder="[[label]]"
     autofocus="[[autofocus]]" spellcheck="false">
-  <div slot="prefix" id="icon" class="cr-icon icon-search" alt=""></div>
+  <div slot="inline-prefix" id="icon" class="cr-icon icon-search" alt=""></div>
   <cr-icon-button id="clearSearch" class="icon-cancel"
       hidden$="[[!hasSearchText]]" slot="suffix" on-click="onClearClick_"
       title="[[clearLabel]]">
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index ceaf0141..a2f13d2 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -212,6 +212,7 @@
     ":metrics_browser_proxy",
     ":open_window_proxy",
     "about_page:about_page_browser_proxy.m",
+    "autofill_page:multi_store_exception_entry",
     "autofill_page:multi_store_password_ui_entry",
     "autofill_page:password_manager_proxy",
     "people_page:sync_browser_proxy.m",
diff --git a/chrome/browser/resources/settings/autofill_page/BUILD.gn b/chrome/browser/resources/settings/autofill_page/BUILD.gn
index 26b9d15..563babb 100644
--- a/chrome/browser/resources/settings/autofill_page/BUILD.gn
+++ b/chrome/browser/resources/settings/autofill_page/BUILD.gn
@@ -16,7 +16,9 @@
     ":blocking_request_manager",
     ":credit_card_edit_dialog",
     ":credit_card_list_entry",
+    ":merge_exceptions_store_copies_behavior",
     ":merge_passwords_store_copies_behavior",
+    ":multi_store_exception_entry",
     ":multi_store_id_handler",
     ":multi_store_password_ui_entry",
     ":password_check",
@@ -167,7 +169,7 @@
 }
 
 js_library("multi_store_exception_entry") {
-  sources = [ "multi_store_password_ui_entry.js" ]
+  sources = [ "multi_store_exception_entry.js" ]
   deps = [
     ":multi_store_id_handler",
     ":password_manager_proxy",
@@ -231,7 +233,9 @@
 
 js_library("passwords_section") {
   deps = [
+    ":merge_exceptions_store_copies_behavior",
     ":merge_passwords_store_copies_behavior",
+    ":multi_store_exception_entry",
     ":multi_store_password_ui_entry",
     ":password_list_item",
     ":password_manager_proxy",
@@ -310,10 +314,19 @@
   deps = [
     ":multi_store_password_ui_entry",
     ":password_manager_proxy",
+    "//ui/webui/resources/js:assert.m",
     "//ui/webui/resources/js:list_property_update_behavior.m",
   ]
 }
 
+js_library("merge_exceptions_store_copies_behavior") {
+  deps = [
+    ":multi_store_exception_entry",
+    ":password_manager_proxy",
+    "//ui/webui/resources/js:assert.m",
+  ]
+}
+
 js_library("remove_password_behavior") {
   deps = [
     ":multi_store_password_ui_entry",
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html
index 702dde9..7724dde 100644
--- a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html
+++ b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.html
@@ -5,13 +5,21 @@
         width: var(--settings-input-max-width);
       }
 
-      .md-select + .md-select {
-        margin-inline-start: 8px;
+      /* Larger cr-input margin (by reserving space for error display) when
+      nickname management is enabled. */
+      :host([nickname-management-enabled_]) cr-input {
+        --cr-input-error-display: block;
+        margin-bottom: 0;
       }
 
-      /* Prevent focus-outline from being chopped by bottom of dialog body. */
-      .md-select {
-        margin-bottom: 2px;
+      /* Override the padding-top (the space is set by save-to-this-device) when
+      nickname management is enabled. */
+      :host([nickname-management-enabled_]) div[slot='button-container'] {
+        padding-top: 0;
+      }
+
+      .md-select + .md-select {
+        margin-inline-start: 8px;
       }
 
       #expired {
@@ -40,24 +48,35 @@
         margin-top: var(--cr-form-field-bottom-spacing);
       }
 
+      :host([nickname-management-enabled_]) #saved-to-this-device-only-label {
+        /* Overall space between input fields, including space between
+           nicknameInput and saved-to-this-device text, between
+           saved-to-this-device text and button. */
+        margin-bottom: 26px;
+        margin-top: 0;
+      }
+
       #year {
         width: 100px;
       }
 
-      /* For nickname input, we might dispay error message. cr-input-width is
-      the same as other input fields. We reserve extra 40px for the suffix
-      character count width.*/
+      /* For nickname input, cr-input-width is the same as other input fields */
       #nicknameInput {
-        --cr-input-error-display: block;
         --cr-input-width: var(--settings-input-max-width);
-        width: calc(var(--settings-input-max-width) + 40px);
+        width: fit-content;
+      }
+
+      #charCount {
+        font-size: var(--cr-form-field-label-font-size);
+        line-height: var(--cr-form-field-label-line-height);
+        padding-inline-start: 8px;
       }
 
       #nicknameInput:not(:focus-within) #charCount {
         display: none;
       }
 
-      /* Same style as cr-input error.*/
+      /* Same style as cr-input error except margin-top. */
       #expired-error {
         display: block;
         font-size: var(--cr-form-field-label-font-size);
@@ -129,7 +148,6 @@
         </span>
         <!-- Place cardholder name field and nickname field after expiration
           when nickname management is enabled.-->
-        <!-- TODO(crbug.com/1063426): Update CSS layout.-->
         <template is="dom-if" if="[[nicknameManagementEnabled_]]">
           <cr-input id="nameInput" label="$i18n{creditCardName}"
               value="{{creditCard.name}}" spellcheck="false">
diff --git a/chrome/browser/resources/settings/autofill_page/merge_exceptions_store_copies_behavior.js b/chrome/browser/resources/settings/autofill_page/merge_exceptions_store_copies_behavior.js
new file mode 100644
index 0000000..0a204f2
--- /dev/null
+++ b/chrome/browser/resources/settings/autofill_page/merge_exceptions_store_copies_behavior.js
@@ -0,0 +1,79 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview This behavior bundles the functionality for retrieving password
+ * exceptions (websites where the user has chosen never to save passwords) from
+ * the password manager, and deduplicating eventual copies stored both on the
+ * device and in the account.
+ */
+
+import {assert} from 'chrome://resources/js/assert.m.js';
+
+import {MultiStoreExceptionEntry} from './multi_store_exception_entry.js';
+import {PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js';
+
+/**
+ * @polymerBehavior
+ */
+export const MergeExceptionsStoreCopiesBehavior = {
+
+  properties: {
+    /**
+     * An array of sites to display.
+     * @type {!Array<!MultiStoreExceptionEntry>}
+     */
+    passwordExceptions: {
+      type: Array,
+      value: () => [],
+    },
+
+  },
+
+  /**
+   * @type {?function(!Array<PasswordManagerProxy.ExceptionEntry>):void}
+   * @private
+   */
+  setPasswordExceptionsListener_: null,
+
+  /** @override */
+  attached() {
+    this.setPasswordExceptionsListener_ = list => {
+      this.passwordExceptions = this.mergeExceptionsStoreDuplicates_(list);
+    };
+
+    PasswordManagerImpl.getInstance().getExceptionList(
+        this.setPasswordExceptionsListener_);
+    PasswordManagerImpl.getInstance().addExceptionListChangedListener(
+        this.setPasswordExceptionsListener_);
+  },
+
+  /** @override */
+  detached() {
+    PasswordManagerImpl.getInstance().removeExceptionListChangedListener(
+        assert(this.setPasswordExceptionsListener_));
+  },
+
+  /**
+   * @param {!Array<!PasswordManagerProxy.ExceptionEntry>} exceptionList
+   * @return {!Array<!MultiStoreExceptionEntry>}
+   * @private
+   */
+  mergeExceptionsStoreDuplicates_(exceptionList) {
+    /** @type {!Array<!MultiStoreExceptionEntry>} */
+    const multiStoreEntries = [];
+    /** @type {!Map<number, !MultiStoreExceptionEntry>} */
+    const frontendIdToMergedEntry = new Map();
+    for (const entry of exceptionList) {
+      if (frontendIdToMergedEntry.has(entry.frontendId)) {
+        frontendIdToMergedEntry.get(entry.frontendId).merge(entry);
+      } else {
+        const multiStoreEntry = new MultiStoreExceptionEntry(entry);
+        frontendIdToMergedEntry.set(entry.frontendId, multiStoreEntry);
+        multiStoreEntries.push(multiStoreEntry);
+      }
+    }
+    return multiStoreEntries;
+  },
+};
diff --git a/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js b/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js
index 30080fed..87ded984 100644
--- a/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js
+++ b/chrome/browser/resources/settings/autofill_page/merge_passwords_store_copies_behavior.js
@@ -30,17 +30,14 @@
       value: () => [],
     },
 
-    /**
-     * @type {?function(!Array<PasswordManagerProxy.PasswordUiEntry>):void}
-     * @private
-     */
-    setSavedPasswordsListener_: {
-      type: Object,
-      value: null,
-    },
-
   },
 
+  /**
+   * @type {?function(!Array<PasswordManagerProxy.PasswordUiEntry>):void}
+   * @private
+   */
+  setSavedPasswordsListener_: null,
+
   /** @override */
   attached() {
     this.setSavedPasswordsListener_ = passwordList => {
@@ -62,6 +59,7 @@
     this.notifySplices('savedPasswords', []);
   },
 
+  /** @override */
   detached() {
     PasswordManagerImpl.getInstance().removeSavedPasswordListChangedListener(
         assert(this.setSavedPasswordsListener_));
diff --git a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js
index c432cf1..38c6984 100644
--- a/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js
+++ b/chrome/browser/resources/settings/autofill_page/password_manager_proxy.js
@@ -87,6 +87,13 @@
   removeException(id) {}
 
   /**
+   * Should remove the password exceptions and notify that the list has changed.
+   * @param {!Array<number>} ids The ids for the exception url entries being
+   * removed. Any |id| not in the list is ignored.
+   */
+  removeExceptions(ids) {}
+
+  /**
    * Should undo the last saved password or exception removal and notify that
    * the list has changed.
    */
@@ -382,6 +389,11 @@
   }
 
   /** @override */
+  removeExceptions(ids) {
+    chrome.passwordsPrivate.removePasswordExceptions(ids);
+  }
+
+  /** @override */
   undoRemoveSavedPasswordOrException() {
     chrome.passwordsPrivate.undoRemoveSavedPasswordOrException();
   }
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.js b/chrome/browser/resources/settings/autofill_page/passwords_section.js
index 0373fb2..788dd22 100644
--- a/chrome/browser/resources/settings/autofill_page/passwords_section.js
+++ b/chrome/browser/resources/settings/autofill_page/passwords_section.js
@@ -15,7 +15,6 @@
 import {afterNextRender, html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 
 import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.m.js';
-import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
 import 'chrome://resources/cr_elements/cr_link_row/cr_link_row.m.js';
@@ -43,7 +42,10 @@
 import '../prefs/prefs.m.js';
 import {PrefsBehavior} from '../prefs/prefs_behavior.m.js';
 import {routes} from '../route.js';
+import {MergeExceptionsStoreCopiesBehavior} from './merge_exceptions_store_copies_behavior.js';
 import {MergePasswordsStoreCopiesBehavior} from './merge_passwords_store_copies_behavior.js';
+import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js';
+import {MultiStoreExceptionEntry} from './multi_store_exception_entry.js';
 import {Router} from '../router.m.js';
 import '../settings_shared_css.m.js';
 import '../site_favicon.js';
@@ -81,6 +83,7 @@
   behaviors: [
     I18nBehavior,
     WebUIListenerBehavior,
+    MergeExceptionsStoreCopiesBehavior,
     MergePasswordsStoreCopiesBehavior,
     PasswordCheckBehavior,
     IronA11yKeysBehavior,
@@ -100,15 +103,6 @@
       notify: true,
     },
 
-    /**
-     * An array of sites to display.
-     * @type {!Array<!PasswordManagerProxy.ExceptionEntry>}
-     */
-    passwordExceptions: {
-      type: Array,
-      value: () => [],
-    },
-
     /** @override */
     subpageRoute: {
       type: Object,
@@ -328,13 +322,8 @@
       this.isOptedInForAccountStorage_ = optedIn;
     };
 
-    const setPasswordExceptionsListener = list => {
-      this.passwordExceptions = list;
-    };
-
     this.setIsOptedInForAccountStorageListener_ =
         setIsOptedInForAccountStorageListener;
-    this.setPasswordExceptionsListener_ = setPasswordExceptionsListener;
 
     // Set the manager. These can be overridden by tests.
     this.passwordManager_ = PasswordManagerImpl.getInstance();
@@ -355,13 +344,10 @@
     // Request initial data.
     this.passwordManager_.isOptedInForAccountStorage().then(
         setIsOptedInForAccountStorageListener);
-    this.passwordManager_.getExceptionList(setPasswordExceptionsListener);
 
     // Listen for changes.
     this.passwordManager_.addAccountStorageOptInStateListener(
         setIsOptedInForAccountStorageListener);
-    this.passwordManager_.addExceptionListChangedListener(
-        setPasswordExceptionsListener);
 
     const syncBrowserProxy = SyncBrowserProxyImpl.getInstance();
 
@@ -394,8 +380,6 @@
 
   /** @override */
   detached() {
-    this.passwordManager_.removeExceptionListChangedListener(
-        assert(this.setPasswordExceptionsListener_));
     this.passwordManager_.removeAccountStorageOptInStateListener(
         assert(this.setIsOptedInForAccountStorageListener_));
   },
@@ -577,11 +561,21 @@
 
   /**
    * Fires an event that should delete the password exception.
-   * @param {!ExceptionEntryEntryEvent} e The polymer event.
+   * @param {!{model: !{item: !chrome.passwordsPrivate.ExceptionEntry}}} e
+   * The polymer event.
    * @private
    */
   onRemoveExceptionButtonTap_(e) {
-    this.passwordManager_.removeException(e.model.item.id);
+    const exception = e.model.item;
+    /** @type {!Array<number>} */
+    const allExceptionIds = [];
+    if (exception.isPresentInAccount()) {
+      allExceptionIds.push(exception.accountId);
+    }
+    if (exception.isPresentOnDevice()) {
+      allExceptionIds.push(exception.deviceId);
+    }
+    this.passwordManager_.removeExceptions(allExceptionIds);
   },
 
   /**
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 761b861..51c9072 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -13,6 +13,7 @@
 if (optimize_webui) {
   settings_pak_file = "os_settings_resources.pak"
   unpak_folder = "os_settings_resources.unpak"
+  unpak_folder_v3 = "os_settings_resources.unpak/chromeos"
 
   optimize_webui("build") {
     host = "os-settings"
@@ -53,6 +54,44 @@
     deps = [ ":unpak" ]
   }
 
+  optimize_webui("build_polymer3") {
+    host = "os-settings"
+    input = rebase_path("$target_gen_dir/$unpak_folder", root_build_dir)
+    js_out_files = [ "os_settings.rollup.js" ]
+    js_module_in_files = [ "chromeos/os_settings.js" ]
+
+    deps = [
+      ":unpak_v3",
+      "../../../../../ui/webui/resources:modulize",
+    ]
+    excludes = [
+      "chrome://resources/js/cr.m.js",
+      "chrome://resources/css/cros_colors.generated.css",
+
+      # TODO: Determine how to move the mojo files into the expected directories
+      # in the unpak folder, so that they can be included in the bundle.
+      "chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js",
+      "app-management/app_management.mojom-lite.js",
+      "app-management/bitmap.mojom-lite.js",
+      "app-management/file_path.mojom-lite.js",
+      "app-management/image_info.mojom-lite.js",
+      "app-management/image.mojom-lite.js",
+      "app-management/types.mojom-lite.js",
+      "constants/routes.mojom-lite.js",
+      "constants/setting.mojom-lite.js",
+      "search/search.mojom-lite.js",
+      "search/search_result_icon.mojom-lite.js",
+      "search/user_action_recorder.mojom-lite.js",
+    ]
+  }
+
+  unpak("unpak_v3") {
+    pak_file = settings_pak_file
+    out_folder = unpak_folder_v3
+
+    deps = [ ":flattened_resources" ]
+  }
+
   unpak("unpak") {
     pak_file = settings_pak_file
     out_folder = unpak_folder
diff --git a/chrome/browser/resources/settings/chromeos/device_page/display.js b/chrome/browser/resources/settings/chromeos/device_page/display.js
index e7e69f2..8f1a163 100644
--- a/chrome/browser/resources/settings/chromeos/device_page/display.js
+++ b/chrome/browser/resources/settings/chromeos/device_page/display.js
@@ -538,6 +538,7 @@
       // Clear the mappings before recalculating.
       this.modeToParentModeMap_ = new Map();
       this.parentModeToRefreshRateMap_ = new Map();
+      this.displayModeList_ = new Array();
 
       // Build the modes into a nested map of width => height => refresh rate.
       const modes = this.createModeMap_(selectedDisplay);
@@ -601,7 +602,7 @@
 
       // Only store one entry in the |resolutionList| per resolution,
       // mapping it to the parentModeIndex for that resolution.
-      this.displayModeList_.push({
+      this.push('displayModeList_', {
         name: resolutionOption,
         value: parentModeIndex,
       });
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
index b60fdef..c33f34d 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.html
@@ -32,6 +32,13 @@
               permission-label="$i18n{appManagementPrintingPermissionLabel}"
               permission-type="PRINTING">
           </app-management-permission-item>
+          <template is="dom-if" if="[[showCameraPermissions_]]">
+            <app-management-permission-item
+                class="subpermission-row" icon="app-management:camera"
+                permission-label="$i18n{appManagementCameraPermissionLabel}"
+                permission-type="CAMERA">
+            </app-management-permission-item>
+          </template>
         </div>
       </div>
 
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js
index c537ae4..8ad8d9b 100644
--- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js
+++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/plugin_vm_page/plugin_vm_detail_view.js
@@ -14,6 +14,17 @@
      * @private {App}
      */
     app_: Object,
+
+    /**
+     * Whether the camera permissions should be shown.
+     * @private {boolean}
+     */
+    showCameraPermissions_: {
+      type: Boolean,
+      value() {
+        return loadTimeData.getBoolean('showPluginVmCameraPermissions');
+      },
+    },
   },
 
   attached() {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js
index 9abda5f..7f1199fb 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -6,5 +6,5 @@
 import './os_reset_page/os_reset_page.m.js';
 import './localized_link/localized_link.m.js';
 
-export {OsResetBrowserProxyImpl} from './os_reset_page/os_reset_browser_proxy.m.js';
-export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '../../lifetime_browser_proxy.m.js';
\ No newline at end of file
+export {LifetimeBrowserProxy, LifetimeBrowserProxyImpl} from '../lifetime_browser_proxy.m.js';
+export {OsResetBrowserProxyImpl} from './os_reset_page/os_reset_browser_proxy.m.js';
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
index d7ea699ad..5b4c49f 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
+++ b/chrome/browser/resources/settings/chromeos/os_settings_resources_v3.grdp
@@ -29,6 +29,7 @@
            file="${root_gen_dir}/chrome/browser/resources/settings/lifetime_browser_proxy.m.js"
            use_base_dir="false"
            compress="false"
+           preprocess="true"
            type="BINDATA"/>
   <include name="IDR_OS_SETTINGS_SETTINGS_SHARED_CSS_M_JS"
            file="${root_gen_dir}/chrome/browser/resources/settings/settings_shared_css.m.js"
diff --git a/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js b/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js
index 82374ef..ebd603b0 100644
--- a/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js
+++ b/chrome/browser/resources/settings/chromeos/os_settings_search_box/os_search_result_row.js
@@ -7,24 +7,31 @@
  */
 cr.define('settings', function() {
   /**
-   * A list of characters that will be ignored during the tokenization and
-   * comparison of search result text.
-   * TODO(crbug/1072912): Ask linguist for a list of delimiters that make sense.
+   * A list of hyphens in all languages that will be ignored during the
+   * tokenization and comparison of search result text.
+   * Hyphen characters list is taken from here: http://jkorpela.fi/dashes.html.
+   * U+002D(-), U+007E(~), U+058A(֊), U+05BE(־), U+1806(᠆), U+2010(‐),
+   * U+2011(‑), U+2012(‒), U+2013(–), U+2014(—), U+2015(―), U+2053(⁓),
+   * U+207B(⁻), U+208B(₋), U+2212(−), U+2E3A(⸺ ), U+2E3B(⸻  ), U+301C(〜),
+   * U+3030(〰), U+30A0(゠), U+FE58(﹘), U+FE63(﹣), U+FF0D(-).
    * @type {!Array<string>}
    */
-  const IGNORED_CHARS = ['-'];
+  const HYPHENS = [
+    '-', '~', '֊', '־', '᠆', '‐',  '‑',  '‒',  '–',  '—',  '―', '⁓',
+    '⁻', '₋', '−', '⸺', '⸻', '〜', '〰', '゠', '﹘', '﹣', '-'
+  ];
 
   /**
-   * String form of the regexp expressing ignored chars.
+   * String form of the regexp expressing hyphen chars.
    * @type {string}
    */
-  const IGNORED_CHARS_REGEX_STR = `[${IGNORED_CHARS.join('')}]`;
+  const HYPHENS_REGEX_STR = `[${HYPHENS.join('')}]`;
 
   /**
-   * Regexp expressing ignored chars.
+   * Regexp expressing hyphen chars.
    * @type {!RegExp}
    */
-  const IGNORED_CHARS_REGEX = new RegExp(IGNORED_CHARS_REGEX_STR, 'g');
+  const HYPHENS_REGEX = new RegExp(HYPHENS_REGEX_STR, 'g');
 
   /**
    * @param {string} sourceString The string to be modified.
@@ -37,15 +44,15 @@
   }
 
   /**
-   * Used to convert the query and result into the same format without ignored
-   * characters and accents so that easy string comparisons can be performed.
-   *     e.g. |sourceString| = 'BRÛLÉE' returns "brulee"
+   * Used to convert the query and result into the same format without hyphens
+   * and accents so that easy string comparisons can be performed. e.g.
+   * |sourceString| = 'BRÛLÉE' returns "brulee"
    * @param {string} sourceString The string to be normalized.
    * @return {string} The sourceString lowercased with accents in the range
-   *     \u0300 - \u036f removed, and with ignored characters removed.
+   *     \u0300 - \u036f removed, and with hyphens removed.
    */
   function normalizeString(sourceString) {
-    return removeAccents(sourceString).replace(IGNORED_CHARS_REGEX, '');
+    return removeAccents(sourceString).replace(HYPHENS_REGEX, '');
   }
 
   /**
@@ -155,20 +162,20 @@
 
     /**
      * @param {string} innerHtmlToken A case sensitive segment of the result
-     *     text which may or may not contain ignored characters or accents on
+     *     text which may or may not contain hyphens or accents on
      *     characters, and does not contain blank spaces.
      * @param {string} normalizedQuery A lowercased query which does not contain
      *     punctuation.
      * @param {!Array<string>} queryTokens |normalizedQuery| tokenized by
      *     blankspaces of any kind.
      * @return {string} The innerHtmlToken with <b> tags around segments that
-     *     match queryTokens, but also includes ignored characters and accents
+     *     match queryTokens, but also includes hyphens and accents
      *     on characters.
      * @private
      */
     getModifiedInnerHtmlToken_(innerHtmlToken, normalizedQuery, queryTokens) {
       // For comparison purposes with query tokens, lowercase the html token to
-      // be displayed and remove ignored characters. The resulting
+      // be displayed and remove hyphens. The resulting
       // |normalizedToken| will not be the displayed token.
       const normalizedToken = normalizeString(innerHtmlToken);
       if (normalizedQuery.includes(normalizedToken)) {
@@ -185,14 +192,13 @@
       };
 
       // Maps the queryToken to the segment(s) of the html token that contain
-      // the queryToken interweaved with any of the ignored characters that were
+      // the queryToken interweaved with any of the hyphens that were
       // filtered out during normalization. For example, |innerHtmlToken| =
       // 'Wi-Fi-no-blankspsc-WiFi', (i.e. |normalizedToken| =
       // 'WiFinoblankspcWiFi') and |queryTokenLowerCaseNoSpecial| = 'wif', the
       // resulting mapping would be ['Wi-F', 'WiF'].
       const queryTokenToSegment = (queryToken) => {
-        const regExpStr =
-            queryToken.split('').join(`${IGNORED_CHARS_REGEX_STR}*`);
+        const regExpStr = queryToken.split('').join(`${HYPHENS_REGEX_STR}*`);
 
         // Since |queryToken| does not contain accents and |innerHtmlToken| may
         // have accents matches must be made without accents on characters.
@@ -207,7 +213,7 @@
       };
 
       // Contains lowercase segments of the innerHtmlToken that may or may not
-      // contain ignored characters and accents on characters.
+      // contain hyphens and accents on characters.
       const matches =
           queryTokens.filter(queryTokenFilter).map(queryTokenToSegment).flat();
 
@@ -230,7 +236,7 @@
     /**
      * Tokenize the result and query text, and match the tokens even if they
      * are out of order. Both the result and query text are tokenized by
-     * blankspaces, and compared without ignored characters or accents on
+     * blankspaces, and compared without hyphens or accents on
      * characters. As each result token is processed, it is compared with every
      * query token. Bold the segment of the result token that is a substring of
      * a query token. e.g. Smaller query block: if "wif on" is queried, a result
@@ -241,10 +247,10 @@
      * @private
      */
     getTokenizeMatchedBoldTagged_() {
-      // Lowercase and remove ignored characters from the query.
+      // Lowercase and remove hyphens from the query.
       const normalizedQuery = normalizeString(this.searchQuery);
 
-      // Use blankspace to tokenize the query without ignored characters.
+      // Use blankspace to tokenize the query without hyphens.
       const queryTokens = normalizedQuery.split(/\s/);
 
       // Get innerHtmlTokens with bold tags around matching segments.
diff --git a/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd b/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd
index 10d1469d..280fe278b 100644
--- a/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd
+++ b/chrome/browser/resources/settings/os_settings_resources_vulcanized.grd
@@ -88,6 +88,18 @@
                file="${root_gen_dir}\chrome\browser\ui\webui\settings\chromeos\search\user_action_recorder.mojom-lite.js"
                use_base_dir="false"
                type="BINDATA" />
+
+      <!-- Polymer3 related files-->
+      <include name="IDR_OS_SETTINGS_SETTINGS_ROLLUP_JS"
+               file="${root_gen_dir}\chrome\browser\resources\settings\chromeos\os_settings.rollup.js"
+               use_base_dir="false"
+               preprocess="true"
+               compress="gzip"
+               type="BINDATA" />
+      <include name="IDR_OS_SETTINGS_OS_SETTINGS_V3_HTML"
+               file="chromeos/os_settings_v3.html"
+               compress="false"
+               type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_page.js b/chrome/browser/resources/settings/safety_check_page/safety_check_page.js
index a3e8be2..9eb7c68 100644
--- a/chrome/browser/resources/settings/safety_check_page/safety_check_page.js
+++ b/chrome/browser/resources/settings/safety_check_page/safety_check_page.js
@@ -187,7 +187,7 @@
    * @private
    */
   showChromeCleanerChild_: function() {
-    return loadTimeData.valueExists('privacySettingsRedesignEnabled') &&
-        loadTimeData.getBoolean('privacySettingsRedesignEnabled');
+    return loadTimeData.valueExists('safetyCheckChromeCleanerChildEnabled') &&
+        loadTimeData.getBoolean('safetyCheckChromeCleanerChildEnabled');
   },
 });
diff --git a/chrome/browser/resources/settings/settings_resources_v3.grdp b/chrome/browser/resources/settings/settings_resources_v3.grdp
index 3ad6fbff..649a67ca 100644
--- a/chrome/browser/resources/settings/settings_resources_v3.grdp
+++ b/chrome/browser/resources/settings/settings_resources_v3.grdp
@@ -86,7 +86,11 @@
              file="autofill_page/blocking_request_manager.js"
              compress="false" type="BINDATA" />
   </if>
-    <include name="IDR_SETTINGS_AUTOFILL_PAGE_MERGE_PASSWORDS_STORE_COPIES_BEHAVIOR_JS"
+  <include name="IDR_SETTINGS_AUTOFILL_PAGE_MERGE_EXCEPTIONS_STORE_COPIES_BEHAVIOR_JS"
+           file="autofill_page/merge_exceptions_store_copies_behavior.js"
+           compress="false" type="BINDATA"
+           preprocess="true" />
+  <include name="IDR_SETTINGS_AUTOFILL_PAGE_MERGE_PASSWORDS_STORE_COPIES_BEHAVIOR_JS"
            file="autofill_page/merge_passwords_store_copies_behavior.js"
            compress="false" type="BINDATA"
            preprocess="true" />
diff --git a/chrome/browser/resources/tab_strip/tab_list.js b/chrome/browser/resources/tab_strip/tab_list.js
index a1524c0b..c6e0f31 100644
--- a/chrome/browser/resources/tab_strip/tab_list.js
+++ b/chrome/browser/resources/tab_strip/tab_list.js
@@ -98,7 +98,7 @@
 }
 
 /** @implements {DragManagerDelegate} */
-class TabListElement extends CustomElement {
+export class TabListElement extends CustomElement {
   static get template() {
     return `{__html_template__}`;
   }
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index d041bd3..4725ed5 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -242,6 +242,8 @@
       ]
       deps += [
         ":advanced_protection",
+        ":chrome_enterprise_url_lookup_service",
+        ":chrome_enterprise_url_lookup_service_factory",
         "//chrome/common/safe_browsing:archive_analyzer_results",
         "//chrome/common/safe_browsing:binary_feature_extractor",
         "//chrome/common/safe_browsing:disk_image_type_sniffer_mac",
@@ -278,6 +280,36 @@
   }
 }
 
+source_set("chrome_enterprise_url_lookup_service_factory") {
+  sources = [
+    "chrome_enterprise_url_lookup_service_factory.cc",
+    "chrome_enterprise_url_lookup_service_factory.h",
+  ]
+
+  deps = [
+    ":chrome_enterprise_url_lookup_service",
+    ":verdict_cache_manager_factory",
+    "//chrome/common",
+    "//components/keyed_service/content",
+    "//content/public/browser",
+  ]
+}
+
+source_set("chrome_enterprise_url_lookup_service") {
+  sources = [
+    "chrome_enterprise_url_lookup_service.cc",
+    "chrome_enterprise_url_lookup_service.h",
+  ]
+
+  deps = [
+    "//components/safe_browsing/core:realtimeapi_proto",
+    "//components/safe_browsing/core:verdict_cache_manager",
+    "//components/safe_browsing/core/realtime:policy_engine",
+    "//components/safe_browsing/core/realtime:url_lookup_service_base",
+    "//services/network/public/cpp:cpp",
+  ]
+}
+
 source_set("url_lookup_service_factory") {
   sources = [
     "url_lookup_service_factory.cc",
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc
new file mode 100644
index 0000000..68abd50
--- /dev/null
+++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.cc
@@ -0,0 +1,52 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h"
+
+#include "base/callback.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/dm_token_utils.h"
+#include "components/policy/core/common/cloud/dm_token.h"
+#include "components/safe_browsing/core/proto/realtimeapi.pb.h"
+#include "components/safe_browsing/core/realtime/policy_engine.h"
+#include "components/safe_browsing/core/realtime/url_lookup_service_base.h"
+#include "components/safe_browsing/core/verdict_cache_manager.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "url/gurl.h"
+
+namespace safe_browsing {
+
+ChromeEnterpriseRealTimeUrlLookupService::
+    ChromeEnterpriseRealTimeUrlLookupService(
+        scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+        VerdictCacheManager* cache_manager,
+        Profile* profile)
+    : RealTimeUrlLookupServiceBase(cache_manager),
+      url_loader_factory_(url_loader_factory),
+      profile_(profile) {}
+
+ChromeEnterpriseRealTimeUrlLookupService::
+    ~ChromeEnterpriseRealTimeUrlLookupService() = default;
+
+void ChromeEnterpriseRealTimeUrlLookupService::StartLookup(
+    const GURL& url,
+    RTLookupRequestCallback request_callback,
+    RTLookupResponseCallback response_callback) {
+  // TODO(crbug.com/1085261): Implement this method.
+}
+
+bool ChromeEnterpriseRealTimeUrlLookupService::CanPerformFullURLLookup() const {
+  return RealTimePolicyEngine::CanPerformEnterpriseFullURLLookup(
+      GetDMToken().is_valid(), profile_->IsOffTheRecord());
+}
+
+bool ChromeEnterpriseRealTimeUrlLookupService::CanCheckSubresourceURL() const {
+  return false;
+}
+
+policy::DMToken ChromeEnterpriseRealTimeUrlLookupService::GetDMToken() const {
+  return ::safe_browsing::GetDMToken(profile_);
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h
new file mode 100644
index 0000000..e0f12415
--- /dev/null
+++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h
@@ -0,0 +1,65 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SAFE_BROWSING_CHROME_ENTERPRISE_URL_LOOKUP_SERVICE_H_
+#define CHROME_BROWSER_SAFE_BROWSING_CHROME_ENTERPRISE_URL_LOOKUP_SERVICE_H_
+
+#include <memory>
+#include <string>
+
+#include "components/safe_browsing/core/realtime/url_lookup_service_base.h"
+#include "url/gurl.h"
+
+namespace network {
+class SharedURLLoaderFactory;
+}  // namespace network
+
+namespace policy {
+class DMToken;
+}  // namespace policy
+
+class Profile;
+
+namespace safe_browsing {
+
+// This class implements the real time lookup feature for a given user/profile.
+// It is separated from the base class for logic that is related to enterprise
+// users.(See: go/chrome-protego-enterprise-dd)
+class ChromeEnterpriseRealTimeUrlLookupService
+    : public RealTimeUrlLookupServiceBase {
+ public:
+  ChromeEnterpriseRealTimeUrlLookupService(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
+      VerdictCacheManager* cache_manager,
+      Profile* profile);
+  ~ChromeEnterpriseRealTimeUrlLookupService() override;
+
+  // RealTimeUrlLookupServiceBase:
+  bool CanPerformFullURLLookup() const override;
+
+  bool CanCheckSubresourceURL() const override;
+
+  void StartLookup(const GURL& url,
+                   RTLookupRequestCallback request_callback,
+                   RTLookupResponseCallback response_callback) override;
+
+ private:
+  policy::DMToken GetDMToken() const;
+
+  // The URLLoaderFactory we use to issue network requests.
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+
+  // Unowned object used for checking profile based settings.
+  Profile* profile_;
+
+  base::WeakPtrFactory<ChromeEnterpriseRealTimeUrlLookupService> weak_factory_{
+      this};
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeEnterpriseRealTimeUrlLookupService);
+
+};  // class ChromeEnterpriseRealTimeUrlLookupService
+
+}  // namespace safe_browsing
+
+#endif  // CHROME_BROWSER_SAFE_BROWSING_CHROME_ENTERPRISE_URL_LOOKUP_SERVICE_H_
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.cc b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.cc
new file mode 100644
index 0000000..757d448f
--- /dev/null
+++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.cc
@@ -0,0 +1,57 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.h"
+
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service.h"
+#include "chrome/browser/safe_browsing/safe_browsing_service.h"
+#include "chrome/browser/safe_browsing/verdict_cache_manager_factory.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/safe_browsing/core/verdict_cache_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.h"
+
+namespace safe_browsing {
+
+// static
+ChromeEnterpriseRealTimeUrlLookupService*
+ChromeEnterpriseRealTimeUrlLookupServiceFactory::GetForProfile(
+    Profile* profile) {
+  return static_cast<ChromeEnterpriseRealTimeUrlLookupService*>(
+      GetInstance()->GetServiceForBrowserContext(profile, /* create= */ true));
+}
+
+// static
+ChromeEnterpriseRealTimeUrlLookupServiceFactory*
+ChromeEnterpriseRealTimeUrlLookupServiceFactory::GetInstance() {
+  return base::Singleton<
+      ChromeEnterpriseRealTimeUrlLookupServiceFactory>::get();
+}
+
+ChromeEnterpriseRealTimeUrlLookupServiceFactory::
+    ChromeEnterpriseRealTimeUrlLookupServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "ChromeEnterpriseRealTimeUrlLookupService",
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(VerdictCacheManagerFactory::GetInstance());
+}
+
+KeyedService*
+ChromeEnterpriseRealTimeUrlLookupServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  if (!g_browser_process->safe_browsing_service()) {
+    return nullptr;
+  }
+  Profile* profile = Profile::FromBrowserContext(context);
+  auto url_loader_factory =
+      std::make_unique<network::CrossThreadPendingSharedURLLoaderFactory>(
+          g_browser_process->safe_browsing_service()->GetURLLoaderFactory());
+  return new ChromeEnterpriseRealTimeUrlLookupService(
+      network::SharedURLLoaderFactory::Create(std::move(url_loader_factory)),
+      VerdictCacheManagerFactory::GetForProfile(profile), profile);
+}
+
+}  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.h b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.h
new file mode 100644
index 0000000..56d7cdc5
--- /dev/null
+++ b/chrome/browser/safe_browsing/chrome_enterprise_url_lookup_service_factory.h
@@ -0,0 +1,52 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SAFE_BROWSING_CHROME_ENTERPRISE_URL_LOOKUP_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_SAFE_BROWSING_CHROME_ENTERPRISE_URL_LOOKUP_SERVICE_FACTORY_H_
+
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class KeyedService;
+class Profile;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace safe_browsing {
+
+class ChromeEnterpriseRealTimeUrlLookupService;
+
+// Singleton that owns ChromeEnterpriseRealTimeUrlLookupService objects, one for
+// each active Profile. It listens to profile destroy events and destroy its
+// associated service. It returns nullptr if the profile is in the Incognito
+// mode.
+class ChromeEnterpriseRealTimeUrlLookupServiceFactory
+    : public BrowserContextKeyedServiceFactory {
+ public:
+  // Creates the service if it doesn't exist already for the given |profile|.
+  // If the service already exists, return its pointer.
+  static ChromeEnterpriseRealTimeUrlLookupService* GetForProfile(
+      Profile* profile);
+
+  // Get the singleton instance.
+  static ChromeEnterpriseRealTimeUrlLookupServiceFactory* GetInstance();
+
+ private:
+  friend struct base::DefaultSingletonTraits<
+      ChromeEnterpriseRealTimeUrlLookupServiceFactory>;
+
+  ChromeEnterpriseRealTimeUrlLookupServiceFactory();
+  ~ChromeEnterpriseRealTimeUrlLookupServiceFactory() override = default;
+
+  // BrowserContextKeyedServiceFactory:
+  KeyedService* BuildServiceInstanceFor(
+      content::BrowserContext* context) const override;
+
+  DISALLOW_COPY_AND_ASSIGN(ChromeEnterpriseRealTimeUrlLookupServiceFactory);
+};
+
+}  // namespace safe_browsing
+#endif  // CHROME_BROWSER_SAFE_BROWSING_CHROME_ENTERPRISE_URL_LOOKUP_SERVICE_FACTORY_H_
diff --git a/chrome/browser/safe_browsing/client_side_detection_host.cc b/chrome/browser/safe_browsing/client_side_detection_host.cc
index f351843..7551a47 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host.cc
@@ -390,17 +390,10 @@
     if (IsSafeBrowsingEnabled(*profile->GetPrefs())) {
       if (IsExtendedReportingEnabled(*profile->GetPrefs()) ||
           IsEnhancedProtectionEnabled(*profile->GetPrefs())) {
-        DVLOG(2) << "Sending phishing model " << model_loader_extended->name()
-                 << " to RenderFrameHost @" << frame;
         model = model_loader_extended->model_str();
       } else {
-        DVLOG(2) << "Sending phishing model " << model_loader_standard->name()
-                 << " to RenderFrameHost @" << frame;
         model = model_loader_standard->model_str();
       }
-    } else {
-      DVLOG(2) << "Disabling client-side phishing detection for "
-               << "RenderFrameHost @" << frame;
     }
 
     if (phishing_detector_)
diff --git a/chrome/browser/safe_browsing/client_side_detection_service.cc b/chrome/browser/safe_browsing/client_side_detection_service.cc
index 072c981..87e5ef4 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service.cc
@@ -10,7 +10,6 @@
 #include "base/bind.h"
 #include "base/containers/queue.h"
 #include "base/location.h"
-#include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_functions.h"
@@ -260,8 +259,6 @@
     request->mutable_population()->set_user_population(
         ChromeUserPopulation::SAFE_BROWSING);
   }
-  DVLOG(2) << "Starting report for hit on model " << request->model_filename();
-
   request->mutable_population()->set_profile_management_status(
       GetProfileManagementStatus(
           g_browser_process->browser_policy_connector()));
@@ -269,7 +266,6 @@
   std::string request_data;
   if (!request->SerializeToString(&request_data)) {
     UMA_HISTOGRAM_COUNTS_1M("SBClientPhishing.RequestNotSerialized", 1);
-    DVLOG(1) << "Unable to serialize the CSD request. Proto file changed?";
     if (!callback.is_null())
       callback.Run(GURL(request->url()), false);
     return;
@@ -352,10 +348,6 @@
     cache_[info->phishing_url] =
         base::WrapUnique(new CacheState(response.phishy(), base::Time::Now()));
     is_phishing = response.phishy();
-  } else {
-    DLOG(ERROR) << "Unable to get the server verdict for URL: "
-                << info->phishing_url << " net_error: " << net_error << " "
-                << "response_code:" << response_code;
   }
   if (!info->callback.is_null())
     info->callback.Run(info->phishing_url, is_phishing);
diff --git a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
index f5ce201..4bd8502 100644
--- a/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_service_unittest.cc
@@ -135,12 +135,6 @@
     return csd_service_->phishing_report_times_;
   }
 
-  void SetCache(const GURL& gurl, bool is_phishing, base::Time time) {
-    csd_service_->cache_[gurl] =
-        std::make_unique<ClientSideDetectionService::CacheState>(is_phishing,
-                                                                 time);
-  }
-
   void TestCache() {
     auto& cache = csd_service_->cache_;
     base::Time now = base::Time::Now();
@@ -193,21 +187,6 @@
     EXPECT_TRUE(is_phishing);
   }
 
-  void AddFeature(const std::string& name, double value,
-                  ClientPhishingRequest* request) {
-    ClientPhishingRequest_Feature* feature = request->add_feature_map();
-    feature->set_name(name);
-    feature->set_value(value);
-  }
-
-  void AddNonModelFeature(const std::string& name, double value,
-                          ClientPhishingRequest* request) {
-    ClientPhishingRequest_Feature* feature =
-        request->add_non_model_feature_map();
-    feature->set_name(name);
-    feature->set_value(value);
-  }
-
  protected:
   content::BrowserTaskEnvironment task_environment_;
   std::unique_ptr<ClientSideDetectionService> csd_service_;
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
index 5d92ccf9..b47f131 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
@@ -368,12 +368,30 @@
 
     // The BinaryFCMService will handle all recoverable errors. In case of
     // unrecoverable error, there's nothing we can do here.
-    binary_fcm_service_->UnregisterInstanceID(instance_id, base::DoNothing());
+    binary_fcm_service_->UnregisterInstanceID(
+        instance_id,
+        base::BindOnce(&BinaryUploadService::InstanceIDUnregisteredCallback,
+                       weakptr_factory_.GetWeakPtr()));
+  } else {
+    // |binary_fcm_service_| can be null in tests, but
+    // InstanceIDUnregisteredCallback should be called anyway so the requests
+    // waiting on authentication can complete.
+    InstanceIDUnregisteredCallback(true);
   }
 
   active_tokens_.erase(token_it);
 }
 
+void BinaryUploadService::InstanceIDUnregisteredCallback(bool) {
+  // Calling RunAuthorizationCallbacks after the instance ID of the initial
+  // authentication is unregistered avoids registration/unregistration conflicts
+  // with normal requests.
+  if (!authorization_callbacks_.empty() &&
+      can_upload_enterprise_data_.has_value()) {
+    RunAuthorizationCallbacks();
+  }
+}
+
 void BinaryUploadService::RecordRequestMetrics(
     Request* request,
     Result result,
@@ -420,7 +438,7 @@
   deep_scanning_request_.set_fcm_notification_token(token);
 }
 
-void BinaryUploadService::Request::set_dm_token(const std::string& token) {
+void BinaryUploadService::Request::set_device_token(const std::string& token) {
   deep_scanning_request_.set_dm_token(token);
 }
 
@@ -492,7 +510,7 @@
       auto request = std::make_unique<ValidateDataUploadRequest>(base::BindOnce(
           &BinaryUploadService::ValidateDataUploadRequestCallback,
           weakptr_factory_.GetWeakPtr()));
-      request->set_dm_token(dm_token.value());
+      request->set_device_token(dm_token.value());
       UploadForDeepScanning(std::move(request));
     }
     return;
@@ -505,7 +523,6 @@
     DeepScanningClientResponse response) {
   pending_validate_data_upload_request_ = false;
   can_upload_enterprise_data_ = result == BinaryUploadService::Result::SUCCESS;
-  RunAuthorizationCallbacks();
 }
 
 void BinaryUploadService::RunAuthorizationCallbacks() {
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
index d57dea3..b7c7894 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
@@ -134,7 +134,7 @@
     void set_request_malware_scan(
         MalwareDeepScanningClientRequest malware_request);
     void set_fcm_token(const std::string& token);
-    void set_dm_token(const std::string& token);
+    void set_device_token(const std::string& token);
     void set_request_token(const std::string& token);
     void set_filename(const std::string& filename);
     void set_digest(const std::string& digest);
@@ -173,6 +173,11 @@
   // different URL than scans for Advanced Protection users.
   static GURL GetUploadUrl(bool is_advanced_protection_request);
 
+ protected:
+  void FinishRequest(Request* request,
+                     Result result,
+                     DeepScanningClientResponse response);
+
  private:
   friend class BinaryUploadServiceTest;
 
@@ -197,10 +202,6 @@
 
   void OnTimeout(Request* request);
 
-  void FinishRequest(Request* request,
-                     Result result,
-                     DeepScanningClientResponse response);
-
   bool IsActive(Request* request);
 
   void MaybeUploadForDeepScanningCallback(std::unique_ptr<Request> request,
@@ -210,6 +211,9 @@
   void ValidateDataUploadRequestCallback(BinaryUploadService::Result result,
                                          DeepScanningClientResponse response);
 
+  // Callback once a request's instance ID is unregistered.
+  void InstanceIDUnregisteredCallback(bool);
+
   void RecordRequestMetrics(Request* request,
                             Result result,
                             const DeepScanningClientResponse& response);
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
index d595d6b3..ae624bc 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
@@ -569,9 +569,9 @@
     request->set_request_malware_scan(std::move(malware_request));
   }
 
-  request->set_dm_token(GetDMToken(Profile::FromBrowserContext(
-                                       web_contents_->GetBrowserContext()))
-                            .value());
+  request->set_device_token(GetDMToken(Profile::FromBrowserContext(
+                                           web_contents_->GetBrowserContext()))
+                                .value());
 }
 
 void DeepScanningDialogDelegate::FillAllResultsWith(bool status) {
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc
index 420a6cf..607efe6 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc
@@ -46,8 +46,8 @@
   // Finish the authentication request. Called after ShowForWebContents to
   // simulate an async callback.
   void ReturnAuthorizedResponse() {
-    authorization_request_->FinishRequest(authorization_result_,
-                                          DeepScanningClientResponse());
+    FinishRequest(authorization_request_.get(), authorization_result_,
+                  DeepScanningClientResponse());
   }
 
   void SetResponseForText(BinaryUploadService::Result result,
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc
index 5f2f56b80..090ce95d 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.cc
@@ -129,7 +129,12 @@
         base::Time::Now() - start_time_);
     std::move(callback_).Run(/*success=*/true, *response_body.get());
   } else {
-    if (retry_count_ < kMaxRetryAttempts) {
+    if (response_code < 500 || retry_count_ >= kMaxRetryAttempts) {
+      RecordUploadSuccessHistogram(/*success=*/false);
+      base::UmaHistogramMediumTimes("SBMultipartUploader.FailedUploadDuration",
+                                    base::Time::Now() - start_time_);
+      std::move(callback_).Run(/*success=*/false, *response_body.get());
+    } else {
       content::GetUIThreadTaskRunner({})->PostDelayedTask(
           FROM_HERE,
           base::BindOnce(&MultipartUploadRequest::SendRequest,
@@ -137,11 +142,6 @@
           current_backoff_);
       current_backoff_ *= kBackoffFactor;
       retry_count_++;
-    } else {
-      RecordUploadSuccessHistogram(/*success=*/false);
-      base::UmaHistogramMediumTimes("SBMultipartUploader.FailedUploadDuration",
-                                    base::Time::Now() - start_time_);
-      std::move(callback_).Run(/*success=*/false, *response_body.get());
     }
   }
 }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader_unittest.cc
index fd09ce0..fc1a70b 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader_unittest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader_unittest.cc
@@ -64,16 +64,30 @@
 }
 
 TEST_F(MultipartUploadRequestTest, RetriesCorrectly) {
-  MockMultipartUploadRequest mock_request;
+  {
+    MockMultipartUploadRequest mock_request;
 
-  EXPECT_CALL(mock_request, SendRequest())
-      .Times(3)
-      .WillRepeatedly(Invoke([&mock_request]() {
-        mock_request.RetryOrFinish(net::OK, net::HTTP_BAD_REQUEST,
-                                   std::make_unique<std::string>("response"));
-      }));
-  mock_request.Start();
-  task_environment_.FastForwardUntilNoTasksRemain();
+    EXPECT_CALL(mock_request, SendRequest())
+        .Times(1)
+        .WillRepeatedly(Invoke([&mock_request]() {
+          mock_request.RetryOrFinish(net::OK, net::HTTP_BAD_REQUEST,
+                                     std::make_unique<std::string>("response"));
+        }));
+    mock_request.Start();
+    task_environment_.FastForwardUntilNoTasksRemain();
+  }
+  {
+    MockMultipartUploadRequest mock_request;
+
+    EXPECT_CALL(mock_request, SendRequest())
+        .Times(3)
+        .WillRepeatedly(Invoke([&mock_request]() {
+          mock_request.RetryOrFinish(net::OK, net::HTTP_SERVICE_UNAVAILABLE,
+                                     std::make_unique<std::string>("response"));
+        }));
+    mock_request.Start();
+    task_environment_.FastForwardUntilNoTasksRemain();
+  }
 }
 
 TEST_F(MultipartUploadRequestTest,
@@ -109,7 +123,7 @@
 
     histograms.ExpectUniqueSample(
         "SBMultipartUploader.NetworkRequestResponseCodeOrError",
-        net::HTTP_FORBIDDEN, 3);
+        net::HTTP_FORBIDDEN, 1);
   }
 
   {
@@ -126,7 +140,24 @@
 
     histograms.ExpectUniqueSample(
         "SBMultipartUploader.NetworkRequestResponseCodeOrError",
-        net::ERR_FAILED, 3);
+        net::ERR_FAILED, 1);
+  }
+
+  {
+    base::HistogramTester histograms;
+    MockMultipartUploadRequest mock_request;
+
+    EXPECT_CALL(mock_request, SendRequest())
+        .WillRepeatedly(Invoke([&mock_request]() {
+          mock_request.RetryOrFinish(net::OK, net::HTTP_INTERNAL_SERVER_ERROR,
+                                     std::make_unique<std::string>("response"));
+        }));
+    mock_request.Start();
+    task_environment_.FastForwardUntilNoTasksRemain();
+
+    histograms.ExpectUniqueSample(
+        "SBMultipartUploader.NetworkRequestResponseCodeOrError",
+        net::HTTP_INTERNAL_SERVER_ERROR, 3);
   }
 }
 
diff --git a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
index c3d71da..45677491 100644
--- a/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
+++ b/chrome/browser/safe_browsing/download_protection/deep_scanning_request.cc
@@ -213,7 +213,7 @@
     request->set_request_malware_scan(std::move(malware_request));
   } else if (trigger_ == DeepScanTrigger::TRIGGER_POLICY) {
     policy::DMToken dm_token = GetDMToken(profile);
-    request->set_dm_token(dm_token.value());
+    request->set_device_token(dm_token.value());
 
     if (base::FeatureList::IsEnabled(kContentComplianceEnabled) &&
         (analysis_settings_.tags.count("dlp") == 1)) {
diff --git a/chrome/browser/safe_browsing/safe_browsing_tab_observer.cc b/chrome/browser/safe_browsing/safe_browsing_tab_observer.cc
index 73adb513..8602f91 100644
--- a/chrome/browser/safe_browsing/safe_browsing_tab_observer.cc
+++ b/chrome/browser/safe_browsing/safe_browsing_tab_observer.cc
@@ -87,11 +87,6 @@
   } else {
     safebrowsing_detection_host_.reset();
   }
-
-  content::RenderFrameHost* rfh = web_contents_->GetMainFrame();
-  mojo::AssociatedRemote<chrome::mojom::ChromeRenderFrame> client;
-  rfh->GetRemoteAssociatedInterfaces()->GetInterface(&client);
-  client->SetClientSidePhishingDetection(safe_browsing);
 #endif
 }
 
diff --git a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
index 576916f..9e2f1f45 100644
--- a/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
+++ b/chrome/browser/safe_browsing/url_checker_delegate_impl.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/profiles/profile_io_data.h"
 #include "chrome/browser/safe_browsing/ui_manager.h"
 #include "chrome/browser/safe_browsing/user_interaction_observer.h"
-#include "components/prerender/prerender_final_status.h"
+#include "components/prerender/common/prerender_final_status.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/safe_browsing/content/triggers/suspicious_site_trigger.h"
 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
diff --git a/chrome/browser/search_engines/chrome_template_url_service_client.cc b/chrome/browser/search_engines/chrome_template_url_service_client.cc
index 0d55f291..ef3abcd 100644
--- a/chrome/browser/search_engines/chrome_template_url_service_client.cc
+++ b/chrome/browser/search_engines/chrome_template_url_service_client.cc
@@ -8,8 +8,7 @@
 
 ChromeTemplateURLServiceClient::ChromeTemplateURLServiceClient(
     history::HistoryService* history_service)
-    : owner_(NULL),
-      history_service_(history_service) {
+    : owner_(nullptr), history_service_(history_service) {
   // TODO(sky): bug 1166191. The keywords should be moved into the history
   // db, which will mean we no longer need this notification and the history
   // backend can handle automatically adding the search terms as the user
diff --git a/chrome/browser/sessions/tab_restore_service_unittest.cc b/chrome/browser/sessions/tab_restore_service_unittest.cc
index 29969982..f3f9172 100644
--- a/chrome/browser/sessions/tab_restore_service_unittest.cc
+++ b/chrome/browser/sessions/tab_restore_service_unittest.cc
@@ -80,7 +80,7 @@
         user_agent_override_(blink::UserAgentOverride::UserAgentOnly(
             "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.19"
             " (KHTML, like Gecko) Chrome/18.0.1025.45 Safari/535.19")),
-        time_factory_(NULL),
+        time_factory_(nullptr),
         window_id_(SessionID::FromSerializedValue(1)),
         tab_id_(SessionID::FromSerializedValue(2)) {
     user_agent_override_.ua_metadata_override.emplace();
diff --git a/chrome/browser/share/DEPS b/chrome/browser/share/DEPS
index b67d2d4..6c3dfff 100644
--- a/chrome/browser/share/DEPS
+++ b/chrome/browser/share/DEPS
@@ -2,6 +2,7 @@
   # TODO(crbug/1022172): Remove this dependency when ShareActivity is moved to
   # chrome/browser/share.
   "+chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java",
+  "+chrome/android/java/src/org/chromium/chrome/browser/FileProviderHelper.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java",
   "+chrome/android/java/src/org/chromium/chrome/browser/document/ChromeLauncherActivity.java",
@@ -20,6 +21,13 @@
   "+chrome/services/qrcode_generator",
   "+components/browser_ui/notifications/android",
   "+components/browser_ui/share/android",
+  "+components/browser_ui/android/bottomsheet",
   "+content/public/android/java/src/org/chromium/content_public/browser/RenderWidgetHostView.java",
   "+content/public/android/java/src/org/chromium/content_public/browser/WebContents.java",
+
+  # TODO(crbug/1002277): Remove once BottomSheetController is modularized.
+  "+chrome/android/java/src/org/chromium/chrome/browser/widget/bottomsheet",
+
+  # TODO(crbug/1090917): Remove this dependency once the STTS java code is moved.
+  "+chrome/android/java/src/org/chromium/chrome/browser/send_tab_to_self/SendTabToSelfShareActivity.java",
 ]
diff --git a/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml b/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml
index bdfd64c..dd85e4f 100644
--- a/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml
+++ b/chrome/browser/share/android/java/res/layout/screenshot_share_sheet.xml
@@ -12,6 +12,8 @@
         android:layout_width="match_parent"
         android:layout_height="match_parent">
 
+    <!-- TODO (crbug.com/1034733) Fix that this button is being 
+    partially covered by the iamgeview -->
         <org.chromium.ui.widget.ChromeImageButton
             android:id="@+id/close_button"
             style="@style/ToolbarButton"
@@ -19,64 +21,84 @@
             android:contentDescription="@string/close"
             app:tint="@color/default_icon_color_tint_list" />
 
-       <!-- TODO: Add a frame layout to hold the screenshot preview.  -->
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
 
-       <LinearLayout
-           android:layout_width="match_parent"
-           android:layout_height="56dp"
-           android:layout_marginStart="36dp"
-           android:layout_marginEnd="36dp"
-           android:weightSum="4"
-           android:orientation="horizontal"
-           android:layout_gravity="start|bottom">
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="0dp"
+                android:layout_weight="1">
 
-           <TextView
-               android:id="@+id/edit"
-               android:text="@string/screenshot_edit_title"
-               style="@style/SplitToolbarButton"
-               android:drawableTop="@drawable/edit"
-               android:layout_weight="1"
-               android:gravity="center"
-               android:layout_gravity="end|bottom"
-               android:background="?attr/selectableItemBackgroundBorderless"
-               app:tint="@color/default_icon_color_tint_list" />
+                <org.chromium.ui.widget.ChromeImageView
+                    android:id="@+id/screenshot"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:gravity="center_horizontal"
+                    android:layout_gravity="center_horizontal"
+                    android:padding="16dp" />
 
-           <TextView
-               android:id="@+id/delete"
-               android:text="@string/screenshot_delete_title"
-               style="@style/SplitToolbarButton"
-               android:drawableTop="@drawable/delete"
-               android:layout_weight="1"
-               android:gravity="center"
-               android:layout_gravity="center|bottom"
-               android:background="?attr/selectableItemBackgroundBorderless"
-               app:tint="@color/default_icon_color_tint_list" />
+            </FrameLayout>
 
-           <TextView
-               android:id="@+id/save"
-               android:text="@string/screenshot_save_title"
-               style="@style/SplitToolbarButton"
-               android:drawableTop="@drawable/save"
-               android:layout_weight="1"
-               android:gravity="center"
-               android:layout_gravity="center|bottom"
-               android:background="?attr/selectableItemBackgroundBorderless"
-               app:tint="@color/default_icon_color_tint_list" />
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="56dp"
+                android:layout_marginStart="36dp"
+                android:layout_marginEnd="36dp"
+                android:weightSum="4"
+                android:orientation="horizontal"
+                android:gravity="bottom"
+                android:layout_gravity="start|bottom">
 
-           <TextView
-               android:id="@+id/share"
-               android:text="@string/screenshot_share_title"
-               style="@style/SplitToolbarButton"
-               android:drawableTop="@drawable/share"
-               android:layout_weight="1"
-               android:gravity="center"
-               android:layout_gravity="start|bottom"
-               android:background="?attr/selectableItemBackgroundBorderless"
-               app:tint="@color/default_icon_color_tint_list" />
+                <TextView
+                    android:id="@+id/edit"
+                    android:text="@string/screenshot_edit_title"
+                    style="@style/SplitToolbarButton"
+                    android:drawableTop="@drawable/edit"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:layout_gravity="end|bottom"
+                    android:background="?attr/selectableItemBackgroundBorderless"
+                    app:tint="@color/default_icon_color_tint_list" />
+
+                <TextView
+                    android:id="@+id/delete"
+                    android:text="@string/screenshot_delete_title"
+                    style="@style/SplitToolbarButton"
+                    android:drawableTop="@drawable/delete"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:layout_gravity="center|bottom"
+                    android:background="?attr/selectableItemBackgroundBorderless"
+                    app:tint="@color/default_icon_color_tint_list" />
+
+                <TextView
+                    android:id="@+id/save"
+                    android:text="@string/screenshot_save_title"
+                    style="@style/SplitToolbarButton"
+                    android:drawableTop="@drawable/save"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:layout_gravity="center|bottom"
+                    android:background="?attr/selectableItemBackgroundBorderless"
+                    app:tint="@color/default_icon_color_tint_list" />
+
+                <TextView
+                    android:id="@+id/share"
+                    android:text="@string/screenshot_share_title"
+                    style="@style/SplitToolbarButton"
+                    android:drawableTop="@drawable/share"
+                    android:layout_weight="1"
+                    android:gravity="center"
+                    android:layout_gravity="start|bottom"
+                    android:background="?attr/selectableItemBackgroundBorderless"
+                    app:tint="@color/default_icon_color_tint_list" />
+
+            </LinearLayout>
 
         </LinearLayout>
 
-
     </RelativeLayout>
 
 </org.chromium.chrome.browser.share.screenshot.ScreenshotShareSheetView>
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotCoordinator.java
index 1511fb9..1334cb1 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotCoordinator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotCoordinator.java
@@ -78,7 +78,8 @@
      * Opens the screenshot sharesheet.
      */
     private void launchSharesheet() {
-        ScreenshotShareSheetCoordinator shareSheet = new ScreenshotShareSheetCoordinator(mActivity);
+        ScreenshotShareSheetDialogCoordinator shareSheet =
+                new ScreenshotShareSheetDialogCoordinator(mActivity, mScreenshot);
         shareSheet.showShareSheet();
         mScreenshot = null;
     }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetCoordinator.java
index 75e14d92..956a937 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetCoordinator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetCoordinator.java
@@ -4,39 +4,41 @@
 
 package org.chromium.chrome.browser.share.screenshot;
 
-import android.app.Activity;
-import android.app.FragmentManager;
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
 
 /**
  * Coordinator for displaying the screenshot share sheet.
  */
 public class ScreenshotShareSheetCoordinator {
-    private final ScreenshotShareSheetDialog mDialog;
-    private final FragmentManager mFragmentManager;
+    private final ScreenshotShareSheetMediator mMediator;
+    private final PropertyModel mModel;
 
     /**
      * Constructs a new ShareSheetCoordinator.
      *
      * @param context The context to use for user permissions.
+     * @param screenshot The screenshot to be shared.
+     * @param deleteRunanble The runnable to be called on cancel or delete.
+     * @param screenshotShareSheetView the view for the screenshot share sheet.
      */
-    public ScreenshotShareSheetCoordinator(Activity activity) {
-        mDialog = new ScreenshotShareSheetDialog();
+    public ScreenshotShareSheetCoordinator(Context context, Bitmap screenshot,
+            Runnable deleteRunnable, ScreenshotShareSheetView screenshotShareSheetView) {
+        ArrayList<PropertyKey> allProperties =
+                new ArrayList<>(Arrays.asList(ScreenshotShareSheetViewProperties.ALL_KEYS));
+        mModel = new PropertyModel(allProperties);
 
-        mFragmentManager = activity.getFragmentManager();
-        // TODO(crbug/1024586) Flesh out MVC for the upstream screenshot MVC.
-    }
+        mModel.set(ScreenshotShareSheetViewProperties.SCREENSHOT_BITMAP, screenshot);
+        mMediator = new ScreenshotShareSheetMediator(mModel, deleteRunnable);
 
-    /**
-     * Show the main share sheet dialog.
-     */
-    protected void showShareSheet() {
-        mDialog.show(mFragmentManager, null);
-    }
-
-    /**
-     * Dismiss the main dialog.
-     */
-    public void dismiss() {
-        mDialog.dismiss();
+        PropertyModelChangeProcessor.create(
+                mModel, screenshotShareSheetView, ScreenshotShareSheetViewBinder::bind);
     }
 }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialog.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialog.java
index 74d5457..25ba769 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialog.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialog.java
@@ -7,25 +7,37 @@
 import android.app.Dialog;
 import android.app.DialogFragment;
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.os.Bundle;
-import android.view.View;
 
 import androidx.appcompat.app.AlertDialog;
 
 import org.chromium.chrome.R;
-import org.chromium.ui.widget.ChromeImageButton;
 
 /**
  * ScreenshotShareSheetDialog is the main view for sharing non edited screenshots.
  */
 public class ScreenshotShareSheetDialog extends DialogFragment {
     private Context mContext;
+    private ScreenshotShareSheetView mDialogView;
+    private Bitmap mScreenshot;
+    private Runnable mDeleteRunnable;
 
     /**
      * The ScreenshotShareSheetDialog constructor.
      */
     public ScreenshotShareSheetDialog() {}
 
+    /**
+     * Initialize the dialog outside of the constructor as fragments require default constructor.
+     * @param screenshot The screenshot image to show.
+     * @param deleteRunnable The function to call on delete.
+     */
+    public void init(Bitmap screenshot, Runnable deleteRunnable) {
+        mScreenshot = screenshot;
+        mDeleteRunnable = deleteRunnable;
+    }
+
     @Override
     public void onAttach(Context context) {
         super.onAttach(context);
@@ -36,18 +48,13 @@
     public Dialog onCreateDialog(Bundle savedInstanceState) {
         AlertDialog.Builder builder =
                 new AlertDialog.Builder(getActivity(), R.style.Theme_Chromium_Fullscreen);
-        builder.setView(getDialogView());
-        return builder.create();
-    }
-
-    private View getDialogView() {
-        ScreenshotShareSheetView dialogView =
+        ScreenshotShareSheetView screenshotShareSheetView =
                 (ScreenshotShareSheetView) getActivity().getLayoutInflater().inflate(
                         org.chromium.chrome.browser.share.R.layout.screenshot_share_sheet, null);
-        ChromeImageButton closeButton =
-                (ChromeImageButton) dialogView.findViewById(R.id.close_button);
-        closeButton.setOnClickListener(v -> dismiss());
+        builder.setView(screenshotShareSheetView);
 
-        return dialogView;
+        ScreenshotShareSheetCoordinator shareCoordinator = new ScreenshotShareSheetCoordinator(
+                mContext, mScreenshot, mDeleteRunnable, screenshotShareSheetView);
+        return builder.create();
     }
 }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialogCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialogCoordinator.java
new file mode 100644
index 0000000..f817c39
--- /dev/null
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialogCoordinator.java
@@ -0,0 +1,45 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.share.screenshot;
+
+import android.app.Activity;
+import android.app.FragmentManager;
+import android.graphics.Bitmap;
+
+/**
+ * Coordinator for displaying the screenshot share sheet dialog.
+ */
+public class ScreenshotShareSheetDialogCoordinator {
+    private final ScreenshotShareSheetDialog mDialog;
+    private final FragmentManager mFragmentManager;
+    private final Bitmap mScreenshot;
+
+    /**
+     * Constructs a new ShareSheetCoordinator.
+     *
+     * @param context The context to use for user permissions.
+     * @param screenshot The screenshot to be shared.
+     */
+    public ScreenshotShareSheetDialogCoordinator(Activity activity, Bitmap screenshot) {
+        mFragmentManager = activity.getFragmentManager();
+        mScreenshot = screenshot;
+        mDialog = new ScreenshotShareSheetDialog();
+        mDialog.init(mScreenshot, this::dismiss);
+    }
+
+    /**
+     * Show the main share sheet dialog.
+     */
+    protected void showShareSheet() {
+        mDialog.show(mFragmentManager, null);
+    }
+
+    /**
+     * Dismiss the main dialog.
+     */
+    public void dismiss() {
+        mDialog.dismiss();
+    }
+}
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java
index 11c6a3b..9c7a1a0 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java
@@ -4,25 +4,56 @@
 
 package org.chromium.chrome.browser.share.screenshot;
 
-import android.content.Context;
-
+import org.chromium.chrome.browser.share.screenshot.ScreenshotShareSheetViewProperties.NoArgOperation;
 import org.chromium.ui.modelutil.PropertyModel;
 
 /**
  * ScreenshotShareSheetMediator is in charge of calculating and setting values for
  * ScreenshotShareSheetViewProperties.
  */
-class ScreenshotShareSheetMediator implements ShareImageFileUtils.OnImageSaveListener {
-    private final Context mContext;
-    private final PropertyModel mPropertyModel;
+class ScreenshotShareSheetMediator {
+    private final PropertyModel mModel;
 
+    private final Runnable mDeleteRunnable;
     /**
      * The ScreenshotShareSheetMediator constructor.
      * @param context The context to use.
      * @param propertyModel The property modelto use to communicate with views.
      */
-    ScreenshotShareSheetMediator(Context context, PropertyModel propertyModel) {
-        mContext = context;
-        mPropertyModel = propertyModel;
+    ScreenshotShareSheetMediator(PropertyModel propertyModel, Runnable deleteRunnable) {
+        mDeleteRunnable = deleteRunnable;
+        mModel = propertyModel;
+        mModel.set(ScreenshotShareSheetViewProperties.NO_ARG_OPERATION_LISTENER,
+                operation -> { performNoArgOperation(operation); });
+    }
+
+    /**
+     * Performs the operation passed in.
+     *
+     * @param operation The operation to perform.
+     */
+    public void performNoArgOperation(
+            @ScreenshotShareSheetViewProperties.NoArgOperation int operation) {
+        if (NoArgOperation.SHARE == operation) {
+            share();
+        } else if (NoArgOperation.SAVE == operation) {
+            save();
+        } else if (NoArgOperation.DELETE == operation) {
+            mDeleteRunnable.run();
+        }
+    }
+
+    /**
+     * Sends the current image to the share target.
+     */
+    private void share() {
+        // TODO(crbug/1024586): export image
+    }
+
+    /**
+     * Saves the current image.
+     */
+    private void save() {
+        // TODO(crbug/1024586):save image
     }
 }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetView.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetView.java
index 301b757..7778455b 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetView.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetView.java
@@ -5,9 +5,18 @@
 package org.chromium.chrome.browser.share.screenshot;
 
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
+import android.view.View;
 import android.widget.FrameLayout;
 
+import org.chromium.base.Callback;
+import org.chromium.chrome.browser.share.R;
+import org.chromium.chrome.browser.share.screenshot.ScreenshotShareSheetViewProperties.NoArgOperation;
+import org.chromium.ui.widget.ChromeImageView;
+
 /**
  * Manages the Android View representing the Screenshot share panel.
  */
@@ -16,4 +25,40 @@
     public ScreenshotShareSheetView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
+
+    /**
+     * Sets the listeners for all no arg operations.
+     *
+     * @param noArgOperationCallback Callback to perform.
+     */
+    public void setNoArgOperationsListeners(Callback<Integer> noArgOperationCallback) {
+        setNoArgOperationListener(NoArgOperation.SHARE, R.id.share, noArgOperationCallback);
+        setNoArgOperationListener(NoArgOperation.SAVE, R.id.save, noArgOperationCallback);
+        setNoArgOperationListener(NoArgOperation.DELETE, R.id.delete, noArgOperationCallback);
+        setNoArgOperationListener(NoArgOperation.DELETE, R.id.close_button, noArgOperationCallback);
+    }
+
+    /**
+     * Sets the listener for an operation with zero arguments.
+     *
+     * @param operation The type of operation as defined by BottomBarProperties.NoArgOperation
+     * @param viewId The id to listen for a tap on
+     * @param setNoArgOperationCallback The callback to perform on tap
+     */
+    private void setNoArgOperationListener(
+            Integer operation, int viewId, Callback<Integer> noArgOperationCallback) {
+        View button = findViewById(viewId);
+        button.setOnClickListener(v -> { noArgOperationCallback.onResult(operation); });
+    }
+
+    /**
+     * Updates Screenshot image on panel.
+     *
+     * @param bitmap The {@link Bitmap} to display.
+     */
+    public void updateScreenshotBitmap(Bitmap bitmap) {
+        ChromeImageView screenshotImageView = findViewById(R.id.screenshot);
+        Drawable drawable = new BitmapDrawable(bitmap);
+        screenshotImageView.setImageDrawable(drawable);
+    }
 }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewBinder.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewBinder.java
index 1bdafae5..c0ca721 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewBinder.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewBinder.java
@@ -6,11 +6,17 @@
 
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
-import org.chromium.ui.modelutil.PropertyModelChangeProcessor.ViewBinder;
 
 /** The view binder for the Screenshot Share Sheet. */
-class ScreenshotShareSheetViewBinder
-        implements ViewBinder<PropertyModel, ScreenshotShareSheetView, PropertyKey> {
-    @Override
-    public void bind(PropertyModel model, ScreenshotShareSheetView view, PropertyKey propertyKey) {}
+class ScreenshotShareSheetViewBinder {
+    public static void bind(
+            PropertyModel model, ScreenshotShareSheetView view, PropertyKey propertyKey) {
+        if (ScreenshotShareSheetViewProperties.NO_ARG_OPERATION_LISTENER == propertyKey) {
+            view.setNoArgOperationsListeners(
+                    model.get(ScreenshotShareSheetViewProperties.NO_ARG_OPERATION_LISTENER));
+        } else if (ScreenshotShareSheetViewProperties.SCREENSHOT_BITMAP == propertyKey) {
+            view.updateScreenshotBitmap(
+                    model.get(ScreenshotShareSheetViewProperties.SCREENSHOT_BITMAP));
+        }
+    }
 }
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewProperties.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewProperties.java
index 41407a88..68828506 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewProperties.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewProperties.java
@@ -4,8 +4,40 @@
 
 package org.chromium.chrome.browser.share.screenshot;
 
+import android.graphics.Bitmap;
+
+import androidx.annotation.IntDef;
+
+import org.chromium.base.Callback;
 import org.chromium.ui.modelutil.PropertyKey;
+import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 
 class ScreenshotShareSheetViewProperties {
-    public static final PropertyKey[] ALL_KEYS = {};
+    /**
+     * Callback to perform the specified operation. Argument to callback must be a
+     * NoArgOperation
+     */
+    public static final WritableObjectPropertyKey<Callback<Integer>> NO_ARG_OPERATION_LISTENER =
+            new WritableObjectPropertyKey<Callback<Integer>>();
+
+    public static final WritableObjectPropertyKey<Bitmap> SCREENSHOT_BITMAP =
+            new WritableObjectPropertyKey<>();
+    /**
+     * Set of operations that don't require additional arguments. If a callback requires an
+     * argument, it should defined separately.
+     */
+    @IntDef({NoArgOperation.NONE, NoArgOperation.SHARE, NoArgOperation.SAVE, NoArgOperation.DELETE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface NoArgOperation {
+        int NONE = 0;
+        int SHARE = 1;
+        int SAVE = 2;
+        int DELETE = 3;
+    }
+
+    public static final PropertyKey[] ALL_KEYS =
+            new PropertyKey[] {NO_ARG_OPERATION_LISTENER, SCREENSHOT_BITMAP};
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
similarity index 93%
rename from chrome/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProvider.java
rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
index 42074ce..afcd12a5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProvider.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import android.app.Activity;
 import android.content.ClipData;
@@ -12,6 +12,7 @@
 import androidx.annotation.IntDef;
 import androidx.appcompat.content.res.AppCompatResources;
 
+import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
@@ -19,20 +20,16 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
-import org.chromium.chrome.browser.printing.TabPrinter;
 import org.chromium.chrome.browser.send_tab_to_self.SendTabToSelfShareActivity;
-import org.chromium.chrome.browser.share.ShareSheetPropertyModelBuilder.ContentType;
 import org.chromium.chrome.browser.share.qrcode.QrCodeCoordinator;
 import org.chromium.chrome.browser.share.screenshot.ScreenshotCoordinator;
+import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController.SheetState;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetObserver;
 import org.chromium.chrome.browser.widget.bottomsheet.EmptyBottomSheetObserver;
 import org.chromium.components.browser_ui.share.ShareParams;
-import org.chromium.printing.PrintManagerDelegateImpl;
-import org.chromium.printing.PrintingController;
-import org.chromium.printing.PrintingControllerImpl;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.widget.Toast;
 
@@ -50,13 +47,15 @@
 /**
  * Provides {@code PropertyModel}s of Chrome-provided sharing options.
  */
-class ChromeProvidedSharingOptionsProvider {
+// TODO(crbug/1022172): Should be package-protected once modularization is complete.
+public class ChromeProvidedSharingOptionsProvider {
     private final Activity mActivity;
     private final Supplier<Tab> mTabProvider;
     private final BottomSheetController mBottomSheetController;
     private final ShareSheetBottomSheetContent mBottomSheetContent;
     private final PrefServiceBridge mPrefServiceBridge;
     private final ShareParams mShareParams;
+    private final Callback<Tab> mPrintTabCallback;
     private final long mShareStartTime;
     private ScreenshotCoordinator mScreenshotCoordinator;
     private Map<Integer, Set<Integer>> mSharingOptionToContentTypes;
@@ -72,18 +71,20 @@
      * @param prefServiceBridge The {@link PrefServiceBridge} singleton. This provides printing
      * preferences.
      * @param shareParams The {@link ShareParams} for the current share.
+     * @param printTab A {@link Callback} that will print a given Tab.
      * @param shareStartTime The start time of the current share.
      */
     ChromeProvidedSharingOptionsProvider(Activity activity, Supplier<Tab> tabProvider,
             BottomSheetController bottomSheetController,
             ShareSheetBottomSheetContent bottomSheetContent, PrefServiceBridge prefServiceBridge,
-            ShareParams shareParams, long shareStartTime) {
+            ShareParams shareParams, Callback<Tab> printTab, long shareStartTime) {
         mActivity = activity;
         mTabProvider = tabProvider;
         mBottomSheetController = bottomSheetController;
         mBottomSheetContent = bottomSheetContent;
         mPrefServiceBridge = prefServiceBridge;
         mShareParams = shareParams;
+        mPrintTabCallback = printTab;
         mShareStartTime = shareStartTime;
         mSharingOptionToContentTypes = createSharingOptionToContentTypesMap();
     }
@@ -249,11 +250,7 @@
                             "Sharing.SharingHubAndroid.TimeToShare",
                             System.currentTimeMillis() - mShareStartTime);
                     mBottomSheetController.hideContent(mBottomSheetContent, true);
-                    PrintingController printingController = PrintingControllerImpl.getInstance();
-                    if (printingController != null && !printingController.isBusy()) {
-                        printingController.startPrint(new TabPrinter(mTabProvider.get()),
-                                new PrintManagerDelegateImpl(mActivity));
-                    }
+                    mPrintTabCallback.onResult(mTabProvider.get());
                 },
                 /*isFirstParty=*/true);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetBottomSheetContent.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetBottomSheetContent.java
rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java
index 78c7ee4..b175c876 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetBottomSheetContent.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import android.content.Context;
 import android.view.LayoutInflater;
@@ -31,7 +31,7 @@
 /**
  * Bottom sheet content to display a 2-row custom share sheet.
  */
-public class ShareSheetBottomSheetContent implements BottomSheetContent, OnItemClickListener {
+class ShareSheetBottomSheetContent implements BottomSheetContent, OnItemClickListener {
     private Context mContext;
     private ViewGroup mToolbarView;
     private ViewGroup mContentView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
similarity index 85%
rename from chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java
rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
index 66546ba..b436b70 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetCoordinator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
@@ -2,18 +2,21 @@
 // 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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import android.app.Activity;
 
 import androidx.annotation.VisibleForTesting;
 import androidx.appcompat.content.res.AppCompatResources;
 
+import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
+import org.chromium.chrome.browser.share.ChromeShareExtras;
+import org.chromium.chrome.browser.share.ShareHelper;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.share.ShareParams;
@@ -26,11 +29,13 @@
 /**
  * Coordinator for displaying the share sheet.
  */
-class ShareSheetCoordinator {
+// TODO(crbug/1022172): Should be package-protected once modularization is complete.
+public class ShareSheetCoordinator {
     private final BottomSheetController mBottomSheetController;
     private final Supplier<Tab> mTabProvider;
     private final ShareSheetPropertyModelBuilder mPropertyModelBuilder;
     private final PrefServiceBridge mPrefServiceBridge;
+    private final Callback<Tab> mPrintTabCallback;
     private long mShareStartTime;
     private boolean mExcludeFirstParty;
 
@@ -43,16 +48,20 @@
      * @param prefServiceBridge The {@link PrefServiceBridge} singleton. This provides preferences
      * for the Chrome-provided property models.
      */
-    ShareSheetCoordinator(BottomSheetController controller, Supplier<Tab> tabProvider,
-            ShareSheetPropertyModelBuilder modelBuilder, PrefServiceBridge prefServiceBridge) {
+    // TODO(crbug/1022172): Should be package-protected once modularization is complete.
+    public ShareSheetCoordinator(BottomSheetController controller, Supplier<Tab> tabProvider,
+            ShareSheetPropertyModelBuilder modelBuilder, PrefServiceBridge prefServiceBridge,
+            Callback<Tab> printTab) {
         mBottomSheetController = controller;
         mTabProvider = tabProvider;
         mPropertyModelBuilder = modelBuilder;
         mExcludeFirstParty = false;
         mPrefServiceBridge = prefServiceBridge;
+        mPrintTabCallback = printTab;
     }
 
-    void showShareSheet(
+    // TODO(crbug/1022172): Should be package-protected once modularization is complete.
+    public void showShareSheet(
             ShareParams params, ChromeShareExtras chromeShareExtras, long shareStartTime) {
         Activity activity = params.getWindow().getActivity().get();
         if (activity == null) {
@@ -94,7 +103,7 @@
         ChromeProvidedSharingOptionsProvider chromeProvidedSharingOptionsProvider =
                 new ChromeProvidedSharingOptionsProvider(activity, mTabProvider,
                         mBottomSheetController, bottomSheet, mPrefServiceBridge, shareParams,
-                        mShareStartTime);
+                        mPrintTabCallback, mShareStartTime);
 
         return chromeProvidedSharingOptionsProvider.createPropertyModels(contentTypes);
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetItemViewProperties.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetItemViewProperties.java
similarity index 94%
rename from chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetItemViewProperties.java
rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetItemViewProperties.java
index 0bbfc5843..fed07a8c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetItemViewProperties.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetItemViewProperties.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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import android.graphics.drawable.Drawable;
 import android.view.View.OnClickListener;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java
similarity index 92%
rename from chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java
rename to chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java
index 269ef4a..561af223 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilder.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import android.content.ComponentName;
 import android.content.Intent;
@@ -18,6 +18,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.share.ShareHelper;
 import org.chromium.chrome.browser.widget.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.share.ShareParams;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -37,7 +38,8 @@
  * Android L+: system share sheet
  * #chrome-sharing-hub enabled: custom share sheet
  */
-class ShareSheetPropertyModelBuilder {
+// TODO(crbug/1022172): Should be package-protected once modularization is complete.
+public class ShareSheetPropertyModelBuilder {
     @IntDef({ContentType.LINK_PAGE_VISIBLE, ContentType.LINK_PAGE_NOT_VISIBLE, ContentType.TEXT,
             ContentType.IMAGE, ContentType.OTHER_FILE_TYPE})
     @Retention(RetentionPolicy.SOURCE)
@@ -77,7 +79,8 @@
     private final BottomSheetController mBottomSheetController;
     private final PackageManager mPackageManager;
 
-    ShareSheetPropertyModelBuilder(
+    // TODO(crbug/1022172): Should be package-protected once modularization is complete.
+    public ShareSheetPropertyModelBuilder(
             BottomSheetController bottomSheetController, PackageManager packageManager) {
         mBottomSheetController = bottomSheetController;
         mPackageManager = packageManager;
@@ -86,9 +89,9 @@
     /**
      * Returns a set of {@link ShareSheetCoordinator.ContentType}s for the current share.
      *
-     * <p>If {@link ChromeFeatureList.CHROME_SHARING_HUB_V15} is not enabled, this returns a set of
-     * all of the {@link ContentType}s. Otherwise, it adds {@link ContentType}s according to the
-     * following logic:
+     * <p>If {@link ChromeFeatureList.CHROME_SHARING_HUB_V15} is not enabled, this returns a set
+     * of all of the {@link ContentType}s. Otherwise, it adds {@link ContentType}s according to
+     * the following logic:
      *
      * <ul>
      *     <li>If a URL is present, {@code isUrlOfVisiblePage} determines whether to add
@@ -133,9 +136,9 @@
         List<ResolveInfo> resolveInfoList = mPackageManager.queryIntentActivities(intent, 0);
         List<ResolveInfo> thirdPartyActivities = new ArrayList<>();
 
-        // Construct a list of 3P apps. The list should be sorted by the country-specific ranking
-        // when available or the fallback list defined above.  If less than MAX_NUM_APPS are
-        // available the list is filled with whatever else is available.
+        // Construct a list of 3P apps. The list should be sorted by the country-specific
+        // ranking when available or the fallback list defined above.  If less than MAX_NUM_APPS
+        // are available the list is filled with whatever else is available.
         for (String s : thirdPartyActivityNames) {
             for (ResolveInfo res : resolveInfoList) {
                 if (res.activityInfo.name.equals(s)) {
diff --git a/chrome/browser/share/android/java_sources.gni b/chrome/browser/share/android/java_sources.gni
index 0533fb5..7febf8d 100644
--- a/chrome/browser/share/android/java_sources.gni
+++ b/chrome/browser/share/android/java_sources.gni
@@ -29,7 +29,14 @@
   "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotCoordinator.java",
   "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetCoordinator.java",
   "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialog.java",
+  "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetDialogCoordinator.java",
+  "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java",
   "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetView.java",
   "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewBinder.java",
   "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewProperties.java",
+  "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java",
+  "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetBottomSheetContent.java",
+  "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java",
+  "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetItemViewProperties.java",
+  "//chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilder.java",
 ]
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java
index 9dc359f..ad67858 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java
@@ -4,13 +4,9 @@
 
 package org.chromium.chrome.browser.share.clipboard;
 
-import android.content.Context;
 import android.graphics.Bitmap;
-import android.net.Uri;
 import android.support.test.filters.SmallTest;
 
-import androidx.core.content.FileProvider;
-
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -19,12 +15,12 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ContentUriUtils;
-import org.chromium.base.ContextUtils;
 import org.chromium.base.task.AsyncTask;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.FileProviderHelper;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.ChromeActivityTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -33,7 +29,6 @@
 import org.chromium.ui.base.Clipboard;
 
 import java.io.ByteArrayOutputStream;
-import java.io.File;
 import java.io.IOException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -53,17 +48,6 @@
 
     private byte[] mTestImageData;
 
-    private class FileProviderHelper implements ContentUriUtils.FileProviderUtil {
-        private static final String API_AUTHORITY_SUFFIX = ".FileProvider";
-
-        @Override
-        public Uri getContentUriFromFile(File file) {
-            Context appContext = ContextUtils.getApplicationContext();
-            return FileProvider.getUriForFile(
-                    appContext, appContext.getPackageName() + API_AUTHORITY_SUFFIX, file);
-        }
-    }
-
     private class AsyncTaskRunnableHelper extends CallbackHelper implements Runnable {
         @Override
         public void run() {
@@ -82,6 +66,9 @@
 
     @Before
     public void setUp() {
+        // Clear the clipboard.
+        Clipboard.getInstance().setText("");
+
         Bitmap bitmap =
                 Bitmap.createBitmap(/* width = */ 10, /* height = */ 10, Bitmap.Config.ARGB_8888);
         ByteArrayOutputStream baos = new ByteArrayOutputStream();
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediatorUnitTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediatorUnitTest.java
new file mode 100644
index 0000000..0715b61
--- /dev/null
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediatorUnitTest.java
@@ -0,0 +1,64 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.share.screenshot;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.Callback;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.ui.modelutil.PropertyModel;
+
+/**
+ * Tests for {@link ScreenshotShareSheetMediator}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+// clang-format off
+@Features.EnableFeatures(ChromeFeatureList.CHROME_SHARE_SCREENSHOT)
+public class ScreenshotShareSheetMediatorUnitTest {
+    // clang-format on
+    @Rule
+    public TestRule mProcessor = new Features.JUnitProcessor();
+
+    @Mock
+    Runnable mDeleteRunnable;
+
+    private PropertyModel mModel;
+    private ScreenshotShareSheetMediator mMediator;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        doNothing().when(mDeleteRunnable).run();
+
+        mModel = new PropertyModel(ScreenshotShareSheetViewProperties.ALL_KEYS);
+
+        mMediator = new ScreenshotShareSheetMediator(mModel, mDeleteRunnable);
+    }
+    @Test
+    public void onClickDelete() {
+        Callback<Integer> callback =
+                mModel.get(ScreenshotShareSheetViewProperties.NO_ARG_OPERATION_LISTENER);
+        callback.onResult(ScreenshotShareSheetViewProperties.NoArgOperation.DELETE);
+
+        verify(mDeleteRunnable).run();
+    }
+    @After
+    public void tearDown() {}
+}
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java
new file mode 100644
index 0000000..96fc9d66
--- /dev/null
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetViewTest.java
@@ -0,0 +1,104 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.share.screenshot;
+
+import android.support.test.annotation.UiThreadTest;
+import android.support.test.filters.MediumTest;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.Callback;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.share.R;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.browser_ui.widget.selectable_list.SelectionDelegate;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+import org.chromium.ui.modelutil.PropertyModel;
+import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
+import org.chromium.ui.test.util.DummyUiActivityTestCase;
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Tests for the {@link ScreenshotShareSheetView}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@Features.EnableFeatures(ChromeFeatureList.CHROME_SHARE_SCREENSHOT)
+public class ScreenshotShareSheetViewTest extends DummyUiActivityTestCase {
+    private ScreenshotShareSheetView mScreenshotView;
+    private PropertyModel mScreenshotModel;
+    private PropertyModelChangeProcessor mScreenshotMCP;
+
+    private AtomicBoolean mCloseClicked = new AtomicBoolean();
+    private AtomicBoolean mShareClicked = new AtomicBoolean();
+    private AtomicBoolean mSaveClicked = new AtomicBoolean();
+
+    private Callback<Integer> mMockNoArgListener = new Callback<Integer>() {
+        @Override
+        public void onResult(@ScreenshotShareSheetViewProperties.NoArgOperation Integer operation) {
+            if (ScreenshotShareSheetViewProperties.NoArgOperation.SHARE == operation) {
+                mShareClicked.set(true);
+            } else if (ScreenshotShareSheetViewProperties.NoArgOperation.SAVE == operation) {
+                mSaveClicked.set(true);
+            } else if (ScreenshotShareSheetViewProperties.NoArgOperation.DELETE == operation) {
+                mCloseClicked.set(true);
+            }
+        }
+    };
+
+    @Override
+    public void setUpTest() throws Exception {
+        super.setUpTest();
+        ViewGroup view = new LinearLayout(getActivity());
+        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            getActivity().setContentView(view, params);
+
+            mScreenshotView = (ScreenshotShareSheetView) getActivity().getLayoutInflater().inflate(
+                    R.layout.screenshot_share_sheet, null);
+
+            view.addView(mScreenshotView);
+        });
+
+        SelectionDelegate<Integer> mSelectionDelegate = new SelectionDelegate<>();
+
+        mScreenshotModel =
+                new PropertyModel.Builder(ScreenshotShareSheetViewProperties.ALL_KEYS)
+                        .with(ScreenshotShareSheetViewProperties.NO_ARG_OPERATION_LISTENER,
+                                mMockNoArgListener)
+                        .build();
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            mScreenshotMCP = PropertyModelChangeProcessor.create(
+                    mScreenshotModel, mScreenshotView, ScreenshotShareSheetViewBinder::bind);
+        });
+    }
+
+    @Test
+    @MediumTest
+    @UiThreadTest
+    public void testClickToClose() {
+        ImageView closeButton = mScreenshotView.findViewById(R.id.close_button);
+
+        Assert.assertFalse(mCloseClicked.get());
+        closeButton.performClick();
+        Assert.assertTrue(mCloseClicked.get());
+        mCloseClicked.set(false);
+    }
+
+    @Override
+    public void tearDownTest() throws Exception {
+        mScreenshotMCP.destroy();
+        super.tearDownTest();
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
similarity index 96%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderTest.java
rename to chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
index d0f6ab7..05d58e42 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ChromeProvidedSharingOptionsProviderTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -27,7 +27,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.PrefServiceBridge;
-import org.chromium.chrome.browser.share.ShareSheetPropertyModelBuilder.ContentType;
+import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -65,7 +65,9 @@
         mChromeProvidedSharingOptionsProvider = new ChromeProvidedSharingOptionsProvider(mActivity,
                 /*activityTabProvider=*/null, /*bottomSheetController=*/null,
                 new ShareSheetBottomSheetContent(mActivity), mPrefServiceBridge,
-                /*shareParams=*/null, /*shareStartTime=*/0);
+                /*shareParams=*/null,
+                /*TabPrinterDelegate=*/null,
+                /*shareStartTime=*/0);
 
         // Return false to indicate printing is disabled.
         Mockito.when(mPrefServiceBridge.getBoolean(anyString())).thenReturn(false);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java
similarity index 96%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java
rename to chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java
index 4c8e960..9f7a380 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetCoordinatorTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -74,7 +74,8 @@
                              any(), any(), anyBoolean(), anyLong()))
                 .thenReturn(thirdPartyPropertyModels);
 
-        mShareSheetCoordinator = new ShareSheetCoordinator(null, null, mPropertyModelBuilder, null);
+        mShareSheetCoordinator =
+                new ShareSheetCoordinator(null, null, mPropertyModelBuilder, null, null);
     }
 
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java
similarity index 98%
rename from chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilderTest.java
rename to chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java
index e2199bd8..a6abf262 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/share/ShareSheetPropertyModelBuilderTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.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.share;
+package org.chromium.chrome.browser.share.share_sheet;
 
 import static org.junit.Assert.assertEquals;
 import static org.mockito.Matchers.any;
@@ -32,7 +32,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.share.ShareSheetPropertyModelBuilder.ContentType;
+import org.chromium.chrome.browser.share.share_sheet.ShareSheetPropertyModelBuilder.ContentType;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
diff --git a/chrome/browser/share/android/test_java_sources.gni b/chrome/browser/share/android/test_java_sources.gni
index 82b0d1a..7b7736b 100644
--- a/chrome/browser/share/android/test_java_sources.gni
+++ b/chrome/browser/share/android/test_java_sources.gni
@@ -3,4 +3,11 @@
 # found in the LICENSE file.
 
 # TODO(crbug.com/1022172): This should be a separate build target when circular dependencies are removed.
-share_test_java_sources = [ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java" ]
+share_test_java_sources = [
+  "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/clipboard/ClipboardImageFileProviderTest.java",
+  "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java",
+  "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinatorTest.java",
+  "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetPropertyModelBuilderTest.java",
+]
+
+share_junit_test_java_sources = [ "//chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediatorUnitTest.java" ]
diff --git a/chrome/browser/sharing/sharing_sync_preference.cc b/chrome/browser/sharing/sharing_sync_preference.cc
index 92b4332..c8bea4d 100644
--- a/chrome/browser/sharing/sharing_sync_preference.cc
+++ b/chrome/browser/sharing/sharing_sync_preference.cc
@@ -8,7 +8,7 @@
 #include "base/feature_list.h"
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "base/values.h"
 #include "chrome/browser/sharing/features.h"
 #include "chrome/browser/sharing/proto/sharing_message.pb.h"
@@ -133,9 +133,9 @@
                      &base64_vapid_key);
 
   DictionaryPrefUpdate update(prefs_, prefs::kSharingVapidKey);
-  update->SetString(kVapidECPrivateKey, base64_vapid_key);
-  update->SetString(kVapidCreationTimestamp,
-                    base::CreateTimeValue(creation_timestamp).GetString());
+  update->SetStringKey(kVapidECPrivateKey, base64_vapid_key);
+  update->SetKey(kVapidCreationTimestamp,
+                 util::TimeToValue(creation_timestamp));
 }
 
 void SharingSyncPreference::SetVapidKeyChangeObserver(
@@ -164,11 +164,11 @@
   if (authorized_entity_ptr)
     authorized_entity = *authorized_entity_ptr;
 
-  base::Time timestamp;
-  if (!base::GetValueAsTime(*timestamp_value, &timestamp))
+  base::Optional<base::Time> timestamp = util::ValueToTime(timestamp_value);
+  if (!timestamp)
     return base::nullopt;
 
-  return FCMRegistration(authorized_entity, timestamp);
+  return FCMRegistration(authorized_entity, *timestamp);
 }
 
 void SharingSyncPreference::SetFCMRegistration(FCMRegistration registration) {
@@ -180,7 +180,7 @@
     update->RemoveKey(kRegistrationAuthorizedEntity);
   }
   update->SetKey(kRegistrationTimestamp,
-                 base::CreateTimeValue(registration.timestamp));
+                 util::TimeToValue(registration.timestamp));
 }
 
 void SharingSyncPreference::ClearFCMRegistration() {
diff --git a/chrome/browser/sharing/sharing_sync_preference_unittest.cc b/chrome/browser/sharing/sharing_sync_preference_unittest.cc
index eb85d93..eaa38457 100644
--- a/chrome/browser/sharing/sharing_sync_preference_unittest.cc
+++ b/chrome/browser/sharing/sharing_sync_preference_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/guid.h"
 #include "base/time/time.h"
-#include "base/value_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/sharing/fake_device_info.h"
 #include "chrome/browser/sharing/proto/sharing_message.pb.h"
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc
index 47cd75521..2ee086f0 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -8,6 +8,7 @@
 
 #include "base/check.h"
 #include "base/i18n/case_conversion.h"
+#include "base/optional.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
@@ -19,11 +20,15 @@
 #include "chrome/browser/signin/signin_features.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 
-DiceWebSigninInterceptor::DiceWebSigninInterceptor(Profile* profile)
+DiceWebSigninInterceptor::DiceWebSigninInterceptor(
+    Profile* profile,
+    std::unique_ptr<Delegate> delegate)
     : profile_(profile),
-      identity_manager_(IdentityManagerFactory::GetForProfile(profile)) {
+      identity_manager_(IdentityManagerFactory::GetForProfile(profile)),
+      delegate_(std::move(delegate)) {
   DCHECK(profile_);
   DCHECK(identity_manager_);
+  DCHECK(delegate_);
 }
 
 DiceWebSigninInterceptor::~DiceWebSigninInterceptor() = default;
@@ -49,6 +54,7 @@
 
   account_id_ = account_id;
   is_interception_in_progress_ = true;
+  Observe(web_contents);
 
   base::Optional<AccountInfo> account_info =
       identity_manager_
@@ -56,12 +62,14 @@
               account_id_);
   DCHECK(account_info) << "Intercepting unknown account.";
 
-  if (IsAccountInAnotherProfile(*account_info,
-                                &g_browser_process->profile_manager()
-                                     ->GetProfileAttributesStorage())) {
-    // TODO(https://crbug.com/1076880): implement profile switch bubble.
-    NOTIMPLEMENTED();
-    Reset();
+  if (ShouldShowProfileSwitchBubble(*account_info,
+                                    &g_browser_process->profile_manager()
+                                         ->GetProfileAttributesStorage())) {
+    delegate_->ShowSigninInterceptionBubble(
+        SigninInterceptionType::kProfileSwitch, web_contents, *account_info,
+        base::BindOnce(&DiceWebSigninInterceptor::OnProfileSwitchChoice,
+                       base::Unretained(this)));
+
     return;
   }
 
@@ -89,13 +97,14 @@
 }
 
 void DiceWebSigninInterceptor::Reset() {
+  Observe(/*web_contents=*/nullptr);
   account_info_update_observer_.RemoveAll();
   on_account_info_update_timeout_.Cancel();
   is_interception_in_progress_ = false;
   account_id_ = CoreAccountId();
 }
 
-bool DiceWebSigninInterceptor::IsAccountInAnotherProfile(
+bool DiceWebSigninInterceptor::ShouldShowProfileSwitchBubble(
     const CoreAccountInfo& intercepted_account_info,
     ProfileAttributesStorage* profile_attribute_storage) {
   // Check if there is already an existing profile with this account.
@@ -166,19 +175,44 @@
   account_info_update_observer_.RemoveAll();
   on_account_info_update_timeout_.Cancel();
 
-  if (ShouldShowEnterpriseBubble(info)) {
-    // TODO(https://crbug.com/1076880): Implement enterprise interception.
-    NOTIMPLEMENTED();
-    Reset();
-    return;
-  }
-  if (ShouldShowMultiUserBubble(info)) {
-    // TODO(https://crbug.com/1076880): Implement multiuser interception.
-    NOTIMPLEMENTED();
+  base::Optional<SigninInterceptionType> interception_type;
+
+  if (ShouldShowEnterpriseBubble(info))
+    interception_type = SigninInterceptionType::kEnterprise;
+  else if (ShouldShowMultiUserBubble(info))
+    interception_type = SigninInterceptionType::kMultiUser;
+
+  if (!interception_type) {
+    // Signin should not be intercepted.
     Reset();
     return;
   }
 
-  // Signin should not be intercepted.
+  delegate_->ShowSigninInterceptionBubble(
+      *interception_type, web_contents(), info,
+      base::BindOnce(&DiceWebSigninInterceptor::OnProfileCreationChoice,
+                     base::Unretained(this)));
+}
+
+void DiceWebSigninInterceptor::OnProfileCreationChoice(bool create) {
+  if (!create) {
+    Reset();
+    return;
+  }
+
+  // TODO(https://crbug.com/1076880): Create a new profile, and move the account
+  // to it.
+  NOTIMPLEMENTED();
+  Reset();
+}
+
+void DiceWebSigninInterceptor::OnProfileSwitchChoice(bool switch_profile) {
+  if (!switch_profile) {
+    Reset();
+    return;
+  }
+
+  // TODO(https://crbug.com/1076880): Switch to the other profile.
+  NOTIMPLEMENTED();
   Reset();
 }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.h b/chrome/browser/signin/dice_web_signin_interceptor.h
index dd5abc8..f1ca28bb 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor.h
+++ b/chrome/browser/signin/dice_web_signin_interceptor.h
@@ -5,6 +5,9 @@
 #ifndef CHROME_BROWSER_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_H_
 #define CHROME_BROWSER_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_H_
 
+#include <memory>
+
+#include "base/callback_forward.h"
 #include "base/cancelable_callback.h"
 #include "base/feature_list.h"
 #include "base/gtest_prod_util.h"
@@ -29,7 +32,26 @@
                                  public content::WebContentsObserver,
                                  public signin::IdentityManager::Observer {
  public:
-  explicit DiceWebSigninInterceptor(Profile* profile);
+  enum class SigninInterceptionType { kProfileSwitch, kEnterprise, kMultiUser };
+
+  // Delegate class responsible for showing the various interception UIs.
+  class Delegate {
+   public:
+    virtual ~Delegate() = default;
+
+    // Shows the signin interception bubble and calls |callback| to indicate
+    // whether the user should continue in a new profile.
+    // The callback is never called if the delegate is deleted before it
+    // completes.
+    virtual void ShowSigninInterceptionBubble(
+        SigninInterceptionType signin_interception_type,
+        content::WebContents* web_contents,
+        const AccountInfo& account_info,
+        base::OnceCallback<void(bool)> callback) = 0;
+  };
+
+  DiceWebSigninInterceptor(Profile* profile,
+                           std::unique_ptr<Delegate> delegate);
   ~DiceWebSigninInterceptor() override;
 
   DiceWebSigninInterceptor(const DiceWebSigninInterceptor&) = delete;
@@ -55,7 +77,7 @@
 
  private:
   FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptorTest,
-                           IsAccountInAnotherProfile);
+                           ShouldShowProfileSwitchBubble);
   FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptorTest,
                            NoBubbleWithSingleAccount);
   FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptorTest,
@@ -64,13 +86,17 @@
                            ShouldShowEnterpriseBubbleWithoutUPA);
   FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptorTest,
                            ShouldShowMultiUserBubble);
+  FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptorTest,
+                           InterceptionInProgress);
+  FRIEND_TEST_ALL_PREFIXES(DiceWebSigninInterceptorTest,
+                           NoInterceptionWithOneAccount);
 
   // Cancels any current signin interception and resets the interceptor to its
   // initial state.
   void Reset();
 
   // Helper functions to determine which interception UI should be shown.
-  bool IsAccountInAnotherProfile(
+  bool ShouldShowProfileSwitchBubble(
       const CoreAccountInfo& intercepted_account_info,
       ProfileAttributesStorage* profile_attribute_storage);
   bool ShouldShowEnterpriseBubble(const AccountInfo& intercepted_account_info);
@@ -79,8 +105,15 @@
   // signin::IdentityManager::Observer:
   void OnExtendedAccountInfoUpdated(const AccountInfo& info) override;
 
+  // Called after the user chose whether a new profile would be created.
+  void OnProfileCreationChoice(bool create);
+  // Called after the user chose whether the session should continue in a new
+  // profile.
+  void OnProfileSwitchChoice(bool switch_profile);
+
   Profile* const profile_;
   signin::IdentityManager* const identity_manager_;
+  std::unique_ptr<Delegate> delegate_;
 
   // Members below are related to the interception in progress.
   bool is_interception_in_progress_ = false;
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_delegate.cc b/chrome/browser/signin/dice_web_signin_interceptor_delegate.cc
new file mode 100644
index 0000000..8c17d218
--- /dev/null
+++ b/chrome/browser/signin/dice_web_signin_interceptor_delegate.cc
@@ -0,0 +1,74 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/signin/dice_web_signin_interceptor_delegate.h"
+
+#include <memory>
+
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/sync/profile_signin_confirmation_helper.h"
+#include "chrome/browser/ui/tab_dialogs.h"
+#include "components/signin/public/identity_manager/account_info.h"
+
+namespace {
+
+// TODO(https://crbug.com/1076880): Delete this class once the real interception
+// UI is implemented.
+class EnterpriseConfirmationDialogDelegate
+    : public ui::ProfileSigninConfirmationDelegate {
+ public:
+  explicit EnterpriseConfirmationDialogDelegate(
+      base::OnceCallback<void(bool)> callback)
+      : callback_(std::move(callback)) {}
+
+  ~EnterpriseConfirmationDialogDelegate() override = default;
+
+  void OnCancelSignin() override {
+    // Cancelling signin won't be supported with the real UI.
+    NOTIMPLEMENTED();
+    OnContinueSignin();
+  }
+
+  void OnContinueSignin() override { std::move(callback_).Run(false); }
+
+  void OnSigninWithNewProfile() override { std::move(callback_).Run(true); }
+
+ private:
+  base::OnceCallback<void(bool)> callback_;
+};
+
+}  // namespace
+
+DiceWebSigninInterceptorDelegate::DiceWebSigninInterceptorDelegate() = default;
+
+DiceWebSigninInterceptorDelegate::~DiceWebSigninInterceptorDelegate() = default;
+
+void DiceWebSigninInterceptorDelegate::ShowSigninInterceptionBubble(
+    DiceWebSigninInterceptor::SigninInterceptionType signin_interception_type,
+    content::WebContents* web_contents,
+    const AccountInfo& account_info,
+    base::OnceCallback<void(bool)> callback) {
+  if (signin_interception_type !=
+      DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise) {
+    // Only the enterprise interception is currently implemented.
+    std::move(callback).Run(false);
+    return;
+  }
+
+  // TODO(https://crbug.com/1076880): Implement the interception UI. In the
+  // meantime, the enterprise sync confirmation prompt is shown instead.
+  if (!web_contents) {
+    std::move(callback).Run(false);
+    return;
+  }
+
+  TabDialogs::FromWebContents(web_contents)
+      ->ShowProfileSigninConfirmation(
+          chrome::FindBrowserWithWebContents(web_contents),
+          Profile::FromBrowserContext(web_contents->GetBrowserContext()),
+          account_info.email,
+          std::make_unique<EnterpriseConfirmationDialogDelegate>(
+              std::move(callback)));
+}
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_delegate.h b/chrome/browser/signin/dice_web_signin_interceptor_delegate.h
new file mode 100644
index 0000000..374c9025
--- /dev/null
+++ b/chrome/browser/signin/dice_web_signin_interceptor_delegate.h
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_DELEGATE_H_
+#define CHROME_BROWSER_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_DELEGATE_H_
+
+#include "chrome/browser/signin/dice_web_signin_interceptor.h"
+
+#include "base/callback_forward.h"
+
+namespace content {
+class WebContents;
+}
+
+struct AccountInfo;
+
+class DiceWebSigninInterceptorDelegate
+    : public DiceWebSigninInterceptor::Delegate {
+ public:
+  DiceWebSigninInterceptorDelegate();
+  ~DiceWebSigninInterceptorDelegate() override;
+
+  // DiceWebSigninInterceptor::Delegate
+  void ShowSigninInterceptionBubble(
+      DiceWebSigninInterceptor::SigninInterceptionType signin_interception_type,
+      content::WebContents* web_contents,
+      const AccountInfo& account_info,
+      base::OnceCallback<void(bool)> callback) override;
+};
+
+#endif  // CHROME_BROWSER_SIGNIN_DICE_WEB_SIGNIN_INTERCEPTOR_DELEGATE_H_
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_factory.cc b/chrome/browser/signin/dice_web_signin_interceptor_factory.cc
index 723b4fe3..40e8fdf0 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor_factory.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor_factory.cc
@@ -6,6 +6,7 @@
 
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/dice_web_signin_interceptor.h"
+#include "chrome/browser/signin/dice_web_signin_interceptor_delegate.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/keyed_service/content/browser_context_dependency_manager.h"
 
@@ -33,5 +34,7 @@
 
 KeyedService* DiceWebSigninInterceptorFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
-  return new DiceWebSigninInterceptor(Profile::FromBrowserContext(context));
+  return new DiceWebSigninInterceptor(
+      Profile::FromBrowserContext(context),
+      std::make_unique<DiceWebSigninInterceptorDelegate>());
 }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
index 15e8c76..38f1aaa8 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
@@ -6,23 +6,41 @@
 
 #include <memory>
 
+#include "base/callback.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
 #include "chrome/browser/profiles/profile_attributes_storage.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_test_util.h"
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
+#include "chrome/browser/signin/signin_features.h"
 #include "chrome/common/chrome_constants.h"
 #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/signin/public/identity_manager/identity_test_environment.h"
 #include "content/public/test/browser_task_environment.h"
+#include "content/public/test/test_web_contents_factory.h"
 #include "services/network/test/test_url_loader_factory.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
+class MockDiceWebSigninInterceptorDelegate
+    : public DiceWebSigninInterceptor::Delegate {
+ public:
+  MOCK_METHOD(void,
+              ShowSigninInterceptionBubble,
+              (DiceWebSigninInterceptor::SigninInterceptionType
+                   signin_interception_type,
+               content::WebContents* web_contents,
+               const AccountInfo& account_info,
+               base::OnceCallback<void(bool)> callback),
+              (override));
+};
+
 // If the account info is valid, does nothing. Otherwise fills the extended
 // fields with default values.
 void MakeValidAccountInfo(AccountInfo* info) {
@@ -48,8 +66,14 @@
     return dice_web_signin_interceptor_.get();
   }
 
+  MockDiceWebSigninInterceptorDelegate* mock_delegate() {
+    return mock_delegate_;
+  }
+
   Profile* profile() { return profile_; }
 
+  content::WebContents* web_contents() { return web_contents_; }
+
   ProfileAttributesStorage* profile_attributes_storage() {
     return profile_manager_->profile_attributes_storage();
   }
@@ -65,6 +89,7 @@
  private:
   // testing::Test:
   void SetUp() override {
+    feature_list_.InitAndEnableFeature(kDiceWebSigninInterceptionFeature);
     // Create a testing profile registered in the profile manager.
     profile_manager_ = std::make_unique<TestingProfileManager>(
         TestingBrowserProcess::GetGlobal());
@@ -85,35 +110,48 @@
     identity_test_env_profile_adaptor_->identity_test_env()
         ->SetTestURLLoaderFactory(&test_url_loader_factory_);
 
-    dice_web_signin_interceptor_ =
-        std::make_unique<DiceWebSigninInterceptor>(profile_);
+    auto delegate = std::make_unique<
+        testing::StrictMock<MockDiceWebSigninInterceptorDelegate>>();
+    mock_delegate_ = delegate.get();
+    dice_web_signin_interceptor_ = std::make_unique<DiceWebSigninInterceptor>(
+        profile_, std::move(delegate));
+
+    web_contents_ = test_web_contents_factory_.CreateWebContents(profile_);
   }
 
   void TearDown() override {
+    test_web_contents_factory_.DestroyWebContents(web_contents_);
     dice_web_signin_interceptor_->Shutdown();
-    profile_ = nullptr;
     identity_test_env_profile_adaptor_.reset();
     profile_manager_->DeleteTestingProfile(chrome::kInitialProfile);
   }
 
+  base::test::ScopedFeatureList feature_list_;
   content::BrowserTaskEnvironment task_environment_;
   network::TestURLLoaderFactory test_url_loader_factory_;
+  content::TestWebContentsFactory test_web_contents_factory_;
   std::unique_ptr<TestingProfileManager> profile_manager_;
-  TestingProfile* profile_ = nullptr;
   std::unique_ptr<IdentityTestEnvironmentProfileAdaptor>
       identity_test_env_profile_adaptor_;
   std::unique_ptr<DiceWebSigninInterceptor> dice_web_signin_interceptor_;
+
+  // Owned by profile_manager_
+  TestingProfile* profile_ = nullptr;
+  // Owned by dice_web_signin_interceptor_
+  MockDiceWebSigninInterceptorDelegate* mock_delegate_ = nullptr;
+  // Owned by test_web_contents_factory_
+  content::WebContents* web_contents_ = nullptr;
 };
 
-TEST_F(DiceWebSigninInterceptorTest, IsAccountInAnotherProfile) {
+TEST_F(DiceWebSigninInterceptorTest, ShouldShowProfileSwitchBubble) {
   AccountInfo account_info =
       identity_test_env()->MakeAccountAvailable("bob@example.com");
-  EXPECT_FALSE(interceptor()->IsAccountInAnotherProfile(
+  EXPECT_FALSE(interceptor()->ShouldShowProfileSwitchBubble(
       account_info, profile_attributes_storage()));
 
   // Add another profile with no account.
   CreateTestingProfile("Profile 1");
-  EXPECT_FALSE(interceptor()->IsAccountInAnotherProfile(
+  EXPECT_FALSE(interceptor()->ShouldShowProfileSwitchBubble(
       account_info, profile_attributes_storage()));
 
   // Add another profile with a different account.
@@ -125,13 +163,13 @@
   ASSERT_NE(kOtherGaiaID, account_info.gaia);
   entry->SetAuthInfo(kOtherGaiaID, base::UTF8ToUTF16("Bob"),
                      /*is_consented_primary_account=*/true);
-  EXPECT_FALSE(interceptor()->IsAccountInAnotherProfile(
+  EXPECT_FALSE(interceptor()->ShouldShowProfileSwitchBubble(
       account_info, profile_attributes_storage()));
 
   // Change the account to match.
   entry->SetAuthInfo(account_info.gaia, base::UTF8ToUTF16("Bob"),
                      /*is_consented_primary_account=*/false);
-  EXPECT_TRUE(interceptor()->IsAccountInAnotherProfile(
+  EXPECT_TRUE(interceptor()->ShouldShowProfileSwitchBubble(
       account_info, profile_attributes_storage()));
 }
 
@@ -248,3 +286,171 @@
   identity_test_env()->UpdateAccountInfoForAccount(account_info_1);
   EXPECT_FALSE(interceptor()->ShouldShowMultiUserBubble(account_info_1));
 }
+
+TEST_F(DiceWebSigninInterceptorTest, NoInterception) {
+  // Setup for profile switch interception.
+  AccountInfo account_info =
+      identity_test_env()->MakeAccountAvailable("bob@example.com");
+  Profile* profile_2 = CreateTestingProfile("Profile 2");
+  ProfileAttributesEntry* entry;
+  ASSERT_TRUE(profile_attributes_storage()->GetProfileAttributesWithPath(
+      profile_2->GetPath(), &entry));
+  entry->SetAuthInfo(account_info.gaia, base::UTF8ToUTF16("Bob"),
+                     /*is_consented_primary_account=*/false);
+
+  // Check that Sync signin is not intercepted.
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/true);
+  testing::Mock::VerifyAndClearExpectations(mock_delegate());
+
+  // Check that reauth is not intercepted.
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/false,
+                                         /*is_sync_signin=*/false);
+  testing::Mock::VerifyAndClearExpectations(mock_delegate());
+
+  // Check that interception works otherwise, as a sanity check.
+  EXPECT_CALL(
+      *mock_delegate(),
+      ShowSigninInterceptionBubble(
+          DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch,
+          web_contents(), account_info, testing::_));
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+}
+
+TEST_F(DiceWebSigninInterceptorTest, InterceptionInProgress) {
+  // Setup for profile switch interception.
+  AccountInfo account_info =
+      identity_test_env()->MakeAccountAvailable("bob@example.com");
+  Profile* profile_2 = CreateTestingProfile("Profile 2");
+  ProfileAttributesEntry* entry;
+  ASSERT_TRUE(profile_attributes_storage()->GetProfileAttributesWithPath(
+      profile_2->GetPath(), &entry));
+  entry->SetAuthInfo(account_info.gaia, base::UTF8ToUTF16("Bob"),
+                     /*is_consented_primary_account=*/false);
+
+  // Start an interception.
+  base::OnceCallback<void(bool)> delegate_callback;
+  EXPECT_CALL(
+      *mock_delegate(),
+      ShowSigninInterceptionBubble(
+          DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch,
+          web_contents(), account_info, testing::_))
+      .WillOnce(testing::WithArg<3>(testing::Invoke(
+          [&delegate_callback](base::OnceCallback<void(bool)> callback) {
+            delegate_callback = std::move(callback);
+          })));
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+  testing::Mock::VerifyAndClearExpectations(mock_delegate());
+  EXPECT_TRUE(interceptor()->is_interception_in_progress_);
+
+  // Check that there is no interception while another one is in progress.
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+  testing::Mock::VerifyAndClearExpectations(mock_delegate());
+
+  // Complete the interception that was in progress.
+  std::move(delegate_callback).Run(false);
+  EXPECT_FALSE(interceptor()->is_interception_in_progress_);
+
+  // A new interception can now start.
+  EXPECT_CALL(
+      *mock_delegate(),
+      ShowSigninInterceptionBubble(
+          DiceWebSigninInterceptor::SigninInterceptionType::kProfileSwitch,
+          web_contents(), account_info, testing::_));
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+}
+
+// Interception other than the profile switch require at least 2 accounts.
+TEST_F(DiceWebSigninInterceptorTest, NoInterceptionWithOneAccount) {
+  AccountInfo account_info =
+      identity_test_env()->MakeAccountAvailable("bob@example.com");
+  // Interception aborts even if the account info is not available.
+  ASSERT_FALSE(
+      identity_test_env()
+          ->identity_manager()
+          ->FindExtendedAccountInfoForAccountWithRefreshTokenByAccountId(
+              account_info.account_id)
+          ->IsValid());
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+  EXPECT_FALSE(interceptor()->is_interception_in_progress_);
+}
+
+TEST_F(DiceWebSigninInterceptorTest, WaitForAccountInfoAvailable) {
+  identity_test_env()->MakeUnconsentedPrimaryAccountAvailable(
+      "bob@example.com");
+  AccountInfo account_info =
+      identity_test_env()->MakeAccountAvailable("alice@example.com");
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+  // Delegate was not called yet.
+  testing::Mock::VerifyAndClearExpectations(mock_delegate());
+
+  // Account info becomes available, interception happens.
+  EXPECT_CALL(*mock_delegate(),
+              ShowSigninInterceptionBubble(
+                  DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise,
+                  web_contents(), account_info, testing::_));
+  MakeValidAccountInfo(&account_info);
+  account_info.hosted_domain = "example.com";
+  identity_test_env()->UpdateAccountInfoForAccount(account_info);
+}
+
+TEST_F(DiceWebSigninInterceptorTest, AccountInfoAlreadyAvailable) {
+  identity_test_env()->MakeUnconsentedPrimaryAccountAvailable(
+      "bob@example.com");
+  AccountInfo account_info =
+      identity_test_env()->MakeAccountAvailable("alice@example.com");
+  MakeValidAccountInfo(&account_info);
+  account_info.hosted_domain = "example.com";
+  identity_test_env()->UpdateAccountInfoForAccount(account_info);
+
+  // Account info is already available, interception happens immediately.
+  EXPECT_CALL(*mock_delegate(),
+              ShowSigninInterceptionBubble(
+                  DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise,
+                  web_contents(), account_info, testing::_));
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+}
+
+TEST_F(DiceWebSigninInterceptorTest, MultiUserInterception) {
+  identity_test_env()->MakeUnconsentedPrimaryAccountAvailable(
+      "bob@example.com");
+  AccountInfo account_info =
+      identity_test_env()->MakeAccountAvailable("alice@example.com");
+  MakeValidAccountInfo(&account_info);
+  identity_test_env()->UpdateAccountInfoForAccount(account_info);
+
+  // Account info is already available, interception happens immediately.
+  EXPECT_CALL(*mock_delegate(),
+              ShowSigninInterceptionBubble(
+                  DiceWebSigninInterceptor::SigninInterceptionType::kMultiUser,
+                  web_contents(), account_info, testing::_));
+  interceptor()->MaybeInterceptWebSignin(web_contents(),
+                                         account_info.account_id,
+                                         /*is_new_account=*/true,
+                                         /*is_sync_signin=*/false);
+}
diff --git a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
index 16d4884..3f27e18 100644
--- a/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
+++ b/chrome/browser/signin/process_dice_header_delegate_impl_unittest.cc
@@ -35,10 +35,26 @@
 signin_metrics::PromoAction kTestPromoAction =
     signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO;
 
+// Dummy delegate that declines all interceptions.
+class TestDiceWebSigninInterceptorDelegate
+    : public DiceWebSigninInterceptor::Delegate {
+ public:
+  ~TestDiceWebSigninInterceptorDelegate() override = default;
+  void ShowSigninInterceptionBubble(
+      DiceWebSigninInterceptor::SigninInterceptionType signin_interception_type,
+      content::WebContents* web_contents,
+      const AccountInfo& account_info,
+      base::OnceCallback<void(bool)> callback) override {
+    std::move(callback).Run(false);
+  }
+};
+
 class MockDiceWebSigninInterceptor : public DiceWebSigninInterceptor {
  public:
   explicit MockDiceWebSigninInterceptor(Profile* profile)
-      : DiceWebSigninInterceptor(profile) {}
+      : DiceWebSigninInterceptor(
+            profile,
+            std::make_unique<TestDiceWebSigninInterceptorDelegate>()) {}
   ~MockDiceWebSigninInterceptor() override = default;
 
   MOCK_METHOD(void,
diff --git a/chrome/browser/speech/DEPS b/chrome/browser/speech/DEPS
new file mode 100644
index 0000000..1a12a09
--- /dev/null
+++ b/chrome/browser/speech/DEPS
@@ -0,0 +1,5 @@
+include_rules = [
+  "+chrome/services/speech/buildflags.h",
+  "+services/network/network_context.h",
+  "+services/network/public/cpp"
+]
diff --git a/chrome/browser/speech/speech_recognition_service.cc b/chrome/browser/speech/speech_recognition_service.cc
index 4fe13fe8..eae2b509 100644
--- a/chrome/browser/speech/speech_recognition_service.cc
+++ b/chrome/browser/speech/speech_recognition_service.cc
@@ -6,13 +6,24 @@
 
 #include "chrome/browser/service_sandbox_type.h"
 #include "chrome/grit/generated_resources.h"
+#include "content/public/browser/browser_context.h"
 #include "content/public/browser/service_process_host.h"
+#include "content/public/browser/storage_partition.h"
+#include "services/network/network_context.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace speech {
 
 constexpr base::TimeDelta kIdleProcessTimeout = base::TimeDelta::FromSeconds(5);
 
-SpeechRecognitionService::SpeechRecognitionService() = default;
+SpeechRecognitionService::SpeechRecognitionService(
+    content::BrowserContext* context)
+#if !BUILDFLAG(ENABLE_SODA)
+    : context_(context)
+#endif  // !BUILDFLAG(ENABLE_SODA)
+{
+}
+
 SpeechRecognitionService::~SpeechRecognitionService() = default;
 
 void SpeechRecognitionService::Create(
@@ -21,6 +32,27 @@
   speech_recognition_service_->BindContext(std::move(receiver));
 }
 
+void SpeechRecognitionService::OnNetworkServiceDisconnect() {
+#if !BUILDFLAG(ENABLE_SODA)
+  // If the Speech On-Device API is not enabled, pass the URL loader factory to
+  // the speech recognition service to allow network requests to the Open Speech
+  // API.
+  mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory;
+  network::mojom::URLLoaderFactoryParamsPtr params =
+      network::mojom::URLLoaderFactoryParams::New();
+  params->process_id = network::mojom::kBrowserProcessId;
+  params->is_trusted = false;
+  params->automatically_assign_isolation_info = true;
+  network::mojom::NetworkContext* network_context =
+      content::BrowserContext::GetDefaultStoragePartition(context_)
+          ->GetNetworkContext();
+  network_context->CreateURLLoaderFactory(
+      url_loader_factory.InitWithNewPipeAndPassReceiver(), std::move(params));
+  speech_recognition_service_->SetUrlLoaderFactory(
+      std::move(url_loader_factory));
+#endif  // !BUILDFLAG(ENABLE_SODA)
+}
+
 void SpeechRecognitionService::LaunchIfNotRunning() {
   if (speech_recognition_service_.is_bound())
     return;
@@ -38,6 +70,10 @@
   // terminated if it isn't already.
   speech_recognition_service_.reset_on_disconnect();
   speech_recognition_service_.reset_on_idle_timeout(kIdleProcessTimeout);
-}
 
+  speech_recognition_service_client_.reset();
+  speech_recognition_service_->BindSpeechRecognitionServiceClient(
+      speech_recognition_service_client_.BindNewPipeAndPassRemote());
+  OnNetworkServiceDisconnect();
+}
 }  // namespace speech
diff --git a/chrome/browser/speech/speech_recognition_service.h b/chrome/browser/speech/speech_recognition_service.h
index 25f308e..d48d498b 100644
--- a/chrome/browser/speech/speech_recognition_service.h
+++ b/chrome/browser/speech/speech_recognition_service.h
@@ -5,18 +5,25 @@
 #ifndef CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_SERVICE_H_
 #define CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_SERVICE_H_
 
+#include "chrome/services/speech/buildflags.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "media/mojo/mojom/speech_recognition_service.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
+namespace content {
+class BrowserContext;
+}  // namespace content
+
 namespace speech {
 
 // Provides a mojo endpoint in the browser that allows the renderer process to
 // launch and initialize the sandboxed speech recognition service
 // process.
-class SpeechRecognitionService : public KeyedService {
+class SpeechRecognitionService
+    : public KeyedService,
+      public media::mojom::SpeechRecognitionServiceClient {
  public:
-  SpeechRecognitionService();
+  explicit SpeechRecognitionService(content::BrowserContext* context);
   SpeechRecognitionService(const SpeechRecognitionService&) = delete;
   SpeechRecognitionService& operator=(const SpeechRecognitionService&) = delete;
   ~SpeechRecognitionService() override;
@@ -24,14 +31,25 @@
   void Create(
       mojo::PendingReceiver<media::mojom::SpeechRecognitionContext> receiver);
 
+  // media::mojom::SpeechRecognitionServiceClient
+  void OnNetworkServiceDisconnect() override;
+
  private:
   // Launches the speech recognition service in a sandboxed utility process.
   void LaunchIfNotRunning();
 
+#if !BUILDFLAG(ENABLE_SODA)
+  // The browser context associated with the keyed service.
+  content::BrowserContext* const context_;
+#endif  // !BUILDFLAG(ENABLE_SODA)
+
   // The remote to the speech recognition service. The browser will not launch a
   // new speech recognition service process if this remote is already bound.
   mojo::Remote<media::mojom::SpeechRecognitionService>
       speech_recognition_service_;
+
+  mojo::Receiver<media::mojom::SpeechRecognitionServiceClient>
+      speech_recognition_service_client_{this};
 };
 
 }  // namespace speech
diff --git a/chrome/browser/speech/speech_recognition_service_factory.cc b/chrome/browser/speech/speech_recognition_service_factory.cc
index 0e40e1f..ea562a8 100644
--- a/chrome/browser/speech/speech_recognition_service_factory.cc
+++ b/chrome/browser/speech/speech_recognition_service_factory.cc
@@ -31,6 +31,6 @@
 SpeechRecognitionServiceFactory::~SpeechRecognitionServiceFactory() = default;
 
 KeyedService* SpeechRecognitionServiceFactory::BuildServiceInstanceFor(
-    content::BrowserContext* profile) const {
-  return new speech::SpeechRecognitionService();
+    content::BrowserContext* context) const {
+  return new speech::SpeechRecognitionService(context);
 }
diff --git a/chrome/browser/speech/speech_recognition_service_factory.h b/chrome/browser/speech/speech_recognition_service_factory.h
index 6ef9f781..5aba35f 100644
--- a/chrome/browser/speech/speech_recognition_service_factory.h
+++ b/chrome/browser/speech/speech_recognition_service_factory.h
@@ -34,7 +34,7 @@
 
   // BrowserContextKeyedServiceFactory:
   KeyedService* BuildServiceInstanceFor(
-      content::BrowserContext* profile) const override;
+      content::BrowserContext* context) const override;
 };
 
 #endif  // CHROME_BROWSER_SPEECH_SPEECH_RECOGNITION_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ssl/ssl_browsertest.cc b/chrome/browser/ssl/ssl_browsertest.cc
index 88fc170..fe7018a 100644
--- a/chrome/browser/ssl/ssl_browsertest.cc
+++ b/chrome/browser/ssl/ssl_browsertest.cc
@@ -2097,7 +2097,7 @@
 #if defined(USE_NSS_CERTS)
 class SSLUITestWithClientCert : public SSLUITestBase {
  public:
-  SSLUITestWithClientCert() : cert_db_(NULL) {}
+  SSLUITestWithClientCert() : cert_db_(nullptr) {}
 
   void SetUpOnMainThread() override {
     SSLUITestBase::SetUpOnMainThread();
diff --git a/chrome/browser/supervised_user/supervised_user_site_list.cc b/chrome/browser/supervised_user/supervised_user_site_list.cc
index 8af13478..4ecacb0 100644
--- a/chrome/browser/supervised_user/supervised_user_site_list.cc
+++ b/chrome/browser/supervised_user/supervised_user_site_list.cc
@@ -10,7 +10,6 @@
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/logging.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
@@ -30,7 +29,6 @@
 
 std::unique_ptr<base::Value> ReadFileOnBlockingThread(
     const base::FilePath& path) {
-  SCOPED_UMA_HISTOGRAM_TIMER("ManagedUsers.Whitelist.ReadDuration");
   JSONFileValueDeserializer deserializer(path);
   int error_code;
   std::string error_msg;
@@ -97,7 +95,7 @@
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
       base::BindOnce(&ReadFileOnBlockingThread, path),
       base::BindOnce(&SupervisedUserSiteList::OnJsonLoaded, id, title,
-                     large_icon_path, path, base::TimeTicks::Now(), callback));
+                     large_icon_path, path, callback));
 }
 
 SupervisedUserSiteList::SupervisedUserSiteList(
@@ -147,17 +145,11 @@
     const base::string16& title,
     const base::FilePath& large_icon_path,
     const base::FilePath& path,
-    base::TimeTicks start_time,
     const SupervisedUserSiteList::LoadedCallback& callback,
     std::unique_ptr<base::Value> value) {
   if (!value)
     return;
 
-  if (!start_time.is_null()) {
-    UMA_HISTOGRAM_TIMES("ManagedUsers.Whitelist.JsonParseDuration",
-                        base::TimeTicks::Now() - start_time);
-  }
-
   base::DictionaryValue* dict = nullptr;
   if (!value->GetAsDictionary(&dict)) {
     LOG(ERROR) << "Whitelist " << path.value() << " is invalid";
diff --git a/chrome/browser/supervised_user/supervised_user_site_list.h b/chrome/browser/supervised_user/supervised_user_site_list.h
index af27d52b..98510b9 100644
--- a/chrome/browser/supervised_user/supervised_user_site_list.h
+++ b/chrome/browser/supervised_user/supervised_user_site_list.h
@@ -20,7 +20,6 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
-#include "base/time/time.h"
 #include "url/gurl.h"
 
 namespace base {
@@ -103,7 +102,6 @@
       const base::string16& title,
       const base::FilePath& large_icon_path,
       const base::FilePath& path,
-      base::TimeTicks start_time,
       const SupervisedUserSiteList::LoadedCallback& callback,
       std::unique_ptr<base::Value> value);
 
diff --git a/chrome/browser/supervised_user/supervised_user_whitelist_service.cc b/chrome/browser/supervised_user/supervised_user_whitelist_service.cc
index b909c474..988a4f2 100644
--- a/chrome/browser/supervised_user/supervised_user_whitelist_service.cc
+++ b/chrome/browser/supervised_user/supervised_user_whitelist_service.cc
@@ -339,21 +339,16 @@
   SupervisedUserSiteList::Load(
       id, title, large_icon_path, whitelist_path,
       base::Bind(&SupervisedUserWhitelistService::OnWhitelistLoaded,
-                 weak_ptr_factory_.GetWeakPtr(), id, base::TimeTicks::Now()));
+                 weak_ptr_factory_.GetWeakPtr(), id));
 }
 
 void SupervisedUserWhitelistService::OnWhitelistLoaded(
     const std::string& id,
-    base::TimeTicks start_time,
     const scoped_refptr<SupervisedUserSiteList>& whitelist) {
   if (!whitelist) {
     LOG(WARNING) << "Couldn't load whitelist " << id;
     return;
   }
-
-  UMA_HISTOGRAM_TIMES("ManagedUsers.Whitelist.TotalLoadDuration",
-                      base::TimeTicks::Now() - start_time);
-
   // If the whitelist has been unregistered in the mean time, ignore it.
   if (registered_whitelists_.count(id) == 0u)
     return;
diff --git a/chrome/browser/supervised_user/supervised_user_whitelist_service.h b/chrome/browser/supervised_user/supervised_user_whitelist_service.h
index d4eb6e7..c1e5b450 100644
--- a/chrome/browser/supervised_user/supervised_user_whitelist_service.h
+++ b/chrome/browser/supervised_user/supervised_user_whitelist_service.h
@@ -14,7 +14,6 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
-#include "base/time/time.h"
 #include "chrome/browser/supervised_user/supervised_users.h"
 #include "components/sync/model/syncable_service.h"
 
@@ -122,7 +121,6 @@
                         const base::FilePath& whitelist_path);
   void OnWhitelistLoaded(
       const std::string& id,
-      base::TimeTicks start_time,
       const scoped_refptr<SupervisedUserSiteList>& whitelist);
 
   PrefService* prefs_;
diff --git a/chrome/browser/sync/test/integration/two_client_printers_sync_test.cc b/chrome/browser/sync/test/integration/two_client_printers_sync_test.cc
index 650736ee..c02bbbe 100644
--- a/chrome/browser/sync/test/integration/two_client_printers_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_printers_sync_test.cc
@@ -257,7 +257,6 @@
 IN_PROC_BROWSER_TEST_F(TwoClientPrintersSyncTest,
                        InvalidPpdReferenceResolution) {
   ASSERT_TRUE(SetupClients());
-  base::HistogramTester histograms;
 
   // Initialize sync bridge with test printer.
   auto printer = CreateTestPrinterSpecifics(0);
@@ -288,6 +287,4 @@
   spec_ppd_ref = spec_printer->ppd_reference();
   EXPECT_FALSE(spec_ppd_ref.autoconf());
   EXPECT_TRUE(spec_ppd_ref.has_user_supplied_ppd_url());
-  histograms.ExpectBucketCount("Printing.CUPS.InvalidPpdResolved",
-                               1 /* kResolved */, 1);
 }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
index 210203d..4b507ddd 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/EmptyTabObserver.java
@@ -76,6 +76,9 @@
     public void onCrash(Tab tab) {}
 
     @Override
+    public void webContentsWillSwap(Tab tab) {}
+
+    @Override
     public void onWebContentsSwapped(Tab tab, boolean didStartLoad, boolean didFinishLoad) {}
 
     @Override
@@ -149,5 +152,5 @@
             int bottomControlsMinHeightOffsetY) {}
 
     @Override
-    public void onContentViewScrollingStateChanged(boolean scrolling) {}
+    public void onContentViewScrollingStateChanged(Tab tab, boolean scrolling) {}
 }
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java
index ff92aa2..190aaaa 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/TabObserver.java
@@ -153,6 +153,12 @@
     void onRestoreFailed(Tab tab);
 
     /**
+     * Called when the WebContents of a {@link Tab} is about to be swapped.
+     * @param tab The notifying {@link Tab}
+     */
+    void webContentsWillSwap(Tab tab);
+
+    /**
      * Called when the WebContents of a {@link Tab} have been swapped.
      * @param tab The notifying {@link Tab}.
      * @param didStartLoad Whether WebContentsObserver::DidStartProvisionalLoadForFrame() has
@@ -342,5 +348,5 @@
      * Called when scrolling state of Tab's content view changes.
      * @param scrolling {@code true} if scrolling started; {@code false} if stopped.
      */
-    void onContentViewScrollingStateChanged(boolean scrolling);
+    void onContentViewScrollingStateChanged(Tab tab, boolean scrolling);
 }
diff --git a/chrome/browser/tabmodel/BUILD.gn b/chrome/browser/tabmodel/BUILD.gn
index be2e6cd0..2225c91 100644
--- a/chrome/browser/tabmodel/BUILD.gn
+++ b/chrome/browser/tabmodel/BUILD.gn
@@ -7,8 +7,10 @@
 android_library("java") {
   sources = [
     "android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModel.java",
+    "android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelFilter.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/TabList.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/TabModel.java",
+    "android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java",
     "android/java/src/org/chromium/chrome/browser/tabmodel/TabModelUtils.java",
   ]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelFilter.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelFilter.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelFilter.java
rename to chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/EmptyTabModelFilter.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
similarity index 100%
rename from chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
rename to chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
diff --git a/chrome/browser/themes/theme_syncable_service_unittest.cc b/chrome/browser/themes/theme_syncable_service_unittest.cc
index e500c9e..e59dd5c1 100644
--- a/chrome/browser/themes/theme_syncable_service_unittest.cc
+++ b/chrome/browser/themes/theme_syncable_service_unittest.cc
@@ -176,7 +176,7 @@
 
 class ThemeSyncableServiceTest : public testing::Test {
  protected:
-  ThemeSyncableServiceTest() : fake_theme_service_(NULL) {}
+  ThemeSyncableServiceTest() : fake_theme_service_(nullptr) {}
 
   ~ThemeSyncableServiceTest() override {}
 
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 13bd740..11b04bbb 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -241,8 +241,6 @@
     "webui/log_web_ui_url.h",
     "webui/media/media_engagement_ui.cc",
     "webui/media/media_engagement_ui.h",
-    "webui/media/media_feeds_ui.cc",
-    "webui/media/media_feeds_ui.h",
     "webui/media/media_history_ui.cc",
     "webui/media/media_history_ui.h",
     "webui/media/webrtc_logs_ui.cc",
@@ -614,6 +612,12 @@
     }
   } else {
     # !is_android
+
+    sources += [
+      "webui/media/media_feeds_ui.cc",
+      "webui/media/media_feeds_ui.h",
+    ]
+
     deps += [ "//components/autofill/content/browser/webauthn" ]
   }
 
@@ -798,12 +802,6 @@
       ]
     }
 
-    if (enable_password_change_in_leaked_dialog) {
-      sources += [
-        "android/passwords/credential_leak_dialog_password_change_view_android.cc",
-        "android/passwords/credential_leak_dialog_password_change_view_android.h",
-      ]
-    }
     deps += [
       "//chrome/android:jni_headers",
       "//chrome/android/features/dev_ui:buildflags",
@@ -1756,6 +1754,8 @@
       "webui/chromeos/bluetooth_dialog_localized_strings_provider.h",
       "webui/chromeos/bluetooth_pairing_dialog.cc",
       "webui/chromeos/bluetooth_pairing_dialog.h",
+      "webui/chromeos/camera/camera_ui.cc",
+      "webui/chromeos/camera/camera_ui.h",
       "webui/chromeos/cellular_setup/cellular_setup_dialog.cc",
       "webui/chromeos/cellular_setup/cellular_setup_dialog.h",
       "webui/chromeos/cellular_setup/cellular_setup_dialog_launcher.cc",
@@ -2118,6 +2118,7 @@
       "//chrome/browser/chromeos",
       "//chrome/browser/chromeos:backdrop_wallpaper_proto",
       "//chrome/browser/chromeos/net/network_health/public/mojom:mojom",
+      "//chrome/browser/resources/chromeos:camera_resources",
       "//chrome/browser/resources/chromeos:network_health_resources",
       "//chrome/browser/ui/webui/app_management:mojo_bindings",
       "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings",
@@ -2131,7 +2132,6 @@
       "//chromeos/assistant:buildflags",
       "//chromeos/audio",
       "//chromeos/components/account_manager",
-      "//chromeos/components/camera_app_ui",
       "//chromeos/components/help_app_ui",
       "//chromeos/components/media_app_ui",
       "//chromeos/components/multidevice",
diff --git a/chrome/browser/ui/android/overlay/overlay_window_android.h b/chrome/browser/ui/android/overlay/overlay_window_android.h
index 0aa5e4ff..a0373b53 100644
--- a/chrome/browser/ui/android/overlay/overlay_window_android.h
+++ b/chrome/browser/ui/android/overlay/overlay_window_android.h
@@ -59,7 +59,7 @@
   gfx::Rect GetBounds() override;
   void UpdateVideoSize(const gfx::Size& natural_size) override;
   void SetPlaybackState(PlaybackState playback_state) override {}
-  void SetAlwaysHidePlayPauseButton(bool is_visible) override {}
+  void SetPlayPauseButtonVisibility(bool is_visible) override {}
   void SetSkipAdButtonVisibility(bool is_visible) override {}
   void SetNextTrackButtonVisibility(bool is_visible) override {}
   void SetPreviousTrackButtonVisibility(bool is_visible) override {}
diff --git a/chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.cc b/chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.cc
deleted file mode 100644
index 960eaee..0000000
--- a/chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.cc
+++ /dev/null
@@ -1,70 +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 "chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.h"
-#include <cstdint>
-
-#include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "chrome/android/chrome_jni_headers/CredentialLeakDialogPasswordChangeBridge_jni.h"
-#include "chrome/browser/password_manager/chrome_password_manager_client.h"
-#include "chrome/browser/password_manager/credential_leak_password_change_controller_android.h"
-#include "chrome/grit/generated_resources.h"
-#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
-#include "components/password_manager/core/common/password_manager_pref_names.h"
-#include "components/prefs/pref_service.h"
-#include "components/strings/grit/components_strings.h"
-#include "content/public/browser/web_contents.h"
-#include "ui/android/window_android.h"
-#include "ui/base/l10n/l10n_util.h"
-
-CredentialLeakDialogPasswordChangeViewAndroid::
-    CredentialLeakDialogPasswordChangeViewAndroid(
-        CredentialLeakPasswordChangeControllerAndroid* controller)
-    : controller_(controller) {}
-
-CredentialLeakDialogPasswordChangeViewAndroid::
-    ~CredentialLeakDialogPasswordChangeViewAndroid() {
-  Java_CredentialLeakDialogPasswordChangeBridge_destroy(
-      base::android::AttachCurrentThread(), java_object_);
-}
-
-void CredentialLeakDialogPasswordChangeViewAndroid::Show(
-    ui::WindowAndroid* window_android) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  java_object_.Reset(Java_CredentialLeakDialogPasswordChangeBridge_create(
-      env, window_android->GetJavaObject(), reinterpret_cast<intptr_t>(this)));
-
-  Java_CredentialLeakDialogPasswordChangeBridge_showDialog(
-      env, java_object_,
-      base::android::ConvertUTF16ToJavaString(env, controller_->GetTitle()),
-      base::android::ConvertUTF16ToJavaString(env,
-                                              controller_->GetDescription()),
-      base::android::ConvertUTF16ToJavaString(
-          env, controller_->GetAcceptButtonLabel()),
-      controller_->ShouldShowCancelButton()
-          ? base::android::ConvertUTF16ToJavaString(
-                env, controller_->GetCancelButtonLabel())
-          : nullptr);
-}
-
-void CredentialLeakDialogPasswordChangeViewAndroid::Accepted(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj) {
-  controller_->OnAcceptDialog();
-}
-
-void CredentialLeakDialogPasswordChangeViewAndroid::Cancelled(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj) {
-  controller_->OnCancelDialog();
-}
-
-void CredentialLeakDialogPasswordChangeViewAndroid::Closed(
-    JNIEnv* env,
-    const base::android::JavaParamRef<jobject>& obj) {
-  controller_->OnCloseDialog();
-}
diff --git a/chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.h b/chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.h
deleted file mode 100644
index 95679f4..0000000
--- a/chrome/browser/ui/android/passwords/credential_leak_dialog_password_change_view_android.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_ANDROID_PASSWORDS_CREDENTIAL_LEAK_DIALOG_PASSWORD_CHANGE_VIEW_ANDROID_H_
-#define CHROME_BROWSER_UI_ANDROID_PASSWORDS_CREDENTIAL_LEAK_DIALOG_PASSWORD_CHANGE_VIEW_ANDROID_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "chrome/browser/ui/passwords/password_dialog_prompts.h"
-
-namespace ui {
-class WindowAndroid;
-}
-
-class CredentialLeakPasswordChangeControllerAndroid;
-
-// TODO (crbug/1058764) Unfork credential leak dialog password change when
-// prototype is done.
-
-// Modal dialog displaying a warning for the user when an entered credential was
-// detected to have been part of a leak. Communicated with its Java counterpart
-// and passes responses back to the
-// |CredentialLeakPasswordChangeControllerAndroid|.
-class CredentialLeakDialogPasswordChangeViewAndroid {
- public:
-  explicit CredentialLeakDialogPasswordChangeViewAndroid(
-      CredentialLeakPasswordChangeControllerAndroid* controller);
-  ~CredentialLeakDialogPasswordChangeViewAndroid();
-
-  // Called to create and show the dialog.
-  void Show(ui::WindowAndroid* window_android);
-
-  // Called from Java via JNI.
-  void Accepted(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
-
-  // Called from Java via JNI.
-  void Cancelled(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
-
-  // Called from Java via JNI.
-  void Closed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
-
- private:
-  // The controller which owns this dialog and handles the dialog events.
-  CredentialLeakPasswordChangeControllerAndroid* controller_;
-
-  // The corresponding java object.
-  base::android::ScopedJavaGlobalRef<jobject> java_object_;
-
-  DISALLOW_COPY_AND_ASSIGN(CredentialLeakDialogPasswordChangeViewAndroid);
-};
-
-#endif  // CHROME_BROWSER_UI_ANDROID_PASSWORDS_CREDENTIAL_LEAK_DIALOG_PASSWORD_CHANGE_VIEW_ANDROID_H_
diff --git a/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc b/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc
index b8de591..a81f3fb 100644
--- a/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc
+++ b/chrome/browser/ui/app_list/search/drive_quick_access_provider.cc
@@ -26,6 +26,9 @@
 namespace app_list {
 namespace {
 
+using FileAvailability =
+    file_manager::file_tasks::FileTasksNotifier::FileAvailability;
+
 constexpr int kMaxItems = 5;
 
 // Error codes returned by the Drive QuickAccess API call. These values persist
@@ -100,6 +103,8 @@
     : profile_(profile),
       drive_service_(
           drive::DriveIntegrationServiceFactory::GetForProfile(profile)),
+      file_tasks_notifier_(
+          file_manager::file_tasks::FileTasksNotifier::GetForProfile(profile)),
       search_controller_(search_controller),
       suggested_files_enabled_(app_list_features::IsSuggestedFilesEnabled()) {
   DCHECK(profile_);
@@ -150,37 +155,73 @@
       "Apps.AppList.DriveQuickAccessProvider.TimeFromFetchToZeroStateStart",
       base::TimeTicks::Now() - latest_fetch_start_time_);
 
-  // Results are launched via DriveFS, so DriveFS must be mounted.
+  // Results are launched via DriveFS, so DriveFS must be mounted. We must also
+  // have a FileTasksNotifier instance to check file availability.
   bool drive_fs_mounted = drive_service_ && drive_service_->IsMounted();
   LogDriveFSMounted(drive_fs_mounted);
-  if (!drive_fs_mounted)
+  if (!drive_fs_mounted || !file_tasks_notifier_)
     return;
 
-  // If there are no items in the cache, the previous call may have failed so
-  // retry. We return no results in this case, because waiting for the new
-  // results would introduce too much latency.
+  // If there are no items in the cache, return no results, because waiting for
+  // new results would introduce too much latency.
   UMA_HISTOGRAM_BOOLEAN("Apps.AppList.DriveQuickAccessProvider.CacheEmpty",
                         results_cache_.empty());
-  if (results_cache_.empty()) {
-    GetQuickAccessItems(base::DoNothing());
+  if (results_cache_.empty())
     return;
+
+  // Copy the results vector to ensure the QueryFileAvailability and SetResults
+  // calls operate on the same set of results, because |results_cache_| could be
+  // updated at any time.
+  std::vector<base::FilePath> result_paths;
+  for (const auto& result : results_cache_) {
+    result_paths.emplace_back(
+        ReparentToDriveMount(result.path, drive_service_));
   }
 
-  SearchProvider::Results results;
-  for (const auto& result : results_cache_) {
-    const auto& path = ReparentToDriveMount(result.path, drive_service_);
+  // The |file_tasks_notifier_| pointer references a KeyedService, which has the
+  // same lifetime as |profile_|. The app list is destroyed before the profile,
+  // so the base::Unretained pointer below is safe.
+  task_runner_.get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &file_manager::file_tasks::FileTasksNotifier::QueryFileAvailability,
+          base::Unretained(file_tasks_notifier_), result_paths,
+          base::BindOnce(&DriveQuickAccessProvider::PublishResults,
+                         weak_factory_.GetWeakPtr(), result_paths)));
+}
 
-    results.emplace_back(std::make_unique<DriveQuickAccessResult>(
-        path, result.confidence, profile_));
-    // Add suggestion chip file results
+void DriveQuickAccessProvider::PublishResults(
+    const std::vector<base::FilePath>& results,
+    std::vector<file_manager::file_tasks::FileTasksNotifier::FileAvailability>
+        availability) {
+  DCHECK_EQ(results.size(), availability.size());
+
+  // Assign scores to results by simply using their position in the results
+  // list. The confidence scores returned by the QuickAccess API are not
+  // reliable, but the ordering of the results is: the first result is
+  // better than the second, etc. Resulting scores are in [0, 1].
+  int item_index = 0;
+  const double total_items = static_cast<double>(results.size());
+  SearchProvider::Results provider_results;
+  for (int i = 0; i < static_cast<int>(results.size()); ++i) {
+    if (availability[i] != FileAvailability::kOk)
+      continue;
+
+    const double score = 1.0 - (item_index / total_items);
+    ++item_index;
+
+    provider_results.emplace_back(
+        std::make_unique<DriveQuickAccessResult>(results[i], score, profile_));
     if (suggested_files_enabled_) {
-      results.emplace_back(std::make_unique<DriveQuickAccessChipResult>(
-          path, result.confidence, profile_));
+      provider_results.emplace_back(
+          std::make_unique<DriveQuickAccessChipResult>(results[i], score,
+                                                       profile_));
     }
   }
+
+  SwapResults(&provider_results);
   UMA_HISTOGRAM_TIMES("Apps.AppList.DriveQuickAccessProvider.Latency",
                       base::TimeTicks::Now() - query_start_time_);
-  SwapResults(&results);
 }
 
 void DriveQuickAccessProvider::AppListShown() {
@@ -242,18 +283,7 @@
 void DriveQuickAccessProvider::SetResultsCache(
     base::OnceCallback<void()> on_done,
     const std::vector<drive::QuickAccessItem>& drive_results) {
-  results_cache_.clear();
-
-  // Assign scores to results by simply using their position in the results
-  // list. The confidence scores returned by the QuickAccess API are not
-  // reliable, but the ordering of the results is: the first result is
-  // better than the second, etc. Resulting scores are in [0, 1].
-  const double max_score = static_cast<double>(drive_results.size());
-  for (int i = 0; i < static_cast<int>(drive_results.size()); ++i) {
-    results_cache_.push_back(
-        {drive_results[i].path, 1.0 - (static_cast<double>(i) / max_score)});
-  }
-
+  results_cache_ = std::move(drive_results);
   std::move(on_done).Run();
 }
 
diff --git a/chrome/browser/ui/app_list/search/drive_quick_access_provider.h b/chrome/browser/ui/app_list/search/drive_quick_access_provider.h
index 269deb19..fcb72f7 100644
--- a/chrome/browser/ui/app_list/search/drive_quick_access_provider.h
+++ b/chrome/browser/ui/app_list/search/drive_quick_access_provider.h
@@ -14,6 +14,7 @@
 #include "base/strings/string16.h"
 #include "base/time/time.h"
 #include "chrome/browser/chromeos/drive/drive_integration_service.h"
+#include "chrome/browser/chromeos/file_manager/file_tasks_notifier.h"
 #include "chrome/browser/ui/app_list/search/search_provider.h"
 
 class Profile;
@@ -47,11 +48,16 @@
   void SetResultsCache(
       base::OnceCallback<void()> on_done,
       const std::vector<drive::QuickAccessItem>& drive_results);
+  void PublishResults(
+      const std::vector<base::FilePath>& results,
+      std::vector<file_manager::file_tasks::FileTasksNotifier::FileAvailability>
+          availability);
 
   void StartSearchController();
 
   Profile* const profile_;
   drive::DriveIntegrationService* const drive_service_;
+  file_manager::file_tasks::FileTasksNotifier* const file_tasks_notifier_;
   SearchController* const search_controller_;
 
   // Whether the suggested files experiment is enabled.
diff --git a/chrome/browser/ui/ash/DEPS b/chrome/browser/ui/ash/DEPS
index eea9e3f..3d5e595 100644
--- a/chrome/browser/ui/ash/DEPS
+++ b/chrome/browser/ui/ash/DEPS
@@ -11,7 +11,7 @@
   ".*test.*": [
    "!ash",
    "+ash/shortcut_viewer",
-   "+ash/shortcut_viewer/strings/grit/ash_components_strings.h",
+   "+ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h",
    "+ash/keyboard/ui",
    "+ash/public",
    "+ash/assistant/ui/assistant_ui_constants.h",
diff --git a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
index 007f7058..e839496 100644
--- a/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
+++ b/chrome/browser/ui/ash/accelerator_commands_browsertest.cc
@@ -33,18 +33,6 @@
 
 namespace {
 
-// WidgetDelegateView which allows the widget to be maximized.
-class MaximizableWidgetDelegate : public views::WidgetDelegateView {
- public:
-  MaximizableWidgetDelegate() {}
-  ~MaximizableWidgetDelegate() override {}
-
-  bool CanMaximize() const override { return true; }
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(MaximizableWidgetDelegate);
-};
-
 bool IsInImmersive(aura::Window* window) {
   return window->GetProperty(ash::kImmersiveIsActive);
 }
@@ -153,7 +141,8 @@
 
   // 5) Miscellaneous windows (e.g. task manager).
   views::Widget::InitParams params;
-  params.delegate = new MaximizableWidgetDelegate();
+  params.delegate = new views::WidgetDelegateView;
+  params.delegate->SetCanMaximize(true);
   params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   views::Widget misc_widget;
   widget = &misc_widget;
diff --git a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
index 35dd421..d0c22e26 100644
--- a/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
+++ b/chrome/browser/ui/ash/keyboard_shortcut_viewer_metadata_unittest.cc
@@ -11,7 +11,7 @@
 
 #include "ash/public/cpp/accelerators.h"
 #include "ash/shortcut_viewer/keyboard_shortcut_item.h"
-#include "ash/shortcut_viewer/strings/grit/ash_components_strings.h"
+#include "ash/shortcut_viewer/strings/grit/shortcut_viewer_strings.h"
 #include "base/hash/md5.h"
 #include "base/macros.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc
index abeea0a..1e5e975 100644
--- a/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc
+++ b/chrome/browser/ui/ash/launcher/app_service/app_service_app_window_crostini_tracker.cc
@@ -6,6 +6,7 @@
 
 #include "ash/public/cpp/multi_user_window_manager.h"
 #include "ash/public/cpp/shelf_model.h"
+#include "ash/public/cpp/window_properties.h"
 #include "base/containers/flat_tree.h"
 #include "base/time/time.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
@@ -205,6 +206,13 @@
     return std::string();
   }
 
+  ash::ShelfID shelf_id =
+      ash::ShelfID::Deserialize(window->GetProperty(ash::kShelfIDKey));
+  if (shelf_id.app_id == crostini::kCrostiniInstallerShelfId ||
+      shelf_id.app_id == crostini::kCrostiniUpgraderShelfId) {
+    return shelf_id.app_id;
+  }
+
   // Handle browser windows, such as the Crostini terminal.
   Browser* browser = chrome::FindBrowserWithWindow(window);
   if (browser) {
@@ -219,7 +227,7 @@
     // cause inconsistent error.
     auto* proxy_ = apps::AppServiceProxyFactory::GetForProfile(
         app_service_controller_->owner()->profile());
-    const ash::ShelfID shelf_id = proxy_->InstanceRegistry().GetShelfId(window);
+    shelf_id = proxy_->InstanceRegistry().GetShelfId(window);
     if (shelf_id.app_id != app_id) {
       app_service_controller_->app_service_instance_helper()->OnInstances(
           shelf_id.app_id, window, std::string(),
diff --git a/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc b/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc
index fec89b9..2790cc0 100644
--- a/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc
+++ b/chrome/browser/ui/aura/tab_contents/web_drag_bookmark_handler_aura.cc
@@ -15,9 +15,7 @@
 using content::WebContents;
 
 WebDragBookmarkHandlerAura::WebDragBookmarkHandlerAura()
-    : bookmark_tab_helper_(NULL),
-      web_contents_(NULL) {
-}
+    : bookmark_tab_helper_(nullptr), web_contents_(nullptr) {}
 
 WebDragBookmarkHandlerAura::~WebDragBookmarkHandlerAura() {
 }
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
index 6706dfd5..7b247d30 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_unittest.cc
@@ -227,7 +227,7 @@
  public:
   AutofillPopupControllerUnitTest()
       : autofill_client_(new MockAutofillClient()),
-        autofill_popup_controller_(NULL) {}
+        autofill_popup_controller_(nullptr) {}
   ~AutofillPopupControllerUnitTest() override = default;
 
   void SetUp() override {
diff --git a/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc b/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc
index 53b45c3d..c0b5a805 100644
--- a/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc
+++ b/chrome/browser/ui/bookmarks/bookmark_tab_helper.cc
@@ -89,8 +89,8 @@
 BookmarkTabHelper::BookmarkTabHelper(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       is_starred_(false),
-      bookmark_model_(NULL),
-      bookmark_drag_(NULL) {
+      bookmark_model_(nullptr),
+      bookmark_drag_(nullptr) {
   bookmark_model_ = BookmarkModelFactory::GetForBrowserContext(
       web_contents->GetBrowserContext());
   if (bookmark_model_)
diff --git a/chrome/browser/ui/browser_unittest.cc b/chrome/browser/ui/browser_unittest.cc
index 92bdb4e..3bdd82f 100644
--- a/chrome/browser/ui/browser_unittest.cc
+++ b/chrome/browser/ui/browser_unittest.cc
@@ -333,7 +333,7 @@
   class BookmarkBarStateTestBrowserWindow : public TestBrowserWindow {
    public:
     BookmarkBarStateTestBrowserWindow()
-        : browser_(NULL), bookmark_bar_state_(BookmarkBar::HIDDEN) {}
+        : browser_(nullptr), bookmark_bar_state_(BookmarkBar::HIDDEN) {}
     ~BookmarkBarStateTestBrowserWindow() override {}
 
     void set_browser(Browser* browser) { browser_ = browser; }
diff --git a/chrome/browser/ui/caption_bubble_controller.h b/chrome/browser/ui/caption_bubble_controller.h
index 6ad4dc1..59a0c13 100644
--- a/chrome/browser/ui/caption_bubble_controller.h
+++ b/chrome/browser/ui/caption_bubble_controller.h
@@ -37,14 +37,16 @@
 
   static std::unique_ptr<CaptionBubbleController> Create(Browser* browser);
 
-  // Called when a transcription is received from the service.
-  virtual void OnTranscription(
+  // Called when a transcription is received from the service. Returns whether
+  // the transcription result was set on the caption bubble successfully.
+  // Transcriptions will halt if this returns false.
+  virtual bool OnTranscription(
       const chrome::mojom::TranscriptionResultPtr& transcription_result,
-      content::WebContents* web_contents) {}
+      content::WebContents* web_contents) = 0;
 
   // Called when the caption style changes.
   virtual void UpdateCaptionStyle(
-      base::Optional<ui::CaptionStyle> caption_style) {}
+      base::Optional<ui::CaptionStyle> caption_style) = 0;
 };
 
 }  // namespace captions
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc
index 1145a28f..a194356 100644
--- a/chrome/browser/ui/chrome_pages.cc
+++ b/chrome/browser/ui/chrome_pages.cc
@@ -141,6 +141,7 @@
   const std::string query_string = base::StrCat(
       {kChromeReleaseNotesURL, "?version=", milestone, "&tags=", board_name,
        ",", region, ",", language, ",", channel_name, ",", user_type});
+  VLOG(0) << "Release Notes Query String: " << query_string;
   return query_string;
 }
 
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
index bce79631..8ef98a1 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller_state_unittest.cc
@@ -84,9 +84,7 @@
 };
 
 FullscreenControllerTestWindow::FullscreenControllerTestWindow()
-    : state_(NORMAL),
-      browser_(NULL) {
-}
+    : state_(NORMAL), browser_(nullptr) {}
 
 void FullscreenControllerTestWindow::EnterFullscreen(
     const GURL& url,
diff --git a/chrome/browser/ui/login/login_handler_browsertest.cc b/chrome/browser/ui/login/login_handler_browsertest.cc
index e602046..9b4d6ba 100644
--- a/chrome/browser/ui/login/login_handler_browsertest.cc
+++ b/chrome/browser/ui/login/login_handler_browsertest.cc
@@ -29,7 +29,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/prefs/pref_service.h"
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_origin.h"
 #include "components/security_interstitials/content/security_interstitial_tab_helper.h"
 #include "components/security_interstitials/content/ssl_blocking_page.h"
 #include "content/public/browser/notification_details.h"
diff --git a/chrome/browser/ui/search_engines/template_url_table_model.cc b/chrome/browser/ui/search_engines/template_url_table_model.cc
index bbc62ed..4f83807 100644
--- a/chrome/browser/ui/search_engines/template_url_table_model.cc
+++ b/chrome/browser/ui/search_engines/template_url_table_model.cc
@@ -18,7 +18,7 @@
 
 TemplateURLTableModel::TemplateURLTableModel(
     TemplateURLService* template_url_service)
-    : observer_(NULL), template_url_service_(template_url_service) {
+    : observer_(nullptr), template_url_service_(template_url_service) {
   DCHECK(template_url_service);
   template_url_service_->AddObserver(this);
   template_url_service_->Load();
diff --git a/chrome/browser/ui/singleton_tabs.cc b/chrome/browser/ui/singleton_tabs.cc
index 6f7e94a..6d99c68 100644
--- a/chrome/browser/ui/singleton_tabs.cc
+++ b/chrome/browser/ui/singleton_tabs.cc
@@ -132,7 +132,7 @@
        ++browser_it) {
     Browser* browser = *browser_it;
     // When tab switching, only look at same profile and anonymity level.
-    if (browser->profile()->IsSameProfileAndType(profile)) {
+    if (profile == browser->profile()) {
       int index = GetIndexOfExistingTab(browser, params);
       if (index >= 0)
         return {browser, index};
diff --git a/chrome/browser/ui/startup/startup_browser_creator_impl.cc b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
index e59b1f6..1436937 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_impl.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_impl.cc
@@ -347,8 +347,8 @@
     chrome::startup::IsFirstRun is_first_run)
     : cur_dir_(cur_dir),
       command_line_(command_line),
-      profile_(NULL),
-      browser_creator_(NULL),
+      profile_(nullptr),
+      browser_creator_(nullptr),
       is_first_run_(is_first_run == chrome::startup::IS_FIRST_RUN) {}
 
 StartupBrowserCreatorImpl::StartupBrowserCreatorImpl(
@@ -358,7 +358,7 @@
     chrome::startup::IsFirstRun is_first_run)
     : cur_dir_(cur_dir),
       command_line_(command_line),
-      profile_(NULL),
+      profile_(nullptr),
       browser_creator_(browser_creator),
       is_first_run_(is_first_run == chrome::startup::IS_FIRST_RUN) {}
 
diff --git a/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
index 4762453..5705ecf3 100644
--- a/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
+++ b/chrome/browser/ui/sync/profile_signin_confirmation_helper_unittest.cc
@@ -127,9 +127,7 @@
 class ProfileSigninConfirmationHelperTest : public testing::Test {
  public:
   ProfileSigninConfirmationHelperTest()
-      : user_prefs_(NULL),
-        model_(NULL) {
-  }
+      : user_prefs_(nullptr), model_(nullptr) {}
 
   void SetUp() override {
     ASSERT_TRUE(profile_dir_.CreateUniqueTempDir());
diff --git a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop.cc b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop.cc
index ed6b208..e31679e 100644
--- a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop.cc
+++ b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop.cc
@@ -6,6 +6,7 @@
 
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
+#include "base/optional.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/thread_pool.h"
@@ -95,10 +96,10 @@
   // Collect the data that needs to be scanned.
   if (!drop_data.url_title.empty())
     data.text.push_back(drop_data.url_title);
-  if (!drop_data.text.is_null())
-    data.text.push_back(drop_data.text.string());
-  if (!drop_data.html.is_null())
-    data.text.push_back(drop_data.html.string());
+  if (drop_data.text)
+    data.text.push_back(*drop_data.text);
+  if (drop_data.html)
+    data.text.push_back(*drop_data.html);
   if (!drop_data.file_contents.empty())
     data.text.push_back(base::UTF8ToUTF16(drop_data.file_contents));
 
diff --git a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc
index 033198e..b1e144e 100644
--- a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc
+++ b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc
@@ -8,8 +8,8 @@
 #include "base/bind.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
-#include "base/strings/nullable_string16.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
@@ -189,7 +189,7 @@
 // Make sure DropData::text is handled correctly.
 TEST_P(ChromeWebContentsViewDelegateHandleOnPerformDrop, Text) {
   content::DropData data;
-  data.text = base::NullableString16(base::UTF8ToUTF16("text"), false);
+  data.text = base::UTF8ToUTF16("text");
 
   SetExpectedRequestsCount(0);
   RunTest(data, /*enable=*/false, /*scan_succeeds=*/true);
@@ -202,7 +202,7 @@
 // Make sure DropData::html is handled correctly.
 TEST_P(ChromeWebContentsViewDelegateHandleOnPerformDrop, Html) {
   content::DropData data;
-  data.html = base::NullableString16(base::UTF8ToUTF16("<html></html>"), false);
+  data.html = base::UTF8ToUTF16("<html></html>");
 
   SetExpectedRequestsCount(0);
   RunTest(data, /*enable=*/false, /*scan_succeeds=*/true);
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index ab86be5..98389f5 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -31,8 +31,6 @@
 #include "chrome/browser/history/top_sites_factory.h"
 #include "chrome/browser/infobars/infobar_service.h"
 #include "chrome/browser/installable/installable_manager.h"
-#include "chrome/browser/media/feeds/media_feeds_contents_observer.h"
-#include "chrome/browser/media/feeds/media_feeds_service.h"
 #include "chrome/browser/media/history/media_history_contents_observer.h"
 #include "chrome/browser/media/media_engagement_service.h"
 #include "chrome/browser/metrics/desktop_session_duration/desktop_session_duration_observer.h"
@@ -149,6 +147,11 @@
 #include "chrome/browser/ui/hats/hats_helper.h"
 #endif
 
+#if !defined(OS_ANDROID)
+#include "chrome/browser/media/feeds/media_feeds_contents_observer.h"
+#include "chrome/browser/media/feeds/media_feeds_service.h"
+#endif
+
 #if BUILDFLAG(ENABLE_CAPTIVE_PORTAL_DETECTION)
 #include "components/captive_portal/content/captive_portal_tab_helper.h"
 #endif
@@ -259,8 +262,6 @@
   IsolatedPrerenderTabHelper::CreateForWebContents(web_contents);
   if (MediaEngagementService::IsEnabled())
     MediaEngagementService::CreateWebContentsObserver(web_contents);
-  if (media_feeds::MediaFeedsService::IsEnabled())
-    MediaFeedsContentsObserver::CreateForWebContents(web_contents);
   if (base::FeatureList::IsEnabled(media::kUseMediaHistoryStore))
     MediaHistoryContentsObserver::CreateForWebContents(web_contents);
   metrics::RendererUptimeWebContentsObserver::CreateForWebContents(
@@ -360,6 +361,8 @@
       std::make_unique<JavaScriptTabModalDialogManagerDelegateDesktop>(
           web_contents));
   ManagePasswordsUIController::CreateForWebContents(web_contents);
+  if (media_feeds::MediaFeedsService::IsEnabled())
+    MediaFeedsContentsObserver::CreateForWebContents(web_contents);
   pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
       web_contents, std::make_unique<ChromePDFWebContentsHelperClient>());
   SadTabHelper::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc b/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc
index 69c37ad..375549d0 100644
--- a/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc
+++ b/chrome/browser/ui/tab_modal_confirm_dialog_browsertest.cc
@@ -54,8 +54,8 @@
 }
 
 TabModalConfirmDialogTest::TabModalConfirmDialogTest()
-    : delegate_(NULL),
-      dialog_(NULL),
+    : delegate_(nullptr),
+      dialog_(nullptr),
       accepted_count_(0),
       canceled_count_(0),
       closed_count_(0) {}
diff --git a/chrome/browser/ui/tabs/pinned_tab_service_unittest.cc b/chrome/browser/ui/tabs/pinned_tab_service_unittest.cc
index 1d7410b..0f3d2be 100644
--- a/chrome/browser/ui/tabs/pinned_tab_service_unittest.cc
+++ b/chrome/browser/ui/tabs/pinned_tab_service_unittest.cc
@@ -35,7 +35,7 @@
 
 class PinnedTabServiceTest : public BrowserWithTestWindowTest {
  public:
-  PinnedTabServiceTest() : pinned_tab_service_(NULL) {}
+  PinnedTabServiceTest() : pinned_tab_service_(nullptr) {}
 
  protected:
   TestingProfile* CreateProfile() override {
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc
index 9080ac1..1480d44 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.cc
@@ -69,7 +69,7 @@
 
 void CaptionBubbleControllerViews::OnCaptionBubbleCloseClicked() {
   // Hide the caption bubble on the active tab.
-  caption_texts_[active_contents_].clear();
+  caption_bubble_models_[active_contents_].close();
   // TODO(crbug.com/1051150): Ensure that caption bubble disappears on the tab
   // if it is currently displaying an error message.
   SetCaptionBubbleText();
@@ -84,13 +84,14 @@
   browser_ = nullptr;
 }
 
-void CaptionBubbleControllerViews::OnTranscription(
+bool CaptionBubbleControllerViews::OnTranscription(
     const chrome::mojom::TranscriptionResultPtr& transcription_result,
     content::WebContents* web_contents) {
-  if (!caption_bubble_)
-    return;
-  std::string& partial_text = caption_texts_[web_contents].partial_text;
-  std::string& final_text = caption_texts_[web_contents].final_text;
+  if (!caption_bubble_ || caption_bubble_models_[web_contents].is_closed)
+    return false;
+
+  std::string& partial_text = caption_bubble_models_[web_contents].partial_text;
+  std::string& final_text = caption_bubble_models_[web_contents].final_text;
 
   partial_text = transcription_result->transcription;
   SetCaptionBubbleText();
@@ -117,6 +118,7 @@
       SetCaptionBubbleText();
     }
   }
+  return true;
 }
 
 void CaptionBubbleControllerViews::OnTabStripModelChanged(
@@ -128,7 +130,7 @@
   if (!selection.active_tab_changed())
     return;
   if (selection.selected_tabs_were_removed)
-    caption_texts_.erase(selection.old_contents);
+    caption_bubble_models_.erase(selection.old_contents);
 
   active_contents_ = selection.new_contents;
   SetCaptionBubbleText();
@@ -136,8 +138,8 @@
 
 void CaptionBubbleControllerViews::SetCaptionBubbleText() {
   std::string text;
-  if (active_contents_ && caption_texts_.count(active_contents_))
-    text = caption_texts_[active_contents_].full_text();
+  if (active_contents_ && caption_bubble_models_.count(active_contents_))
+    text = caption_bubble_models_[active_contents_].full_text();
   caption_bubble_->SetText(text);
 }
 
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h
index 7d2a0a4..feffa6c 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views.h
@@ -20,13 +20,15 @@
 
 class CaptionBubble;
 
-struct CaptionText {
+struct CaptionBubbleModel {
   std::string final_text;
   std::string partial_text;
+  bool is_closed = false;
 
-  void clear() {
+  void close() {
     final_text.clear();
     partial_text.clear();
+    is_closed = true;
   }
 
   std::string full_text() { return final_text + partial_text; }
@@ -48,8 +50,10 @@
   CaptionBubbleControllerViews& operator=(const CaptionBubbleControllerViews&) =
       delete;
 
-  // Called when a transcription is received from the service.
-  void OnTranscription(
+  // Called when a transcription is received from the service. Returns whether
+  // the transcription result was set on the caption bubble successfully.
+  // Transcriptions will halt if this returns false.
+  bool OnTranscription(
       const chrome::mojom::TranscriptionResultPtr& transcription_result,
       content::WebContents* web_contents) override;
 
@@ -93,7 +97,8 @@
   // final texts in order to show the latest partial text to a user when they
   // switch back to the tab in case the speech service has not sent a final
   // transcription in a while.
-  std::unordered_map<content::WebContents*, CaptionText> caption_texts_;
+  std::unordered_map<content::WebContents*, CaptionBubbleModel>
+      caption_bubble_models_;
 };
 }  // namespace captions
 
diff --git a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
index afb6828e..36d7fb9 100644
--- a/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
+++ b/chrome/browser/ui/views/accessibility/caption_bubble_controller_views_browsertest.cc
@@ -106,14 +106,14 @@
     EXPECT_EQ(bubble_bounds.bottom(), anchor_bounds.bottom() - 48);
   }
 
-  void OnPartialTranscription(std::string text, int tab_index = 0) {
-    GetController()->OnTranscription(
+  bool OnPartialTranscription(std::string text, int tab_index = 0) {
+    return GetController()->OnTranscription(
         chrome::mojom::TranscriptionResult::New(text, false),
         browser()->tab_strip_model()->GetWebContentsAt(tab_index));
   }
 
-  void OnFinalTranscription(std::string text, int tab_index = 0) {
-    GetController()->OnTranscription(
+  bool OnFinalTranscription(std::string text, int tab_index = 0) {
+    return GetController()->OnTranscription(
         chrome::mojom::TranscriptionResult::New(text, true),
         browser()->tab_strip_model()->GetWebContentsAt(tab_index));
   }
@@ -343,12 +343,21 @@
 }
 
 IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest, CloseButtonCloses) {
-  OnPartialTranscription("Elephants have 3-4 toenails per foot");
+  bool success = OnFinalTranscription("Elephants have 3-4 toenails per foot");
+  EXPECT_TRUE(success);
   EXPECT_TRUE(GetCaptionWidget());
   EXPECT_TRUE(GetCaptionWidget()->IsVisible());
+  EXPECT_EQ("Elephants have 3-4 toenails per foot", GetLabelText());
   ClickCloseButton();
   EXPECT_TRUE(GetCaptionWidget());
   EXPECT_FALSE(GetCaptionWidget()->IsVisible());
+  success = OnFinalTranscription(
+      "Elephants wander 35 miles a day in search of water");
+  EXPECT_FALSE(success);
+  EXPECT_EQ("", GetLabelText());
+
+  // TODO(crbug.com/1055150): The caption bubble should reappear when the tab
+  // refreshes.
 }
 
 IN_PROC_BROWSER_TEST_F(CaptionBubbleControllerViewsTest,
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc b/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc
index 1e296d5..16cbf857 100644
--- a/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc
+++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.cc
@@ -40,7 +40,7 @@
 
 LocalCardMigrationIconView::~LocalCardMigrationIconView() {}
 
-views::BubbleDialogDelegateView* LocalCardMigrationIconView::GetBubble() const {
+views::BubbleDialogDelegate* LocalCardMigrationIconView::GetBubble() const {
   ManageMigrationUiController* controller = GetController();
   if (!controller)
     return nullptr;
diff --git a/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h b/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h
index 90212b6f..88f3353 100644
--- a/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h
+++ b/chrome/browser/ui/views/autofill/payments/local_card_migration_icon_view.h
@@ -25,7 +25,7 @@
   ~LocalCardMigrationIconView() override;
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
 
diff --git a/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc b/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc
index b9ed9cc..c1cf65e 100644
--- a/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc
+++ b/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.cc
@@ -39,7 +39,7 @@
 
 SavePaymentIconView::~SavePaymentIconView() = default;
 
-views::BubbleDialogDelegateView* SavePaymentIconView::GetBubble() const {
+views::BubbleDialogDelegate* SavePaymentIconView::GetBubble() const {
   SavePaymentIconController* controller = GetController();
   if (!controller)
     return nullptr;
diff --git a/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.h b/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.h
index 9b8bbda..239c50a 100644
--- a/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.h
+++ b/chrome/browser/ui/views/autofill/payments/save_payment_icon_view.h
@@ -25,7 +25,7 @@
   ~SavePaymentIconView() override;
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
 
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc
index 40b1562..6d0e1bdc 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc
@@ -61,7 +61,7 @@
                                          views::MenuRunner::HAS_MNEMONICS |
                                              views::MenuRunner::IS_NESTED |
                                              views::MenuRunner::CONTEXT_MENU)),
-      observer_(NULL),
+      observer_(nullptr),
       close_on_remove_(close_on_remove) {
   ui::SimpleMenuModel* menu_model = controller_->menu_model();
   for (int i = 0; i < menu_model->GetItemCount(); ++i) {
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
index b174547..f6e9f747 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate.cc
@@ -75,13 +75,12 @@
       profile_(browser->profile()),
       page_navigator_(navigator),
       parent_(parent),
-      menu_(NULL),
-      parent_menu_item_(NULL),
+      menu_(nullptr),
+      parent_menu_item_(nullptr),
       next_menu_id_(IDC_FIRST_BOOKMARK_MENU),
-      real_delegate_(NULL),
+      real_delegate_(nullptr),
       is_mutating_model_(false),
-      location_(BOOKMARK_LAUNCH_LOCATION_NONE) {
-}
+      location_(BOOKMARK_LAUNCH_LOCATION_NONE) {}
 
 BookmarkMenuDelegate::~BookmarkMenuDelegate() {
   GetBookmarkModel()->RemoveObserver(this);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
index a33f8ec6..fc4b5e11 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_menu_delegate_unittest.cc
@@ -23,7 +23,7 @@
 
 class BookmarkMenuDelegateTest : public BrowserWithTestWindowTest {
  public:
-  BookmarkMenuDelegateTest() : model_(NULL) {}
+  BookmarkMenuDelegateTest() : model_(nullptr) {}
 
   void SetUp() override {
     BrowserWithTestWindowTest::SetUp();
diff --git a/chrome/browser/ui/views/download/download_started_animation_views.cc b/chrome/browser/ui/views/download/download_started_animation_views.cc
index 0937131..d1ec926e 100644
--- a/chrome/browser/ui/views/download/download_started_animation_views.cc
+++ b/chrome/browser/ui/views/download/download_started_animation_views.cc
@@ -60,7 +60,7 @@
 
 DownloadStartedAnimationViews::DownloadStartedAnimationViews(
     content::WebContents* web_contents)
-    : gfx::LinearAnimation(kMoveTime, kFrameRateHz, NULL), popup_(NULL) {
+    : gfx::LinearAnimation(kMoveTime, kFrameRateHz, nullptr), popup_(nullptr) {
   gfx::ImageSkia download_image =
       gfx::CreateVectorIcon(kFileDownloadShelfIcon, 72, gfx::kGoogleBlue500);
 
diff --git a/chrome/browser/ui/views/extensions/browser_action_drag_data.cc b/chrome/browser/ui/views/extensions/browser_action_drag_data.cc
index dacc7bb8..17e17ec 100644
--- a/chrome/browser/ui/views/extensions/browser_action_drag_data.cc
+++ b/chrome/browser/ui/views/extensions/browser_action_drag_data.cc
@@ -21,13 +21,10 @@
 }
 
 BrowserActionDragData::BrowserActionDragData()
-    : profile_(NULL), index_(static_cast<size_t>(-1)) {
-}
+    : profile_(nullptr), index_(static_cast<size_t>(-1)) {}
 
-BrowserActionDragData::BrowserActionDragData(
-    const std::string& id, int index)
-    : profile_(NULL), id_(id), index_(index) {
-}
+BrowserActionDragData::BrowserActionDragData(const std::string& id, int index)
+    : profile_(nullptr), id_(id), index_(index) {}
 
 bool BrowserActionDragData::GetDropFormats(
     std::set<ui::ClipboardFormatType>* format_types) {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index c701f86..9266342 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -486,6 +486,8 @@
 
 BrowserView::BrowserView(std::unique_ptr<Browser> browser)
     : views::ClientView(nullptr, nullptr), browser_(std::move(browser)) {
+  SetHasWindowSizeControls(!chrome::IsRunningInForcedAppMode());
+
   browser_->tab_strip_model()->AddObserver(this);
   immersive_mode_controller_ = chrome::CreateImmersiveModeController();
 
@@ -1987,22 +1989,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 // BrowserView, views::WidgetDelegate implementation:
 
-bool BrowserView::CanResize() const {
-  // Windows in forced app mode take the whole screen, should not be resized.
-  return !chrome::IsRunningInForcedAppMode();
-}
-
-bool BrowserView::CanMaximize() const {
-  // Windows in forced app mode take the whole screen, should not be resized.
-  return !chrome::IsRunningInForcedAppMode();
-}
-
-bool BrowserView::CanMinimize() const {
-  // There is no shelf in forced app mode, therefore we should not be able to
-  // minimize windows.
-  return !chrome::IsRunningInForcedAppMode();
-}
-
 bool BrowserView::CanActivate() const {
   javascript_dialogs::AppModalDialogQueue* queue =
       javascript_dialogs::AppModalDialogQueue::GetInstance();
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index 4c2c03f..cec9ce7 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -457,9 +457,6 @@
                                   ui::Accelerator* accelerator) const override;
 
   // views::WidgetDelegate:
-  bool CanResize() const override;
-  bool CanMaximize() const override;
-  bool CanMinimize() const override;
   bool CanActivate() const override;
   base::string16 GetWindowTitle() const override;
   base::string16 GetAccessibleWindowTitle() const override;
diff --git a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc b/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc
index 7ff8ccf..a1c985c 100644
--- a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc
+++ b/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc
@@ -96,6 +96,7 @@
   views::Widget* const widget = GetWidget();
   if (!widget_observer_.IsObserving(widget))
     widget_observer_.Add(widget);
+  UpdateButtonVisibility();
 }
 
 void GlassBrowserCaptionButtonContainer::OnPaintBackground(
@@ -111,6 +112,10 @@
 void GlassBrowserCaptionButtonContainer::OnWidgetBoundsChanged(
     views::Widget* widget,
     const gfx::Rect& new_bounds) {
+  UpdateButtonVisibility();
+}
+
+void GlassBrowserCaptionButtonContainer::UpdateButtonVisibility() {
   const bool is_maximized = frame_view_->IsMaximized();
   restore_button_->SetVisible(is_maximized);
   maximize_button_->SetVisible(!is_maximized);
diff --git a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.h b/chrome/browser/ui/views/frame/glass_browser_caption_button_container.h
index dfb4c0c..683d83fc 100644
--- a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.h
+++ b/chrome/browser/ui/views/frame/glass_browser_caption_button_container.h
@@ -43,6 +43,10 @@
   void ResetWindowControls();
   void ButtonPressed(views::Button* sender);
 
+  // Sets caption button visibility based on window state. Only one of maximize
+  // or restore button should ever be visible at the same time.
+  void UpdateButtonVisibility();
+
   GlassBrowserFrameView* const frame_view_;
   Windows10CaptionButton* const minimize_button_;
   Windows10CaptionButton* const maximize_button_;
diff --git a/chrome/browser/ui/views/javascript_app_modal_event_blocker_x11.cc b/chrome/browser/ui/views/javascript_app_modal_event_blocker_x11.cc
index 78210adb..f999dda 100644
--- a/chrome/browser/ui/views/javascript_app_modal_event_blocker_x11.cc
+++ b/chrome/browser/ui/views/javascript_app_modal_event_blocker_x11.cc
@@ -25,8 +25,7 @@
 
 JavascriptAppModalEventBlockerX11::JavascriptAppModalEventBlockerX11(
     aura::Window* modal_window)
-    : modal_window_(modal_window),
-      browser_view_with_modal_dialog_(NULL) {
+    : modal_window_(modal_window), browser_view_with_modal_dialog_(nullptr) {
   aura::Window* topmost_transient_parent =
       GetTopmostTransientParent(modal_window);
   browser_view_with_modal_dialog_ =
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc
index e080939d..5b3a797d 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.cc
@@ -99,7 +99,7 @@
       controller_.get(), status_);
 }
 
-views::BubbleDialogDelegateView* CookieControlsIconView::GetBubble() const {
+views::BubbleDialogDelegate* CookieControlsIconView::GetBubble() const {
   return CookieControlsBubbleView::GetCookieBubble();
 }
 
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.h b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.h
index 6d9acc0..8896e08e 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.h
+++ b/chrome/browser/ui/views/location_bar/cookie_controls_icon_view.h
@@ -31,7 +31,7 @@
   void OnBlockedCookiesCountChanged(int blocked_cookies) override;
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
 
diff --git a/chrome/browser/ui/views/location_bar/find_bar_icon.cc b/chrome/browser/ui/views/location_bar/find_bar_icon.cc
index cb6caafb..da3eeb53 100644
--- a/chrome/browser/ui/views/location_bar/find_bar_icon.cc
+++ b/chrome/browser/ui/views/location_bar/find_bar_icon.cc
@@ -51,7 +51,7 @@
 
 void FindBarIcon::OnExecuting(ExecuteSource execute_source) {}
 
-views::BubbleDialogDelegateView* FindBarIcon::GetBubble() const {
+views::BubbleDialogDelegate* FindBarIcon::GetBubble() const {
   return nullptr;
 }
 
diff --git a/chrome/browser/ui/views/location_bar/find_bar_icon.h b/chrome/browser/ui/views/location_bar/find_bar_icon.h
index ab5daf3..c6cfbc3 100644
--- a/chrome/browser/ui/views/location_bar/find_bar_icon.h
+++ b/chrome/browser/ui/views/location_bar/find_bar_icon.h
@@ -24,7 +24,7 @@
   // PageActionIconView:
   void UpdateImpl() override;
   void OnExecuting(ExecuteSource execute_source) override;
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
   const char* GetClassName() const override;
diff --git a/chrome/browser/ui/views/location_bar/intent_picker_view.cc b/chrome/browser/ui/views/location_bar/intent_picker_view.cc
index 7a8c645..6779cac 100644
--- a/chrome/browser/ui/views/location_bar/intent_picker_view.cc
+++ b/chrome/browser/ui/views/location_bar/intent_picker_view.cc
@@ -73,7 +73,7 @@
 #endif  //  defined(OS_CHROMEOS)
 }
 
-views::BubbleDialogDelegateView* IntentPickerView::GetBubble() const {
+views::BubbleDialogDelegate* IntentPickerView::GetBubble() const {
   return IntentPickerBubbleView::intent_picker_bubble();
 }
 
diff --git a/chrome/browser/ui/views/location_bar/intent_picker_view.h b/chrome/browser/ui/views/location_bar/intent_picker_view.h
index 5528499..54a36b3 100644
--- a/chrome/browser/ui/views/location_bar/intent_picker_view.h
+++ b/chrome/browser/ui/views/location_bar/intent_picker_view.h
@@ -23,7 +23,7 @@
  protected:
   // PageActionIconView:
   void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
   const char* GetClassName() const override;
diff --git a/chrome/browser/ui/views/location_bar/permission_chip.cc b/chrome/browser/ui/views/location_bar/permission_chip.cc
index df72775..9c1875e9 100644
--- a/chrome/browser/ui/views/location_bar/permission_chip.cc
+++ b/chrome/browser/ui/views/location_bar/permission_chip.cc
@@ -22,6 +22,7 @@
 #include "ui/gfx/favicon_size.h"
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/background.h"
+#include "ui/views/controls/button/button_controller.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/fill_layout.h"
@@ -42,8 +43,39 @@
 }
 }  // namespace
 
+// ButtonController that NotifyClick from being called when the
+// BubbleOwnerDelegate's bubble is showing. Otherwise the bubble will show again
+// immediately after being closed via losing focus.
+class BubbleButtonController : public views::ButtonController {
+ public:
+  BubbleButtonController(
+      views::Button* button,
+      BubbleOwnerDelegate* bubble_owner,
+      std::unique_ptr<views::ButtonControllerDelegate> delegate)
+      : views::ButtonController(button, std::move(delegate)),
+        bubble_owner_(bubble_owner) {}
+
+  bool OnMousePressed(const ui::MouseEvent& event) override {
+    suppress_button_release_ = bubble_owner_->IsBubbleShowing();
+    return views::ButtonController::OnMousePressed(event);
+  }
+
+  bool IsTriggerableEvent(const ui::Event& event) override {
+    // TODO(olesiamarukhno): There is the same logic in IconLabelBubbleView,
+    // this class should be reused in the future to avoid duplication.
+    if (event.IsMouseEvent())
+      return !bubble_owner_->IsBubbleShowing() && !suppress_button_release_;
+
+    return views::ButtonController::IsTriggerableEvent(event);
+  }
+
+ private:
+  bool suppress_button_release_ = false;
+  BubbleOwnerDelegate* bubble_owner_ = nullptr;
+};
+
 PermissionChip::PermissionChip(Browser* browser)
-    : views::AnimationDelegateViews(nullptr), browser_(browser) {
+    : views::AnimationDelegateViews(this), browser_(browser) {
   SetLayoutManager(std::make_unique<views::FillLayout>());
   SetVisible(false);
 
@@ -51,7 +83,17 @@
       this, base::string16(), views::style::CONTEXT_BUTTON_MD));
   chip_button_->SetProminent(true);
   chip_button_->SetCornerRadius(GetIconSize());
+  chip_button_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
   chip_button_->SetElideBehavior(gfx::ElideBehavior::FADE_TAIL);
+  chip_button_->SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
+  // Equalizing padding on the left, right and between icon and label.
+  chip_button_->SetImageLabelSpacing(
+      GetLayoutInsets(LOCATION_BAR_ICON_INTERIOR_PADDING).left());
+
+  chip_button_->SetButtonController(std::make_unique<BubbleButtonController>(
+      chip_button_, this,
+      std::make_unique<views::Button::DefaultButtonControllerDelegate>(
+          chip_button_)));
 
   constexpr auto kAnimationDuration = base::TimeDelta::FromMilliseconds(350);
   animation_ = std::make_unique<gfx::SlideAnimation>(this);
@@ -125,25 +167,17 @@
   // deactivation.
   DCHECK(!prompt_bubble_);
 
-  // TODO(olesiamarukhno): Remove ink drop animation when the bubble is opened.
-  if (is_bubble_showing_) {
-    // If the user clicks on the chip when the bubble is open, they probably
-    // don't want to see the chip so we collapse it immediately.
-    animation_->Hide();
-  } else {
-    prompt_bubble_ =
-        new PermissionPromptBubbleView(browser_, delegate_, requested_time_);
-    prompt_bubble_->Show();
-    prompt_bubble_->GetWidget()->AddObserver(this);
-    // Restart the timer after user clicks on the chip to open the bubble.
-    StartCollapseTimer();
-    if (!already_recorded_interaction_) {
-      base::UmaHistogramLongTimes("Permissions.Chip.TimeToInteraction",
-                                  base::TimeTicks::Now() - requested_time_);
-      already_recorded_interaction_ = true;
-    }
+  prompt_bubble_ =
+      new PermissionPromptBubbleView(browser_, delegate_, requested_time_);
+  prompt_bubble_->Show();
+  prompt_bubble_->GetWidget()->AddObserver(this);
+  // Restart the timer after user clicks on the chip to open the bubble.
+  StartCollapseTimer();
+  if (!already_recorded_interaction_) {
+    base::UmaHistogramLongTimes("Permissions.Chip.TimeToInteraction",
+                                base::TimeTicks::Now() - requested_time_);
+    already_recorded_interaction_ = true;
   }
-  is_bubble_showing_ = !is_bubble_showing_;
 }
 
 void PermissionChip::AnimationEnded(const gfx::Animation* animation) {
@@ -157,10 +191,15 @@
   PreferredSizeChanged();
 }
 
-void PermissionChip::OnWidgetClosing(views::Widget* widget) {
+void PermissionChip::OnWidgetDestroying(views::Widget* widget) {
   DCHECK_EQ(widget, prompt_bubble_->GetWidget());
   widget->RemoveObserver(this);
   prompt_bubble_ = nullptr;
+  animation_->Hide();
+}
+
+bool PermissionChip::IsBubbleShowing() const {
+  return prompt_bubble_ != nullptr;
 }
 
 void PermissionChip::Collapse() {
diff --git a/chrome/browser/ui/views/location_bar/permission_chip.h b/chrome/browser/ui/views/location_bar/permission_chip.h
index 286e469..994ff57e 100644
--- a/chrome/browser/ui/views/location_bar/permission_chip.h
+++ b/chrome/browser/ui/views/location_bar/permission_chip.h
@@ -25,12 +25,18 @@
 class Widget;
 }  // namespace views
 
+class BubbleOwnerDelegate {
+ public:
+  virtual bool IsBubbleShowing() const = 0;
+};
+
 // A chip view shown in the location bar to notify user about a permission
 // request. Shows a permission bubble on click.
 class PermissionChip : public views::View,
                        public views::AnimationDelegateViews,
-                       views::ButtonListener,
-                       views::WidgetObserver {
+                       public views::ButtonListener,
+                       public views::WidgetObserver,
+                       public BubbleOwnerDelegate {
  public:
   explicit PermissionChip(Browser* browser);
   PermissionChip(const PermissionChip& mask_layer) = delete;
@@ -56,7 +62,10 @@
   void ButtonPressed(views::Button* sender, const ui::Event& event) override;
 
   // views::WidgetObserver:
-  void OnWidgetClosing(views::Widget* widget) override;
+  void OnWidgetDestroying(views::Widget* widget) override;
+
+  // BubbleOwnerDelegate:
+  bool IsBubbleShowing() const override;
 
  private:
   void Collapse();
@@ -79,8 +88,6 @@
   // The button that displays the icon and text.
   views::MdTextButton* chip_button_;
 
-  bool is_bubble_showing_ = false;
-
   // The time when the permission was requested.
   base::TimeTicks requested_time_;
 
diff --git a/chrome/browser/ui/views/location_bar/permission_chip_browsertest.cc b/chrome/browser/ui/views/location_bar/permission_chip_browsertest.cc
new file mode 100644
index 0000000..2fa23e9
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/permission_chip_browsertest.cc
@@ -0,0 +1,59 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/permission_chip.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "chrome/test/permissions/permission_request_manager_test_api.h"
+#include "content/public/test/browser_test.h"
+
+class PermissionChipBrowserTest : public UiBrowserTest {
+ public:
+  PermissionChipBrowserTest() {
+    feature_list_.InitAndEnableFeature(features::kPermissionChip);
+  }
+
+  PermissionChipBrowserTest(const PermissionChipBrowserTest&) = delete;
+  PermissionChipBrowserTest& operator=(const PermissionChipBrowserTest&) =
+      delete;
+
+  // UiBrowserTest:
+  void ShowUi(const std::string& name) override {
+    std::unique_ptr<test::PermissionRequestManagerTestApi> test_api_ =
+        std::make_unique<test::PermissionRequestManagerTestApi>(browser());
+    EXPECT_TRUE(test_api_->manager());
+    test_api_->AddSimpleRequest(ContentSettingsType::GEOLOCATION);
+    EXPECT_TRUE(browser()->window()->IsActive());
+
+    base::RunLoop().RunUntilIdle();
+  }
+
+  bool VerifyUi() override {
+    BrowserView* browser_view =
+        BrowserView::GetBrowserViewForBrowser(browser());
+    PermissionChip* permission_chip =
+        browser_view->toolbar()->location_bar()->permission_chip();
+
+    return permission_chip && permission_chip->GetVisible();
+  }
+
+  void WaitForUserDismissal() override {
+    // Consider closing the browser to be dismissal.
+    ui_test_utils::WaitForBrowserToClose();
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(PermissionChipBrowserTest, InvokeUi_geolocation) {
+  ShowAndVerifyUi();
+}
diff --git a/chrome/browser/ui/views/location_bar/permission_chip_prompt_browsertest.cc b/chrome/browser/ui/views/location_bar/permission_chip_prompt_browsertest.cc
new file mode 100644
index 0000000..61e48bf
--- /dev/null
+++ b/chrome/browser/ui/views/location_bar/permission_chip_prompt_browsertest.cc
@@ -0,0 +1,57 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/browser/ui/ui_features.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/location_bar/permission_chip.h"
+#include "chrome/browser/ui/views/toolbar/toolbar_view.h"
+#include "chrome/test/permissions/permission_request_manager_test_api.h"
+#include "content/public/test/browser_test.h"
+#include "ui/events/base_event_utils.h"
+
+class PermissionChipPromptBrowserTest : public DialogBrowserTest {
+ public:
+  PermissionChipPromptBrowserTest() {
+    feature_list_.InitAndEnableFeature(features::kPermissionChip);
+  }
+
+  PermissionChipPromptBrowserTest(const PermissionChipPromptBrowserTest&) =
+      delete;
+  PermissionChipPromptBrowserTest& operator=(
+      const PermissionChipPromptBrowserTest&) = delete;
+
+  // DialogBrowserTest:
+  void ShowUi(const std::string& name) override {
+    std::unique_ptr<test::PermissionRequestManagerTestApi> test_api_ =
+        std::make_unique<test::PermissionRequestManagerTestApi>(browser());
+    EXPECT_TRUE(test_api_->manager());
+    test_api_->AddSimpleRequest(ContentSettingsType::GEOLOCATION);
+    EXPECT_TRUE(browser()->window()->IsActive());
+
+    base::RunLoop().RunUntilIdle();
+
+    BrowserView* browser_view =
+        BrowserView::GetBrowserViewForBrowser(browser());
+    PermissionChip* permission_chip =
+        browser_view->toolbar()->location_bar()->permission_chip();
+    ASSERT_TRUE(permission_chip);
+
+    permission_chip->ButtonPressed(
+        permission_chip->button(),
+        ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+                       ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0));
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(PermissionChipPromptBrowserTest, InvokeUi_geolocation) {
+  ShowAndVerifyUi();
+}
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index 3a075ca6..02c04ddc 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -108,7 +108,7 @@
   chrome::BookmarkCurrentTab(browser_);
 }
 
-views::BubbleDialogDelegateView* StarView::GetBubble() const {
+views::BubbleDialogDelegate* StarView::GetBubble() const {
   return BookmarkBubbleView::bookmark_bubble();
 }
 
diff --git a/chrome/browser/ui/views/location_bar/star_view.h b/chrome/browser/ui/views/location_bar/star_view.h
index b95676cd..787e841 100644
--- a/chrome/browser/ui/views/location_bar/star_view.h
+++ b/chrome/browser/ui/views/location_bar/star_view.h
@@ -32,7 +32,7 @@
   void UpdateImpl() override;
   void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
   void ExecuteCommand(ExecuteSource source) override;
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   SkColor GetInkDropBaseColor() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
index 71e1d4f..471d3bf 100644
--- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
+++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.cc
@@ -111,6 +111,7 @@
                                                  content::kMaxURLDisplayChars)),
       command_updater_(this),
       exclusive_access_manager_(this) {
+  SetHasWindowSizeControls(true);
   DCHECK(frame);
   DCHECK(delegate);
 }
@@ -256,18 +257,6 @@
   return delegate_->web_contents();
 }
 
-bool PresentationReceiverWindowView::CanResize() const {
-  return true;
-}
-
-bool PresentationReceiverWindowView::CanMaximize() const {
-  return true;
-}
-
-bool PresentationReceiverWindowView::CanMinimize() const {
-  return true;
-}
-
 void PresentationReceiverWindowView::DeleteDelegate() {
   auto* const delegate = delegate_;
   delete this;
diff --git a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.h b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.h
index 530da5a0..e789d046 100644
--- a/chrome/browser/ui/views/media_router/presentation_receiver_window_view.h
+++ b/chrome/browser/ui/views/media_router/presentation_receiver_window_view.h
@@ -74,9 +74,6 @@
   content::WebContents* GetActiveWebContents() const final;
 
   // views::WidgetDelegateView overrides.
-  bool CanResize() const final;
-  bool CanMaximize() const final;
-  bool CanMinimize() const final;
   void DeleteDelegate() final;
   base::string16 GetWindowTitle() const final;
 
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc b/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc
index 3b3bbc5..f5000e3 100644
--- a/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc
+++ b/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.cc
@@ -28,8 +28,7 @@
   SetVisible(false);
 }
 
-views::BubbleDialogDelegateView* NativeFileSystemAccessIconView::GetBubble()
-    const {
+views::BubbleDialogDelegate* NativeFileSystemAccessIconView::GetBubble() const {
   return NativeFileSystemUsageBubbleView::GetBubble();
 }
 
diff --git a/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.h b/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.h
index 5a9a125..721f5f9 100644
--- a/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.h
+++ b/chrome/browser/ui/views/native_file_system/native_file_system_access_icon_view.h
@@ -17,7 +17,7 @@
       PageActionIconView::Delegate* page_action_icon_delegate);
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
   void OnExecuting(ExecuteSource execute_source) override;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
index ffa9abd..7a83c36ea 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -193,9 +193,14 @@
   return model_->GetMatchIcon(match, vector_icon_color);
 }
 
-void OmniboxPopupContentsView::SetSelectedLine(size_t index) {
+void OmniboxPopupContentsView::SetSelectedLineForMouseOrTouch(size_t index) {
   DCHECK(HasMatchAt(index));
-  model_->SetSelectedLine(index, false, false);
+  // We do this to prevent de-focusing auxiliary buttons due to drag.
+  if (index == model_->selected_line())
+    return;
+
+  OmniboxPopupModel::LineState line_state = OmniboxPopupModel::NORMAL;
+  model_->SetSelection(OmniboxPopupModel::Selection(index, line_state));
 }
 
 bool OmniboxPopupContentsView::IsSelectedIndex(size_t index) const {
@@ -433,7 +438,7 @@
     case ui::ET_GESTURE_TAP_DOWN:
     case ui::ET_GESTURE_SCROLL_BEGIN:
     case ui::ET_GESTURE_SCROLL_UPDATE:
-      SetSelectedLine(index);
+      SetSelectedLineForMouseOrTouch(index);
       break;
     case ui::ET_GESTURE_TAP:
     case ui::ET_GESTURE_SCROLL_END:
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
index c550d393..4d1f091 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.h
@@ -50,8 +50,9 @@
   gfx::Image GetMatchIcon(const AutocompleteMatch& match,
                           SkColor vector_icon_color) const;
 
-  // Sets the line specified by |index| as selected.
-  virtual void SetSelectedLine(size_t index);
+  // Sets the line specified by |index| as selected and, if |index| is
+  // different than the previous index, sets the line state to NORMAL.
+  virtual void SetSelectedLineForMouseOrTouch(size_t index);
 
   // Returns true if the line specified by |index| is selected.
   virtual bool IsSelectedIndex(size_t index) const;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
index 66d593a..197a8df7 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view_browsertest.cc
@@ -393,10 +393,10 @@
   // Each time the selection changes, we should have a text/name change event.
   // This makes it possible for screen readers to have the updated match content
   // when they are notified the selection changed.
-  popup_view()->model()->SetSelectedLine(1, false, false);
+  popup_view()->model()->SetSelection(OmniboxPopupModel::Selection(1));
   EXPECT_EQ(observer.text_changed_on_listboxoption_count(), 1);
 
-  popup_view()->model()->SetSelectedLine(2, false, false);
+  popup_view()->model()->SetSelection(OmniboxPopupModel::Selection(2));
   EXPECT_EQ(observer.text_changed_on_listboxoption_count(), 2);
 }
 
@@ -436,13 +436,13 @@
   EXPECT_EQ(observer.selected_children_changed_count(), 0);
   EXPECT_EQ(observer.active_descendant_changed_count(), 0);
 
-  // This is equivalent of the user arrowing down in the omnibox.
-  popup_view()->model()->SetSelectedLine(1, false, false);
+  // This is equiverlent of the user arrowing down in the omnibox.
+  popup_view()->model()->SetSelection(OmniboxPopupModel::Selection(1));
   EXPECT_EQ(observer.selected_children_changed_count(), 1);
   EXPECT_EQ(observer.active_descendant_changed_count(), 1);
 
   // This is equivalent of the user arrowing up in the omnibox.
-  popup_view()->model()->SetSelectedLine(0, false, false);
+  popup_view()->model()->SetSelection(OmniboxPopupModel::Selection(0));
   EXPECT_EQ(observer.selected_children_changed_count(), 2);
   EXPECT_EQ(observer.active_descendant_changed_count(), 2);
 
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index cd69dc9d..85bd5d2 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -376,7 +376,7 @@
 
 bool OmniboxResultView::OnMousePressed(const ui::MouseEvent& event) {
   if (event.IsOnlyLeftMouseButton())
-    popup_contents_view_->SetSelectedLine(model_index_);
+    popup_contents_view_->SetSelectedLineForMouseOrTouch(model_index_);
   return true;
 }
 
@@ -386,7 +386,7 @@
     // set the state to be selected or hovered, depending on the mouse button.
     if (event.IsOnlyLeftMouseButton()) {
       if (!IsMatchSelected())
-        popup_contents_view_->SetSelectedLine(model_index_);
+        popup_contents_view_->SetSelectedLineForMouseOrTouch(model_index_);
       if (suggestion_tab_switch_button_) {
         gfx::Point point_in_child_coords(event.location());
         View::ConvertPointToTarget(this, suggestion_tab_switch_button_,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
index 966d03b..128706d 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view_unittest.cc
@@ -39,7 +39,9 @@
             /*location_bar_view=*/nullptr),
         selected_index_(0) {}
 
-  void SetSelectedLine(size_t index) override { selected_index_ = index; }
+  void SetSelectedLineForMouseOrTouch(size_t index) override {
+    selected_index_ = index;
+  }
 
   bool IsSelectedIndex(size_t index) const override {
     return selected_index_ == index;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 724b8d0..136a606e 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -12,6 +12,10 @@
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "base/time/time.h"
 #include "build/build_config.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/command_updater.h"
@@ -44,7 +48,10 @@
 #include "components/strings/grit/components_strings.h"
 #include "components/url_formatter/elide_url.h"
 #include "components/vector_icons/vector_icons.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
+#include "extensions/common/constants.h"
 #include "net/base/escape.h"
 #include "third_party/metrics_proto/omnibox_event.pb.h"
 #include "third_party/skia/include/core/SkColor.h"
@@ -102,6 +109,14 @@
 constexpr base::Feature kOmniboxCanCopyHyperlinksToClipboard{
     "OmniboxCanCopyHyperlinksToClipboard", base::FEATURE_ENABLED_BY_DEFAULT};
 
+// When certain field trials are enabled, the path is hidden and reshown after
+// the user hovers on the omnibox for at least this long.
+const uint32_t kExtendedHoverThresholdMs = 500;
+
+// When certain field trials are enabled, the path is hidden this long after
+// page load.
+const uint32_t kPathFadeOutDelayMs = 4000;
+
 // OmniboxState ---------------------------------------------------------------
 
 // Stores omnibox state for each tab.
@@ -148,24 +163,28 @@
 
 }  // namespace
 
-// Animation chosen to match the default values in the edwardjung prototype.
+// Animates the path from |starting_color| to |ending_color|. The fading starts
+// after |delay_ms| ms.
 class OmniboxViewViews::PathFadeAnimation
     : public views::AnimationDelegateViews {
  public:
-  PathFadeAnimation(OmniboxViewViews* view, SkColor starting_color)
+  PathFadeAnimation(OmniboxViewViews* view,
+                    SkColor starting_color,
+                    SkColor ending_color,
+                    uint32_t delay_ms)
       : AnimationDelegateViews(view),
         view_(view),
         starting_color_(starting_color),
-        animation_(
-            {
-                gfx::MultiAnimation::Part(
-                    base::TimeDelta::FromMilliseconds(4000),
-                    gfx::Tween::ZERO),
-                gfx::MultiAnimation::Part(
-                    base::TimeDelta::FromMilliseconds(300),
-                    gfx::Tween::FAST_OUT_SLOW_IN),
-            },
-            gfx::MultiAnimation::kDefaultTimerInterval) {
+        ending_color_(ending_color),
+        animation_(gfx::MultiAnimation::Parts({
+                       gfx::MultiAnimation::Part(
+                           base::TimeDelta::FromMilliseconds(delay_ms),
+                           gfx::Tween::ZERO),
+                       gfx::MultiAnimation::Part(
+                           base::TimeDelta::FromMilliseconds(300),
+                           gfx::Tween::FAST_OUT_SLOW_IN),
+                   }),
+                   gfx::MultiAnimation::kDefaultTimerInterval) {
     DCHECK(view_);
 
     animation_.set_delegate(this);
@@ -181,19 +200,31 @@
 
   void Stop() { animation_.Stop(); }
 
+  bool IsAnimating() { return animation_.is_animating(); }
+
+  // Stops the animation if currently running and sets the starting color to
+  // |starting_color|.
+  void ResetStartingColor(SkColor starting_color) {
+    Stop();
+    starting_color_ = starting_color;
+  }
+
+  SkColor GetCurrentColor() {
+    return gfx::Tween::ColorValueBetween(animation_.GetCurrentValue(),
+                                         starting_color_, ending_color_);
+  }
+
   // views::AnimationDelegateViews:
   void AnimationProgressed(const gfx::Animation* animation) override {
     DCHECK(!view_->model()->user_input_in_progress());
-
-    SkColor color = gfx::Tween::ColorValueBetween(
-        animation->GetCurrentValue(), starting_color_, SK_ColorTRANSPARENT);
-    view_->ApplyColor(color, path_bounds_);
+    view_->ApplyColor(GetCurrentColor(), path_bounds_);
   }
 
  private:
   // Non-owning pointer. |view_| must always outlive this class.
   OmniboxViewViews* view_;
   SkColor starting_color_;
+  SkColor ending_color_;
 
   // The path text range we are fading.
   gfx::Range path_bounds_;
@@ -257,6 +288,8 @@
     // Initialize the popup view using the same font.
     popup_view_.reset(
         new OmniboxPopupContentsView(this, model(), location_bar_view_));
+    if (OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction())
+      Observe(location_bar_view_->GetWebContents());
   }
 
   // Override the default FocusableBorder from Textfield, since the
@@ -349,8 +382,12 @@
   // Cancel any existing path fading animation. The path style will be reset
   // in the following lines, so there should be no ill effects from cancelling
   // the animation midway.
-  if (path_fade_animation_)
-    path_fade_animation_->Stop();
+  if (path_fade_out_animation_)
+    path_fade_out_animation_->Stop();
+  if (path_fade_in_animation_)
+    path_fade_in_animation_->Stop();
+  if (path_fade_out_fast_animation_)
+    path_fade_out_fast_animation_->Stop();
 
   // If the current contents is a URL, turn on special URL rendering mode in
   // RenderText.
@@ -360,20 +397,28 @@
   SetStyle(gfx::TEXT_STYLE_STRIKE, false);
 
   base::string16 text = GetText();
-  bool path_eligible_for_fading = UpdateTextStyle(
-      text, text_is_url, model()->client()->GetSchemeClassifier());
+  UpdateTextStyle(text, text_is_url, model()->client()->GetSchemeClassifier());
 
   // Only fade the path when everything but the host is de-emphasized.
-  if (path_fade_animation_ && path_eligible_for_fading && !HasFocus() &&
-      !model()->user_input_in_progress()) {
-    url::Component scheme, host;
-    AutocompleteInput::ParseForEmphasizeComponents(
-        text, model()->client()->GetSchemeClassifier(), &scheme, &host);
-    gfx::Range path_bounds(host.end(), text.size());
-
+  if (path_fade_out_animation_ && CanFadePath()) {
     // Whenever the text changes, EmphasizeURLComponents is called again, and
     // the animation is reset with a new |path_bounds|.
-    path_fade_animation_->Start(path_bounds);
+    path_fade_out_animation_->Start(GetPathBounds());
+  }
+
+  if (OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction()) {
+    Observe(location_bar_view_->GetWebContents());
+    // Clear the fade-in animation (if it exists; it won't exist if
+    // reveal-on-hover is not enabled). If reveal-on-hover is enabled, it will
+    // be recreated after the path is faded out in DidGetUserInteraction().
+    // Creating it here would cause the path to unnecessarily fade in on hover
+    // before it's been faded out by user interaction.
+    path_fade_in_animation_.reset();
+  } else if (OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
+    // If reveal-on-hover is enabled and hide-on-interaction is disabled, hide
+    // the path now.
+    if (CanFadePath())
+      ApplyColor(SK_ColorTRANSPARENT, GetPathBounds());
   }
 }
 
@@ -603,11 +648,31 @@
       GetThemeProvider(), OmniboxPart::LOCATION_BAR_TEXT_DIMMED);
   set_placeholder_text_color(dimmed_text_color);
 
-  if (base::FeatureList::IsEnabled(
-          omnibox::kHideSteadyStateUrlPathQueryAndRef)) {
+  if (OmniboxFieldTrial::IsHidePathQueryRefEnabled()) {
     // The animation only applies when the path is dimmed to begin with.
-    path_fade_animation_ =
-        std::make_unique<PathFadeAnimation>(this, dimmed_text_color);
+
+    // In on-hover and on-interaction variations, the path fades in or out based
+    // on user interactions, not automatically after a timeout.
+    if (OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction()) {
+      // When hiding the path on interaction, don't create the fade-in animation
+      // yet. The hover fade-in animation (if enabled) will be created later in
+      // DidGetUserInteraction() after the path is faded out.
+      path_fade_out_fast_animation_ = std::make_unique<PathFadeAnimation>(
+          this, dimmed_text_color, SK_ColorTRANSPARENT, 0);
+    } else if (OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
+      // When reveal-on-hover is enabled but not hide-on-interaction, create
+      // both the fade-in and fade-out animations now.
+      path_fade_in_animation_ = std::make_unique<PathFadeAnimation>(
+          this, SK_ColorTRANSPARENT, dimmed_text_color,
+          kExtendedHoverThresholdMs);
+      path_fade_out_fast_animation_ = std::make_unique<PathFadeAnimation>(
+          this, dimmed_text_color, SK_ColorTRANSPARENT, 0);
+    } else {
+      // When neither reveal-on-hover nor hide-on-interaction are enabled, fade
+      // out the path after a fixed delay.
+      path_fade_out_animation_ = std::make_unique<PathFadeAnimation>(
+          this, dimmed_text_color, SK_ColorTRANSPARENT, kPathFadeOutDelayMs);
+    }
   }
 
   EmphasizeURLComponents();
@@ -673,7 +738,7 @@
   return views::Textfield::GetSelectedText();
 }
 
-void OmniboxViewViews::OnPaste() {
+void OmniboxViewViews::OnOmniboxPaste() {
   const base::string16 text(GetClipboardText());
 
   if (text.empty() ||
@@ -1092,11 +1157,38 @@
 void OmniboxViewViews::OnMouseMoved(const ui::MouseEvent& event) {
   if (location_bar_view_)
     location_bar_view_->OnOmniboxHovered(true);
+
+  if (!OmniboxFieldTrial::IsHidePathQueryRefEnabled() ||
+      !OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
+    return;
+  }
+  if (!CanFadePath())
+    return;
+  path_fade_out_fast_animation_->Stop();
+  if (path_fade_in_animation_ && !path_fade_in_animation_->IsAnimating())
+    path_fade_in_animation_->Start(GetPathBounds());
 }
 
 void OmniboxViewViews::OnMouseExited(const ui::MouseEvent& event) {
   if (location_bar_view_)
     location_bar_view_->OnOmniboxHovered(false);
+
+  if (!OmniboxFieldTrial::IsHidePathQueryRefEnabled() ||
+      !OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
+    return;
+  }
+  if (!CanFadePath())
+    return;
+  // When hide-on-interaction is enabled, we don't want to fade the path in or
+  // out until there's user interaction with the page. In this variation,
+  // |path_fade_in_animation_| is created in DidGetUserInteraction() so its
+  // existence signals that user interaction has taken place already.
+  if (path_fade_in_animation_) {
+    path_fade_out_fast_animation_->ResetStartingColor(
+        path_fade_in_animation_->GetCurrentColor());
+    path_fade_in_animation_->Stop();
+    path_fade_out_fast_animation_->Start(GetPathBounds());
+  }
 }
 
 bool OmniboxViewViews::IsItemForCommandIdDynamic(int command_id) const {
@@ -1141,7 +1233,7 @@
 
 bool OmniboxViewViews::OnMousePressed(const ui::MouseEvent& event) {
   if (model()->popup_model()) {  // Can be null in tests.
-    model()->popup_model()->ClearSelectionState();
+    model()->popup_model()->SetSelectedLineState(OmniboxPopupModel::NORMAL);
   }
   is_mouse_pressed_ = true;
 
@@ -1521,6 +1613,27 @@
          location_bar_view_->command_updater()->IsCommandEnabled(command_id);
 }
 
+void OmniboxViewViews::DidGetUserInteraction(
+    const blink::WebInputEvent::Type type) {
+  if (!OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction())
+    return;
+
+  DCHECK(path_fade_out_fast_animation_);
+  path_fade_out_fast_animation_->Stop();
+  if (CanFadePath())
+    path_fade_out_fast_animation_->Start(GetPathBounds());
+  // Now that the path is fading out, create the animation to bring it back on
+  // hover (if enabled via field trial).
+  if (OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover()) {
+    path_fade_in_animation_ = std::make_unique<PathFadeAnimation>(
+        this, SK_ColorTRANSPARENT,
+        GetOmniboxColor(GetThemeProvider(),
+                        OmniboxPart::LOCATION_BAR_TEXT_DIMMED),
+        kExtendedHoverThresholdMs);
+  }
+  Observe(nullptr);
+}
+
 base::string16 OmniboxViewViews::GetSelectionClipboardText() const {
   return SanitizeTextForPaste(Textfield::GetSelectionClipboardText());
 }
@@ -1574,7 +1687,7 @@
       model()->OnUpOrDownKeyPressed(1);
       break;
     case ui::TextEditCommand::PASTE:
-      OnPaste();
+      OnOmniboxPaste();
       break;
     default:
       Textfield::ExecuteTextEditCommand(command);
@@ -2003,3 +2116,27 @@
 void OmniboxViewViews::OnTemplateURLServiceChanged() {
   InstallPlaceholderText();
 }
+
+gfx::Range OmniboxViewViews::GetPathBounds() {
+  url::Component scheme, host;
+  base::string16 text = GetText();
+  AutocompleteInput::ParseForEmphasizeComponents(
+      text, model()->client()->GetSchemeClassifier(), &scheme, &host);
+  return gfx::Range(host.end(), text.size());
+}
+
+bool OmniboxViewViews::CanFadePath() {
+  if (HasFocus() || model()->user_input_in_progress())
+    return false;
+  if (!model()->CurrentTextIsURL())
+    return false;
+  base::string16 text = GetText();
+  url::Component scheme, host;
+  AutocompleteInput::ParseForEmphasizeComponents(
+      text, model()->client()->GetSchemeClassifier(), &scheme, &host);
+
+  const base::string16 url_scheme = text.substr(scheme.begin, scheme.len);
+  return url_scheme != base::UTF8ToUTF16(extensions::kExtensionScheme) &&
+         url_scheme != base::UTF8ToUTF16(url::kDataScheme) &&
+         host.is_nonempty();
+}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index c28000b..49d72594b 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -20,6 +20,7 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "components/search_engines/template_url_service.h"
 #include "components/search_engines/template_url_service_observer.h"
+#include "content/public/browser/web_contents_observer.h"
 #include "ui/base/window_open_disposition.h"
 #include "ui/compositor/compositor.h"
 #include "ui/compositor/compositor_observer.h"
@@ -56,7 +57,8 @@
 #endif
                          public views::TextfieldController,
                          public ui::CompositorObserver,
-                         public TemplateURLServiceObserver {
+                         public TemplateURLServiceObserver,
+                         public content::WebContentsObserver {
  public:
   // The internal view class name.
   static const char kViewClassName[];
@@ -152,6 +154,9 @@
   base::string16 GetLabelForCommandId(int command_id) const override;
   bool IsCommandIdEnabled(int command_id) const override;
 
+  // content::WebContentsObserver:
+  void DidGetUserInteraction(const blink::WebInputEvent::Type type) override;
+
   // For testing only.
   OmniboxPopupContentsView* GetPopupContentsViewForTesting() const {
     return popup_view_.get();
@@ -195,7 +200,7 @@
   // as is. We want to strip whitespace and other things (see GetClipboardText()
   // for details). The function invokes OnBefore/AfterPossibleChange() as
   // necessary.
-  void OnPaste();
+  void OnOmniboxPaste();
 
   // Handle keyword hint tab-to-search and tabbing through dropdown results.
   bool HandleEarlyTabActions(const ui::KeyEvent& event);
@@ -306,14 +311,33 @@
   // TemplateURLServiceObserver:
   void OnTemplateURLServiceChanged() override;
 
+  // Returns the bounds from the end of the currently displayed URL's host to
+  // the end of the URL.
+  gfx::Range GetPathBounds();
+
+  // Returns true if the currently displayed URL's path is eligible for fading.
+  // This takes into account the omnibox's current state (e.g. the path
+  // shouldn't fade if the user is currently editing it) as well as properties
+  // of the current text (e.g. extension URLs or non-URLs shouldn't have their
+  // paths faded).
+  bool CanFadePath();
+
   // When true, the location bar view is read only and also is has a slightly
   // different presentation (smaller font size). This is used for popups.
   bool popup_window_mode_;
 
   std::unique_ptr<OmniboxPopupContentsView> popup_view_;
 
-  // Animation used to fade out the path under some elision settings.
-  std::unique_ptr<PathFadeAnimation> path_fade_animation_;
+  // Animations used to fade in/out the path under some elision settings.
+
+  // Fades the path in after a short delay. Under certain variations, this
+  // animation is not created until the user interacts with the page, so it's
+  // not always guaranteed to exist.
+  std::unique_ptr<PathFadeAnimation> path_fade_in_animation_;
+  // Waits a few seconds and then fades the path out.
+  std::unique_ptr<PathFadeAnimation> path_fade_out_animation_;
+  // Fades the path out without a delay.
+  std::unique_ptr<PathFadeAnimation> path_fade_out_fast_animation_;
 
   // Selection persisted across temporary text changes, like popup suggestions.
   std::vector<gfx::Range> saved_temporary_selection_;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.cc b/chrome/browser/ui/views/overlay/overlay_window_views.cc
index 9b857313..46cb8b13 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.cc
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.cc
@@ -490,8 +490,7 @@
   GetBackToTabControlsLayer()->SetVisible(is_visible);
   previous_track_controls_view_->ToggleVisibility(is_visible &&
                                                   show_previous_track_button_);
-  play_pause_controls_view_->SetVisible(is_visible &&
-                                        !always_hide_play_pause_button_);
+  play_pause_controls_view_->SetVisible(is_visible && show_play_pause_button_);
   next_track_controls_view_->ToggleVisibility(is_visible &&
                                               show_next_track_button_);
 
@@ -545,7 +544,7 @@
   visible_controls_views.push_back(back_to_tab_controls_view_);
   if (show_previous_track_button_)
     visible_controls_views.push_back(previous_track_controls_view_);
-  if (!always_hide_play_pause_button_)
+  if (show_play_pause_button_)
     visible_controls_views.push_back(play_pause_controls_view_);
   if (show_next_track_button_)
     visible_controls_views.push_back(next_track_controls_view_);
@@ -709,11 +708,11 @@
   play_pause_controls_view_->SetPlaybackState(playback_state);
 }
 
-void OverlayWindowViews::SetAlwaysHidePlayPauseButton(bool is_visible) {
-  if (always_hide_play_pause_button_ == !is_visible)
+void OverlayWindowViews::SetPlayPauseButtonVisibility(bool is_visible) {
+  if (show_play_pause_button_ == is_visible)
     return;
 
-  always_hide_play_pause_button_ = !is_visible;
+  show_play_pause_button_ = is_visible;
   UpdateControlsBounds();
 }
 
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h
index 92542e5..459a85d 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.h
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -48,7 +48,7 @@
   gfx::Rect GetBounds() override;
   void UpdateVideoSize(const gfx::Size& natural_size) override;
   void SetPlaybackState(PlaybackState playback_state) override;
-  void SetAlwaysHidePlayPauseButton(bool is_visible) override;
+  void SetPlayPauseButtonVisibility(bool is_visible) override;
   void SetSkipAdButtonVisibility(bool is_visible) override;
   void SetNextTrackButtonVisibility(bool is_visible) override;
   void SetPreviousTrackButtonVisibility(bool is_visible) override;
@@ -183,9 +183,8 @@
   // components has been initialized.
   bool has_been_shown_ = false;
 
-  // Whether or not the play/pause button will always be hidden. This is the
-  // case for media streams video that user is not allowed to play/pause.
-  bool always_hide_play_pause_button_ = false;
+  // Whether or not the play/pause button will be shown.
+  bool show_play_pause_button_ = false;
 
   // The upper and lower bounds of |current_size_|. These are determined by the
   // size of the primary display work area when Picture-in-Picture is initiated.
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view.h b/chrome/browser/ui/views/page_action/page_action_icon_view.h
index ab1094e..9792a5a3 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view.h
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view.h
@@ -31,7 +31,7 @@
 }
 
 namespace views {
-class BubbleDialogDelegateView;
+class BubbleDialogDelegate;
 }
 
 // Represents an inbuilt (as opposed to an extension) page action icon that
@@ -71,7 +71,7 @@
   void Update();
 
   // Returns the bubble instance for the icon.
-  virtual views::BubbleDialogDelegateView* GetBubble() const = 0;
+  virtual views::BubbleDialogDelegate* GetBubble() const = 0;
 
   // Retrieve the text to be used for a tooltip or accessible name.
   virtual base::string16 GetTextForTooltipAndAccessibleName() const = 0;
diff --git a/chrome/browser/ui/views/page_action/page_action_icon_view_unittest.cc b/chrome/browser/ui/views/page_action/page_action_icon_view_unittest.cc
index 9b899c7..4dab440 100644
--- a/chrome/browser/ui/views/page_action/page_action_icon_view_unittest.cc
+++ b/chrome/browser/ui/views/page_action/page_action_icon_view_unittest.cc
@@ -66,9 +66,7 @@
     SetUpForInOutAnimation();
   }
 
-  views::BubbleDialogDelegateView* GetBubble() const override {
-    return nullptr;
-  }
+  views::BubbleDialogDelegate* GetBubble() const override { return nullptr; }
   base::string16 GetTextForTooltipAndAccessibleName() const override {
     return base::ASCIIToUTF16("TestTooltip");
   }
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.cc b/chrome/browser/ui/views/page_action/pwa_install_view.cc
index f956a33..f876110 100644
--- a/chrome/browser/ui/views/page_action/pwa_install_view.cc
+++ b/chrome/browser/ui/views/page_action/pwa_install_view.cc
@@ -62,7 +62,7 @@
                                     base::DoNothing());
 }
 
-views::BubbleDialogDelegateView* PwaInstallView::GetBubble() const {
+views::BubbleDialogDelegate* PwaInstallView::GetBubble() const {
   // TODO(https://907351): Implement.
   return nullptr;
 }
diff --git a/chrome/browser/ui/views/page_action/pwa_install_view.h b/chrome/browser/ui/views/page_action/pwa_install_view.h
index ccc8d31..52c4a51f 100644
--- a/chrome/browser/ui/views/page_action/pwa_install_view.h
+++ b/chrome/browser/ui/views/page_action/pwa_install_view.h
@@ -22,7 +22,7 @@
   // PageActionIconView:
   void UpdateImpl() override;
   void OnExecuting(PageActionIconView::ExecuteSource source) override;
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
   const char* GetClassName() const override;
diff --git a/chrome/browser/ui/views/page_action/zoom_view.cc b/chrome/browser/ui/views/page_action/zoom_view.cc
index 64784d6..07ef9946 100644
--- a/chrome/browser/ui/views/page_action/zoom_view.cc
+++ b/chrome/browser/ui/views/page_action/zoom_view.cc
@@ -100,7 +100,7 @@
   ZoomBubbleView::ShowBubble(GetWebContents(), ZoomBubbleView::USER_GESTURE);
 }
 
-views::BubbleDialogDelegateView* ZoomView::GetBubble() const {
+views::BubbleDialogDelegate* ZoomView::GetBubble() const {
   return ZoomBubbleView::GetZoomBubble();
 }
 
diff --git a/chrome/browser/ui/views/page_action/zoom_view.h b/chrome/browser/ui/views/page_action/zoom_view.h
index 4a7b75c..d7bc4f3c 100644
--- a/chrome/browser/ui/views/page_action/zoom_view.h
+++ b/chrome/browser/ui/views/page_action/zoom_view.h
@@ -27,7 +27,7 @@
   // PageActionIconView:
   void UpdateImpl() override;
   void OnExecuting(PageActionIconView::ExecuteSource source) override;
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   const gfx::VectorIcon& GetVectorIcon() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
   const char* GetClassName() const override;
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
index 7a639b2ec..6de05f1 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
+++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.cc
@@ -53,7 +53,7 @@
   parent()->Layout();
 }
 
-views::BubbleDialogDelegateView* ManagePasswordsIconViews::GetBubble() const {
+views::BubbleDialogDelegate* ManagePasswordsIconViews::GetBubble() const {
   return PasswordBubbleViewBase::manage_password_bubble();
 }
 
diff --git a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h
index 3f5fa12f..924baf6 100644
--- a/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h
+++ b/chrome/browser/ui/views/passwords/manage_passwords_icon_views.h
@@ -29,7 +29,7 @@
   void SetState(password_manager::ui::State state) override;
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   void OnExecuting(PageActionIconView::ExecuteSource source) override;
   bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.cc b/chrome/browser/ui/views/passwords/password_save_update_view.cc
index 451accd9..6b374f5 100644
--- a/chrome/browser/ui/views/passwords/password_save_update_view.cc
+++ b/chrome/browser/ui/views/passwords/password_save_update_view.cc
@@ -11,6 +11,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/browser/ui/passwords/password_dialog_prompts.h"
@@ -33,6 +34,7 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/editable_combobox/editable_combobox.h"
 #include "ui/views/controls/textfield/textfield.h"
@@ -43,11 +45,6 @@
 
 namespace {
 
-// Controls whether we should update the bubble title when transitioning
-// between Save and Update states.
-const base::Feature kUpdatePasswordSaveUpdateBubbleTitle{
-    "UpdatePasswordSaveUpdateBubbleTitle", base::FEATURE_ENABLED_BY_DEFAULT};
-
 enum PasswordSaveUpdateViewColumnSetType {
   // | | (LEADING, FILL) | | (FILL, FILL) | |
   // Used for the username/password line of the bubble, for the pending view.
@@ -168,13 +165,6 @@
       l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_SHOW_PASSWORD));
   button->SetToggledTooltipText(
       l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_HIDE_PASSWORD));
-  button->SetImage(views::ImageButton::STATE_NORMAL,
-                   *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-                       IDR_SHOW_PASSWORD_HOVER));
-  button->SetToggledImage(
-      views::ImageButton::STATE_NORMAL,
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          IDR_HIDE_PASSWORD_HOVER));
   button->SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
   button->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
   button->SetToggled(are_passwords_revealed);
@@ -426,6 +416,15 @@
                ? IDR_SAVE_PASSWORD_DARK
                : IDR_SAVE_PASSWORD;
   GetBubbleFrameView()->SetHeaderView(CreateHeaderImage(id));
+
+  const SkColor icon_color = GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_DefaultIconColor);
+  views::SetImageFromVectorIconWithColor(password_view_button_, kEyeIcon,
+                                         GetDefaultSizeOfVectorIcon(kEyeIcon),
+                                         icon_color);
+  views::SetToggledImageFromVectorIconWithColor(
+      password_view_button_, kEyeCrossedIcon,
+      GetDefaultSizeOfVectorIcon(kEyeCrossedIcon), icon_color);
 }
 
 void PasswordSaveUpdateView::TogglePasswordVisibility() {
@@ -496,8 +495,7 @@
           is_update_bubble_ ? IDS_PASSWORD_MANAGER_CANCEL_BUTTON
                             : IDS_PASSWORD_MANAGER_BUBBLE_BLACKLIST_BUTTON));
 
-  if (base::FeatureList::IsEnabled(kUpdatePasswordSaveUpdateBubbleTitle))
-    SetTitle(controller_.GetTitle());
+  SetTitle(controller_.GetTitle());
 }
 
 std::unique_ptr<views::View> PasswordSaveUpdateView::CreateFooterView() {
diff --git a/chrome/browser/ui/views/passwords/password_save_update_view.h b/chrome/browser/ui/views/passwords/password_save_update_view.h
index d867f37f..405e0d7 100644
--- a/chrome/browser/ui/views/passwords/password_save_update_view.h
+++ b/chrome/browser/ui/views/passwords/password_save_update_view.h
@@ -14,10 +14,6 @@
 namespace views {
 class EditableCombobox;
 class ToggleImageButton;
-
-#if defined(PASSWORD_STORE_SELECT_ENABLED)
-class Checkbox;
-#endif  // defined(PASSWORD_STORE_SELECT_ENABLED)
 }  // namespace views
 
 class PasswordSignInPromoView;
@@ -86,10 +82,6 @@
   // The view for the password value.
   views::EditableCombobox* password_dropdown_;
 
-#if defined(PASSWORD_STORE_SELECT_ENABLED)
-  views::Checkbox* account_store_checkbox_ = nullptr;
-#endif  // defined(PASSWORD_STORE_SELECT_ENABLED)
-
   bool are_passwords_revealed_;
 };
 
diff --git a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
index 2b390ab..c853ceb 100644
--- a/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
+++ b/chrome/browser/ui/views/passwords/password_save_update_with_account_store_view.cc
@@ -11,6 +11,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
+#include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
 #include "chrome/browser/ui/passwords/password_dialog_prompts.h"
@@ -34,6 +35,7 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/views/bubble/bubble_frame_view.h"
 #include "ui/views/controls/button/image_button.h"
+#include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/button/md_text_button.h"
 #include "ui/views/controls/combobox/combobox.h"
 #include "ui/views/controls/editable_combobox/editable_combobox.h"
@@ -193,13 +195,6 @@
       l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_SHOW_PASSWORD));
   button->SetToggledTooltipText(
       l10n_util::GetStringUTF16(IDS_MANAGE_PASSWORDS_HIDE_PASSWORD));
-  button->SetImage(views::ImageButton::STATE_NORMAL,
-                   *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-                       IDR_SHOW_PASSWORD_HOVER));
-  button->SetToggledImage(
-      views::ImageButton::STATE_NORMAL,
-      ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          IDR_HIDE_PASSWORD_HOVER));
   button->SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER);
   button->SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE);
   button->SetToggled(are_passwords_revealed);
@@ -542,6 +537,15 @@
                ? IDR_SAVE_PASSWORD_DARK
                : IDR_SAVE_PASSWORD;
   GetBubbleFrameView()->SetHeaderView(CreateHeaderImage(id));
+
+  const SkColor icon_color = GetNativeTheme()->GetSystemColor(
+      ui::NativeTheme::kColorId_DefaultIconColor);
+  views::SetImageFromVectorIconWithColor(password_view_button_, kEyeIcon,
+                                         GetDefaultSizeOfVectorIcon(kEyeIcon),
+                                         icon_color);
+  views::SetToggledImageFromVectorIconWithColor(
+      password_view_button_, kEyeCrossedIcon,
+      GetDefaultSizeOfVectorIcon(kEyeCrossedIcon), icon_color);
 }
 
 void PasswordSaveUpdateWithAccountStoreView::TogglePasswordVisibility() {
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
new file mode 100644
index 0000000..9dda3e1
--- /dev/null
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/run_loop.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/test/test_browser_dialog.h"
+#include "chrome/test/permissions/permission_request_manager_test_api.h"
+#include "content/public/test/browser_test.h"
+
+class PermissionPromptBubbleViewBrowserTest : public DialogBrowserTest {
+ public:
+  PermissionPromptBubbleViewBrowserTest() = default;
+
+  PermissionPromptBubbleViewBrowserTest(
+      const PermissionPromptBubbleViewBrowserTest&) = delete;
+  PermissionPromptBubbleViewBrowserTest& operator=(
+      const PermissionPromptBubbleViewBrowserTest&) = delete;
+
+  // DialogBrowserTest:
+  void ShowUi(const std::string& name) override {
+    std::unique_ptr<test::PermissionRequestManagerTestApi> test_api_ =
+        std::make_unique<test::PermissionRequestManagerTestApi>(browser());
+    EXPECT_TRUE(test_api_->manager());
+    test_api_->AddSimpleRequest(ContentSettingsType::GEOLOCATION);
+    EXPECT_TRUE(browser()->window()->IsActive());
+
+    base::RunLoop().RunUntilIdle();
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(PermissionPromptBubbleViewBrowserTest,
+                       InvokeUi_geolocation) {
+  ShowAndVerifyUi();
+}
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
index 8284375..da9e7f5 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.cc
@@ -52,17 +52,25 @@
   } else {
     LocationBarView* lbv = GetLocationBarView();
     if (base::FeatureList::IsEnabled(features::kPermissionChip) && lbv) {
-      lbv->permission_chip()->Show(delegate);
+      permission_chip_ = lbv->permission_chip();
+      permission_chip_->Show(delegate);
       prompt_style_ = PromptStyle::kChip;
     } else {
       prompt_bubble_ = new PermissionPromptBubbleView(browser, delegate,
                                                       base::TimeTicks::Now());
       prompt_bubble_->Show();
+      prompt_bubble_->GetWidget()->AddObserver(this);
       prompt_style_ = PromptStyle::kBubble;
     }
   }
 }
 
+void PermissionPromptImpl::OnWidgetClosing(views::Widget* widget) {
+  DCHECK_EQ(widget, prompt_bubble_->GetWidget());
+  widget->RemoveObserver(this);
+  prompt_bubble_ = nullptr;
+}
+
 PermissionPromptImpl::~PermissionPromptImpl() {
   if (prompt_bubble_)
     prompt_bubble_->GetWidget()->Close();
@@ -72,10 +80,8 @@
     content_settings::UpdateLocationBarUiForWebContents(web_contents_);
   }
 
-  if (prompt_style_ == PromptStyle::kChip) {
-    LocationBarView* lbv = GetLocationBarView();
-    DCHECK(lbv);
-    lbv->permission_chip()->Hide();
+  if (prompt_style_ == PromptStyle::kChip && permission_chip_) {
+    permission_chip_->Hide();
   }
 }
 
diff --git a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h
index a67e99f..9b8926c 100644
--- a/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h
+++ b/chrome/browser/ui/views/permission_bubble/permission_prompt_impl.h
@@ -19,7 +19,8 @@
 // This object will create or trigger UI to reflect that a website is requesting
 // a permission. The UI is usually a popup bubble, but may instead be a location
 // bar icon (the "quiet" prompt).
-class PermissionPromptImpl : public permissions::PermissionPrompt {
+class PermissionPromptImpl : public permissions::PermissionPrompt,
+                             public views::WidgetObserver {
  public:
   PermissionPromptImpl(Browser* browser,
                        content::WebContents* web_contents,
@@ -34,6 +35,9 @@
     return prompt_bubble_;
   }
 
+  // views::WidgetObserver:
+  void OnWidgetClosing(views::Widget* widget) override;
+
  private:
   enum class PromptStyle;
 
@@ -48,6 +52,8 @@
 
   PromptStyle prompt_style_;
 
+  PermissionChip* permission_chip_ = nullptr;
+
   DISALLOW_COPY_AND_ASSIGN(PermissionPromptImpl);
 };
 
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.cc b/chrome/browser/ui/views/profiles/profile_picker_view.cc
index 6d91911..db958310 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_view.cc
@@ -51,6 +51,7 @@
 
 ProfilePickerView::ProfilePickerView()
     : web_view_(nullptr), initialized_(InitState::kNotInitialized) {
+  SetHasWindowSizeControls(true);
   SetButtons(ui::DIALOG_BUTTON_NONE);
   set_use_custom_frame(false);
   // TODO(crbug.com/1063856): Add |RecordDialogCreation|.
@@ -119,18 +120,6 @@
   return gfx::Size(kWindowWidth, kWindowHeight);
 }
 
-bool ProfilePickerView::CanResize() const {
-  return true;
-}
-
-bool ProfilePickerView::CanMaximize() const {
-  return true;
-}
-
-bool ProfilePickerView::CanMinimize() const {
-  return true;
-}
-
 base::string16 ProfilePickerView::GetWindowTitle() const {
   return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
 }
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.h b/chrome/browser/ui/views/profiles/profile_picker_view.h
index eca23da0..305a090 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view.h
+++ b/chrome/browser/ui/views/profiles/profile_picker_view.h
@@ -39,9 +39,6 @@
 
   // views::DialogDelegateView:
   gfx::Size CalculatePreferredSize() const override;
-  bool CanResize() const override;
-  bool CanMaximize() const override;
-  bool CanMinimize() const override;
   base::string16 GetWindowTitle() const override;
   void WindowClosing() override;
 
diff --git a/chrome/browser/ui/views/profiles/user_manager_view.cc b/chrome/browser/ui/views/profiles/user_manager_view.cc
index 7d0c1ee..0fffd69 100644
--- a/chrome/browser/ui/views/profiles/user_manager_view.cc
+++ b/chrome/browser/ui/views/profiles/user_manager_view.cc
@@ -67,6 +67,7 @@
     const std::string& email_address,
     const GURL& url)
     : parent_(parent), web_view_(web_view), email_address_(email_address) {
+  SetHasWindowSizeControls(true);
   SetButtons(ui::DIALOG_BUTTON_NONE);
   set_use_custom_frame(false);
 
@@ -89,18 +90,6 @@
   web_view_->LoadInitialURL(GURL(chrome::kChromeUISigninErrorURL));
 }
 
-bool UserManagerProfileDialogDelegate::CanResize() const {
-  return true;
-}
-
-bool UserManagerProfileDialogDelegate::CanMaximize() const {
-  return true;
-}
-
-bool UserManagerProfileDialogDelegate::CanMinimize() const {
-  return true;
-}
-
 ui::ModalType UserManagerProfileDialogDelegate::GetModalType() const {
   return ui::MODAL_TYPE_WINDOW;
 }
@@ -295,6 +284,7 @@
       delegate_(nullptr),
       user_manager_started_showing_(base::Time()) {
   SetButtons(ui::DIALOG_BUTTON_NONE);
+  SetHasWindowSizeControls(true);
   set_use_custom_frame(false);
   keep_alive_ = std::make_unique<ScopedKeepAlive>(
       KeepAliveOrigin::USER_MANAGER_VIEW, KeepAliveRestartOption::DISABLED);
@@ -443,18 +433,6 @@
   return gfx::Size(UserManager::kWindowWidth, UserManager::kWindowHeight);
 }
 
-bool UserManagerView::CanResize() const {
-  return true;
-}
-
-bool UserManagerView::CanMaximize() const {
-  return true;
-}
-
-bool UserManagerView::CanMinimize() const {
-  return true;
-}
-
 base::string16 UserManagerView::GetWindowTitle() const {
   return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
 }
diff --git a/chrome/browser/ui/views/profiles/user_manager_view.h b/chrome/browser/ui/views/profiles/user_manager_view.h
index 7fef0b5d..33fbf516 100644
--- a/chrome/browser/ui/views/profiles/user_manager_view.h
+++ b/chrome/browser/ui/views/profiles/user_manager_view.h
@@ -45,9 +45,6 @@
 
   // views::DialogDelegate:
   gfx::Size CalculatePreferredSize() const override;
-  bool CanResize() const override;
-  bool CanMaximize() const override;
-  bool CanMinimize() const override;
   ui::ModalType GetModalType() const override;
   void DeleteDelegate() override;
   base::string16 GetWindowTitle() const override;
@@ -120,9 +117,6 @@
   gfx::Size CalculatePreferredSize() const override;
 
   // views::DialogDelegateView:
-  bool CanResize() const override;
-  bool CanMaximize() const override;
-  bool CanMinimize() const override;
   base::string16 GetWindowTitle() const override;
   void WindowClosing() override;
 
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.cc b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.cc
index 162fa78..e095038 100644
--- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.cc
+++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.cc
@@ -32,7 +32,7 @@
 
 QRCodeGeneratorIconView::~QRCodeGeneratorIconView() = default;
 
-views::BubbleDialogDelegateView* QRCodeGeneratorIconView::GetBubble() const {
+views::BubbleDialogDelegate* QRCodeGeneratorIconView::GetBubble() const {
   content::WebContents* web_contents = GetWebContents();
   if (!web_contents)
     return nullptr;
diff --git a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.h b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.h
index 14a8936..9d16d000 100644
--- a/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.h
+++ b/chrome/browser/ui/views/qrcode_generator/qrcode_generator_icon_view.h
@@ -23,7 +23,7 @@
   ~QRCodeGeneratorIconView() override;
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
   bool ShouldShowLabel() const override;
diff --git a/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.cc b/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.cc
index 35a95ca..5836cc7e 100644
--- a/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.cc
+++ b/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.cc
@@ -136,7 +136,7 @@
 
 // TODO(gilmanmh): Consider displaying a bubble the first time a user
 // activates the icon to explain what Reader Mode is.
-views::BubbleDialogDelegateView* ReaderModeIconView::GetBubble() const {
+views::BubbleDialogDelegate* ReaderModeIconView::GetBubble() const {
   return nullptr;
 }
 
diff --git a/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.h b/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.h
index fe21e93..d26b4182 100644
--- a/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.h
+++ b/chrome/browser/ui/views/reader_mode/reader_mode_icon_view.h
@@ -15,9 +15,6 @@
 namespace content {
 class NavigationHandle;
 }
-namespace views {
-class BubbleDialogDelegateView;
-}
 class CommandUpdater;
 class PrefService;
 
@@ -51,7 +48,7 @@
 
   // GetBubble() is required by PageActionIconView; however, the icon
   // intentionally does not display a bubble when activated.
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
 
   // dom_distiller::DistillabilityObserver overrides:
   void OnResult(const dom_distiller::DistillabilityResult& result) override;
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.cc b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.cc
index b6aac0ce..e9e1ba9 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.cc
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.cc
@@ -34,7 +34,7 @@
 
 SendTabToSelfIconView::~SendTabToSelfIconView() {}
 
-views::BubbleDialogDelegateView* SendTabToSelfIconView::GetBubble() const {
+views::BubbleDialogDelegate* SendTabToSelfIconView::GetBubble() const {
   SendTabToSelfBubbleController* controller = GetController();
   if (!controller) {
     return nullptr;
diff --git a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.h b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.h
index 33d569883..0094ff0 100644
--- a/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.h
+++ b/chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_icon_view.h
@@ -25,7 +25,7 @@
   ~SendTabToSelfIconView() override;
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
 
diff --git a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
index 4de15dc..8c98940 100644
--- a/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
+++ b/chrome/browser/ui/views/sharing/click_to_call_browsertest.cc
@@ -449,13 +449,14 @@
 
   // Wait until the bubble is visible.
   run_loop.Run();
-  views::BubbleDialogDelegateView* bubble =
+  views::BubbleDialogDelegate* bubble =
       GetPageActionIconView(PageActionIconType::kClickToCall)->GetBubble();
   ASSERT_NE(nullptr, bubble);
 
 #if defined(OS_CHROMEOS)
   // Ensure that the dialog shows the origin in column id 1.
-  EXPECT_NE(nullptr, static_cast<views::GridLayout*>(bubble->GetLayoutManager())
+  EXPECT_NE(nullptr, static_cast<views::GridLayout*>(
+                         bubble->GetContentsView()->GetLayoutManager())
                          ->GetColumnSet(1));
 #else
   // Ensure that the dialog shows the origin in the footnote.
diff --git a/chrome/browser/ui/views/sharing/sharing_icon_view.cc b/chrome/browser/ui/views/sharing/sharing_icon_view.cc
index 4c5e71e..2d1c870 100644
--- a/chrome/browser/ui/views/sharing/sharing_icon_view.cc
+++ b/chrome/browser/ui/views/sharing/sharing_icon_view.cc
@@ -11,6 +11,7 @@
 #include "ui/gfx/scoped_canvas.h"
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/animation/ink_drop.h"
+#include "ui/views/bubble/bubble_dialog_delegate_view.h"
 
 namespace {
 // Progress state when the full length of the animation text is visible.
@@ -154,7 +155,7 @@
   return loading_animation_;
 }
 
-views::BubbleDialogDelegateView* SharingIconView::GetBubble() const {
+views::BubbleDialogDelegate* SharingIconView::GetBubble() const {
   auto* controller = GetController();
   return controller ? get_bubble_callback_.Run(controller->dialog()) : nullptr;
 }
diff --git a/chrome/browser/ui/views/sharing/sharing_icon_view.h b/chrome/browser/ui/views/sharing/sharing_icon_view.h
index 188e4115..242e738 100644
--- a/chrome/browser/ui/views/sharing/sharing_icon_view.h
+++ b/chrome/browser/ui/views/sharing/sharing_icon_view.h
@@ -9,6 +9,11 @@
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "third_party/skia/include/core/SkColor.h"
 
+namespace views {
+// TODO(ellyjones): Remove this.
+class BubbleDialogDelegateView;
+}  // namespace views
+
 // The location bar icon to show the sharing features bubble.
 class SharingIconView : public PageActionIconView {
  public:
@@ -33,7 +38,7 @@
   void OnExecuting(PageActionIconView::ExecuteSource execute_source) override;
   bool IsTriggerableEvent(const ui::Event& event) override;
   const gfx::VectorIcon& GetVectorIconBadge() const override;
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
   const gfx::VectorIcon& GetVectorIcon() const override;
   base::string16 GetTextForTooltipAndAccessibleName() const override;
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc b/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
index daa96ff..a286e286 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector_browsertest.cc
@@ -46,7 +46,7 @@
       : io_loop_finished_event_(
             base::WaitableEvent::ResetPolicy::AUTOMATIC,
             base::WaitableEvent::InitialState::NOT_SIGNALED),
-        selector_(NULL) {}
+        selector_(nullptr) {}
 
   void SetUpInProcessBrowserTestFixture() override {
     base::FilePath certs_dir = net::GetTestCertsDirectory();
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
index 3d1b816..d9036d9dc 100644
--- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc
+++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -398,8 +398,8 @@
       was_source_maximized_(false),
       was_source_fullscreen_(false),
       did_restore_window_(false),
-      tab_strip_to_attach_to_after_exit_(NULL),
-      move_loop_widget_(NULL),
+      tab_strip_to_attach_to_after_exit_(nullptr),
+      move_loop_widget_(nullptr),
       is_mutating_(false),
       attach_x_(-1),
       attach_index_(-1) {
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
index 5fb0dce..67d5dcb0 100644
--- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view.cc
@@ -49,10 +49,32 @@
 #include "ui/base/win/shell.h"
 #endif
 
+#if defined(OS_CHROMEOS)
+#include "ash/public/cpp/metrics_util.h"
+#endif
+
 namespace {
 // Maximum number of lines that a title label occupies.
 constexpr int kHoverCardTitleMaxLines = 2;
 
+#if defined(OS_CHROMEOS)
+// UMA histograms that record animation smoothness for fade-in and fade-out
+// animations of tab hover card.
+constexpr char kHoverCardFadeInSmoothnessHistogramName[] =
+    "Chrome.Tabs.AnimationSmoothness.HoverCard.FadeIn";
+constexpr char kHoverCardFadeOutSmoothnessHistogramName[] =
+    "Chrome.Tabs.AnimationSmoothness.HoverCard.FadeOut";
+
+void RecordFadeInSmoothness(int smoothness) {
+  UMA_HISTOGRAM_PERCENTAGE(kHoverCardFadeInSmoothnessHistogramName, smoothness);
+}
+
+void RecordFadeOutSmoothness(int smoothness) {
+  UMA_HISTOGRAM_PERCENTAGE(kHoverCardFadeOutSmoothnessHistogramName,
+                           smoothness);
+}
+#endif
+
 bool AreHoverCardImagesEnabled() {
   return base::FeatureList::IsEnabled(features::kTabHoverCardImages);
 }
@@ -120,8 +142,13 @@
   explicit WidgetFadeAnimationDelegate(views::Widget* hover_card)
       : AnimationDelegateViews(hover_card->GetRootView()),
         widget_(hover_card),
-        fade_animation_(std::make_unique<gfx::LinearAnimation>(this)) {}
-  ~WidgetFadeAnimationDelegate() override {}
+#if defined(OS_CHROMEOS)
+        throughput_tracker_(
+            hover_card->GetCompositor()->RequestNewThroughputTracker()),
+#endif
+        fade_animation_(std::make_unique<gfx::LinearAnimation>(this)) {
+  }
+  ~WidgetFadeAnimationDelegate() override = default;
 
   enum class FadeAnimationState {
     // No animation is running.
@@ -153,6 +180,10 @@
     widget_->Show();
     fade_animation_ = std::make_unique<gfx::LinearAnimation>(this);
     fade_animation_->SetDuration(kFadeInDuration);
+#if defined(OS_CHROMEOS)
+    throughput_tracker_.Start(ash::metrics_util::ForSmoothness(
+        base::BindRepeating(&RecordFadeInSmoothness)));
+#endif
     fade_animation_->Start();
   }
 
@@ -164,6 +195,10 @@
     fade_animation_ = std::make_unique<gfx::LinearAnimation>(this);
     set_animation_state(FadeAnimationState::FADE_OUT);
     fade_animation_->SetDuration(kFadeOutDuration);
+#if defined(OS_CHROMEOS)
+    throughput_tracker_.Start(ash::metrics_util::ForSmoothness(
+        base::BindRepeating(&RecordFadeOutSmoothness)));
+#endif
     fade_animation_->Start();
   }
 
@@ -172,6 +207,9 @@
       return;
 
     fade_animation_->Stop();
+#if defined(OS_CHROMEOS)
+    throughput_tracker_.Cancel();
+#endif
     set_animation_state(FadeAnimationState::IDLE);
     widget_->SetOpacity(1.0f);
   }
@@ -197,10 +235,16 @@
 
   void AnimationEnded(const gfx::Animation* animation) override {
     AnimationProgressed(animation);
+#if defined(OS_CHROMEOS)
+    throughput_tracker_.Stop();
+#endif
     set_animation_state(FadeAnimationState::IDLE);
   }
 
   views::Widget* const widget_;
+#if defined(OS_CHROMEOS)
+  ui::ThroughputTracker throughput_tracker_;
+#endif
   std::unique_ptr<gfx::LinearAnimation> fade_animation_;
   FadeAnimationState animation_state_ = FadeAnimationState::IDLE;
 
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc
index 3b13bc9..8ae1572 100644
--- a/chrome/browser/ui/views/task_manager_view.cc
+++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -161,18 +161,6 @@
   return nullptr;
 }
 
-bool TaskManagerView::CanResize() const {
-  return true;
-}
-
-bool TaskManagerView::CanMaximize() const {
-  return true;
-}
-
-bool TaskManagerView::CanMinimize() const {
-  return true;
-}
-
 bool TaskManagerView::ExecuteWindowsCommand(int command_id) {
   return false;
 }
@@ -289,6 +277,7 @@
   SetButtons(ui::DIALOG_BUTTON_OK);
   SetButtonLabel(ui::DIALOG_BUTTON_OK,
                  l10n_util::GetStringUTF16(IDS_TASK_MANAGER_KILL));
+  SetHasWindowSizeControls(true);
 
   // Avoid calling Accept() when closing the dialog, since Accept() here means
   // "kill task" (!).
diff --git a/chrome/browser/ui/views/task_manager_view.h b/chrome/browser/ui/views/task_manager_view.h
index caacaa1..e94f0d02 100644
--- a/chrome/browser/ui/views/task_manager_view.h
+++ b/chrome/browser/ui/views/task_manager_view.h
@@ -55,9 +55,6 @@
 
   // views::DialogDelegateView:
   views::View* GetInitiallyFocusedView() override;
-  bool CanResize() const override;
-  bool CanMaximize() const override;
-  bool CanMinimize() const override;
   bool ExecuteWindowsCommand(int command_id) override;
   base::string16 GetWindowTitle() const override;
   gfx::ImageSkia GetWindowIcon() override;
diff --git a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
index b9dcfc8..3e63e222 100644
--- a/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/toolbar/toolbar_action_view_interactive_uitest.cc
@@ -210,9 +210,10 @@
 // TODO(crbug.com/963678): fails on ChromeOS as it's assuming SendMouseMove()
 // synchronously updates the location of the mouse (which is needed by
 // SendMouseClick()).
-#if defined(OS_CHROMEOS)
+#if defined(OS_CHROMEOS) || defined(OS_WIN)
 // TODO(pkasting): https://crbug.com/911374 Menu controller thinks the mouse is
 // already down when handling the left click.
+// TODO(crbug.com/1092372): Flaky on Win7.
 #define MAYBE_TestClickingOnOverflowedAction \
   DISABLED_TestClickingOnOverflowedAction
 #else
diff --git a/chrome/browser/ui/views/translate/translate_icon_view.cc b/chrome/browser/ui/views/translate/translate_icon_view.cc
index 8118a598..375a16f 100644
--- a/chrome/browser/ui/views/translate/translate_icon_view.cc
+++ b/chrome/browser/ui/views/translate/translate_icon_view.cc
@@ -31,7 +31,7 @@
 
 TranslateIconView::~TranslateIconView() {}
 
-views::BubbleDialogDelegateView* TranslateIconView::GetBubble() const {
+views::BubbleDialogDelegate* TranslateIconView::GetBubble() const {
   return TranslateBubbleView::GetCurrentBubble();
 }
 
diff --git a/chrome/browser/ui/views/translate/translate_icon_view.h b/chrome/browser/ui/views/translate/translate_icon_view.h
index be8a314..9e9c739 100644
--- a/chrome/browser/ui/views/translate/translate_icon_view.h
+++ b/chrome/browser/ui/views/translate/translate_icon_view.h
@@ -20,7 +20,7 @@
   ~TranslateIconView() override;
 
   // PageActionIconView:
-  views::BubbleDialogDelegateView* GetBubble() const override;
+  views::BubbleDialogDelegate* GetBubble() const override;
   void UpdateImpl() override;
 
  protected:
diff --git a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
index 60307b0..4c6c97b 100644
--- a/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_link_capturing_browsertest.cc
@@ -23,9 +23,11 @@
   ~WebAppLinkCapturingBrowserTest() override = default;
 
   void SetUp() override {
+    // TODO(crbug.com/1092789): Migrate the implementation to make web app link
+    // capturing feature to work with AppServiceIntentHandling.
     features_.InitWithFeatures({features::kDesktopPWAsTabStrip,
                                 features::kDesktopPWAsTabStripLinkCapturing},
-                               {});
+                               {features::kAppServiceIntentHandling});
     WebAppNavigationBrowserTest::SetUp();
   }
 
diff --git a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
index 88cb0e9..a9e0b93f 100644
--- a/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
+++ b/chrome/browser/ui/webauthn/authenticator_dialog_browsertest.cc
@@ -90,12 +90,18 @@
       model->CollectPIN(8, base::BindOnce([](std::string pin) {}));
     } else if (name == "inline_bio_enrollment") {
       model->StartInlineBioEnrollment(base::DoNothing());
-      timer_.Start(FROM_HERE, base::TimeDelta::FromSeconds(2),
-                   base::BindLambdaForTesting([&, weak_model = model.get()] {
-                     weak_model->OnSampleCollected(--bio_samples_remaining_);
-                     if (bio_samples_remaining_ <= 0)
-                       timer_.Stop();
-                   }));
+      timer_.Start(
+          FROM_HERE, base::TimeDelta::FromSeconds(2),
+          base::BindLambdaForTesting([&, weak_model = model->GetWeakPtr()] {
+            if (!weak_model || weak_model->current_step() !=
+                                   AuthenticatorRequestDialogModel::Step::
+                                       kInlineBioEnrollment) {
+              return;
+            }
+            weak_model->OnSampleCollected(--bio_samples_remaining_);
+            if (bio_samples_remaining_ <= 0)
+              timer_.Stop();
+          }));
     } else if (name == "retry_uv") {
       model->OnRetryUserVerification(5);
     } else if (name == "retry_uv_two_tries_remaining") {
diff --git a/chrome/browser/ui/webui/app_management/app_management.mojom b/chrome/browser/ui/webui/app_management/app_management.mojom
index 87aba3d..bba2836 100644
--- a/chrome/browser/ui/webui/app_management/app_management.mojom
+++ b/chrome/browser/ui/webui/app_management/app_management.mojom
@@ -87,4 +87,5 @@
 // The Plugin VM app publisher uses this enum directly.
 enum PluginVmPermissionType {
   PRINTING = 0,
+  CAMERA = 1,
 };
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 0cf5a37..f0b901aa0 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -18,7 +18,6 @@
 #include "chrome/browser/buildflags.h"
 #include "chrome/browser/devtools/devtools_ui_bindings.h"
 #include "chrome/browser/engagement/site_engagement_service.h"
-#include "chrome/browser/media/feeds/media_feeds_service.h"
 #include "chrome/browser/media/history/media_history_keyed_service.h"
 #include "chrome/browser/media/media_engagement_service.h"
 #include "chrome/browser/profiles/profile.h"
@@ -32,6 +31,7 @@
 #include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_error_ui.h"
 #include "chrome/browser/ui/webui/chromeos/account_manager/account_manager_welcome_ui.h"
 #include "chrome/browser/ui/webui/chromeos/account_manager/account_migration_welcome_ui.h"
+#include "chrome/browser/ui/webui/chromeos/camera/camera_ui.h"
 #include "chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.h"
 #include "chrome/browser/ui/webui/components/components_ui.h"
 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
@@ -70,14 +70,11 @@
 #include "chrome/browser/ui/webui/usb_internals/usb_internals_ui.h"
 #include "chrome/browser/ui/webui/user_actions/user_actions_ui.h"
 #include "chrome/browser/ui/webui/version_ui.h"
-#include "chrome/browser/web_applications/system_web_app_manager.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/common/webui_url_constants.h"
-#include "chromeos/components/camera_app_ui/camera_app_ui.h"
-#include "chromeos/components/camera_app_ui/url_constants.h"
 #include "components/favicon/core/favicon_service.h"
 #include "components/favicon_base/favicon_util.h"
 #include "components/favicon_base/select_favicon_frames.h"
@@ -133,6 +130,7 @@
 #include "chrome/browser/ui/webui/feed_internals/feed_internals_ui.h"
 #endif  // BUILDFLAG(ENABLE_FEED_IN_CHROME)
 #else   // defined(OS_ANDROID)
+#include "chrome/browser/media/feeds/media_feeds_service.h"
 #include "chrome/browser/media/router/media_router_feature.h"
 #include "chrome/browser/ui/webui/bookmarks/bookmarks_ui.h"
 #include "chrome/browser/ui/webui/devtools_ui.h"
@@ -641,10 +639,9 @@
     return &NewWebUI<SysInternalsUI>;
   if (url.host_piece() == chrome::kChromeUIAssistantOptInHost)
     return &NewWebUI<chromeos::AssistantOptInUI>;
-  if (url.host_piece() == chromeos::kChromeUICameraAppHost &&
-      web_app::SystemWebAppManager::IsAppEnabled(
-          web_app::SystemAppType::CAMERA)) {
-    return &NewWebUI<chromeos::CameraAppUI>;
+  if (url.host_piece() == chrome::kChromeUICameraHost &&
+      chromeos::CameraUI::IsEnabled()) {
+    return &NewWebUI<chromeos::CameraUI>;
   }
 
   if (url.host_piece() == chrome::kChromeUIArcGraphicsTracingHost)
@@ -817,10 +814,12 @@
     return &NewWebUI<MediaEngagementUI>;
   }
 
+#if !defined(OS_ANDROID)
   if (media_feeds::MediaFeedsService::IsEnabled() &&
       url.host_piece() == chrome::kChromeUIMediaFeedsHost) {
     return &NewWebUI<MediaFeedsUI>;
   }
+#endif
 
   if (media_history::MediaHistoryKeyedService::IsEnabled() &&
       url.host_piece() == chrome::kChromeUIMediaHistoryHost) {
diff --git a/chrome/browser/ui/webui/chromeos/camera/camera_ui.cc b/chrome/browser/ui/webui/chromeos/camera/camera_ui.cc
new file mode 100644
index 0000000..9906f67
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/camera/camera_ui.cc
@@ -0,0 +1,86 @@
+// 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/webui/chromeos/camera/camera_ui.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/feature_list.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/webui/webui_util.h"
+#include "chrome/browser/web_applications/system_web_app_manager.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/grit/browser_resources.h"
+#include "chrome/grit/camera_resources.h"
+#include "chrome/grit/camera_resources_map.h"
+#include "chromeos/constants/chromeos_features.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "mojo/public/js/grit/mojo_bindings_resources.h"
+
+namespace chromeos {
+
+namespace {
+
+content::WebUIDataSource* CreateCameraUIHTMLSource() {
+  content::WebUIDataSource* source =
+      content::WebUIDataSource::Create(chrome::kChromeUICameraHost);
+
+  // Add all settings resources.
+  webui::AddResourcePathsBulk(
+      source, base::make_span(kCameraResources, kCameraResourcesSize));
+
+  static constexpr webui::ResourcePath kAdditionalResources[] = {
+      // Add WebUI version of the CCA browser proxy.
+      {"src/js/browser_proxy/browser_proxy.js", IDR_CAMERA_WEBUI_BROWSER_PROXY},
+
+      // Add mojom-lite files under expected paths.
+      {"src/js/mojo/camera_intent.mojom-lite.js",
+       IDR_CAMERA_CAMERA_INTENT_MOJOM_LITE_JS},
+      {"src/js/mojo/image_capture.mojom-lite.js",
+       IDR_CAMERA_IMAGE_CAPTURE_MOJOM_LITE_JS},
+      {"src/js/mojo/camera_common.mojom-lite.js",
+       IDR_CAMERA_CAMERA_COMMON_MOJOM_LITE_JS},
+      {"src/js/mojo/camera_metadata.mojom-lite.js",
+       IDR_CAMERA_CAMERA_METADATA_MOJOM_LITE_JS},
+      {"src/js/mojo/camera_metadata_tags.mojom-lite.js",
+       IDR_CAMERA_CAMERA_METADATA_TAGS_MOJOM_LITE_JS},
+      {"src/js/mojo/camera_app.mojom-lite.js", IDR_CAMERA_APP_MOJOM_LITE_JS},
+      {"src/js/mojo/mojo_bindings_lite.js", IDR_MOJO_MOJO_BINDINGS_LITE_JS},
+
+      // Add System Web App resources.
+      {"pwa.html", IDR_PWA_HTML},
+  };
+  webui::AddResourcePathsBulk(source, kAdditionalResources);
+
+  source->UseStringsJs();
+
+  return source;
+}
+
+}  // namespace
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// CameraUI
+//
+///////////////////////////////////////////////////////////////////////////////
+
+CameraUI::CameraUI(content::WebUI* web_ui) : ui::MojoWebUIController(web_ui) {
+  Profile* profile = Profile::FromWebUI(web_ui);
+
+  // Set up the data source.
+  content::WebUIDataSource* source = CreateCameraUIHTMLSource();
+  content::WebUIDataSource::Add(profile, source);
+}
+
+CameraUI::~CameraUI() = default;
+
+// static
+bool CameraUI::IsEnabled() {
+  return web_app::SystemWebAppManager::IsAppEnabled(
+      web_app::SystemAppType::CAMERA);
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/camera/camera_ui.h b/chrome/browser/ui/webui/chromeos/camera/camera_ui.h
new file mode 100644
index 0000000..31dabca
--- /dev/null
+++ b/chrome/browser/ui/webui/chromeos/camera/camera_ui.h
@@ -0,0 +1,27 @@
+// 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_WEBUI_CHROMEOS_CAMERA_CAMERA_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_CAMERA_CAMERA_UI_H_
+
+#include "base/macros.h"
+#include "ui/webui/mojo_web_ui_controller.h"
+
+namespace chromeos {
+
+class CameraUI : public ui::MojoWebUIController {
+ public:
+  explicit CameraUI(content::WebUI* web_ui);
+  ~CameraUI() override;
+
+  // True when the Camera as a System Web App flag is true.
+  static bool IsEnabled();
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(CameraUI);
+};
+
+}  // namespace chromeos
+
+#endif  // CHROME_BROWSER_UI_WEBUI_CHROMEOS_CAMERA_CAMERA_UI_H_
diff --git a/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc b/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc
index 4c0d0fc..28c41a9 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.cc
@@ -4,10 +4,13 @@
 
 #include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_dialog.h"
 
+#include "ash/public/cpp/shelf_types.h"
+#include "ash/public/cpp/window_properties.h"
 #include "base/bind_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/crostini/crostini_features.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
+#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h"
 #include "chrome/browser/ui/webui/chromeos/crostini_installer/crostini_installer_ui.h"
 #include "chrome/common/webui_url_constants.h"
 #include "ui/base/ui_base_types.h"
@@ -75,6 +78,10 @@
 void CrostiniInstallerDialog::AdjustWidgetInitParams(
     views::Widget::InitParams* params) {
   params->z_order = ui::ZOrderLevel::kNormal;
+
+  const ash::ShelfID shelf_id(crostini::kCrostiniInstallerShelfId);
+  params->init_properties_container.SetProperty(ash::kShelfIDKey,
+                                                shelf_id.Serialize());
 }
 
 bool CrostiniInstallerDialog::CanCloseDialog() const {
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
index 12143c2..50ac74f 100644
--- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
+++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.cc
@@ -4,8 +4,11 @@
 
 #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_dialog.h"
 
+#include "ash/public/cpp/shelf_types.h"
+#include "ash/public/cpp/window_properties.h"
 #include "base/metrics/histogram_functions.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
+#include "chrome/browser/chromeos/crostini/crostini_shelf_utils.h"
 #include "chrome/browser/chromeos/crostini/crostini_simple_types.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h"
@@ -67,6 +70,10 @@
 void CrostiniUpgraderDialog::AdjustWidgetInitParams(
     views::Widget::InitParams* params) {
   params->z_order = ui::ZOrderLevel::kNormal;
+
+  const ash::ShelfID shelf_id(crostini::kCrostiniUpgraderShelfId);
+  params->init_properties_container.SetProperty(ash::kShelfIDKey,
+                                                shelf_id.Serialize());
 }
 
 void CrostiniUpgraderDialog::SetDeletionClosureForTesting(
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
index c584d03..fa1b2ce 100644
--- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -64,15 +64,8 @@
 namespace {
 
 void LaunchResetScreen() {
-  // Don't recreate WizardController if it already exists.
-  WizardController* const wizard_controller =
-      WizardController::default_controller();
-  if (wizard_controller && !wizard_controller->login_screen_started()) {
-    wizard_controller->AdvanceToScreen(ResetView::kScreenId);
-  } else {
-    DCHECK(LoginDisplayHost::default_host());
-    LoginDisplayHost::default_host()->StartWizard(ResetView::kScreenId);
-  }
+  DCHECK(LoginDisplayHost::default_host());
+  LoginDisplayHost::default_host()->StartWizard(ResetView::kScreenId);
 }
 
 }  // namespace
@@ -230,24 +223,15 @@
 }
 
 void CoreOobeHandler::ShowEnableDebuggingScreen() {
-  // Don't recreate WizardController if it already exists.
-  WizardController* wizard_controller = WizardController::default_controller();
-  if (wizard_controller && !wizard_controller->login_screen_started()) {
-    wizard_controller->AdvanceToScreen(EnableDebuggingScreenView::kScreenId);
-  }
+  DCHECK(LoginDisplayHost::default_host());
+  LoginDisplayHost::default_host()->StartWizard(
+      EnableDebuggingScreenView::kScreenId);
 }
 
 void CoreOobeHandler::ShowEnableAdbSideloadingScreen() {
-  // Don't recreate WizardController if it already exists.
-  WizardController* wizard_controller = WizardController::default_controller();
-  if (wizard_controller && !wizard_controller->login_screen_started()) {
-    wizard_controller->AdvanceToScreen(
-        EnableAdbSideloadingScreenView::kScreenId);
-  } else {
-    DCHECK(LoginDisplayHost::default_host());
-    LoginDisplayHost::default_host()->StartWizard(
-        EnableAdbSideloadingScreenView::kScreenId);
-  }
+  DCHECK(LoginDisplayHost::default_host());
+  LoginDisplayHost::default_host()->StartWizard(
+      EnableAdbSideloadingScreenView::kScreenId);
 }
 
 void CoreOobeHandler::ShowActiveDirectoryPasswordChangeScreen(
@@ -310,6 +294,9 @@
 }
 
 void CoreOobeHandler::HandleInitialized() {
+  // TODO(crbug.com/1082670): Remove excessive logging after investigation.
+  LOG(ERROR) << "1082670 : CoreOobeHandler::HandleInitialized";
+
   GetOobeUI()->InitializeHandlers();
   AllowJavascript();
 }
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
index c35f357..81308cb 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.cc
@@ -778,12 +778,12 @@
 
 void EnrollmentScreenHandler::OnGetCookiesForCompleteLogin(
     const std::string& user,
-    const net::CookieStatusList& cookies,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies,
+    const net::CookieAccessResultList& excluded_cookies) {
   std::string auth_code;
-  for (const auto& cookie_with_status : cookies) {
-    if (cookie_with_status.cookie.Name() == "oauth_code") {
-      auth_code = cookie_with_status.cookie.Value();
+  for (const auto& cookie_with_access_result : cookies) {
+    if (cookie_with_access_result.cookie.Name() == "oauth_code") {
+      auth_code = cookie_with_access_result.cookie.Value();
       break;
     }
   }
diff --git a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
index b83224e..4feaf4b 100644
--- a/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/enrollment_screen_handler.h
@@ -105,8 +105,8 @@
   void HandleCompleteLogin(const std::string& user);
   void OnGetCookiesForCompleteLogin(
       const std::string& user,
-      const net::CookieStatusList& cookies,
-      const net::CookieStatusList& excluded_cookies);
+      const net::CookieAccessResultList& cookies,
+      const net::CookieAccessResultList& excluded_cookies);
   void HandleAdCompleteLogin(const std::string& machine_name,
                              const std::string& distinguished_name,
                              const std::string& encryption_types,
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 a9705d3e..3cd464d 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.cc
@@ -965,11 +965,11 @@
 }
 
 void GaiaScreenHandler::OnGetCookiesForCompleteAuthentication(
-    const net::CookieStatusList& cookies,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies,
+    const net::CookieAccessResultList& excluded_cookies) {
   std::string auth_code, gaps_cookie;
-  for (const auto& cookie_with_status : cookies) {
-    const auto& cookie = cookie_with_status.cookie;
+  for (const auto& cookie_with_access_result : cookies) {
+    const auto& cookie = cookie_with_access_result.cookie;
     if (cookie.Name() == kOAUTHCodeCookie)
       auth_code = cookie.Value();
     else if (cookie.Name() == kGAPSCookie)
diff --git a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
index 921a2ed..8f2813af 100644
--- a/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h
@@ -332,8 +332,8 @@
 
   void ContinueAuthenticationWhenCookiesAvailable();
   void OnGetCookiesForCompleteAuthentication(
-      const net::CookieStatusList& cookies,
-      const net::CookieStatusList& excluded_cookies);
+      const net::CookieAccessResultList& cookies,
+      const net::CookieAccessResultList& excluded_cookies);
 
   void OnCookieWaitTimeout();
 
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
index 9b3f867..bfb14875 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -545,6 +545,9 @@
 
 OobeUI::OobeUI(content::WebUI* web_ui, const GURL& url)
     : ui::MojoWebUIController(web_ui, true /* enable_chrome_send */) {
+  // TODO(crbug.com/1082670): Remove excessive logging after investigation.
+  LOG(ERROR) << "1082670 : Creating new OobeUI";
+
   display_type_ = GetDisplayType(url);
 
   js_calls_container_ = std::make_unique<JSCallsContainer>();
@@ -643,8 +646,14 @@
 }
 
 void OobeUI::InitializeHandlers() {
+  // TODO(crbug.com/1082670): Remove excessive logging after investigation.
+  LOG(ERROR) << "1082670 : OobeUI::InitializeHandlers";
+
   js_calls_container_->ExecuteDeferredJSCalls(web_ui());
 
+  // TODO(crbug.com/1082670): Remove excessive logging after investigation.
+  LOG(ERROR) << "1082670 : OobeUI::Marking as ready and executing callbacks";
+
   ready_ = true;
   for (size_t i = 0; i < ready_callbacks_.size(); ++i)
     ready_callbacks_[i].Run();
@@ -675,6 +684,9 @@
 }
 
 bool OobeUI::IsJSReady(const base::Closure& display_is_ready_callback) {
+  // TODO(crbug.com/1082670): Remove excessive logging after investigation.
+  LOG(ERROR) << "1082670 : OobeUI::IsJSReady? = " << ready_;
+
   if (!ready_)
     ready_callbacks_.push_back(display_is_ready_callback);
   return ready_;
diff --git a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
index 8d99eb5..52f022a 100644
--- a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.cc
@@ -207,19 +207,19 @@
 void SyncConsentScreenHandler::HandleAcceptAndContinue(
     const login::StringList& consent_description,
     const std::string& consent_confirmation) {
-  Continue(consent_description, consent_confirmation, /*enable_sync=*/true);
+  Continue(consent_description, consent_confirmation, UserChoice::kAccepted);
 }
 
 void SyncConsentScreenHandler::HandleDeclineAndContinue(
     const login::StringList& consent_description,
     const std::string& consent_confirmation) {
-  Continue(consent_description, consent_confirmation, /*enable_sync=*/false);
+  Continue(consent_description, consent_confirmation, UserChoice::kDeclined);
 }
 
 void SyncConsentScreenHandler::Continue(
     const login::StringList& consent_description,
     const std::string& consent_confirmation,
-    bool enable_sync) {
+    UserChoice choice) {
   DCHECK(chromeos::features::IsSplitSettingsSyncEnabled());
   std::vector<int> consent_description_ids;
   int consent_confirmation_id;
@@ -228,8 +228,7 @@
   // Manually add this ID because the string contains a runtime substitution,
   // so it's not included in GetConsentIDs().
   consent_description_ids.push_back(IDS_LOGIN_SYNC_CONSENT_SCREEN_SUBTITLE);
-  screen_->OnAcceptAndContinue(consent_description_ids, consent_confirmation_id,
-                               enable_sync);
+  screen_->OnContinue(consent_description_ids, consent_confirmation_id, choice);
 
   SyncConsentScreen::SyncConsentScreenTestDelegate* test_delegate =
       screen_->GetDelegateForTesting();
diff --git a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h
index dfb8a054..a11e554 100644
--- a/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/sync_consent_screen_handler.h
@@ -42,6 +42,10 @@
  public:
   using TView = SyncConsentScreenView;
 
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused. Public for testing.
+  enum class UserChoice { kDeclined = 0, kAccepted = 1, kMaxValue = kAccepted };
+
   explicit SyncConsentScreenHandler(JSCallsContainer* js_calls_container);
   ~SyncConsentScreenHandler() override;
 
@@ -77,7 +81,7 @@
   // Helper for the accept and decline cases.
   void Continue(const ::login::StringList& consent_description,
                 const std::string& consent_confirmation,
-                bool enable_sync);
+                UserChoice choice);
 
   // Adds resource |resource_id| both to |builder| and to |known_string_ids_|.
   void RememberLocalizedValue(const std::string& name,
diff --git a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h
index be45877..7f2b363 100644
--- a/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h
+++ b/chrome/browser/ui/webui/chromeos/login/update_screen_handler.h
@@ -19,7 +19,7 @@
 // representation. Owned by UpdateScreen.
 class UpdateView {
  public:
-  constexpr static StaticOobeScreenId kScreenId{"update"};
+  constexpr static StaticOobeScreenId kScreenId{"oobe-update"};
 
   virtual ~UpdateView() {}
 
diff --git a/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc b/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
index 1bc52af..c63615e7 100644
--- a/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
+++ b/chrome/browser/ui/webui/downloads/downloads_list_tracker.cc
@@ -16,8 +16,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
-#include "base/value_conversions.h"
-#include "base/values.h"
 #include "chrome/browser/download/download_crx_util.h"
 #include "chrome/browser/download/download_item_model.h"
 #include "chrome/browser/download/download_query.h"
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom b/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom
index 061c1e82..4b4101df 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals.mojom
@@ -60,10 +60,10 @@
   // Inject the client side page object.
   SetClientPage(pending_remote<InterventionsInternalsPage> page);
 
-  // Change the status of ignoring blacklist to |ignored|. |ignored| will
-  // indicate whether the blacklist decision would be ignored when deciding if a
+  // Change the status of ignoring blocklist to |ignored|. |ignored| will
+  // indicate whether the blocklist decision would be ignored when deciding if a
   // preview should be shown or not.
-  SetIgnorePreviewsBlacklistDecision(bool ignored);
+  SetIgnorePreviewsBlocklistDecision(bool ignored);
 };
 
 interface InterventionsInternalsPage {
@@ -72,20 +72,20 @@
   // publishes it on the javscript side.
   LogNewMessage(MessageLog log);
 
-  // Notify the page that |host| has been blacklisted at |time|. The method is
+  // Notify the page that |host| has been blocklisted at |time|. The method is
   // called by InterventionsInternalsPageHandler when PreviewsUIService receives
-  // new blacklisted host.
-  OnBlacklistedHost(string host, int64 time);
+  // new blocklisted host.
+  OnBlocklistedHost(string host, int64 time);
 
-  // Notify the page that user blacklisted status has changed to |blacklisted|.
+  // Notify the page that user blocklisted status has changed to |blocklisted|.
   // The method is called by InterventionsInternalsPageHandler when user's
-  // blacklist status changes.
-  OnUserBlacklistedStatusChange(bool blacklisted);
+  // blocklist status changes.
+  OnUserBlocklistedStatusChange(bool blocklisted);
 
-  // Notify the page that the blacklist is cleared at |time|. The method is
+  // Notify the page that the blocklist is cleared at |time|. The method is
   // called by InterventionsInternalsPageHandler when PreviewsUIService clears
-  // the blacklist.
-  OnBlacklistCleared(int64 time);
+  // the blocklist.
+  OnBlocklistCleared(int64 time);
 
   // Notify the page on the new estimated effective connection type is |type|.
   // Also reports the session's maximum intervention effective connection type
@@ -94,8 +94,8 @@
   // changes.
   UpdateEffectiveConnectionType(string type, string max_intervention_type);
 
-  // Notify the page on whether the blacklist decision is considered or ignored.
+  // Notify the page on whether the blocklist decision is considered or ignored.
   // This method is called by InterventionsInternalsPageHandler when the status
-  // of ignore blacklist decision is updated to |ignored|.
-  OnIgnoreBlacklistDecisionStatusChanged(bool ignored);
+  // of ignore blocklist decision is updated to |ignored|.
+  OnIgnoreBlocklistDecisionStatusChanged(bool ignored);
 };
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
index a956bd2e..fbce5852 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.cc
@@ -62,7 +62,7 @@
 const char kDeferAllScriptFlagHtmlId[] = "defer-all-script-flag";
 const char kNoScriptFlagHtmlId[] = "noscript-flag";
 const char kEctFlagHtmlId[] = "ect-flag";
-const char kIgnorePreviewsBlacklistFlagHtmlId[] = "ignore-previews-blacklist";
+const char kIgnorePreviewsBlocklistFlagHtmlId[] = "ignore-previews-blocklist";
 const char kDataSaverAltConfigHtmlId[] =
     "data-reduction-proxy-server-experiment";
 
@@ -76,8 +76,8 @@
     "chrome://flags/#enable-defer-all-script";
 const char kNoScriptFlagLink[] = "chrome://flags/#enable-noscript-previews";
 const char kEctFlagLink[] = "chrome://flags/#force-effective-connection-type";
-const char kIgnorePreviewsBlacklistLink[] =
-    "chrome://flags/#ignore-previews-blacklist";
+const char kIgnorePreviewsBlocklistLink[] =
+    "chrome://flags/#ignore-previews-blocklist";
 const char kDataSaverAltConfigLink[] =
     "chrome://flags/#enable-data-reduction-proxy-server-experiment";
 
@@ -184,35 +184,35 @@
   page_->LogNewMessage(std::move(mojo_message_ptr));
 }
 
-void InterventionsInternalsPageHandler::SetIgnorePreviewsBlacklistDecision(
+void InterventionsInternalsPageHandler::SetIgnorePreviewsBlocklistDecision(
     bool ignored) {
-  previews_ui_service_->SetIgnorePreviewsBlacklistDecision(ignored);
+  previews_ui_service_->SetIgnorePreviewsBlocklistDecision(ignored);
 }
 
 void InterventionsInternalsPageHandler::OnLastObserverRemove() {
-  // Reset the status of ignoring PreviewsBlackList decisions to default value.
-  previews_ui_service_->SetIgnorePreviewsBlacklistDecision(
-      previews::switches::ShouldIgnorePreviewsBlacklist());
+  // Reset the status of ignoring PreviewsBlockList decisions to default value.
+  previews_ui_service_->SetIgnorePreviewsBlocklistDecision(
+      previews::switches::ShouldIgnorePreviewsBlocklist());
 }
 
-void InterventionsInternalsPageHandler::OnIgnoreBlacklistDecisionStatusChanged(
+void InterventionsInternalsPageHandler::OnIgnoreBlocklistDecisionStatusChanged(
     bool ignored) {
-  page_->OnIgnoreBlacklistDecisionStatusChanged(ignored);
+  page_->OnIgnoreBlocklistDecisionStatusChanged(ignored);
 }
 
-void InterventionsInternalsPageHandler::OnNewBlacklistedHost(
+void InterventionsInternalsPageHandler::OnNewBlocklistedHost(
     const std::string& host,
     base::Time time) {
-  page_->OnBlacklistedHost(host, time.ToJavaTime());
+  page_->OnBlocklistedHost(host, time.ToJavaTime());
 }
 
-void InterventionsInternalsPageHandler::OnUserBlacklistedStatusChange(
-    bool blacklisted) {
-  page_->OnUserBlacklistedStatusChange(blacklisted);
+void InterventionsInternalsPageHandler::OnUserBlocklistedStatusChange(
+    bool blocklisted) {
+  page_->OnUserBlocklistedStatusChange(blocklisted);
 }
 
-void InterventionsInternalsPageHandler::OnBlacklistCleared(base::Time time) {
-  page_->OnBlacklistCleared(time.ToJavaTime());
+void InterventionsInternalsPageHandler::OnBlocklistCleared(base::Time time) {
+  page_->OnBlocklistCleared(time.ToJavaTime());
 }
 
 void InterventionsInternalsPageHandler::GetPreviewsEnabled(
@@ -317,14 +317,14 @@
   ect_status->htmlId = kEctFlagHtmlId;
   flags.push_back(std::move(ect_status));
 
-  auto ignore_previews_blacklist = mojom::PreviewsFlag::New();
-  ignore_previews_blacklist->description =
-      flag_descriptions::kIgnorePreviewsBlacklistName;
-  ignore_previews_blacklist->link = kIgnorePreviewsBlacklistLink;
-  ignore_previews_blacklist->value =
-      GetEnabledStateForSwitch(previews::switches::kIgnorePreviewsBlacklist);
-  ignore_previews_blacklist->htmlId = kIgnorePreviewsBlacklistFlagHtmlId;
-  flags.push_back(std::move(ignore_previews_blacklist));
+  auto ignore_previews_blocklist = mojom::PreviewsFlag::New();
+  ignore_previews_blocklist->description =
+      flag_descriptions::kIgnorePreviewsBlocklistName;
+  ignore_previews_blocklist->link = kIgnorePreviewsBlocklistLink;
+  ignore_previews_blocklist->value =
+      GetEnabledStateForSwitch(previews::switches::kIgnorePreviewsBlocklist);
+  ignore_previews_blocklist->htmlId = kIgnorePreviewsBlocklistFlagHtmlId;
+  flags.push_back(std::move(ignore_previews_blocklist));
 
   auto alt_config_status = mojom::PreviewsFlag::New();
   alt_config_status->description =
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h
index b892a1e..c47656cc 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler.h
@@ -37,15 +37,15 @@
       GetPreviewsFlagsDetailsCallback callback) override;
   void SetClientPage(
       mojo::PendingRemote<mojom::InterventionsInternalsPage> page) override;
-  void SetIgnorePreviewsBlacklistDecision(bool ignore) override;
+  void SetIgnorePreviewsBlocklistDecision(bool ignore) override;
 
   // previews::PreviewsLoggerObserver:
   void OnNewMessageLogAdded(
       const previews::PreviewsLogger::MessageLog& message) override;
-  void OnNewBlacklistedHost(const std::string& host, base::Time time) override;
-  void OnUserBlacklistedStatusChange(bool blacklisted) override;
-  void OnBlacklistCleared(base::Time time) override;
-  void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) override;
+  void OnNewBlocklistedHost(const std::string& host, base::Time time) override;
+  void OnUserBlocklistedStatusChange(bool blocklisted) override;
+  void OnBlocklistCleared(base::Time time) override;
+  void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) override;
   void OnLastObserverRemove() override;
 
  private:
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
index b5a0dde..376ec7c 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_page_handler_unittest.cc
@@ -74,8 +74,8 @@
 constexpr char kDeferAllScriptFlagHtmlId[] = "defer-all-script-flag";
 constexpr char kNoScriptFlagHtmlId[] = "noscript-flag";
 constexpr char kEctFlagHtmlId[] = "ect-flag";
-constexpr char kIgnorePreviewsBlacklistFlagHtmlId[] =
-    "ignore-previews-blacklist";
+constexpr char kIgnorePreviewsBlocklistFlagHtmlId[] =
+    "ignore-previews-blocklist";
 constexpr char kDataSaverAltConfigHtmlId[] =
     "data-reduction-proxy-server-experiment";
 
@@ -89,8 +89,8 @@
 constexpr char kNoScriptFlagLink[] = "chrome://flags/#enable-noscript-previews";
 constexpr char kEctFlagLink[] =
     "chrome://flags/#force-effective-connection-type";
-constexpr char kIgnorePreviewsBlacklistLink[] =
-    "chrome://flags/#ignore-previews-blacklist";
+constexpr char kIgnorePreviewsBlocklistLink[] =
+    "chrome://flags/#ignore-previews-blocklist";
 constexpr char kDataSaverAltConfigLink[] =
     "chrome://flags/#enable-data-reduction-proxy-server-experiment";
 
@@ -141,23 +141,23 @@
  public:
   TestInterventionsInternalsPage(
       mojo::PendingReceiver<mojom::InterventionsInternalsPage> receiver)
-      : receiver_(this, std::move(receiver)), blacklist_ignored_(false) {}
+      : receiver_(this, std::move(receiver)), blocklist_ignored_(false) {}
 
-  ~TestInterventionsInternalsPage() override {}
+  ~TestInterventionsInternalsPage() override = default;
 
   // mojom::InterventionsInternalsPage:
   void LogNewMessage(mojom::MessageLogPtr message) override {
     message_ = std::make_unique<mojom::MessageLogPtr>(std::move(message));
   }
-  void OnBlacklistedHost(const std::string& host, int64_t time) override {
-    host_blacklisted_ = host;
-    host_blacklisted_time_ = time;
+  void OnBlocklistedHost(const std::string& host, int64_t time) override {
+    host_blocklisted_ = host;
+    host_blocklisted_time_ = time;
   }
-  void OnUserBlacklistedStatusChange(bool blacklisted) override {
-    user_blacklisted_ = blacklisted;
+  void OnUserBlocklistedStatusChange(bool blocklisted) override {
+    user_blocklisted_ = blocklisted;
   }
-  void OnBlacklistCleared(int64_t time) override {
-    blacklist_cleared_time_ = time;
+  void OnBlocklistCleared(int64_t time) override {
+    blocklist_cleared_time_ = time;
   }
   void UpdateEffectiveConnectionType(
       const std::string& type,
@@ -166,21 +166,21 @@
     // TODO(thanhdle): Add integration test to test behavior of the pipeline end
     // to end. crbug.com/777936
   }
-  void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) override {
-    blacklist_ignored_ = ignored;
+  void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) override {
+    blocklist_ignored_ = ignored;
   }
 
   // Expose passed in message in LogNewMessage for testing.
   mojom::MessageLogPtr* message() const { return message_.get(); }
 
-  // Expose passed in blacklist events info for testing.
-  std::string host_blacklisted() const { return host_blacklisted_; }
-  int64_t host_blacklisted_time() const { return host_blacklisted_time_; }
-  bool user_blacklisted() const { return user_blacklisted_; }
-  int64_t blacklist_cleared_time() const { return blacklist_cleared_time_; }
+  // Expose passed in blocklist events info for testing.
+  std::string host_blocklisted() const { return host_blocklisted_; }
+  int64_t host_blocklisted_time() const { return host_blocklisted_time_; }
+  bool user_blocklisted() const { return user_blocklisted_; }
+  int64_t blocklist_cleared_time() const { return blocklist_cleared_time_; }
 
-  // Expose the passed in blacklist ignore status for testing.
-  bool blacklist_ignored() const { return blacklist_ignored_; }
+  // Expose the passed in blocklist ignore status for testing.
+  bool blocklist_ignored() const { return blocklist_ignored_; }
 
  private:
   mojo::Receiver<mojom::InterventionsInternalsPage> receiver_;
@@ -188,14 +188,14 @@
   // The MessageLogPtr passed in LogNewMessage method.
   std::unique_ptr<mojom::MessageLogPtr> message_;
 
-  // Received blacklist events info.
-  std::string host_blacklisted_;
-  int64_t host_blacklisted_time_;
-  int64_t user_blacklisted_;
-  int64_t blacklist_cleared_time_;
+  // Received blocklist events info.
+  std::string host_blocklisted_;
+  int64_t host_blocklisted_time_;
+  int64_t user_blocklisted_;
+  int64_t blocklist_cleared_time_;
 
-  // Whether to ignore previews blacklist decisions.
-  bool blacklist_ignored_;
+  // Whether to ignore previews blocklist decisions.
+  bool blocklist_ignored_;
 };
 
 // Mock class to test interaction between the PageHandler and the
@@ -224,10 +224,10 @@
   // previews::PreviewsDeciderImpl:
   void Initialize(
       previews::PreviewsUIService* previews_ui_service,
-      std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store,
+      std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store,
       std::unique_ptr<previews::PreviewsOptimizationGuide> previews_opt_guide,
       const previews::PreviewsIsEnabledCallback& is_enabled_callback,
-      blacklist::BlacklistData::AllowedTypesAndVersions allowed_previews)
+      blocklist::BlocklistData::AllowedTypesAndVersions allowed_previews)
       override {}
 };
 
@@ -244,22 +244,22 @@
             nullptr, /* previews_opt_guide */
             base::BindRepeating(&MockedPreviewsIsEnabled),
             std::move(logger),
-            blacklist::BlacklistData::AllowedTypesAndVersions(),
+            blocklist::BlocklistData::AllowedTypesAndVersions(),
             test_network_quality_tracker),
-        blacklist_ignored_(false) {}
-  ~TestPreviewsUIService() override {}
+        blocklist_ignored_(false) {}
+  ~TestPreviewsUIService() override = default;
 
   // previews::PreviewsUIService:
-  void SetIgnorePreviewsBlacklistDecision(bool ignored) override {
-    blacklist_ignored_ = ignored;
+  void SetIgnorePreviewsBlocklistDecision(bool ignored) override {
+    blocklist_ignored_ = ignored;
   }
 
-  // Exposed blacklist ignored state.
-  bool blacklist_ignored() const { return blacklist_ignored_; }
+  // Exposed blocklist ignored state.
+  bool blocklist_ignored() const { return blocklist_ignored_; }
 
  private:
-  // Whether the blacklist decisions are ignored or not.
-  bool blacklist_ignored_;
+  // Whether the blocklist decisions are ignored or not.
+  bool blocklist_ignored_;
 };
 
 class InterventionsInternalsPageHandlerTest : public testing::Test {
@@ -534,33 +534,33 @@
 }
 
 TEST_F(InterventionsInternalsPageHandlerTest,
-       GetFlagsIgnorePreviewsBlacklistDisabledValue) {
+       GetFlagsIgnorePreviewsBlocklistDisabledValue) {
   // Disabled by default.
   page_handler_->GetPreviewsFlagsDetails(
       base::BindOnce(&MockGetPreviewsFlagsCallback));
-  auto ignore_previews_blacklist =
-      passed_in_flags.find(kIgnorePreviewsBlacklistFlagHtmlId);
+  auto ignore_previews_blocklist =
+      passed_in_flags.find(kIgnorePreviewsBlocklistFlagHtmlId);
 
-  ASSERT_NE(passed_in_flags.end(), ignore_previews_blacklist);
-  EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlacklistName,
-            ignore_previews_blacklist->second->description);
-  EXPECT_EQ(kDisabledFlagValue, ignore_previews_blacklist->second->value);
-  EXPECT_EQ(kIgnorePreviewsBlacklistLink,
-            ignore_previews_blacklist->second->link);
+  ASSERT_NE(passed_in_flags.end(), ignore_previews_blocklist);
+  EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlocklistName,
+            ignore_previews_blocklist->second->description);
+  EXPECT_EQ(kDisabledFlagValue, ignore_previews_blocklist->second->value);
+  EXPECT_EQ(kIgnorePreviewsBlocklistLink,
+            ignore_previews_blocklist->second->link);
 }
 
 TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptDisabledValue) {
   page_handler_->GetPreviewsFlagsDetails(
       base::BindOnce(&MockGetPreviewsFlagsCallback));
-  auto ignore_previews_blacklist =
-      passed_in_flags.find(kIgnorePreviewsBlacklistFlagHtmlId);
+  auto ignore_previews_blocklist =
+      passed_in_flags.find(kIgnorePreviewsBlocklistFlagHtmlId);
 
-  ASSERT_NE(passed_in_flags.end(), ignore_previews_blacklist);
-  EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlacklistName,
-            ignore_previews_blacklist->second->description);
-  EXPECT_EQ(kDisabledFlagValue, ignore_previews_blacklist->second->value);
-  EXPECT_EQ(kIgnorePreviewsBlacklistLink,
-            ignore_previews_blacklist->second->link);
+  ASSERT_NE(passed_in_flags.end(), ignore_previews_blocklist);
+  EXPECT_EQ(flag_descriptions::kIgnorePreviewsBlocklistName,
+            ignore_previews_blocklist->second->description);
+  EXPECT_EQ(kDisabledFlagValue, ignore_previews_blocklist->second->value);
+  EXPECT_EQ(kIgnorePreviewsBlocklistLink,
+            ignore_previews_blocklist->second->link);
 }
 
 TEST_F(InterventionsInternalsPageHandlerTest, GetFlagsNoScriptDefaultValue) {
@@ -844,7 +844,7 @@
   EXPECT_TRUE(logger_->RemovedObserverIsCalled());
 }
 
-TEST_F(InterventionsInternalsPageHandlerTest, OnNewBlacklistedHostPostToPage) {
+TEST_F(InterventionsInternalsPageHandlerTest, OnNewBlocklistedHostPostToPage) {
   const std::string hosts[] = {
       "example_0.com",
       "example_1.com",
@@ -853,75 +853,75 @@
 
   for (auto expected_host : hosts) {
     base::Time expected_time = base::Time::Now();
-    page_handler_->OnNewBlacklistedHost(expected_host, expected_time);
+    page_handler_->OnNewBlocklistedHost(expected_host, expected_time);
     base::RunLoop().RunUntilIdle();
 
-    EXPECT_EQ(expected_host, page_->host_blacklisted());
-    EXPECT_EQ(expected_time.ToJavaTime(), page_->host_blacklisted_time());
+    EXPECT_EQ(expected_host, page_->host_blocklisted());
+    EXPECT_EQ(expected_time.ToJavaTime(), page_->host_blocklisted_time());
   }
 }
 
-TEST_F(InterventionsInternalsPageHandlerTest, OnUserBlacklistedPostToPage) {
-  page_handler_->OnUserBlacklistedStatusChange(true /* blacklisted */);
+TEST_F(InterventionsInternalsPageHandlerTest, OnUserBlocklistedPostToPage) {
+  page_handler_->OnUserBlocklistedStatusChange(true /* blocklisted */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(page_->user_blacklisted());
+  EXPECT_TRUE(page_->user_blocklisted());
 
-  page_handler_->OnUserBlacklistedStatusChange(false /* blacklisted */);
+  page_handler_->OnUserBlocklistedStatusChange(false /* blocklisted */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(page_->user_blacklisted());
+  EXPECT_FALSE(page_->user_blocklisted());
 }
 
-TEST_F(InterventionsInternalsPageHandlerTest, OnBlacklistClearedPostToPage) {
+TEST_F(InterventionsInternalsPageHandlerTest, OnBlocklistClearedPostToPage) {
   base::Time times[] = {
       base::Time::FromJsTime(-413696806000),  // Nov 21 1956 20:13:14 UTC
       base::Time::FromJsTime(758620800000),   // Jan 15 1994 08:00:00 UTC
       base::Time::FromJsTime(1581696550000),  // Feb 14 2020 16:09:10 UTC
   };
   for (auto expected_time : times) {
-    page_handler_->OnBlacklistCleared(expected_time);
+    page_handler_->OnBlocklistCleared(expected_time);
     base::RunLoop().RunUntilIdle();
 
-    EXPECT_EQ(expected_time.ToJavaTime(), page_->blacklist_cleared_time());
+    EXPECT_EQ(expected_time.ToJavaTime(), page_->blocklist_cleared_time());
   }
 }
 
 TEST_F(InterventionsInternalsPageHandlerTest,
-       SetIgnorePreviewsBlacklistDecisionCallsUIServiceCorrectly) {
-  page_handler_->SetIgnorePreviewsBlacklistDecision(true /* ignored */);
-  EXPECT_TRUE(previews_ui_service_->blacklist_ignored());
+       SetIgnorePreviewsBlocklistDecisionCallsUIServiceCorrectly) {
+  page_handler_->SetIgnorePreviewsBlocklistDecision(true /* ignored */);
+  EXPECT_TRUE(previews_ui_service_->blocklist_ignored());
 
-  page_handler_->SetIgnorePreviewsBlacklistDecision(false /* ignored */);
-  EXPECT_FALSE(previews_ui_service_->blacklist_ignored());
+  page_handler_->SetIgnorePreviewsBlocklistDecision(false /* ignored */);
+  EXPECT_FALSE(previews_ui_service_->blocklist_ignored());
 }
 
 TEST_F(InterventionsInternalsPageHandlerTest,
-       PageUpdateOnBlacklistIgnoredChange) {
-  page_handler_->OnIgnoreBlacklistDecisionStatusChanged(true /* ignored */);
+       PageUpdateOnBlocklistIgnoredChange) {
+  page_handler_->OnIgnoreBlocklistDecisionStatusChanged(true /* ignored */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(page_->blacklist_ignored());
+  EXPECT_TRUE(page_->blocklist_ignored());
 
-  page_handler_->OnIgnoreBlacklistDecisionStatusChanged(false /* ignored */);
+  page_handler_->OnIgnoreBlocklistDecisionStatusChanged(false /* ignored */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(page_->blacklist_ignored());
+  EXPECT_FALSE(page_->blocklist_ignored());
 }
 
 TEST_F(InterventionsInternalsPageHandlerTest,
-       IgnoreBlacklistReversedOnLastObserverRemovedCalled) {
-  ASSERT_FALSE(previews::switches::ShouldIgnorePreviewsBlacklist());
+       IgnoreBlocklistReversedOnLastObserverRemovedCalled) {
+  ASSERT_FALSE(previews::switches::ShouldIgnorePreviewsBlocklist());
   page_handler_->OnLastObserverRemove();
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(page_->blacklist_ignored());
+  EXPECT_FALSE(page_->blocklist_ignored());
 }
 
 TEST_F(InterventionsInternalsPageHandlerTest,
-       IgnoreBlacklistReversedOnLastObserverRemovedCalledIgnoreViaFlag) {
+       IgnoreBlocklistReversedOnLastObserverRemovedCalledIgnoreViaFlag) {
   base::test::ScopedCommandLine scoped_command_line;
   base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
-  command_line->AppendSwitch(previews::switches::kIgnorePreviewsBlacklist);
-  ASSERT_TRUE(previews::switches::ShouldIgnorePreviewsBlacklist());
+  command_line->AppendSwitch(previews::switches::kIgnorePreviewsBlocklist);
+  ASSERT_TRUE(previews::switches::ShouldIgnorePreviewsBlocklist());
   page_handler_->OnLastObserverRemove();
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(page_->blacklist_ignored());
+  EXPECT_FALSE(page_->blocklist_ignored());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/webui/media/media_feeds_ui.cc b/chrome/browser/ui/webui/media/media_feeds_ui.cc
index 9fe5e0b..6e91a44 100644
--- a/chrome/browser/ui/webui/media/media_feeds_ui.cc
+++ b/chrome/browser/ui/webui/media/media_feeds_ui.cc
@@ -64,8 +64,10 @@
 
 void MediaFeedsUI::GetItemsForMediaFeed(int64_t feed_id,
                                         GetItemsForMediaFeedCallback callback) {
-  GetMediaHistoryService()->GetItemsForMediaFeedForDebug(feed_id,
-                                                         std::move(callback));
+  GetMediaHistoryService()->GetMediaFeedItems(
+      media_history::MediaHistoryKeyedService::GetMediaFeedItemsRequest::
+          CreateItemsForDebug(feed_id),
+      std::move(callback));
 }
 
 void MediaFeedsUI::FetchMediaFeed(int64_t feed_id,
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index f4aedd7..4171259 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -320,12 +320,17 @@
 void NetInternalsMessageHandler::OnExpectCTQuery(const base::ListValue* list) {
   // |list| should be: [<domain to query>].
   std::string domain;
-  bool domain_result = list->GetString(0, &domain);
-  DCHECK(domain_result);
+  bool result = list->GetString(0, &domain);
+  DCHECK(result);
+
+  url::Origin origin = url::Origin::Create(GURL("https://" + domain));
 
   GetNetworkContext()->GetExpectCTState(
-      domain, base::BindOnce(&NetInternalsMessageHandler::SendJavascriptCommand,
-                             this->AsWeakPtr(), "receivedExpectCTResult"));
+      domain,
+      net::NetworkIsolationKey(origin /* top_frame_site */,
+                               origin /* frame_site */),
+      base::BindOnce(&NetInternalsMessageHandler::SendJavascriptCommand,
+                     this->AsWeakPtr(), "receivedExpectCTResult"));
 }
 
 void NetInternalsMessageHandler::OnExpectCTAdd(const base::ListValue* list) {
@@ -338,6 +343,7 @@
     // name.
     return;
   }
+
   std::string report_uri_str;
   result = list->GetString(1, &report_uri_str);
   DCHECK(result);
@@ -345,9 +351,14 @@
   result = list->GetBoolean(2, &enforce);
   DCHECK(result);
 
+  url::Origin origin = url::Origin::Create(GURL("https://" + domain));
+
   base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
-  GetNetworkContext()->AddExpectCT(domain, expiry, enforce,
-                                   GURL(report_uri_str), base::DoNothing());
+  GetNetworkContext()->AddExpectCT(
+      domain, expiry, enforce, GURL(report_uri_str),
+      net::NetworkIsolationKey(origin /* top_frame_site */,
+                               origin /* frame_site */),
+      base::DoNothing());
 }
 
 void NetInternalsMessageHandler::OnExpectCTTestReport(
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index 3cda52ab..d96bbfc0 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -36,6 +36,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/webui/metrics_handler.h"
+#include "chrome/browser/ui/webui/plural_string_handler.h"
 #include "chrome/browser/ui/webui/print_preview/print_preview_handler.h"
 #include "chrome/browser/ui/webui/theme_source.h"
 #include "chrome/browser/ui/webui/webui_util.h"
@@ -288,12 +289,6 @@
     {"printButton", IDS_PRINT_PREVIEW_PRINT_BUTTON},
     {"printDestinationsTitle", IDS_PRINT_PREVIEW_PRINT_DESTINATIONS_TITLE},
     {"printPagesLabel", IDS_PRINT_PREVIEW_PRINT_PAGES_LABEL},
-    {"printPreviewPageLabelPlural", IDS_PRINT_PREVIEW_PAGE_LABEL_PLURAL},
-    {"printPreviewPageLabelSingular", IDS_PRINT_PREVIEW_PAGE_LABEL_SINGULAR},
-    {"printPreviewSheetsLabelPlural", IDS_PRINT_PREVIEW_SHEETS_LABEL_PLURAL},
-    {"printPreviewSheetsLabelSingular",
-     IDS_PRINT_PREVIEW_SHEETS_LABEL_SINGULAR},
-    {"printPreviewSummaryFormatShort", IDS_PRINT_PREVIEW_SUMMARY_FORMAT_SHORT},
     {"printToGoogleDrive", IDS_PRINT_PREVIEW_PRINT_TO_GOOGLE_DRIVE},
     {"printToPDF", IDS_PRINT_PREVIEW_PRINT_TO_PDF},
     {"printerSharingInviteText", IDS_PRINT_PREVIEW_INVITE_TEXT},
@@ -329,9 +324,6 @@
     {"pinErrorMessage", IDS_PRINT_PREVIEW_PIN_ERROR_MESSAGE},
     {"pinPlaceholder", IDS_PRINT_PREVIEW_PIN_PLACEHOLDER},
     {"printerEulaURL", IDS_PRINT_PREVIEW_EULA_URL},
-    {"sheetsLimitErrorMessage", IDS_PRINT_PREVIEW_SHEETS_LIMIT_ERROR_MESSAGE},
-    {"sheetsLimitLabelSingular", IDS_PRINT_PREVIEW_SHEETS_LIMIT_LABEL_SINGULAR},
-    {"sheetsLimitLabelPlural", IDS_PRINT_PREVIEW_SHEETS_LIMIT_LABEL_PLURAL},
 #endif
 #if defined(OS_MACOSX)
     {"openPdfInPreviewOption", IDS_PRINT_PREVIEW_OPEN_PDF_IN_PREVIEW_APP},
@@ -379,31 +371,32 @@
 
 void SetupPrintPreviewPlugin(content::WebUIDataSource* source) {
   static constexpr webui::ResourcePath kPdfResources[] = {
-    {"pdf/bookmark_type.js", IDR_PDF_BOOKMARK_TYPE_JS},
-    {"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS},
-    {"pdf/constants.js", IDR_PDF_CONSTANTS_JS},
-    {"pdf/controller.js", IDR_PDF_CONTROLLER_JS},
-    {"pdf/elements/icons.js", IDR_PDF_ICONS_JS},
-    {"pdf/elements/shared-vars.js", IDR_PDF_SHARED_VARS_JS},
-    {"pdf/elements/viewer-error-screen.js", IDR_PDF_VIEWER_ERROR_SCREEN_JS},
-    {"pdf/elements/viewer-page-indicator.js",
-     IDR_PRINT_PREVIEW_PDF_VIEWER_PAGE_INDICATOR_JS},
-    {"pdf/elements/viewer-zoom-button.js", IDR_PDF_VIEWER_ZOOM_BUTTON_JS},
-    {"pdf/elements/viewer-zoom-toolbar.js", IDR_PDF_VIEWER_ZOOM_SELECTOR_JS},
-    {"pdf/gesture_detector.js", IDR_PDF_GESTURE_DETECTOR_JS},
-    {"pdf/index.css", IDR_PDF_INDEX_CSS},
-    {"pdf/index.html", IDR_PRINT_PREVIEW_PDF_INDEX_PP_HTML},
-    {"pdf/main_pp.js", IDR_PRINT_PREVIEW_PDF_MAIN_PP_JS},
-    {"pdf/main_util.js", IDR_PDF_MAIN_UTIL_JS},
-    {"pdf/metrics.js", IDR_PDF_METRICS_JS},
-    {"pdf/navigator.js", IDR_PDF_NAVIGATOR_JS},
-    {"pdf/open_pdf_params_parser.js", IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS},
-    {"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS},
-    {"pdf/pdf_viewer.js", IDR_PDF_PDF_VIEWER_JS},
-    {"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS},
-    {"pdf/viewport.js", IDR_PDF_VIEWPORT_JS},
-    {"pdf/viewport_scroller.js", IDR_PDF_VIEWPORT_SCROLLER_JS},
-    {"pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS},
+      {"pdf/bookmark_type.js", IDR_PDF_BOOKMARK_TYPE_JS},
+      {"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS},
+      {"pdf/constants.js", IDR_PDF_CONSTANTS_JS},
+      {"pdf/controller.js", IDR_PDF_CONTROLLER_JS},
+      {"pdf/elements/icons.js", IDR_PDF_ICONS_JS},
+      {"pdf/elements/shared-vars.js", IDR_PDF_SHARED_VARS_JS},
+      {"pdf/elements/viewer-error-screen.js", IDR_PDF_VIEWER_ERROR_SCREEN_JS},
+      {"pdf/elements/viewer-page-indicator.js",
+       IDR_PRINT_PREVIEW_PDF_VIEWER_PAGE_INDICATOR_JS},
+      {"pdf/elements/viewer-zoom-button.js", IDR_PDF_VIEWER_ZOOM_BUTTON_JS},
+      {"pdf/elements/viewer-zoom-toolbar.js", IDR_PDF_VIEWER_ZOOM_SELECTOR_JS},
+      {"pdf/gesture_detector.js", IDR_PDF_GESTURE_DETECTOR_JS},
+      {"pdf/index.css", IDR_PDF_INDEX_CSS},
+      {"pdf/index.html", IDR_PRINT_PREVIEW_PDF_INDEX_PP_HTML},
+      {"pdf/main_pp.js", IDR_PRINT_PREVIEW_PDF_MAIN_PP_JS},
+      {"pdf/main_util.js", IDR_PDF_MAIN_UTIL_JS},
+      {"pdf/metrics.js", IDR_PDF_METRICS_JS},
+      {"pdf/navigator.js", IDR_PDF_NAVIGATOR_JS},
+      {"pdf/open_pdf_params_parser.js", IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS},
+      {"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS},
+      {"pdf/pdf_viewer.js", IDR_PDF_PDF_VIEWER_JS},
+      {"pdf/pdf_viewer_utils.js", IDR_PDF_PDF_VIEWER_UTILS_JS},
+      {"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS},
+      {"pdf/viewport.js", IDR_PDF_VIEWPORT_JS},
+      {"pdf/viewport_scroller.js", IDR_PDF_VIEWPORT_SCROLLER_JS},
+      {"pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS},
   };
   webui::AddResourcePathsBulk(source, kPdfResources);
 
@@ -438,6 +431,19 @@
   PrintPreviewHandler* handler_ptr = handler.get();
   web_ui->AddMessageHandler(std::move(handler));
   web_ui->AddMessageHandler(std::make_unique<MetricsHandler>());
+
+  // Add a handler to provide pluralized strings.
+  auto plural_string_handler = std::make_unique<PluralStringHandler>();
+  plural_string_handler->AddLocalizedString(
+      "printPreviewPageSummaryLabel", IDS_PRINT_PREVIEW_PAGE_SUMMARY_LABEL);
+  plural_string_handler->AddLocalizedString(
+      "printPreviewSheetSummaryLabel", IDS_PRINT_PREVIEW_SHEET_SUMMARY_LABEL);
+#if defined(OS_CHROMEOS)
+  plural_string_handler->AddLocalizedString(
+      "sheetsLimitErrorMessage", IDS_PRINT_PREVIEW_SHEETS_LIMIT_ERROR_MESSAGE);
+#endif
+  web_ui->AddMessageHandler(std::move(plural_string_handler));
+
   return handler_ptr;
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/apps_section.cc b/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
index 749d9eba..e69a6ac 100644
--- a/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/apps_section.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/webui/settings/chromeos/apps_section.h"
 
+#include "base/feature_list.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/chromeos/arc/arc_util.h"
 #include "chrome/browser/chromeos/plugin_vm/plugin_vm_pref_names.h"
@@ -17,6 +18,7 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/os_settings_resources.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "components/arc/arc_prefs.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -320,6 +322,10 @@
 
   html_source->AddBoolean("showPluginVm",
                           ShowPluginVm(profile(), *pref_service_));
+  html_source->AddBoolean(
+      "showPluginVmCameraPermissions",
+      base::FeatureList::IsEnabled(
+          chromeos::features::kPluginVmShowCameraPermissions));
 }
 
 void AppsSection::UpdateAndroidSearchTags() {
diff --git a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
index 97f2eeab..8bddd59 100644
--- a/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/os_settings_ui.cc
@@ -68,6 +68,10 @@
   html_source->AddResourcePath("chromeos/lazy_load.html",
                                IDR_OS_SETTINGS_LAZY_LOAD_VULCANIZED_HTML);
   html_source->SetDefaultResource(IDR_OS_SETTINGS_VULCANIZED_HTML);
+  html_source->AddResourcePath("chromeos/os_settings_v3.html",
+                               IDR_OS_SETTINGS_OS_SETTINGS_V3_HTML);
+  html_source->AddResourcePath("chromeos/os_settings.js",
+                               IDR_OS_SETTINGS_SETTINGS_ROLLUP_JS);
 #else
   webui::SetupWebUIDataSource(
       html_source,
diff --git a/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc b/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc
index 80d2e0e..2bbbcea 100644
--- a/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/search/search_handler.cc
@@ -205,14 +205,8 @@
 
 mojom::SearchResultPtr SearchHandler::ResultToSearchResult(
     const local_search_service::Result& result) const {
-  int message_id;
-
-  // The result's ID is expected to be a stringified int.
-  if (!base::StringToInt(result.id, &message_id))
-    return nullptr;
-
   const SearchConcept* concept =
-      search_tag_registry_->GetTagMetadata(message_id);
+      search_tag_registry_->GetTagMetadata(result.id);
 
   // If the concept was not registered, no metadata is available. This can occur
   // if the search tag was dynamically unregistered during the asynchronous
@@ -258,7 +252,8 @@
 
   return mojom::SearchResult::New(
       /*result_text=*/l10n_util::GetStringUTF16(content_id),
-      /*canonical_result_text=*/l10n_util::GetStringUTF16(message_id), url,
+      /*canonical_result_text=*/
+      l10n_util::GetStringUTF16(concept->canonical_message_id), url,
       concept->icon, result.score, hierarchy_strings, concept->default_rank,
       concept->type, std::move(result_id));
 }
diff --git a/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc b/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc
index 18fa9dc9..83537ead 100644
--- a/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.cc
@@ -4,9 +4,10 @@
 
 #include "chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h"
 
+#include <sstream>
+
 #include "base/feature_list.h"
 #include "base/strings/string_number_conversions.h"
-#include "chrome/browser/chromeos/local_search_service/index.h"
 #include "chrome/browser/chromeos/local_search_service/local_search_service.h"
 #include "chrome/browser/ui/webui/settings/chromeos/search/search_concept.h"
 #include "chromeos/constants/chromeos_features.h"
@@ -31,28 +32,6 @@
   return alt_tag_message_ids;
 }
 
-std::vector<local_search_service::Data> ConceptVectorToDataVector(
-    const std::vector<SearchConcept>& search_tags) {
-  std::vector<local_search_service::Data> data_list;
-
-  for (const auto& concept : search_tags) {
-    // Create a list of Content objects, which use the stringified version of
-    // message IDs as identifiers.
-    std::vector<local_search_service::Content> content_list;
-    for (int message_id : GetMessageIds(concept)) {
-      content_list.emplace_back(
-          /*id=*/base::NumberToString(message_id),
-          /*content=*/l10n_util::GetStringUTF16(message_id));
-    }
-
-    // Use the stringified version of the canonical message ID as an identifier.
-    data_list.emplace_back(base::NumberToString(concept.canonical_message_id),
-                           content_list);
-  }
-
-  return data_list;
-}
-
 }  // namespace
 
 SearchTagRegistry::SearchTagRegistry(
@@ -73,8 +52,7 @@
   // each concept because all concepts are allocated via static
   // base::NoDestructor objects in the Get*SearchConcepts() helper functions.
   for (const auto& concept : search_tags) {
-    for (int message_id : GetMessageIds(concept))
-      message_id_to_metadata_map_[message_id] = &concept;
+    result_id_to_metadata_list_map_[ToResultId(concept)] = &concept;
   }
 }
 
@@ -83,23 +61,64 @@
   if (!base::FeatureList::IsEnabled(features::kNewOsSettingsSearch))
     return;
 
-  std::vector<std::string> ids;
+  std::vector<std::string> data_ids;
   for (const auto& concept : search_tags) {
-    for (int message_id : GetMessageIds(concept))
-      message_id_to_metadata_map_.erase(message_id);
-    ids.push_back(base::NumberToString(concept.canonical_message_id));
+    std::string result_id = ToResultId(concept);
+    result_id_to_metadata_list_map_.erase(result_id);
+    data_ids.push_back(std::move(result_id));
   }
 
-  index_->Delete(ids);
+  index_->Delete(data_ids);
 }
 
 const SearchConcept* SearchTagRegistry::GetTagMetadata(
-    int canonical_message_id) const {
-  const auto it = message_id_to_metadata_map_.find(canonical_message_id);
-  if (it == message_id_to_metadata_map_.end())
+    const std::string& result_id) const {
+  const auto it = result_id_to_metadata_list_map_.find(result_id);
+  if (it == result_id_to_metadata_list_map_.end())
     return nullptr;
   return it->second;
 }
 
+// static
+std::string SearchTagRegistry::ToResultId(const SearchConcept& concept) {
+  std::stringstream ss;
+  switch (concept.type) {
+    case mojom::SearchResultType::kSection:
+      ss << concept.id.section;
+      break;
+    case mojom::SearchResultType::kSubpage:
+      ss << concept.id.subpage;
+      break;
+    case mojom::SearchResultType::kSetting:
+      ss << concept.id.setting;
+      break;
+  }
+  ss << "," << concept.canonical_message_id;
+  return ss.str();
+}
+
+std::vector<local_search_service::Data>
+SearchTagRegistry::ConceptVectorToDataVector(
+    const std::vector<SearchConcept>& search_tags) {
+  std::vector<local_search_service::Data> data_list;
+
+  for (const auto& concept : search_tags) {
+    // Create a list of Content objects, which use the stringified version of
+    // message IDs as identifiers.
+    std::vector<local_search_service::Content> content_list;
+    for (int message_id : GetMessageIds(concept)) {
+      content_list.emplace_back(
+          /*id=*/base::NumberToString(message_id),
+          /*content=*/l10n_util::GetStringUTF16(message_id));
+    }
+
+    // Compute an identifier for this result; the same ID format it used in
+    // GetTagMetadata().
+    data_list.emplace_back(ToResultId(concept), std::move(content_list));
+  }
+
+  return data_list;
+}
+
 }  // namespace settings
 }  // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h b/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h
index bc3d79a..cbec849b 100644
--- a/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h
+++ b/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry.h
@@ -8,6 +8,8 @@
 #include <unordered_map>
 #include <vector>
 
+#include "base/gtest_prod_util.h"
+#include "chrome/browser/chromeos/local_search_service/index.h"
 #include "chrome/browser/ui/webui/settings/chromeos/os_settings_section.h"
 
 namespace local_search_service {
@@ -33,14 +35,26 @@
   void AddSearchTags(const std::vector<SearchConcept>& search_tags);
   void RemoveSearchTags(const std::vector<SearchConcept>& search_tags);
 
-  // Returns the tag metadata associated with |message_id|, which must be one of
-  // the IDS_OS_SETTINGS_TAG_* identifiers used for a search tag. If no metadata
-  // is available, null is returned.
-  const SearchConcept* GetTagMetadata(int message_id) const;
+  // Returns the tag metadata associated with |result_id|, which is the ID
+  // returned by the LocalSearchService. If no metadata is available, null is
+  // returned.
+  const SearchConcept* GetTagMetadata(const std::string& result_id) const;
 
  private:
+  FRIEND_TEST_ALL_PREFIXES(SearchTagRegistryTest, AddAndRemove);
+
+  static std::string ToResultId(const SearchConcept& concept);
+
+  std::vector<local_search_service::Data> ConceptVectorToDataVector(
+      const std::vector<SearchConcept>& search_tags);
+
+  // Index used by the LocalSearchService for string matching.
   local_search_service::Index* index_;
-  std::unordered_map<int, const SearchConcept*> message_id_to_metadata_map_;
+
+  // In-memory cache of all results which have been added to the
+  // LocalSearchService. Contents are kept in sync with |index_|.
+  std::unordered_map<std::string, const SearchConcept*>
+      result_id_to_metadata_list_map_;
 };
 
 }  // namespace settings
diff --git a/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc
index 9d418fd..da7af08 100644
--- a/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/search/search_tag_registry_unittest.cc
@@ -70,10 +70,12 @@
   search_tag_registry_.AddSearchTags(GetPrintingSearchConcepts());
   EXPECT_EQ(3u, index_->GetSize());
 
+  std::string first_tag_id =
+      SearchTagRegistry::ToResultId(GetPrintingSearchConcepts()[0]);
+
   // Tags added should be available via GetTagMetadata().
   const SearchConcept* add_printer_concept =
-      search_tag_registry_.GetTagMetadata(
-          IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER);
+      search_tag_registry_.GetTagMetadata(first_tag_id);
   ASSERT_TRUE(add_printer_concept);
   EXPECT_EQ(mojom::Setting::kAddPrinter, add_printer_concept->id.setting);
 
@@ -82,8 +84,7 @@
   EXPECT_EQ(0u, index_->GetSize());
 
   // The tag should no longer be accessible via GetTagMetadata().
-  add_printer_concept = search_tag_registry_.GetTagMetadata(
-      IDS_OS_SETTINGS_TAG_PRINTING_ADD_PRINTER);
+  add_printer_concept = search_tag_registry_.GetTagMetadata(first_tag_id);
   ASSERT_FALSE(add_printer_concept);
 }
 
diff --git a/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc b/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc
index e2f4c57..b3fd20ec 100644
--- a/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc
+++ b/chrome/browser/ui/webui/settings/custom_home_pages_table_model.cc
@@ -45,9 +45,8 @@
 
 CustomHomePagesTableModel::CustomHomePagesTableModel(Profile* profile)
     : profile_(profile),
-      observer_(NULL),
-      num_outstanding_title_lookups_(0) {
-}
+      observer_(nullptr),
+      num_outstanding_title_lookups_(0) {}
 
 CustomHomePagesTableModel::~CustomHomePagesTableModel() {
 }
diff --git a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
index 83923229..a06c62e 100644
--- a/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
+++ b/chrome/browser/ui/webui/settings/settings_manage_profile_handler.cc
@@ -11,7 +11,6 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/value_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/gaia_info_update_service.h"
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler.cc b/chrome/browser/ui/webui/signin/inline_login_handler.cc
index 4d13827..5172bdc 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler.cc
+++ b/chrome/browser/ui/webui/signin/inline_login_handler.cc
@@ -170,8 +170,8 @@
 
 void InlineLoginHandler::HandleCompleteLoginMessageWithCookies(
     const base::ListValue& args,
-    const net::CookieStatusList& cookies,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies,
+    const net::CookieAccessResultList& excluded_cookies) {
   const base::Value& dict = args.GetList()[0];
 
   const std::string& email = dict.FindKey("email")->GetString();
@@ -179,9 +179,9 @@
   const std::string& gaia_id = dict.FindKey("gaiaId")->GetString();
 
   std::string auth_code;
-  for (const auto& cookie_with_status : cookies) {
-    if (cookie_with_status.cookie.Name() == "oauth_code")
-      auth_code = cookie_with_status.cookie.Value();
+  for (const auto& cookie_with_access_result : cookies) {
+    if (cookie_with_access_result.cookie.Name() == "oauth_code")
+      auth_code = cookie_with_access_result.cookie.Value();
   }
 
   bool skip_for_now = dict.FindBoolKey("skipForNow").value_or(false);
diff --git a/chrome/browser/ui/webui/signin/inline_login_handler.h b/chrome/browser/ui/webui/signin/inline_login_handler.h
index d8e5933..369a66ac0 100644
--- a/chrome/browser/ui/webui/signin/inline_login_handler.h
+++ b/chrome/browser/ui/webui/signin/inline_login_handler.h
@@ -66,8 +66,8 @@
   // from the CookieManager.
   void HandleCompleteLoginMessageWithCookies(
       const base::ListValue& args,
-      const net::CookieStatusList& cookies,
-      const net::CookieStatusList& excluded_cookies);
+      const net::CookieAccessResultList& cookies,
+      const net::CookieAccessResultList& excluded_cookies);
 
   // JS callback to switch the UI from a constrainted dialog to a full tab.
   void HandleSwitchToFullTabMessage(const base::ListValue* args);
diff --git a/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc b/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc
index b08ea97..7c3861b 100644
--- a/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc
+++ b/chrome/browser/ui/webui/signin/signin_create_profile_handler.cc
@@ -15,7 +15,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread_restrictions.h"
-#include "base/value_conversions.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_attributes_entry.h"
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index 2dea17c..d05bd705 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -18,7 +18,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "base/values.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
@@ -314,13 +314,15 @@
   if (!args->Get(0, &profile_path_value))
     return;
 
-  base::FilePath profile_path;
-  if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
+  base::Optional<base::FilePath> profile_path =
+      util::ValueToFilePath(*profile_path_value);
+  if (!profile_path)
     return;
 
   ProfileAttributesEntry* entry;
-  if (!g_browser_process->profile_manager()->GetProfileAttributesStorage().
-          GetProfileAttributesWithPath(profile_path, &entry)) {
+  if (!g_browser_process->profile_manager()
+           ->GetProfileAttributesStorage()
+           .GetProfileAttributesWithPath(*profile_path, &entry)) {
     return;
   }
 
@@ -332,7 +334,7 @@
   if (!args->GetString(2, &password))
     return;
 
-  authenticating_profile_path_ = profile_path;
+  authenticating_profile_path_ = *profile_path;
   email_address_ = base::UTF16ToUTF8(email_address);
 
   // Only try to validate locally or check the password change detection
@@ -371,7 +373,7 @@
     RecordAuthenticatedLaunchUserEvent(
         AuthenticatedLaunchUserEvent::GAIA_REAUTH_DIALOG);
     UserManagerProfileDialog::ShowUnlockDialogWithProfilePath(
-        browser_context, email_address_, profile_path);
+        browser_context, email_address_, *profile_path);
   } else if (entry->IsSigninRequired() && entry->IsSupervised()) {
     // Supervised profile will only be locked when force-sign-in is enabled
     // and it shouldn't be unlocked. Display the error message directly via
@@ -401,7 +403,7 @@
     RecordAuthenticatedLaunchUserEvent(
         AuthenticatedLaunchUserEvent::FORCED_PRIMARY_SIGNIN_DIALOG);
     UserManagerProfileDialog::ShowForceSigninDialog(browser_context,
-                                                    profile_path);
+                                                    *profile_path);
   }
 }
 
@@ -413,8 +415,9 @@
     return;
   }
 
-  base::FilePath profile_path;
-  if (!base::GetValueAsFilePath(*profile_path_value, &profile_path)) {
+  base::Optional<base::FilePath> profile_path =
+      util::ValueToFilePath(*profile_path_value);
+  if (!profile_path) {
     NOTREACHED();
     return;
   }
@@ -432,7 +435,7 @@
 
   // The callback is run if the only profile has been deleted, and a new
   // profile has been created to replace it.
-  webui::DeleteProfileAtPath(profile_path,
+  webui::DeleteProfileAtPath(*profile_path,
                              ProfileMetrics::DELETE_PROFILE_USER_MANAGER);
 }
 
@@ -466,13 +469,15 @@
   if (!args->Get(0, &profile_path_value))
     return;
 
-  base::FilePath profile_path;
-  if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
+  base::Optional<base::FilePath> profile_path =
+      util::ValueToFilePath(*profile_path_value);
+  if (!profile_path)
     return;
 
   ProfileAttributesEntry* entry;
-  if (!g_browser_process->profile_manager()->GetProfileAttributesStorage().
-          GetProfileAttributesWithPath(profile_path, &entry)) {
+  if (!g_browser_process->profile_manager()
+           ->GetProfileAttributesStorage()
+           .GetProfileAttributesWithPath(*profile_path, &entry)) {
     NOTREACHED();
     return;
   }
@@ -486,7 +491,7 @@
     return;
 
   profiles::SwitchToProfile(
-      profile_path, false, /* reuse any existing windows */
+      *profile_path, false, /* reuse any existing windows */
       base::Bind(&UserManagerScreenHandler::OnSwitchToProfileComplete,
                  weak_ptr_factory_.GetWeakPtr()));
 }
@@ -499,20 +504,20 @@
     return;
 
   base::Time start_time = base::Time::Now();
-  base::FilePath profile_path;
-
-  if (!base::GetValueAsFilePath(*profile_path_value, &profile_path))
+  base::Optional<base::FilePath> profile_path =
+      util::ValueToFilePath(*profile_path_value);
+  if (!profile_path)
     return;
 
-  base::Value return_profile_path(profile_path.value());
-  Profile* profile = g_browser_process->profile_manager()->
-      GetProfileByPath(profile_path);
+  base::Value return_profile_path(profile_path->value());
+  Profile* profile =
+      g_browser_process->profile_manager()->GetProfileByPath(*profile_path);
 
   if (profile) {
     GatherStatistics(start_time, profile);
   } else {
     g_browser_process->profile_manager()->LoadProfileByPath(
-        profile_path, false,
+        *profile_path, false,
         base::BindOnce(&UserManagerScreenHandler::GatherStatistics,
                        weak_ptr_factory_.GetWeakPtr(), start_time));
   }
@@ -796,8 +801,7 @@
     profile_value->SetString(kKeyEmailAddress, entry->GetUserName());
     profile_value->SetString(kKeyDisplayName,
                              profiles::GetAvatarNameForProfile(profile_path));
-    profile_value->SetKey(kKeyProfilePath,
-                          base::CreateFilePathValue(profile_path));
+    profile_value->SetKey(kKeyProfilePath, util::FilePathToValue(profile_path));
     profile_value->SetBoolean(kKeyPublicAccount, false);
     profile_value->SetBoolean(kKeyLegacySupervisedUser,
                               entry->IsLegacySupervised());
diff --git a/chrome/browser/web_applications/system_web_app_manager.cc b/chrome/browser/web_applications/system_web_app_manager.cc
index 0d86848..9969cea 100644
--- a/chrome/browser/web_applications/system_web_app_manager.cc
+++ b/chrome/browser/web_applications/system_web_app_manager.cc
@@ -94,9 +94,8 @@
   }
 
   if (SystemWebAppManager::IsAppEnabled(SystemAppType::CAMERA)) {
-    infos.emplace(
-        SystemAppType::CAMERA,
-        SystemAppInfo("Camera", GURL("chrome://camera-app/pwa.html")));
+    infos.emplace(SystemAppType::CAMERA,
+                  SystemAppInfo("Camera", GURL("chrome://camera/pwa.html")));
     infos.at(SystemAppType::CAMERA).uninstall_and_replace = {
         extension_misc::kCameraAppId};
   }
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.cc b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
index b798352..3397dc38 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.cc
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.cc
@@ -569,3 +569,8 @@
   have_paired_phones_ = have_paired_phones;
   qr_generator_key_ = std::move(qr_generator_key);
 }
+
+base::WeakPtr<AuthenticatorRequestDialogModel>
+AuthenticatorRequestDialogModel::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_model.h b/chrome/browser/webauthn/authenticator_request_dialog_model.h
index 496f1c13..e2c23db5 100644
--- a/chrome/browser/webauthn/authenticator_request_dialog_model.h
+++ b/chrome/browser/webauthn/authenticator_request_dialog_model.h
@@ -416,6 +416,8 @@
 
   bool offer_try_again_in_ui() const { return offer_try_again_in_ui_; }
 
+  base::WeakPtr<AuthenticatorRequestDialogModel> GetWeakPtr();
+
  private:
   // Contains the state that will be reset when calling StartOver(). StartOver()
   // might be called at an arbitrary point of execution.
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index e5fced5..6ff33889 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -156,11 +156,11 @@
       sources += [
         "$root_gen_dir/ash/public/cpp/resources/ash_public_unscaled_resources.pak",
         "$root_gen_dir/chrome/browser/supervised_user/supervised_user_unscaled_resources.pak",
+        "$root_gen_dir/chrome/camera_resources.pak",
         "$root_gen_dir/chrome/cellular_setup_resources.pak",
         "$root_gen_dir/chrome/multidevice_setup_resources.pak",
         "$root_gen_dir/chrome/network_health_resources.pak",
         "$root_gen_dir/chrome/os_settings_resources.pak",
-        "$root_gen_dir/chromeos/chromeos_camera_app_resources.pak",
         "$root_gen_dir/chromeos/chromeos_help_app_bundle_resources.pak",
         "$root_gen_dir/chromeos/chromeos_help_app_resources.pak",
         "$root_gen_dir/chromeos/chromeos_media_app_bundle_resources.pak",
@@ -173,12 +173,12 @@
       deps += [
         "//ash/public/cpp/resources:ash_public_unscaled_resources",
         "//chrome/browser/resources:os_settings_resources",
+        "//chrome/browser/resources/chromeos:camera_resources",
         "//chrome/browser/resources/chromeos:cellular_setup_resources",
         "//chrome/browser/resources/chromeos:multidevice_setup_resources",
         "//chrome/browser/resources/chromeos:network_health_resources",
         "//chrome/browser/supervised_user:supervised_user_unscaled_resources",
         "//chromeos/resources",
-        "//chromeos/resources:camera_app_resources",
         "//chromeos/resources:help_app_bundle_resources",
         "//chromeos/resources:help_app_resources",
         "//chromeos/resources:media_app_bundle_resources",
diff --git a/chrome/chrome_repack_locales.gni b/chrome/chrome_repack_locales.gni
index 9160857..f26b0f1b 100644
--- a/chrome/chrome_repack_locales.gni
+++ b/chrome/chrome_repack_locales.gni
@@ -65,7 +65,7 @@
     }
     if (is_chromeos) {
       source_patterns += [
-        "${root_gen_dir}/ash/shortcut_viewer/strings/ash_components_strings_",
+        "${root_gen_dir}/ash/shortcut_viewer/strings/shortcut_viewer_strings_",
         "${root_gen_dir}/ash/strings/ash_strings_",
         "${root_gen_dir}/chromeos/strings/chromeos_strings_",
         "${root_gen_dir}/remoting/resources/",
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index f157249f..f129800d 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -138,7 +138,6 @@
     "pdf_util.h",
     "pref_names_util.cc",
     "pref_names_util.h",
-    "prerender_messages.h",
     "prerender_url_loader_throttle.cc",
     "prerender_url_loader_throttle.h",
     "prerender_util.cc",
@@ -179,6 +178,7 @@
     "//base",
     "//base:base_static",
     "//base:i18n",
+    "//base/util/values:values_util",
     "//chrome:resources",
     "//chrome:strings",
     "//chrome/app/theme:theme_resources",
@@ -262,7 +262,8 @@
     "//components/google/core/common",
     "//components/metrics:call_stack_profile_builder",
     "//components/page_load_metrics/common:common",
-    "//components/prerender",
+    "//components/prerender/common",
+    "//components/prerender/common:mojo_bindings",
   ]
 
   if (enable_plugins) {
@@ -699,7 +700,6 @@
     "network_easter_egg.mojom",
     "open_search_description_document_handler.mojom",
     "plugin.mojom",
-    "prerender_canceler.mojom",
     "renderer_configuration.mojom",
     "sync_encryption_keys_extension.mojom",
   ]
diff --git a/chrome/common/caption.mojom b/chrome/common/caption.mojom
index 44a9a95..657f2159 100644
--- a/chrome/common/caption.mojom
+++ b/chrome/common/caption.mojom
@@ -8,8 +8,9 @@
 // the Live Caption feature.
 interface CaptionHost {
   // Called when the speech recognition client receives a transcription from the
-  // speech service.
-  OnTranscription(TranscriptionResult transcription_result);
+  // speech service. Returns whether the transcription result was received
+  // successfully. Transcriptions will halt if this returns false.
+  OnTranscription(TranscriptionResult transcription_result) => (bool success);
 };
 
 // A transcription result created by the speech recognition client in the
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 195c320..96536a0 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -54,8 +54,8 @@
                                            base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kAppServiceInstanceRegistry{
     "AppServiceInstanceRegistry", base::FEATURE_ENABLED_BY_DEFAULT};
-const base::Feature kAppServiceIntentHandling{
-    "AppServiceIntentHandling", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kAppServiceIntentHandling{"AppServiceIntentHandling",
+                                              base::FEATURE_ENABLED_BY_DEFAULT};
 #endif  // !defined(OS_ANDROID)
 
 // Enables the built-in DNS resolver.
diff --git a/chrome/common/chrome_render_frame.mojom b/chrome/common/chrome_render_frame.mojom
index dc08a008..b415788 100644
--- a/chrome/common/chrome_render_frame.mojom
+++ b/chrome/common/chrome_render_frame.mojom
@@ -49,9 +49,6 @@
   // before onload events are fired.
   ExecuteWebUIJavaScript(mojo_base.mojom.String16 javascript);
 
-  // Sent when the profile changes the kSafeBrowsingEnabled preference.
-  SetClientSidePhishingDetection(bool enable_phishing_detection);
-
   // Requests the web application info from the renderer.
   GetWebApplicationInfo() => (WebApplicationInfo web_application_info);
 
diff --git a/chrome/common/common_message_generator.h b/chrome/common/common_message_generator.h
index 45aee861e..8e1f8513 100644
--- a/chrome/common/common_message_generator.h
+++ b/chrome/common/common_message_generator.h
@@ -6,10 +6,11 @@
 
 #include "chrome/common/search/instant_mojom_traits.h"
 #include "services/network/public/cpp/p2p_param_traits.h"
-#undef CHROME_COMMON_PRERENDER_MESSAGES_H_
-#include "chrome/common/prerender_messages.h"
-#ifndef CHROME_COMMON_PRERENDER_MESSAGES_H_
-#error "Failed to include header chrome/common/prerender_messages.h"
+#undef COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
+#include "components/prerender/common/prerender_messages.h"
+#ifndef COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
+#error \
+    "Failed to include header components/prerender/common/prerender_messages.h"
 #endif
 #undef CHROME_COMMON_RENDER_MESSAGES_H_
 #include "chrome/common/render_messages.h"
diff --git a/chrome/common/custom_handlers/protocol_handler.cc b/chrome/common/custom_handlers/protocol_handler.cc
index 9afb863f..55368f4 100644
--- a/chrome/common/custom_handlers/protocol_handler.cc
+++ b/chrome/common/custom_handlers/protocol_handler.cc
@@ -7,7 +7,7 @@
 #include "base/macros.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "chrome/grit/generated_resources.h"
 #include "content/public/common/origin_util.h"
 #include "extensions/common/constants.h"
@@ -86,10 +86,11 @@
   base::Time time;
   value->GetString("protocol", &protocol);
   value->GetString("url", &url);
-  const base::Value* time_value = value->FindKey("last_modified");
+  base::Optional<base::Time> time_value =
+      util::ValueToTime(value->FindKey("last_modified"));
   // Treat invalid times as the default value.
   if (time_value)
-    ignore_result(base::GetValueAsTime(*time_value, &time));
+    time = *time_value;
   return ProtocolHandler(protocol, GURL(url), time);
 }
 
@@ -105,7 +106,7 @@
   auto d = std::make_unique<base::DictionaryValue>();
   d->SetString("protocol", protocol_);
   d->SetString("url", url_.spec());
-  d->SetKey("last_modified", base::CreateTimeValue(last_modified_));
+  d->SetKey("last_modified", util::TimeToValue(last_modified_));
   return d;
 }
 
diff --git a/chrome/common/features.gni b/chrome/common/features.gni
index 98afaf33..91d3c7c3 100644
--- a/chrome/common/features.gni
+++ b/chrome/common/features.gni
@@ -51,9 +51,6 @@
   enable_one_click_signin =
       is_win || is_mac || (is_linux && !is_chromeos && !is_chromecast)
 
-  # Enables password change in leaked password dialog, disabled by default.
-  enable_password_change_in_leaked_dialog = false
-
   enable_service_discovery = (enable_mdns && !is_android) || is_mac
 
   # Enables use of the session service, which is enabled by default.
diff --git a/chrome/common/media_router/media_source.cc b/chrome/common/media_router/media_source.cc
index 593c5473..1f7dd3f 100644
--- a/chrome/common/media_router/media_source.cc
+++ b/chrome/common/media_router/media_source.cc
@@ -155,4 +155,16 @@
   return IsDialSource() ? url_.path() : "";
 }
 
+std::string MediaSource::TruncateForLogging(size_t max_length) const {
+  const std::string origin = url_.GetOrigin().spec();
+  if (!origin.empty())
+    return origin.substr(0, max_length);
+  // TODO(takumif): Keep the query string by redacting PII. The query string may
+  // contain info useful for debugging such as the required capabilities.
+  const size_t query_start_index = id_.find("?");
+  const size_t length =
+      query_start_index == std::string::npos ? max_length : query_start_index;
+  return id_.substr(0, length);
+}
+
 }  // namespace media_router
diff --git a/chrome/common/media_router/media_source.h b/chrome/common/media_router/media_source.h
index ca713f1..6fdbea9 100644
--- a/chrome/common/media_router/media_source.h
+++ b/chrome/common/media_router/media_source.h
@@ -143,6 +143,9 @@
   // valid DIAL media source.
   std::string AppNameFromDialSource() const;
 
+  // Returns a shortened copy of the media source ID suitable for logging.
+  std::string TruncateForLogging(size_t max_length) const;
+
  private:
   MediaSource::Id id_;
   GURL url_;
diff --git a/chrome/common/media_router/mojom/BUILD.gn b/chrome/common/media_router/mojom/BUILD.gn
index 7463f07..479097a 100644
--- a/chrome/common/media_router/mojom/BUILD.gn
+++ b/chrome/common/media_router/mojom/BUILD.gn
@@ -4,6 +4,11 @@
 
 import("//mojo/public/tools/bindings/mojom.gni")
 
+mojom("logger") {
+  sources = [ "logger.mojom" ]
+  public_deps = [ "//mojo/public/mojom/base" ]
+}
+
 mojom("media_controller") {
   sources = [
     "media_controller.mojom",
diff --git a/chrome/common/media_router/mojom/logger.mojom b/chrome/common/media_router/mojom/logger.mojom
new file mode 100644
index 0000000..340062e
--- /dev/null
+++ b/chrome/common/media_router/mojom/logger.mojom
@@ -0,0 +1,53 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module media_router.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+
+enum LogCategory {
+  kDiscovery,
+  kRoute,
+  kMirroring,
+  kUi,
+};
+
+// Collects logs from Media Router components such as Media Route Providers.
+// The implementation lives in the browser process.
+interface Logger {
+  // Records a log entry of "info" severity. The severities are "info",
+  // "warning", and "error" in increasing order.
+  // |component|: This is usually the name of the class that is emitting the
+  //     log, such as "CastSessionTracker".
+  // |message|: The log message.
+  // |sink_id|: ID of the media sink associated with this log. May be empty if
+  //     the log is not associated with a sink.
+  // |media_source|: ID of the media source, which may be of the format
+  //     "cast:ABCDEFGH?arg1=val1" (app ID and query params) for Cast sessions,
+  //     or the receiver page URL in the case of presentations. May be empty.
+  // |session_id|: ID of the Cast or presentation session associated with this
+  //     log. May be empty.
+  LogInfo(LogCategory category,
+      string component,
+      string message,
+      string sink_id,
+      string media_source,
+      string session_id);
+
+  // Records a log entry of "warning" severity.
+  LogWarning(LogCategory category,
+      string component,
+      string message,
+      string sink_id,
+      string media_source,
+      string session_id);
+
+  // Records a log entry of "error" severity.
+  LogError(LogCategory category,
+      string component,
+      string message,
+      string sink_id,
+      string media_source,
+      string session_id);
+};
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index a1961d58..9b102a8 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1662,6 +1662,10 @@
 // ask the user where they want to download the file (only for Android).
 const char kPromptForDownloadAndroid[] = "download.prompt_for_download_android";
 
+// The prompt status for the download later dialog.
+const char kDownloadLaterPromptStatus[] =
+    "download.download_later_prompt_status";
+
 // Boolean which specifies whether we should display the missing SD card error.
 // This is only applicable for Android.
 const char kShowMissingSdCardErrorAndroid[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index df3fc650..1616466 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -555,6 +555,7 @@
 #endif
 #if defined(OS_ANDROID)
 extern const char kPromptForDownloadAndroid[];
+extern const char kDownloadLaterPromptStatus[];
 extern const char kShowMissingSdCardErrorAndroid[];
 #endif
 
diff --git a/chrome/common/prerender_url_loader_throttle.cc b/chrome/common/prerender_url_loader_throttle.cc
index 96c33d2..924587a 100644
--- a/chrome/common/prerender_url_loader_throttle.cc
+++ b/chrome/common/prerender_url_loader_throttle.cc
@@ -24,9 +24,11 @@
 const char kPurposeHeaderValue[] = "prefetch";
 
 void CallCancelPrerenderForUnsupportedScheme(
-    mojo::PendingRemote<chrome::mojom::PrerenderCanceler> canceler,
+    mojo::PendingRemote<components::prerender::common::mojom::PrerenderCanceler>
+        canceler,
     const GURL& url) {
-  mojo::Remote<chrome::mojom::PrerenderCanceler>(std::move(canceler))
+  mojo::Remote<components::prerender::common::mojom::PrerenderCanceler>(
+      std::move(canceler))
       ->CancelPrerenderForUnsupportedScheme(url);
 }
 
@@ -41,7 +43,8 @@
 PrerenderURLLoaderThrottle::PrerenderURLLoaderThrottle(
     PrerenderMode mode,
     const std::string& histogram_prefix,
-    mojo::PendingRemote<chrome::mojom::PrerenderCanceler> canceler)
+    mojo::PendingRemote<components::prerender::common::mojom::PrerenderCanceler>
+        canceler)
     : mode_(mode),
       histogram_prefix_(histogram_prefix),
       canceler_(std::move(canceler)) {
diff --git a/chrome/common/prerender_url_loader_throttle.h b/chrome/common/prerender_url_loader_throttle.h
index b238e4b..1e8b1e9 100644
--- a/chrome/common/prerender_url_loader_throttle.h
+++ b/chrome/common/prerender_url_loader_throttle.h
@@ -10,8 +10,8 @@
 #include "base/optional.h"
 #include "base/sequenced_task_runner.h"
 #include "base/timer/timer.h"
-#include "chrome/common/prerender_canceler.mojom.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_canceler.mojom.h"
+#include "components/prerender/common/prerender_types.h"
 #include "net/base/request_priority.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
@@ -25,7 +25,8 @@
   PrerenderURLLoaderThrottle(
       PrerenderMode mode,
       const std::string& histogram_prefix,
-      mojo::PendingRemote<chrome::mojom::PrerenderCanceler> canceler);
+      mojo::PendingRemote<
+          components::prerender::common::mojom::PrerenderCanceler> canceler);
   ~PrerenderURLLoaderThrottle() override;
 
   // Called when the prerender is used. This will unpaused requests and set the
@@ -61,7 +62,8 @@
   int redirect_count_ = 0;
   blink::mojom::ResourceType resource_type_;
 
-  mojo::PendingRemote<chrome::mojom::PrerenderCanceler> canceler_;
+  mojo::PendingRemote<components::prerender::common::mojom::PrerenderCanceler>
+      canceler_;
 
   // The throttle changes most request priorities to IDLE during prerendering.
   // The priority is reset back to the original priority when prerendering is
diff --git a/chrome/common/prerender_util.h b/chrome/common/prerender_util.h
index 9b2d00e..a7dacaf 100644
--- a/chrome/common/prerender_util.h
+++ b/chrome/common/prerender_util.h
@@ -7,7 +7,7 @@
 
 #include <string>
 
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 
 class GURL;
 
diff --git a/chrome/common/service_process_util.cc b/chrome/common/service_process_util.cc
index 7e9b588..58a0b0f 100644
--- a/chrome/common/service_process_util.cc
+++ b/chrome/common/service_process_util.cc
@@ -153,7 +153,7 @@
   return command_line;
 }
 
-ServiceProcessState::ServiceProcessState() : state_(NULL) {
+ServiceProcessState::ServiceProcessState() : state_(nullptr) {
   autorun_command_line_ = CreateServiceProcessCommandLine();
   CreateState();
 }
diff --git a/chrome/common/string_matching/BUILD.gn b/chrome/common/string_matching/BUILD.gn
index 183a9ed..db312bb 100644
--- a/chrome/common/string_matching/BUILD.gn
+++ b/chrome/common/string_matching/BUILD.gn
@@ -9,6 +9,8 @@
   sources = [
     "fuzzy_tokenized_string_match.cc",
     "fuzzy_tokenized_string_match.h",
+    "prefix_matcher.cc",
+    "prefix_matcher.h",
     "sequence_matcher.cc",
     "sequence_matcher.h",
     "term_break_iterator.cc",
diff --git a/chrome/common/string_matching/prefix_matcher.cc b/chrome/common/string_matching/prefix_matcher.cc
new file mode 100644
index 0000000..9d2eaba
--- /dev/null
+++ b/chrome/common/string_matching/prefix_matcher.cc
@@ -0,0 +1,133 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/common/string_matching/prefix_matcher.h"
+
+#include "base/check.h"
+#include "base/macros.h"
+#include "chrome/common/string_matching/tokenized_string.h"
+#include "chrome/common/string_matching/tokenized_string_char_iterator.h"
+
+namespace {
+// The factors below are applied when the current char of query matches
+// the current char of the text to be matched. Different factors are chosen
+// based on where the match happens. kIsPrefixMultiplier is used when the
+// matched portion is a prefix of both the query and the text, which implies
+// that the matched chars are at the same position in query and text. This is
+// the most preferred case thus it has the highest score. When the current char
+// of the query and the text does not match, the algorithm moves to the next
+// token in the text and try to match from there. kIsFrontOfWordMultipler will
+// be used if the first char of the token matches the current char of the query.
+// Otherwise, the match is considered as weak and kIsWeakHitMultiplier is
+// used.
+// Examples:
+//   Suppose the text to be matched is 'Google Chrome'.
+//   Query 'go' would yield kIsPrefixMultiplier for each char.
+//   Query 'gc' would use kIsPrefixMultiplier for 'g' and
+//       kIsFrontOfWordMultipler for 'c'.
+//   Query 'ch' would use kIsFrontOfWordMultipler for 'c' and
+//       kIsWeakHitMultiplier for 'h'.
+const double kIsPrefixMultiplier = 1.0;
+const double kIsFrontOfWordMultipler = 0.8;
+const double kIsWeakHitMultiplier = 0.6;
+
+// A relevance score that represents no match.
+const double kNoMatchScore = 0.0;
+}  // namespace
+
+PrefixMatcher::PrefixMatcher(const TokenizedString& query,
+                             const TokenizedString& text)
+    : query_iter_(query),
+      text_iter_(text),
+      current_match_(gfx::Range::InvalidRange()),
+      current_relevance_(kNoMatchScore) {}
+
+bool PrefixMatcher::Match() {
+  while (!RunMatch()) {
+    // No match found and no more states to try. Bail out.
+    if (states_.empty()) {
+      current_relevance_ = kNoMatchScore;
+      current_hits_.clear();
+      return false;
+    }
+
+    PopState();
+
+    // Skip restored match to try other possibilities.
+    AdvanceToNextTextToken();
+  }
+
+  if (current_match_.IsValid())
+    current_hits_.push_back(current_match_);
+
+  return true;
+}
+
+PrefixMatcher::State::State() : relevance(kNoMatchScore) {}
+PrefixMatcher::State::~State() = default;
+PrefixMatcher::State::State(double relevance,
+                            const gfx::Range& current_match,
+                            const Hits& hits,
+                            const TokenizedStringCharIterator& query_iter,
+                            const TokenizedStringCharIterator& text_iter)
+    : relevance(relevance),
+      current_match(current_match),
+      hits(hits.begin(), hits.end()),
+      query_iter_state(query_iter.GetState()),
+      text_iter_state(text_iter.GetState()) {}
+PrefixMatcher::State::State(const PrefixMatcher::State& state) = default;
+
+bool PrefixMatcher::RunMatch() {
+  while (!query_iter_.end() && !text_iter_.end()) {
+    if (query_iter_.Get() == text_iter_.Get()) {
+      PushState();
+
+      if (query_iter_.GetArrayPos() == text_iter_.GetArrayPos())
+        current_relevance_ += kIsPrefixMultiplier;
+      else if (text_iter_.IsFirstCharOfToken())
+        current_relevance_ += kIsFrontOfWordMultipler;
+      else
+        current_relevance_ += kIsWeakHitMultiplier;
+
+      if (!current_match_.IsValid())
+        current_match_.set_start(text_iter_.GetArrayPos());
+      current_match_.set_end(text_iter_.GetArrayPos() +
+                             text_iter_.GetCharSize());
+
+      query_iter_.NextChar();
+      text_iter_.NextChar();
+    } else {
+      AdvanceToNextTextToken();
+    }
+  }
+
+  return query_iter_.end();
+}
+
+void PrefixMatcher::AdvanceToNextTextToken() {
+  if (current_match_.IsValid()) {
+    current_hits_.push_back(current_match_);
+    current_match_ = gfx::Range::InvalidRange();
+  }
+
+  text_iter_.NextToken();
+}
+
+void PrefixMatcher::PushState() {
+  states_.push_back(State(current_relevance_, current_match_, current_hits_,
+                          query_iter_, text_iter_));
+}
+
+void PrefixMatcher::PopState() {
+  DCHECK(!states_.empty());
+
+  State& last_match = states_.back();
+  current_relevance_ = last_match.relevance;
+  current_match_ = last_match.current_match;
+  current_hits_.swap(last_match.hits);
+  query_iter_.SetState(last_match.query_iter_state);
+  text_iter_.SetState(last_match.text_iter_state);
+
+  states_.pop_back();
+}
diff --git a/chrome/common/string_matching/prefix_matcher.h b/chrome/common/string_matching/prefix_matcher.h
new file mode 100644
index 0000000..42f1752
--- /dev/null
+++ b/chrome/common/string_matching/prefix_matcher.h
@@ -0,0 +1,81 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_COMMON_STRING_MATCHING_PREFIX_MATCHER_H_
+#define CHROME_COMMON_STRING_MATCHING_PREFIX_MATCHER_H_
+
+#include "chrome/common/string_matching/tokenized_string.h"
+
+#include "chrome/common/string_matching/tokenized_string_char_iterator.h"
+
+// PrefixMatcher matches the chars of a given query as prefix of tokens in
+// a given text or as prefix of the acronyms of those text tokens.
+class PrefixMatcher {
+ public:
+  typedef std::vector<gfx::Range> Hits;
+  PrefixMatcher(const TokenizedString& query, const TokenizedString& text);
+
+  // Invokes RunMatch to perform prefix match. Use |states_| as a stack to
+  // perform DFS (depth first search) so that all possible matches are
+  // attempted. Stops on the first full match and returns true. Otherwise,
+  // returns false to indicate no match.
+  bool Match();
+
+  double relevance() const { return current_relevance_; }
+  const Hits& hits() const { return current_hits_; }
+
+ private:
+  // Context record of a match.
+  struct State {
+    State();
+    ~State();
+    State(double relevance,
+          const gfx::Range& current_match,
+          const Hits& hits,
+          const TokenizedStringCharIterator& query_iter,
+          const TokenizedStringCharIterator& text_iter);
+    State(const State& state);
+
+    // The current score of the processed query chars.
+    double relevance;
+
+    // Current matching range.
+    gfx::Range current_match;
+
+    // Completed matching ranges of the processed query chars.
+    PrefixMatcher::Hits hits;
+
+    // States of the processed query and text chars.
+    TokenizedStringCharIterator::State query_iter_state;
+    TokenizedStringCharIterator::State text_iter_state;
+  };
+  typedef std::vector<State> States;
+
+  // Match chars from the query and text one by one. For each matching char,
+  // calculate relevance and matching ranges. And the current stats is
+  // recorded so that the match could be skipped later to try other
+  // possibilities. Repeat until any of the iterators run out. Return true if
+  // query iterator runs out, i.e. all chars in query are matched.
+  bool RunMatch();
+
+  // Skip to the next text token and close current match. Invoked when a
+  // mismatch happens or to skip a restored match.
+  void AdvanceToNextTextToken();
+
+  void PushState();
+  void PopState();
+
+  TokenizedStringCharIterator query_iter_;
+  TokenizedStringCharIterator text_iter_;
+
+  States states_;
+  gfx::Range current_match_;
+
+  double current_relevance_;
+  Hits current_hits_;
+
+  DISALLOW_COPY_AND_ASSIGN(PrefixMatcher);
+};
+
+#endif  // CHROME_COMMON_STRING_MATCHING_PREFIX_MATCHER_H_
diff --git a/chrome/common/string_matching/tokenized_string_match.cc b/chrome/common/string_matching/tokenized_string_match.cc
index 0545cb1..57c1c5d 100644
--- a/chrome/common/string_matching/tokenized_string_match.cc
+++ b/chrome/common/string_matching/tokenized_string_match.cc
@@ -8,183 +8,16 @@
 
 #include <cmath>
 
-#include "base/check.h"
 #include "base/i18n/string_search.h"
-#include "base/macros.h"
 #include "base/strings/string_util.h"
-#include "chrome/common/string_matching/tokenized_string_char_iterator.h"
+#include "chrome/common/string_matching/prefix_matcher.h"
 
 namespace {
-
-// The factors below are applied when the current char of query matches
-// the current char of the text to be matched. Different factors are chosen
-// based on where the match happens. kIsPrefixMultiplier is used when the
-// matched portion is a prefix of both the query and the text, which implies
-// that the matched chars are at the same position in query and text. This is
-// the most preferred case thus it has the highest score. When the current char
-// of the query and the text does not match, the algorithm moves to the next
-// token in the text and try to match from there. kIsFrontOfWordMultipler will
-// be used if the first char of the token matches the current char of the query.
-// Otherwise, the match is considered as weak and kIsWeakHitMultiplier is
-// used.
-// Examples:
-//   Suppose the text to be matched is 'Google Chrome'.
-//   Query 'go' would yield kIsPrefixMultiplier for each char.
-//   Query 'gc' would use kIsPrefixMultiplier for 'g' and
-//       kIsFrontOfWordMultipler for 'c'.
-//   Query 'ch' would use kIsFrontOfWordMultipler for 'c' and
-//       kIsWeakHitMultiplier for 'h'.
-//   Query 'oo' does not match any prefix and would use the substring match
-//       fallback, thus kIsSubstringMultiplier is used for each char.
-const double kIsPrefixMultiplier = 1.0;
-const double kIsFrontOfWordMultipler = 0.8;
-const double kIsWeakHitMultiplier = 0.6;
+// Used for each character if there is no prefix match.
 const double kIsSubstringMultiplier = 0.4;
 
 // A relevance score that represents no match.
 const double kNoMatchScore = 0.0;
-
-// PrefixMatcher matches the chars of a given query as prefix of tokens in
-// a given text or as prefix of the acronyms of those text tokens.
-class PrefixMatcher {
- public:
-  PrefixMatcher(const TokenizedString& query, const TokenizedString& text)
-      : query_iter_(query),
-        text_iter_(text),
-        current_match_(gfx::Range::InvalidRange()),
-        current_relevance_(kNoMatchScore) {}
-
-  // Invokes RunMatch to perform prefix match. Use |states_| as a stack to
-  // perform DFS (depth first search) so that all possible matches are
-  // attempted. Stops on the first full match and returns true. Otherwise,
-  // returns false to indicate no match.
-  bool Match() {
-    while (!RunMatch()) {
-      // No match found and no more states to try. Bail out.
-      if (states_.empty()) {
-        current_relevance_ = kNoMatchScore;
-        current_hits_.clear();
-        return false;
-      }
-
-      PopState();
-
-      // Skip restored match to try other possibilites.
-      AdvanceToNextTextToken();
-    }
-
-    if (current_match_.IsValid())
-      current_hits_.push_back(current_match_);
-
-    return true;
-  }
-
-  double relevance() const { return current_relevance_; }
-  const TokenizedStringMatch::Hits& hits() const { return current_hits_; }
-
- private:
-  // Context record of a match.
-  struct State {
-    State() : relevance(kNoMatchScore) {}
-    State(double relevance,
-          const gfx::Range& current_match,
-          const TokenizedStringMatch::Hits& hits,
-          const TokenizedStringCharIterator& query_iter,
-          const TokenizedStringCharIterator& text_iter)
-        : relevance(relevance),
-          current_match(current_match),
-          hits(hits.begin(), hits.end()),
-          query_iter_state(query_iter.GetState()),
-          text_iter_state(text_iter.GetState()) {}
-
-    // The current score of the processed query chars.
-    double relevance;
-
-    // Current matching range.
-    gfx::Range current_match;
-
-    // Completed matching ranges of the processed query chars.
-    TokenizedStringMatch::Hits hits;
-
-    // States of the processed query and text chars.
-    TokenizedStringCharIterator::State query_iter_state;
-    TokenizedStringCharIterator::State text_iter_state;
-  };
-  typedef std::vector<State> States;
-
-  // Match chars from the query and text one by one. For each matching char,
-  // calculate relevance and matching ranges. And the current stats is
-  // recorded so that the match could be skipped later to try other
-  // possiblities. Repeat until any of the iterators run out. Return true if
-  // query iterator runs out, i.e. all chars in query are matched.
-  bool RunMatch() {
-    while (!query_iter_.end() && !text_iter_.end()) {
-      if (query_iter_.Get() == text_iter_.Get()) {
-        PushState();
-
-        if (query_iter_.GetArrayPos() == text_iter_.GetArrayPos())
-          current_relevance_ += kIsPrefixMultiplier;
-        else if (text_iter_.IsFirstCharOfToken())
-          current_relevance_ += kIsFrontOfWordMultipler;
-        else
-          current_relevance_ += kIsWeakHitMultiplier;
-
-        if (!current_match_.IsValid())
-          current_match_.set_start(text_iter_.GetArrayPos());
-        current_match_.set_end(text_iter_.GetArrayPos() +
-                               text_iter_.GetCharSize());
-
-        query_iter_.NextChar();
-        text_iter_.NextChar();
-      } else {
-        AdvanceToNextTextToken();
-      }
-    }
-
-    return query_iter_.end();
-  }
-
-  // Skip to the next text token and close current match. Invoked when a
-  // mismatch happens or to skip a restored match.
-  void AdvanceToNextTextToken() {
-    if (current_match_.IsValid()) {
-      current_hits_.push_back(current_match_);
-      current_match_ = gfx::Range::InvalidRange();
-    }
-
-    text_iter_.NextToken();
-  }
-
-  void PushState() {
-    states_.push_back(State(current_relevance_, current_match_, current_hits_,
-                            query_iter_, text_iter_));
-  }
-
-  void PopState() {
-    DCHECK(!states_.empty());
-
-    State& last_match = states_.back();
-    current_relevance_ = last_match.relevance;
-    current_match_ = last_match.current_match;
-    current_hits_.swap(last_match.hits);
-    query_iter_.SetState(last_match.query_iter_state);
-    text_iter_.SetState(last_match.text_iter_state);
-
-    states_.pop_back();
-  }
-
-  TokenizedStringCharIterator query_iter_;
-  TokenizedStringCharIterator text_iter_;
-
-  States states_;
-  gfx::Range current_match_;
-
-  double current_relevance_;
-  TokenizedStringMatch::Hits current_hits_;
-
-  DISALLOW_COPY_AND_ASSIGN(PrefixMatcher);
-};
-
 }  // namespace
 
 TokenizedStringMatch::TokenizedStringMatch() : relevance_(kNoMatchScore) {}
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 8b63fe5..65f780e 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -28,6 +28,7 @@
 const char kChromeUIBluetoothInternalsHost[] = "bluetooth-internals";
 const char kChromeUIBookmarksHost[] = "bookmarks";
 const char kChromeUIBookmarksURL[] = "chrome://bookmarks/";
+const char kChromeUICameraHost[] = "camera";
 const char kChromeUICertificateViewerHost[] = "view-cert";
 const char kChromeUICertificateViewerURL[] = "chrome://view-cert/";
 const char kChromeUIChromeSigninHost[] = "chrome-signin";
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index ca80dbb..e5d95de 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -36,6 +36,7 @@
 extern const char kChromeUIBluetoothInternalsHost[];
 extern const char kChromeUIBookmarksHost[];
 extern const char kChromeUIBookmarksURL[];
+extern const char kChromeUICameraHost[];
 extern const char kChromeUICertificateViewerHost[];
 extern const char kChromeUICertificateViewerURL[];
 extern const char kChromeUIChromeSigninHost[];
diff --git a/chrome/installer/linux/BUILD.gn b/chrome/installer/linux/BUILD.gn
index b101b0cb..cc49b74b 100644
--- a/chrome/installer/linux/BUILD.gn
+++ b/chrome/installer/linux/BUILD.gn
@@ -24,7 +24,7 @@
   enable_distro_version_check = true
 
   # Enable building snap packages
-  enable_snap_package = false
+  enable_snap_package = is_official_build
 }
 
 assert(is_linux)
diff --git a/chrome/installer/linux/snap/build.sh b/chrome/installer/linux/snap/build.sh
index ce37c98..6e4e65a 100755
--- a/chrome/installer/linux/snap/build.sh
+++ b/chrome/installer/linux/snap/build.sh
@@ -56,9 +56,9 @@
 if [ "$SNAPNAME" = "google-chrome" ]; then
   LOGO="product_logo_256"
   if [ "$CHANNEL" = "beta" ]; then
-    sed -i -e "s:$LOGO.png:$LOGO_beta.png:" "${TMPFILEDIR}/snapcraft.yaml"
+    sed -i -e "s:$LOGO.png:${LOGO}_beta.png:" "${TMPFILEDIR}/snapcraft.yaml"
   elif [ "$CHANNEL" = "unstable" ]; then
-    sed -i -e "s:$LOGO.png:$LOGO_dev.png:" "${TMPFILEDIR}/snapcraft.yaml"
+    sed -i -e "s:$LOGO.png:${LOGO}_dev.png:" "${TMPFILEDIR}/snapcraft.yaml"
   fi
 fi
 
diff --git a/chrome/installer/mac/keystone_install.sh b/chrome/installer/mac/keystone_install.sh
index 15c162a..5b165a4d 100755
--- a/chrome/installer/mac/keystone_install.sh
+++ b/chrome/installer/mac/keystone_install.sh
@@ -595,10 +595,9 @@
 
   trap cleanup EXIT HUP INT QUIT TERM
 
-  readonly PRODUCT_NAME="Google Chrome"
-  readonly APP_DIR="${PRODUCT_NAME}.app"
-  readonly ALTERNATE_APP_DIR="${PRODUCT_NAME} Canary.app"
-  readonly FRAMEWORK_NAME="${PRODUCT_NAME} Framework"
+  readonly APP_DIR_NAMES=( "Google Chrome.app" "Google Chrome Beta.app"
+                           "Google Chrome Dev.app" "Google Chrome Canary.app" )
+  readonly FRAMEWORK_NAME="Google Chrome Framework"
   readonly FRAMEWORK_DIR="${FRAMEWORK_NAME}.framework"
   readonly PATCH_DIR=".patch"
   readonly CONTENTS_DIR="Contents"
@@ -617,6 +616,7 @@
   readonly KS_PRODUCT_KEY="KSProductID"
   readonly KS_URL_KEY="KSUpdateURL"
   readonly KS_BRAND_KEY="KSBrandID"
+  readonly USER_DATA_DIR_PATH_KEY="CrProductDirName"
 
   readonly QUARANTINE_ATTR="com.apple.quarantine"
 
@@ -705,7 +705,22 @@
 
   local update_version_app update_version_ks product_id update_layout_new
   if [[ -z "${is_patch}" ]]; then
-    update_app="${update_dmg_mount_point}/${APP_DIR}"
+    local found_app
+    for app_dir_name in "${APP_DIR_NAMES[@]}"; do
+      note "looking for ${app_dir_name}"
+      update_app="${update_dmg_mount_point}/${app_dir_name}"
+
+      if [[ -d "${update_app}" ]]; then
+        note "found ${app_dir_name}"
+        found_app="y"
+        break
+      fi
+    done
+
+    if [[ -z "${found_app}" ]]; then
+      err "couldn't locate any app on the update dmg"
+      exit 2
+    fi
     note "update_app = ${update_app}"
 
     # Make sure that it's an absolute path.
@@ -714,22 +729,6 @@
       exit 2
     fi
 
-    # Make sure there's something to copy from.
-    if ! [[ -d "${update_app}" ]]; then
-      update_app="${update_dmg_mount_point}/${ALTERNATE_APP_DIR}"
-      note "update_app = ${update_app}"
-
-      if [[ "${update_app:0:1}" != "/" ]]; then
-        err "update_app (alternate) must be an absolute path"
-        exit 2
-      fi
-
-      if ! [[ -d "${update_app}" ]]; then
-        err "update_app must be a directory"
-        exit 2
-      fi
-    fi
-
     # Get some information about the update.
     note "reading update values"
 
@@ -1120,8 +1119,12 @@
     # exists, and ${installed_app} needs to be used as input to dirpatcher
     # in any event.  The new application will be rsynced into place once
     # dirpatcher creates it.
+
     ensure_temp_dir
-    update_app="${g_temp_dir}/${APP_DIR}"
+    # The name of the app for ${update_app} does not matter, as the user's
+    # choice of name for their installed app will not be changed. Choose the
+    # first of the ${APP_DIR_NAMES} as an arbitrary choice.
+    update_app="${g_temp_dir}/${APP_DIR_NAMES[0]}"
     note "update_app = ${update_app}"
 
     note "dirpatching app directory"
@@ -1249,6 +1252,13 @@
   note "tag = ${tag}"
   note "tag_key = ${tag_key}"
 
+  # The user data dir path key is only present for some Chromes.  Suppress
+  # stderr to prevent Keystone from seeing possible error output.
+  local is_sxs_capable
+  is_sxs_capable="$(infoplist_read "${installed_app_plist}" \
+      "${USER_DATA_DIR_PATH_KEY}" 2> /dev/null || true)"
+  note "is_sxs_capable = ${is_sxs_capable}"
+
   # Make sure that the update was successful by comparing the version found in
   # the update with the version now on disk.
   if [[ "${new_version_ks}" != "${update_version_ks}" ]]; then
@@ -1291,19 +1301,19 @@
   local ksadmin_brand_plist_path
   local ksadmin_brand_key
 
-  # Only the stable channel, identified by an empty channel string, has a
-  # brand code. On the beta and dev channels, remove the brand plist if
-  # present. Its presence means that the ticket used to manage a
-  # stable-channel Chrome but the user has since replaced it with a beta or
-  # dev channel version. Since the canary channel can run side-by-side with
-  # another Chrome installation, don't remove the brand plist on that channel,
-  # but skip the rest of the brand logic.
-  if [[ "${channel}" = "beta" ]] || [[ "${channel}" = "dev" ]]; then
+  # Only side-by-side capable channels, either the stable channel (identified by
+  # an empty channel string) or a Chrome that has a custom user data dir, has a
+  # brand code. On non-side-by-side beta and dev channels, remove the brand
+  # plist if present. Its presence means that the ticket used to manage a
+  # stable-channel Chrome but the user has since replaced it with a beta or dev
+  # channel version. With side-by-side channels, don't remove the brand plist on
+  # that channel, but skip the rest of the brand logic.
+  if [[ -n "${is_sxs_capable}" ]]; then
+    # Side-by-side capable Chrome.
+    note "skipping brand code on side-by-side channel ${channel}"
+  elif [[ "${channel}" = "beta" ]] || [[ "${channel}" = "dev" ]]; then
     note "defeating brand code on channel ${channel}"
     rm -f "${brand_plist_path}" 2>/dev/null || true
-  elif [[ -n "${channel}" ]]; then
-    # Canary channel.
-    note "skipping brand code on channel ${channel}"
   else
     # Stable channel.
     # If the user manually updated their copy of Chrome, there might be new
diff --git a/chrome/installer/mac/keystone_install_test.sh b/chrome/installer/mac/keystone_install_test.sh
index bc49c32..4392ae9a 100755
--- a/chrome/installer/mac/keystone_install_test.sh
+++ b/chrome/installer/mac/keystone_install_test.sh
@@ -18,9 +18,9 @@
 fi
 
 # What I test
-PRODNAME="Google Chrome"
-APPNAME="${PRODNAME}.app"
-FWKNAME="${PRODNAME} Framework.framework"
+APPNAME_STABLE="Google Chrome.app"
+APPNAME_CANARY="Google Chrome Canary.app"
+FWKNAME="Google Chrome Framework.framework"
 
 # The version number for fake ksadmin to pretend to be
 KSADMIN_VERSION_LIE="1.0.7.1306"
@@ -38,16 +38,21 @@
 # Run the installer and make sure it fails.
 # If it succeeds, we fail.
 # Arg0: string to print
+# Arg1: expected error code
 function fail_installer() {
   echo $1
   "${INSTALLER}" "${TEMPDIR}" >& /dev/null
   RETURN=$?
   if [ $RETURN -eq 0 ]; then
-    echo "Did not fail (which is a failure)" >& 2
+    echo "  Did not fail (which is a failure)" >& 2
+    cleanup_tempdir
+    exit 1
+  elif [[ $RETURN -ne $2 ]]; then
+    echo "  Failed with unexpected return code ${RETURN} rather than $2" >& 2
     cleanup_tempdir
     exit 1
   else
-    echo "Returns $RETURN"
+    echo "  Successfully failed with return code ${RETURN}"
   fi
 }
 
@@ -58,11 +63,11 @@
   "${INSTALLER}" "${TEMPDIR}" >& /dev/null
   RETURN=$?
   if [ $RETURN -ne 0 ]; then
-    echo "FAILED; returned $RETURN but should have worked" >& 2
+    echo "  FAILED; returned $RETURN but should have worked" >& 2
     cleanup_tempdir
     exit 1
   else
-    echo "worked"
+    echo "  Succeeded"
   fi
 }
 
@@ -113,49 +118,62 @@
 }
 
 # Make a simple source directory - the update that is to be applied
+# Arg0: the name of the application directory
 function make_src() {
+  local appname="${1}"
+
   chmod ugo+w "${TEMPDIR}"
-  rm -rf "${TEMPDIR}/${APPNAME}"
-  RSRCDIR="${TEMPDIR}/${APPNAME}/Contents/Versions/1/${FWKNAME}/Resources"
+  rm -rf "${TEMPDIR}/${APPNAME_STABLE}"
+  rm -rf "${TEMPDIR}/${APPNAME_CANARY}"
+  RSRCDIR="${TEMPDIR}/${appname}/Contents/Versions/1/${FWKNAME}/Resources"
   mkdir -p "${RSRCDIR}"
-  defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \
+  defaults write "${TEMPDIR}/${appname}/Contents/Info" \
       CFBundleShortVersionString "1"
-  defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \
+  defaults write "${TEMPDIR}/${appname}/Contents/Info" \
       KSProductID "com.google.Chrome"
-  defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" \
+  defaults write "${TEMPDIR}/${appname}/Contents/Info" \
       KSVersion "2"
 }
 
 function make_basic_src_and_dest() {
-  make_src
+  make_src "${APPNAME_STABLE}"
   make_new_dest
 }
 
-fail_installer "No source anything"
+fail_installer "No source anything" 2
 
-mkdir "${TEMPDIR}"/"${APPNAME}"
-fail_installer "No source bundle"
+mkdir "${TEMPDIR}"/"${APPNAME_STABLE}"
+fail_installer "No source bundle" 2
 
 make_basic_src_and_dest
 chmod ugo-w "${TEMPDIR}"
-fail_installer "Writable dest directory"
+fail_installer "Writable dest directory" 9
 
 make_basic_src_and_dest
-fail_installer "Was no KSUpdateURL in dest after copy"
+fail_installer "Was no KSUpdateURL in dest after copy" 9
 
 make_basic_src_and_dest
-defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" KSUpdateURL "http://foobar"
+defaults write "${TEMPDIR}/${APPNAME_STABLE}/Contents/Info" \
+    KSUpdateURL "http://foobar"
 export FAKE_SYSTEM_TICKET=1
-fail_installer "User and system ticket both present"
+fail_installer "User and system ticket both present" 4
 export -n FAKE_SYSTEM_TICKET
 
-make_src
+make_src "${APPNAME_STABLE}"
 make_old_dest
-defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" KSUpdateURL "http://foobar"
+defaults write "${TEMPDIR}/${APPNAME_STABLE}/Contents/Info" \
+    KSUpdateURL "http://foobar"
 pass_installer "Old-style update"
 
 make_basic_src_and_dest
-defaults write "${TEMPDIR}/${APPNAME}/Contents/Info" KSUpdateURL "http://foobar"
-pass_installer "ALL"
+defaults write "${TEMPDIR}/${APPNAME_STABLE}/Contents/Info" \
+    KSUpdateURL "http://foobar"
+pass_installer "New-style Stable"
+
+make_src "${APPNAME_CANARY}"
+make_new_dest
+defaults write "${TEMPDIR}/${APPNAME_CANARY}/Contents/Info" \
+    KSUpdateURL "http://foobar"
+pass_installer "New-style Canary"
 
 cleanup_tempdir
diff --git a/chrome/installer/mac/signing/model.py b/chrome/installer/mac/signing/model.py
index 4af09005..51157728 100644
--- a/chrome/installer/mac/signing/model.py
+++ b/chrome/installer/mac/signing/model.py
@@ -287,9 +287,11 @@
     """
 
     def __init__(self, input, output, work):
-        self._input = input
-        self._output = output
+        self._input = os.path.abspath(input)
+        self._output = os.path.abspath(output)
         self._work = work
+        if self._work:
+            self._work = os.path.abspath(self._work)
 
     @property
     def input(self):
diff --git a/chrome/installer/mac/signing/model_test.py b/chrome/installer/mac/signing/model_test.py
index d816ba6..8a3cd1e9 100644
--- a/chrome/installer/mac/signing/model_test.py
+++ b/chrome/installer/mac/signing/model_test.py
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import os.path
 import unittest
 
 from . import model
@@ -135,19 +136,19 @@
 class TestPaths(unittest.TestCase):
 
     def test_construct(self):
-        paths = model.Paths('[INPUT]', '[OUTPUT]', '[WORK]')
-        self.assertEqual('[INPUT]', paths.input)
-        self.assertEqual('[OUTPUT]', paths.output)
-        self.assertEqual('[WORK]', paths.work)
+        paths = model.Paths('[INPUT]', '/[OUTPUT]', '[WORK]')
+        self.assertEqual(os.path.abspath('[INPUT]'), paths.input)
+        self.assertEqual('/[OUTPUT]', paths.output)
+        self.assertEqual(os.path.abspath('[WORK]'), paths.work)
 
     def test_packaging_dir(self):
-        paths = model.Paths('[INPUT]', '[OUTPUT]', '[WORK]')
+        paths = model.Paths('/[INPUT]', '/[OUTPUT]', '/[WORK]')
         packaging_dir = paths.packaging_dir(TestConfig())
-        self.assertEqual('[INPUT]/Product Packaging', packaging_dir)
+        self.assertEqual('/[INPUT]/Product Packaging', packaging_dir)
 
     def test_replace_work(self):
-        paths = model.Paths('[INPUT]', '[OUTPUT]', '[WORK]')
-        self.assertEqual('[WORK]', paths.work)
+        paths = model.Paths('/[INPUT]', '/[OUTPUT]', '/[WORK]')
+        self.assertEqual('/[WORK]', paths.work)
         paths2 = paths.replace_work('{WORK2}')
-        self.assertEqual('[WORK]', paths.work)
-        self.assertEqual('{WORK2}', paths2.work)
+        self.assertEqual('/[WORK]', paths.work)
+        self.assertEqual(os.path.abspath('{WORK2}'), paths2.work)
diff --git a/chrome/installer/mac/signing/modification_test.py b/chrome/installer/mac/signing/modification_test.py
index 6de52ed..c9edd90 100644
--- a/chrome/installer/mac/signing/modification_test.py
+++ b/chrome/installer/mac/signing/modification_test.py
@@ -12,29 +12,29 @@
 def plist_read(*args):
     bundle_id = test_config.TestConfig().base_bundle_id
     plists = {
-        '$W/App Product.app/Contents/Info.plist': {
+        '/$W/App Product.app/Contents/Info.plist': {
             'CFBundleIdentifier': bundle_id,
             'KSProductID': 'test.ksproduct',
             'KSChannelID-full': '-full',
         },
-        '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc/Contents/Info.plist':
+        '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc/Contents/Info.plist':
             {
                 'CFBundleIdentifier':
                     bundle_id + '.AlertNotificationService.xpc'
             },
-        '$W/app-entitlements.plist': {
+        '/$W/app-entitlements.plist': {
             'com.apple.application-identifier': bundle_id
         },
-        '$W/helper-renderer-entitlements.plist': {},
-        '$W/helper-gpu-entitlements.plist': {},
-        '$W/helper-plugin-entitlements.plist': {},
-        '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest':
+        '/$W/helper-renderer-entitlements.plist': {},
+        '/$W/helper-gpu-entitlements.plist': {},
+        '/$W/helper-plugin-entitlements.plist': {},
+        '/$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest':
             {
                 'pfm_domain': bundle_id
             }
     }
-    plists['$W/App Product Canary.app/Contents/Info.plist'] = plists[
-        '$W/App Product.app/Contents/Info.plist']
+    plists['/$W/App Product Canary.app/Contents/Info.plist'] = plists[
+        '/$W/App Product.app/Contents/Info.plist']
     return plists[args[0]]
 
 
@@ -48,7 +48,7 @@
 class TestModification(unittest.TestCase):
 
     def setUp(self):
-        self.paths = model.Paths('$I', '$O', '$W')
+        self.paths = model.Paths('/$I', '/$O', '/$W')
         self.config = test_config.TestConfig()
 
     def _is_framework_unchanged(self, plistlib, mocks):
@@ -62,7 +62,7 @@
                 for tup in call:
                     for arg in tup:
                         # Don't anchor this substring in a particular directory
-                        # because it may appear in any of $I, $O, or $W. Don't
+                        # because it may appear in any of /$I, /$O, or /$W. Don't
                         # anchor it with App Product.app either, because it may
                         # be renamed (to App Product Canary.app).
                         if 'Contents/Frameworks/Product Framework.framework' in arg:
@@ -92,19 +92,20 @@
                 'KSProductID': 'test.ksproduct',
                 'KSChannelID-full': '-full'
             },
-            '$W/App Product.app/Contents/Info.plist',
+            '/$W/App Product.app/Contents/Info.plist',
         )
 
         self.assertEqual(4, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
-            mock.call('$I/Product Packaging/app-entitlements.plist',
-                      '$W/app-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-gpu-entitlements.plist',
-                      '$W/helper-gpu-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
-                      '$W/helper-renderer-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
-                      '$W/helper-plugin-entitlements.plist')
+            mock.call('/$I/Product Packaging/app-entitlements.plist',
+                      '/$W/app-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-gpu-entitlements.plist',
+                      '/$W/helper-gpu-entitlements.plist'),
+            mock.call(
+                '/$I/Product Packaging/helper-renderer-entitlements.plist',
+                '/$W/helper-renderer-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '/$W/helper-plugin-entitlements.plist')
         ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
@@ -125,19 +126,20 @@
                 'KSBrandID': 'MOO',
                 'KSChannelID-full': '-full'
             },
-            '$W/App Product.app/Contents/Info.plist',
+            '/$W/App Product.app/Contents/Info.plist',
         )
 
         self.assertEqual(4, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
-            mock.call('$I/Product Packaging/app-entitlements.plist',
-                      '$W/app-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-gpu-entitlements.plist',
-                      '$W/helper-gpu-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
-                      '$W/helper-renderer-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
-                      '$W/helper-plugin-entitlements.plist')
+            mock.call('/$I/Product Packaging/app-entitlements.plist',
+                      '/$W/app-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-gpu-entitlements.plist',
+                      '/$W/helper-gpu-entitlements.plist'),
+            mock.call(
+                '/$I/Product Packaging/helper-renderer-entitlements.plist',
+                '/$W/helper-renderer-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '/$W/helper-plugin-entitlements.plist')
         ])
         self.assertEqual(0, kwargs['move_file'].call_count)
 
@@ -157,19 +159,20 @@
                 'KSChannelID': 'dev',
                 'KSChannelID-full': 'dev-full'
             },
-            '$W/App Product.app/Contents/Info.plist',
+            '/$W/App Product.app/Contents/Info.plist',
         )
 
         self.assertEqual(4, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
-            mock.call('$I/Product Packaging/app-entitlements.plist',
-                      '$W/app-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-gpu-entitlements.plist',
-                      '$W/helper-gpu-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
-                      '$W/helper-renderer-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
-                      '$W/helper-plugin-entitlements.plist')
+            mock.call('/$I/Product Packaging/app-entitlements.plist',
+                      '/$W/app-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-gpu-entitlements.plist',
+                      '/$W/helper-gpu-entitlements.plist'),
+            mock.call(
+                '/$I/Product Packaging/helper-renderer-entitlements.plist',
+                '/$W/helper-renderer-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '/$W/helper-plugin-entitlements.plist')
         ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
@@ -190,19 +193,20 @@
                 'KSChannelID-full': '-full',
                 'CrProductDirName': 'Farmland/Cows'
             },
-            '$W/App Product.app/Contents/Info.plist',
+            '/$W/App Product.app/Contents/Info.plist',
         )
 
         self.assertEqual(4, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
-            mock.call('$I/Product Packaging/app-entitlements.plist',
-                      '$W/app-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-gpu-entitlements.plist',
-                      '$W/helper-gpu-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
-                      '$W/helper-renderer-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
-                      '$W/helper-plugin-entitlements.plist')
+            mock.call('/$I/Product Packaging/app-entitlements.plist',
+                      '/$W/app-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-gpu-entitlements.plist',
+                      '/$W/helper-gpu-entitlements.plist'),
+            mock.call(
+                '/$I/Product Packaging/helper-renderer-entitlements.plist',
+                '/$W/helper-renderer-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '/$W/helper-plugin-entitlements.plist')
         ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
@@ -223,22 +227,23 @@
                 'KSChannelID-full': '-full',
                 'CFBundleSignature': 'Mooo'
             },
-            '$W/App Product.app/Contents/Info.plist',
+            '/$W/App Product.app/Contents/Info.plist',
         )
 
         self.assertEqual(4, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
-            mock.call('$I/Product Packaging/app-entitlements.plist',
-                      '$W/app-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-gpu-entitlements.plist',
-                      '$W/helper-gpu-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
-                      '$W/helper-renderer-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
-                      '$W/helper-plugin-entitlements.plist')
+            mock.call('/$I/Product Packaging/app-entitlements.plist',
+                      '/$W/app-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-gpu-entitlements.plist',
+                      '/$W/helper-gpu-entitlements.plist'),
+            mock.call(
+                '/$I/Product Packaging/helper-renderer-entitlements.plist',
+                '/$W/helper-renderer-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '/$W/helper-plugin-entitlements.plist')
         ])
         kwargs['write_file'].assert_called_once_with(
-            '$W/App Product.app/Contents/PkgInfo', 'APPLMooo')
+            '/$W/App Product.app/Contents/PkgInfo', 'APPLMooo')
         self.assertEqual(0, kwargs['move_file'].call_count)
 
     def test_distribution_with_brand_and_channel(self, plistlib, **kwargs):
@@ -256,19 +261,20 @@
                 'KSChannelID-full': 'beta-full',
                 'KSBrandID': 'RAWR'
             },
-            '$W/App Product.app/Contents/Info.plist',
+            '/$W/App Product.app/Contents/Info.plist',
         )
 
         self.assertEqual(4, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
-            mock.call('$I/Product Packaging/app-entitlements.plist',
-                      '$W/app-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-gpu-entitlements.plist',
-                      '$W/helper-gpu-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
-                      '$W/helper-renderer-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
-                      '$W/helper-plugin-entitlements.plist')
+            mock.call('/$I/Product Packaging/app-entitlements.plist',
+                      '/$W/app-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-gpu-entitlements.plist',
+                      '/$W/helper-gpu-entitlements.plist'),
+            mock.call(
+                '/$I/Product Packaging/helper-renderer-entitlements.plist',
+                '/$W/helper-renderer-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '/$W/helper-plugin-entitlements.plist')
         ])
         self.assertEqual(0, kwargs['move_file'].call_count)
         self.assertEqual(0, kwargs['write_file'].call_count)
@@ -286,38 +292,39 @@
 
         # Order of file moves is significant.
         self.assertEqual(kwargs['move_file'].mock_calls, [
-            mock.call('$W/App Product.app', '$W/App Product Canary.app'),
+            mock.call('/$W/App Product.app', '/$W/App Product Canary.app'),
             mock.call(
-                '$W/App Product Canary.app/Contents/MacOS/App Product',
-                '$W/App Product Canary.app/Contents/MacOS/App Product Canary'),
+                '/$W/App Product Canary.app/Contents/MacOS/App Product',
+                '/$W/App Product Canary.app/Contents/MacOS/App Product Canary'),
             mock.call(
-                '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.manifest/Contents/Resources/test.signing.bundle_id.manifest',
-                '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest'
+                '/$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.manifest/Contents/Resources/test.signing.bundle_id.manifest',
+                '/$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest'
             ),
             mock.call(
-                '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.manifest',
-                '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest'
+                '/$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.manifest',
+                '/$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest'
             ),
         ])
 
         self.assertEqual(6, kwargs['copy_files'].call_count)
         kwargs['copy_files'].assert_has_calls([
-            mock.call('$I/Product Packaging/app-entitlements.plist',
-                      '$W/app-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-gpu-entitlements.plist',
-                      '$W/helper-gpu-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-renderer-entitlements.plist',
-                      '$W/helper-renderer-entitlements.plist'),
-            mock.call('$I/Product Packaging/helper-plugin-entitlements.plist',
-                      '$W/helper-plugin-entitlements.plist'),
-            mock.call('$I/Product Packaging/app_canary.icns',
-                      '$W/App Product Canary.app/Contents/Resources/app.icns'),
+            mock.call('/$I/Product Packaging/app-entitlements.plist',
+                      '/$W/app-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-gpu-entitlements.plist',
+                      '/$W/helper-gpu-entitlements.plist'),
             mock.call(
-                '$I/Product Packaging/document_canary.icns',
-                '$W/App Product Canary.app/Contents/Resources/document.icns')
+                '/$I/Product Packaging/helper-renderer-entitlements.plist',
+                '/$W/helper-renderer-entitlements.plist'),
+            mock.call('/$I/Product Packaging/helper-plugin-entitlements.plist',
+                      '/$W/helper-plugin-entitlements.plist'),
+            mock.call('/$I/Product Packaging/app_canary.icns',
+                      '/$W/App Product Canary.app/Contents/Resources/app.icns'),
+            mock.call(
+                '/$I/Product Packaging/document_canary.icns',
+                '/$W/App Product Canary.app/Contents/Resources/document.icns')
         ])
         kwargs['write_file'].assert_called_once_with(
-            '$W/App Product Canary.app/Contents/PkgInfo', 'APPLMooo')
+            '/$W/App Product Canary.app/Contents/PkgInfo', 'APPLMooo')
 
         self.assertEqual(7, plistlib.writePlist.call_count)
         plistlib.writePlist.assert_has_calls([
@@ -326,7 +333,7 @@
                     'CFBundleIdentifier':
                         'test.signing.bundle_id.canary.AlertNotificationService.xpc'
                 },
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc/Contents/Info.plist'
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc/Contents/Info.plist'
             ),
             mock.call(
                 {
@@ -337,18 +344,18 @@
                     'KSChannelID-full': 'canary-full',
                     'CrProductDirName': 'Acme/Product Canary',
                     'CFBundleSignature': 'Mooo'
-                }, '$W/App Product Canary.app/Contents/Info.plist'),
+                }, '/$W/App Product Canary.app/Contents/Info.plist'),
             mock.call(
                 {
                     'com.apple.application-identifier':
                         'test.signing.bundle_id.canary'
-                }, '$W/app-entitlements.plist'),
-            mock.call({}, '$W/helper-gpu-entitlements.plist'),
-            mock.call({}, '$W/helper-renderer-entitlements.plist'),
-            mock.call({}, '$W/helper-plugin-entitlements.plist'),
+                }, '/$W/app-entitlements.plist'),
+            mock.call({}, '/$W/helper-gpu-entitlements.plist'),
+            mock.call({}, '/$W/helper-renderer-entitlements.plist'),
+            mock.call({}, '/$W/helper-plugin-entitlements.plist'),
             mock.call({
                 'pfm_domain': 'test.signing.bundle_id.canary'
-            }, '$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest'
+            }, '/$W/App Product Canary.app/Contents/Resources/test.signing.bundle_id.canary.manifest/Contents/Resources/test.signing.bundle_id.canary.manifest'
                      )
         ])
 
diff --git a/chrome/installer/mac/signing/notarize_test.py b/chrome/installer/mac/signing/notarize_test.py
index b9d5e62..ecc120bc 100644
--- a/chrome/installer/mac/signing/notarize_test.py
+++ b/chrome/installer/mac/signing/notarize_test.py
@@ -238,10 +238,10 @@
                 'Foo.app/Contents/Helpers/Helper.app/Contents/XPCServices/'
                 'Service2.xpc', ''),
             CodeSignedProduct('Foo.app', '')
-        ], Paths('in', 'out', 'work'))
+        ], Paths('/in', '/out', '/work'))
         staple.assert_has_calls([
-            mock.call('work/Foo.app/Contents/Helpers/Helper.app/Contents'
+            mock.call('/work/Foo.app/Contents/Helpers/Helper.app/Contents'
                       '/Helpers/Bar.app'),
-            mock.call('work/Foo.app/Contents/Helpers/Helper.app'),
-            mock.call('work/Foo.app')
+            mock.call('/work/Foo.app/Contents/Helpers/Helper.app'),
+            mock.call('/work/Foo.app')
         ])
diff --git a/chrome/installer/mac/signing/parts_test.py b/chrome/installer/mac/signing/parts_test.py
index 0247ab42..3945df5 100644
--- a/chrome/installer/mac/signing/parts_test.py
+++ b/chrome/installer/mac/signing/parts_test.py
@@ -105,10 +105,10 @@
         path = path[first_slash + 1:]
 
         plists = {
-            'App Product.app/Contents/Info.plist': {
+            '$W/App Product.app/Contents/Info.plist': {
                 'KSVersion': '99.0.9999.99'
             },
-            'App Product.app/Contents/Frameworks/Product Framework.framework/Resources/Info.plist':
+            '$W/App Product.app/Contents/Frameworks/Product Framework.framework/Resources/Info.plist':
                 {
                     'CFBundleShortVersionString': other_version
                 }
@@ -127,7 +127,7 @@
 class TestSignChrome(unittest.TestCase):
 
     def setUp(self):
-        self.paths = model.Paths('$I', '$O', '$W')
+        self.paths = model.Paths('/$I', '/$O', '/$W')
 
     @mock.patch('signing.parts._sanity_check_version_keys')
     def test_sign_chrome(self, *args, **kwargs):
@@ -146,8 +146,8 @@
         # Test that the provisioning profile is copied.
         self.assertEqual(kwargs['copy_files'].mock_calls, [
             mock.call.copy_files(
-                '$I/Product Packaging/provisiontest.provisionprofile',
-                '$W/App Product.app/Contents/embedded.provisionprofile')
+                '/$I/Product Packaging/provisiontest.provisionprofile',
+                '/$W/App Product.app/Contents/embedded.provisionprofile')
         ])
 
         # Ensure that all the parts are signed.
@@ -168,10 +168,10 @@
         self.assertEqual(kwargs['run_command'].mock_calls, [
             mock.call.run_command([
                 'codesign', '--display', '--requirements', '-', '--verbose=5',
-                '$W/App Product.app'
+                '/$W/App Product.app'
             ]),
             mock.call.run_command(
-                ['spctl', '--assess', '-vv', '$W/App Product.app']),
+                ['spctl', '--assess', '-vv', '/$W/App Product.app']),
         ])
 
     @mock.patch('signing.parts._sanity_check_version_keys')
@@ -191,7 +191,7 @@
         self.assertEqual(kwargs['run_command'].mock_calls, [
             mock.call.run_command([
                 'codesign', '--display', '--requirements', '-', '--verbose=5',
-                '$W/App Product.app'
+                '/$W/App Product.app'
             ]),
         ])
 
@@ -227,8 +227,8 @@
         # Test that the provisioning profile is copied.
         self.assertEqual(kwargs['copy_files'].mock_calls, [
             mock.call.copy_files(
-                '$I/Product Packaging/provisiontest.provisionprofile',
-                '$W/App Product.app/Contents/embedded.provisionprofile')
+                '/$I/Product Packaging/provisiontest.provisionprofile',
+                '/$W/App Product.app/Contents/embedded.provisionprofile')
         ])
 
         # Ensure that only the app is signed.
@@ -240,10 +240,10 @@
         self.assertEqual(kwargs['run_command'].mock_calls, [
             mock.call.run_command([
                 'codesign', '--display', '--requirements', '-', '--verbose=5',
-                '$W/App Product.app'
+                '/$W/App Product.app'
             ]),
             mock.call.run_command(
-                ['spctl', '--assess', '-vv', '$W/App Product.app']),
+                ['spctl', '--assess', '-vv', '/$W/App Product.app']),
         ])
 
     @mock.patch(
diff --git a/chrome/installer/mac/signing/pipeline_test.py b/chrome/installer/mac/signing/pipeline_test.py
index 6c9a8c1..cf905ce 100644
--- a/chrome/installer/mac/signing/pipeline_test.py
+++ b/chrome/installer/mac/signing/pipeline_test.py
@@ -13,22 +13,22 @@
 
 def _get_work_dir(*args, **kwargs):
     _get_work_dir.count += 1
-    return '$W_{}'.format(_get_work_dir.count)
+    return '/$W_{}'.format(_get_work_dir.count)
 
 
 _get_work_dir.count = 0
 
 
 def _component_property_path(paths, dist_config):
-    return '$W/App Product.plist'
+    return '/$W/App Product.plist'
 
 
 def _productbuild_distribution_path(p, d, c):
-    return '$W/App Product.dist'
+    return '/$W/App Product.dist'
 
 
 def _create_pkgbuild_scripts(p, d):
-    return '$W/scripts'
+    return '/$W/scripts'
 
 
 def _read_plist(p):
@@ -47,7 +47,7 @@
 
 
 def _read_file(p):
-    if p == '$I/Product Packaging/pkg_postinstall.in':
+    if p == '/$I/Product Packaging/pkg_postinstall.in':
         return """app dir is '@APP_DIR@'
 app product is '@APP_PRODUCT@'
 brand code is '@BRAND_CODE@'
@@ -79,7 +79,7 @@
 
     def setUp(self):
         _get_work_dir.count = 0
-        self.paths = model.Paths('$I', '$O', None)
+        self.paths = model.Paths('/$I', '/$O', None)
 
     @mock.patch('signing.modification.customize_distribution')
     def test_customize_and_sign_chrome_no_customize(self, customize, **kwargs):
@@ -91,24 +91,24 @@
         dist = model.Distribution()
         config = test_config.TestConfig()
         dist_config = dist.to_config(config)
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         pipeline._customize_and_sign_chrome(paths, dist_config, '$D', None)
 
         manager.assert_has_calls([
-            mock.call.copy_files('$I/App Product.app', '$W'),
+            mock.call.copy_files('/$I/App Product.app', '/$W'),
             mock.call.customize_distribution(paths, dist, dist_config),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=False),
             mock.call.sign_chrome(paths, dist_config, sign_framework=True),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=True),
             mock.call.make_dir('$D'),
-            mock.call.move_file('$W/App Product.app', '$D/App Product.app')
+            mock.call.move_file('/$W/App Product.app', '$D/App Product.app')
         ])
 
     @mock.patch('signing.modification.customize_distribution')
@@ -125,24 +125,24 @@
             app_name_fragment='Canary')
         config = test_config.TestConfig()
         dist_config = dist.to_config(config)
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         pipeline._customize_and_sign_chrome(paths, dist_config, '$D', None)
 
         manager.assert_has_calls([
-            mock.call.copy_files('$I/App Product.app', '$W'),
+            mock.call.copy_files('/$I/App Product.app', '/$W'),
             mock.call.customize_distribution(paths, dist, dist_config),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=False),
             mock.call.sign_chrome(paths, dist_config, sign_framework=True),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=True),
             mock.call.make_dir('$D'),
-            mock.call.move_file('$W/App Product Canary.app',
+            mock.call.move_file('/$W/App Product Canary.app',
                                 '$D/App Product Canary.app')
         ])
 
@@ -160,18 +160,22 @@
 
         base_dist = model.Distribution()
         base_dist_config = base_dist.to_config(config)
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
+
+        notary_paths = paths.replace_work('/$D')
 
         signed_frameworks = {}
-        pipeline._customize_and_sign_chrome(paths, base_dist_config, '$D',
+        pipeline._customize_and_sign_chrome(paths, base_dist_config,
+                                            notary_paths.work,
                                             signed_frameworks)
 
         branded_dist = model.Distribution(
             branding_code='c0de', packaging_name_fragment='Branded')
         branded_dist_config = branded_dist.to_config(config)
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
-        pipeline._customize_and_sign_chrome(paths, branded_dist_config, '$D',
+        pipeline._customize_and_sign_chrome(paths, branded_dist_config,
+                                            notary_paths.work,
                                             signed_frameworks)
 
         channel_dist = model.Distribution(
@@ -179,81 +183,80 @@
             channel='canary',
             app_name_fragment='Canary')
         channel_dist_config = channel_dist.to_config(config)
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
-        pipeline._customize_and_sign_chrome(paths, channel_dist_config, '$D',
+        pipeline._customize_and_sign_chrome(paths, channel_dist_config,
+                                            notary_paths.work,
                                             signed_frameworks)
 
         manager.assert_has_calls([
-            mock.call.copy_files('$I/App Product.app', '$W'),
+            mock.call.copy_files('/$I/App Product.app', '/$W'),
             mock.call.customize_distribution(paths, base_dist,
                                              base_dist_config),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=False),
             mock.call.sign_chrome(paths, base_dist_config, sign_framework=True),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=True),
-            mock.call.make_dir('$D'),
-            mock.call.move_file('$W/App Product.app', '$D/App Product.app'),
-            mock.call.copy_files('$I/App Product.app', '$W'),
+            mock.call.make_dir('/$D'),
+            mock.call.move_file('/$W/App Product.app', '/$D/App Product.app'),
+            mock.call.copy_files('/$I/App Product.app', '/$W'),
             mock.call.customize_distribution(paths, branded_dist,
                                              branded_dist_config),
-            # TODO(https://crbug.com/964608): $D/$D is a relative path treatment
-            # bug.
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$D/$D/App Product.app/Contents/Frameworks/Product Framework.framework',
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework',
+                '/$D/App Product.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework',
                 dry_run=False),
             mock.call.sign_chrome(
                 paths, branded_dist_config, sign_framework=False),
-            mock.call.make_dir('$D'),
-            mock.call.move_file('$W/App Product.app', '$D/App Product.app'),
-            mock.call.copy_files('$I/App Product.app', '$W'),
+            mock.call.make_dir('/$D'),
+            mock.call.move_file('/$W/App Product.app', '/$D/App Product.app'),
+            mock.call.copy_files('/$I/App Product.app', '/$W'),
             mock.call.customize_distribution(paths, channel_dist,
                                              channel_dist_config),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=False),
             mock.call.sign_chrome(
                 paths, channel_dist_config, sign_framework=True),
             mock.call.copy_dir_overwrite_and_count_changes(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
-                '$W/modified_unsigned_framework',
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework',
+                '/$W/modified_unsigned_framework',
                 dry_run=True),
-            mock.call.make_dir('$D'),
-            mock.call.move_file('$W/App Product Canary.app',
-                                '$D/App Product Canary.app')
+            mock.call.make_dir('/$D'),
+            mock.call.move_file('/$W/App Product Canary.app',
+                                '/$D/App Product Canary.app')
         ])
 
     @mock.patch('signing.notarize.staple')
     def test_staple_chrome_no_customize(self, staple, **kwargs):
         dist = model.Distribution()
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         pipeline._staple_chrome(paths, dist.to_config(test_config.TestConfig()))
 
         self.assertEqual(staple.mock_calls, [
             mock.call(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc'
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc'
             ),
             mock.call(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper.app'
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper.app'
             ),
             mock.call(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Renderer).app'
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Renderer).app'
             ),
             mock.call(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Plugin).app'
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Plugin).app'
             ),
             mock.call(
-                '$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (GPU).app'
+                '/$W/App Product.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (GPU).app'
             ),
-            mock.call('$W/App Product.app')
+            mock.call('/$W/App Product.app')
         ])
 
     @mock.patch('signing.notarize.staple')
@@ -262,27 +265,27 @@
             channel_customize=True,
             channel='canary',
             app_name_fragment='Canary')
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         pipeline._staple_chrome(paths, dist.to_config(test_config.TestConfig()))
 
         self.assertEqual(staple.mock_calls, [
             mock.call(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc'
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/XPCServices/AlertNotificationService.xpc'
             ),
             mock.call(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper.app'
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper.app'
             ),
             mock.call(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Renderer).app'
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Renderer).app'
             ),
             mock.call(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Plugin).app'
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (Plugin).app'
             ),
             mock.call(
-                '$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (GPU).app'
+                '/$W/App Product Canary.app/Contents/Frameworks/Product Framework.framework/Helpers/Product Helper (GPU).app'
             ),
-            mock.call('$W/App Product Canary.app')
+            mock.call('/$W/App Product Canary.app')
         ])
 
     @mock.patch('signing.commands.read_file', _read_file)
@@ -297,15 +300,15 @@
             package_as_dmg=False,
             package_as_pkg=True)
         dist_config = dist.to_config(test_config.TestConfig())
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
-        self.assertEqual('$W/scripts',
+        self.assertEqual('/$W/scripts',
                          pipeline._create_pkgbuild_scripts(paths, dist_config))
 
         manager.assert_has_calls([
-            mock.call.make_dir('$W/scripts'),
-            mock.call.write_file('$W/scripts/postinstall', mock.ANY),
-            mock.call.set_executable('$W/scripts/postinstall')
+            mock.call.make_dir('/$W/scripts'),
+            mock.call.write_file('/$W/scripts/postinstall', mock.ANY),
+            mock.call.set_executable('/$W/scripts/postinstall')
         ])
 
         postinstall_string = manager.mock_calls[1][1][1]
@@ -324,9 +327,9 @@
 
         dist = model.Distribution()
         dist_config = dist.to_config(test_config.TestConfig())
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
-        self.assertEqual('$W/App Product.plist',
+        self.assertEqual('/$W/App Product.plist',
                          pipeline._component_property_path(paths, dist_config))
 
         self.assertEqual(_last_written_plist(), [{
@@ -345,18 +348,18 @@
 
         dist = model.Distribution()
         dist_config = dist.to_config(test_config.TestConfig())
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         component_pkg_path = os.path.join(
             paths.work, '{}.pkg'.format(dist_config.app_product))
 
         self.assertEqual(
-            '$W/App Product.dist',
+            '/$W/App Product.dist',
             pipeline._productbuild_distribution_path(paths, dist_config,
                                                      component_pkg_path))
 
         manager.assert_has_calls([
-            mock.call.write_file('$W/App Product.dist', mock.ANY),
+            mock.call.write_file('/$W/App Product.dist', mock.ANY),
         ])
 
         xml_string = manager.mock_calls[0][1][1]
@@ -378,12 +381,12 @@
         dist = model.Distribution(package_as_dmg=True, package_as_pkg=False)
         dist_config = dist.to_config(config)
 
-        paths = self.paths.replace_work('$W')
-        self.assertEqual('$O/AppProduct-99.0.9999.99.dmg',
+        paths = self.paths.replace_work('/$W')
+        self.assertEqual('/$O/AppProduct-99.0.9999.99.dmg',
                          pipeline._package_and_sign_dmg(paths, dist_config))
 
         manager.assert_has_calls([
-            mock.call.make_dir('$W/empty'),
+            mock.call.make_dir('/$W/empty'),
             mock.call.run_command(mock.ANY),
             mock.call.sign_part(paths, dist_config, mock.ANY),
             mock.call.verify_part(paths, mock.ANY)
@@ -394,7 +397,7 @@
         ][0]
         pkg_dmg_args = run_command[1][0]
 
-        self.assertEqual('$O/AppProduct-99.0.9999.99.dmg',
+        self.assertEqual('/$O/AppProduct-99.0.9999.99.dmg',
                          _get_adjacent_item(pkg_dmg_args, '--target'))
         self.assertEqual(config.app_product,
                          _get_adjacent_item(pkg_dmg_args, '--volname'))
@@ -416,8 +419,8 @@
         dist = model.Distribution(package_as_dmg=False, package_as_pkg=True)
         dist_config = dist.to_config(config)
 
-        paths = self.paths.replace_work('$W')
-        self.assertEqual('$O/AppProduct-99.0.9999.99.pkg',
+        paths = self.paths.replace_work('/$W')
+        self.assertEqual('/$O/AppProduct-99.0.9999.99.pkg',
                          pipeline._package_and_sign_pkg(paths, dist_config))
 
         manager.assert_has_calls(
@@ -430,15 +433,15 @@
         pkgbuild_args = run_commands[0][1][0]
         productbuild_args = run_commands[1][1][0]
 
-        self.assertEqual('$W/payload',
+        self.assertEqual('/$W/payload',
                          _get_adjacent_item(pkgbuild_args, '--root'))
-        self.assertEqual('$W/App Product.plist',
+        self.assertEqual('/$W/App Product.plist',
                          _get_adjacent_item(pkgbuild_args, '--component-plist'))
         self.assertEqual('test.signing.bundle_id',
                          _get_adjacent_item(pkgbuild_args, '--identifier'))
         self.assertEqual('99.0.9999.99',
                          _get_adjacent_item(pkgbuild_args, '--version'))
-        self.assertEqual('$W/scripts',
+        self.assertEqual('/$W/scripts',
                          _get_adjacent_item(pkgbuild_args, '--scripts'))
 
         self.assertEqual('test.signing.bundle_id',
@@ -446,10 +449,10 @@
         self.assertEqual('99.0.9999.99',
                          _get_adjacent_item(productbuild_args, '--version'))
         self.assertEqual(
-            '$W/App Product.dist',
+            '/$W/App Product.dist',
             _get_adjacent_item(productbuild_args, '--distribution'))
         self.assertEqual(
-            '$W', _get_adjacent_item(productbuild_args, '--package-path'))
+            '/$W', _get_adjacent_item(productbuild_args, '--package-path'))
         self.assertEqual('[INSTALLER-IDENTITY]',
                          _get_adjacent_item(productbuild_args, '--sign'))
 
@@ -466,12 +469,12 @@
             package_as_pkg=False)
         dist_config = dist.to_config(config)
 
-        paths = self.paths.replace_work('$W')
-        self.assertEqual('$O/AppProduct-99.0.9999.99-ForCows.dmg',
+        paths = self.paths.replace_work('/$W')
+        self.assertEqual('/$O/AppProduct-99.0.9999.99-ForCows.dmg',
                          pipeline._package_and_sign_dmg(paths, dist_config))
 
         manager.assert_has_calls([
-            mock.call.make_dir('$W/empty'),
+            mock.call.make_dir('/$W/empty'),
             mock.call.run_command(mock.ANY),
             mock.call.sign_part(paths, dist_config, mock.ANY),
             mock.call.verify_part(paths, mock.ANY)
@@ -482,7 +485,7 @@
         ][0]
         pkg_dmg_args = run_command[1][0]
 
-        self.assertEqual('$O/AppProduct-99.0.9999.99-ForCows.dmg',
+        self.assertEqual('/$O/AppProduct-99.0.9999.99-ForCows.dmg',
                          _get_adjacent_item(pkg_dmg_args, '--target'))
         self.assertEqual(config.app_product,
                          _get_adjacent_item(pkg_dmg_args, '--volname'))
@@ -508,8 +511,8 @@
             package_as_pkg=True)
         dist_config = dist.to_config(config)
 
-        paths = self.paths.replace_work('$W')
-        self.assertEqual('$O/AppProduct-99.0.9999.99-ForCows.pkg',
+        paths = self.paths.replace_work('/$W')
+        self.assertEqual('/$O/AppProduct-99.0.9999.99-ForCows.pkg',
                          pipeline._package_and_sign_pkg(paths, dist_config))
 
         manager.assert_has_calls(
@@ -522,15 +525,15 @@
         pkgbuild_args = run_commands[0][1][0]
         productbuild_args = run_commands[1][1][0]
 
-        self.assertEqual('$W/payload',
+        self.assertEqual('/$W/payload',
                          _get_adjacent_item(pkgbuild_args, '--root'))
-        self.assertEqual('$W/App Product.plist',
+        self.assertEqual('/$W/App Product.plist',
                          _get_adjacent_item(pkgbuild_args, '--component-plist'))
         self.assertEqual('test.signing.bundle_id',
                          _get_adjacent_item(pkgbuild_args, '--identifier'))
         self.assertEqual('99.0.9999.99',
                          _get_adjacent_item(pkgbuild_args, '--version'))
-        self.assertEqual('$W/scripts',
+        self.assertEqual('/$W/scripts',
                          _get_adjacent_item(pkgbuild_args, '--scripts'))
 
         self.assertEqual('test.signing.bundle_id',
@@ -538,30 +541,30 @@
         self.assertEqual('99.0.9999.99',
                          _get_adjacent_item(productbuild_args, '--version'))
         self.assertEqual(
-            '$W/App Product.dist',
+            '/$W/App Product.dist',
             _get_adjacent_item(productbuild_args, '--distribution'))
         self.assertEqual(
-            '$W', _get_adjacent_item(productbuild_args, '--package-path'))
+            '/$W', _get_adjacent_item(productbuild_args, '--package-path'))
         self.assertEqual('[INSTALLER-IDENTITY]',
                          _get_adjacent_item(productbuild_args, '--sign'))
 
     def test_package_dmg_no_customize(self, **kwargs):
         dist = model.Distribution()
         config = test_config.TestConfig()
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         dmg_path = pipeline._package_dmg(paths, dist, config)
-        self.assertEqual('$O/AppProduct-99.0.9999.99.dmg', dmg_path)
+        self.assertEqual('/$O/AppProduct-99.0.9999.99.dmg', dmg_path)
 
         pkg_dmg_args = kwargs['run_command'].mock_calls[0][1][0]
 
         self.assertEqual(dmg_path, _get_adjacent_item(pkg_dmg_args, '--target'))
-        self.assertEqual('$I/Product Packaging/chrome_dmg_icon.icns',
+        self.assertEqual('/$I/Product Packaging/chrome_dmg_icon.icns',
                          _get_adjacent_item(pkg_dmg_args, '--icon'))
         self.assertEqual('App Product',
                          _get_adjacent_item(pkg_dmg_args, '--volname'))
-        self.assertEqual('$W/empty', _get_adjacent_item(pkg_dmg_args,
-                                                        '--source'))
+        self.assertEqual('/$W/empty',
+                         _get_adjacent_item(pkg_dmg_args, '--source'))
 
         copy_specs = [
             pkg_dmg_args[i + 1]
@@ -571,10 +574,10 @@
         self.assertEqual(
             set(copy_specs),
             set([
-                '$W/App Product.app:/',
-                '$I/Product Packaging/keystone_install.sh:/.keystone_install',
-                '$I/Product Packaging/chrome_dmg_background.png:/.background/background.png',
-                '$I/Product Packaging/chrome_dmg_dsstore:/.DS_Store'
+                '/$W/App Product.app:/',
+                '/$I/Product Packaging/keystone_install.sh:/.keystone_install',
+                '/$I/Product Packaging/chrome_dmg_background.png:/.background/background.png',
+                '/$I/Product Packaging/chrome_dmg_dsstore:/.DS_Store'
             ]))
 
     def test_package_dmg_customize(self, **kwargs):
@@ -583,20 +586,20 @@
             channel='canary',
             app_name_fragment='Canary')
         config = dist.to_config(test_config.TestConfig())
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         dmg_path = pipeline._package_dmg(paths, dist, config)
-        self.assertEqual('$O/AppProductCanary-99.0.9999.99.dmg', dmg_path)
+        self.assertEqual('/$O/AppProductCanary-99.0.9999.99.dmg', dmg_path)
 
         pkg_dmg_args = kwargs['run_command'].mock_calls[0][1][0]
 
         self.assertEqual(dmg_path, _get_adjacent_item(pkg_dmg_args, '--target'))
-        self.assertEqual('$I/Product Packaging/chrome_canary_dmg_icon.icns',
+        self.assertEqual('/$I/Product Packaging/chrome_canary_dmg_icon.icns',
                          _get_adjacent_item(pkg_dmg_args, '--icon'))
         self.assertEqual('App Product Canary',
                          _get_adjacent_item(pkg_dmg_args, '--volname'))
-        self.assertEqual('$W/empty', _get_adjacent_item(pkg_dmg_args,
-                                                        '--source'))
+        self.assertEqual('/$W/empty',
+                         _get_adjacent_item(pkg_dmg_args, '--source'))
 
         copy_specs = [
             pkg_dmg_args[i + 1]
@@ -606,34 +609,34 @@
         self.assertEqual(
             set(copy_specs),
             set([
-                '$W/App Product Canary.app:/',
-                '$I/Product Packaging/keystone_install.sh:/.keystone_install',
-                '$I/Product Packaging/chrome_dmg_background.png:/.background/background.png',
-                '$I/Product Packaging/chrome_canary_dmg_dsstore:/.DS_Store'
+                '/$W/App Product Canary.app:/',
+                '/$I/Product Packaging/keystone_install.sh:/.keystone_install',
+                '/$I/Product Packaging/chrome_dmg_background.png:/.background/background.png',
+                '/$I/Product Packaging/chrome_canary_dmg_dsstore:/.DS_Store'
             ]))
 
     def test_package_dmg_no_customize_not_chrome(self, **kwargs):
         dist = model.Distribution()
         config = test_config.TestConfigNonChromeBranded()
-        paths = self.paths.replace_work('$W')
+        paths = self.paths.replace_work('/$W')
 
         dmg_path = pipeline._package_dmg(paths, dist, config)
-        self.assertEqual('$O/AppProduct-99.0.9999.99.dmg', dmg_path)
+        self.assertEqual('/$O/AppProduct-99.0.9999.99.dmg', dmg_path)
 
         pkg_dmg_args = kwargs['run_command'].mock_calls[0][1][0]
 
         self.assertEqual(dmg_path, _get_adjacent_item(pkg_dmg_args, '--target'))
         self.assertEqual('App Product',
                          _get_adjacent_item(pkg_dmg_args, '--volname'))
-        self.assertEqual('$W/empty', _get_adjacent_item(pkg_dmg_args,
-                                                        '--source'))
+        self.assertEqual('/$W/empty',
+                         _get_adjacent_item(pkg_dmg_args, '--source'))
 
         copy_specs = [
             pkg_dmg_args[i + 1]
             for i, arg in enumerate(pkg_dmg_args)
             if arg == '--copy'
         ]
-        self.assertEqual(set(copy_specs), set(['$W/App Product.app:/']))
+        self.assertEqual(set(copy_specs), set(['/$W/App Product.app:/']))
 
     def test_package_installer_tools(self, **kwargs):
         manager = mock.Mock()
@@ -645,14 +648,14 @@
 
         # Start and end with the work dir.
         self.assertEqual(
-            mock.call.make_dir('$W_1/diff_tools'), manager.mock_calls[0])
+            mock.call.make_dir('/$W_1/diff_tools'), manager.mock_calls[0])
         self.assertEqual(
-            mock.call.shutil.rmtree('$W_1'), manager.mock_calls[-1])
+            mock.call.shutil.rmtree('/$W_1'), manager.mock_calls[-1])
 
         self.assertEqual(
             mock.call.run_command(
-                ['zip', '-9ry', '$O/diff_tools.zip', 'diff_tools'], cwd='$W_1'),
-            manager.mock_calls[-2])
+                ['zip', '-9ry', '/$O/diff_tools.zip', 'diff_tools'],
+                cwd='/$W_1'), manager.mock_calls[-2])
 
         files_to_copy = set([
             'goobspatch',
@@ -670,8 +673,8 @@
         for call in manager.mock_calls:
             if call[0] == 'copy_files':
                 args = call[1]
-                self.assertTrue(args[0].startswith('$I/Product Packaging/'))
-                self.assertEqual('$W_1/diff_tools', args[1])
+                self.assertTrue(args[0].startswith('/$I/Product Packaging/'))
+                self.assertEqual('/$W_1/diff_tools', args[1])
                 copied_files.append(os.path.basename(args[0]))
 
         self.assertEqual(len(copied_files), len(files_to_copy))
@@ -724,8 +727,8 @@
         for call in manager.mock_calls:
             if call[0] == 'copy_files':
                 args = call[1]
-                self.assertTrue(args[0].startswith('$I/Product Packaging/'))
-                self.assertEqual('$W_1/diff_tools', args[1])
+                self.assertTrue(args[0].startswith('/$I/Product Packaging/'))
+                self.assertEqual('/$W_1/diff_tools', args[1])
                 copied_files.append(os.path.basename(args[0]))
 
         self.assertEqual(len(copied_files), len(files_to_copy))
@@ -752,7 +755,7 @@
 
     def setUp(self, **kwargs):
         _get_work_dir.count = 0
-        self.paths = model.Paths('$I', '$O', None)
+        self.paths = model.Paths('/$I', '/$O', None)
 
     def test_sign_basic_distribution_dmg(self, **kwargs):
         manager = mock.Mock()
@@ -766,7 +769,7 @@
             iter([app_uuid]), iter([dmg_uuid])
         ]
         kwargs[
-            '_package_and_sign_dmg'].return_value = '$O/AppProduct-99.0.9999.99.dmg'
+            '_package_and_sign_dmg'].return_value = '/$O/AppProduct-99.0.9999.99.dmg'
 
         class Config(test_config.TestConfig):
 
@@ -785,29 +788,29 @@
         manager.assert_has_calls([
             # First customize the distribution and sign it.
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99', mock.ANY),
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99', mock.ANY),
 
             # Prepare the app for notarization.
             mock.call.run_command([
                 'zip', '--recurse-paths', '--symlinks', '--quiet',
-                '$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
+                '/$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
             ],
-                                  cwd='$W_1/AppProduct-99.0.9999.99'),
-            mock.call.submit('$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
-            mock.call.shutil.rmtree('$W_2'),
+                                  cwd='/$W_1/AppProduct-99.0.9999.99'),
+            mock.call.submit('/$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
+            mock.call.shutil.rmtree('/$W_2'),
             mock.call.wait_for_results({app_uuid: None}.keys(), mock.ANY),
             mock.call._staple_chrome(
-                self.paths.replace_work('$W_1/AppProduct-99.0.9999.99'),
+                self.paths.replace_work('/$W_1/AppProduct-99.0.9999.99'),
                 mock.ANY),
 
             # Make the DMG.
             mock.call._package_and_sign_dmg(mock.ANY, mock.ANY),
 
             # Notarize the DMG.
-            mock.call.submit('$O/AppProduct-99.0.9999.99.dmg', mock.ANY),
+            mock.call.submit('/$O/AppProduct-99.0.9999.99.dmg', mock.ANY),
             mock.call.wait_for_results({dmg_uuid: None}.keys(), mock.ANY),
-            mock.call.staple('$O/AppProduct-99.0.9999.99.dmg'),
-            mock.call.shutil.rmtree('$W_1'),
+            mock.call.staple('/$O/AppProduct-99.0.9999.99.dmg'),
+            mock.call.shutil.rmtree('/$W_1'),
 
             # Package the installer tools.
             mock.call._package_installer_tools(mock.ANY, mock.ANY),
@@ -825,7 +828,7 @@
             iter([app_uuid]), iter([pkg_uuid])
         ]
         kwargs[
-            '_package_and_sign_pkg'].return_value = '$O/AppProduct-99.0.9999.99.pkg'
+            '_package_and_sign_pkg'].return_value = '/$O/AppProduct-99.0.9999.99.pkg'
 
         class Config(test_config.TestConfig):
 
@@ -844,29 +847,29 @@
         manager.assert_has_calls([
             # First customize the distribution and sign it.
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99', mock.ANY),
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99', mock.ANY),
 
             # Prepare the app for notarization.
             mock.call.run_command([
                 'zip', '--recurse-paths', '--symlinks', '--quiet',
-                '$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
+                '/$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
             ],
-                                  cwd='$W_1/AppProduct-99.0.9999.99'),
-            mock.call.submit('$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
-            mock.call.shutil.rmtree('$W_2'),
+                                  cwd='/$W_1/AppProduct-99.0.9999.99'),
+            mock.call.submit('/$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
+            mock.call.shutil.rmtree('/$W_2'),
             mock.call.wait_for_results({app_uuid: None}.keys(), mock.ANY),
             mock.call._staple_chrome(
-                self.paths.replace_work('$W_1/AppProduct-99.0.9999.99'),
+                self.paths.replace_work('/$W_1/AppProduct-99.0.9999.99'),
                 mock.ANY),
 
             # Make the DMG.
             mock.call._package_and_sign_pkg(mock.ANY, mock.ANY),
 
             # Notarize the DMG.
-            mock.call.submit('$O/AppProduct-99.0.9999.99.pkg', mock.ANY),
+            mock.call.submit('/$O/AppProduct-99.0.9999.99.pkg', mock.ANY),
             mock.call.wait_for_results({pkg_uuid: None}.keys(), mock.ANY),
-            mock.call.staple('$O/AppProduct-99.0.9999.99.pkg'),
-            mock.call.shutil.rmtree('$W_1'),
+            mock.call.staple('/$O/AppProduct-99.0.9999.99.pkg'),
+            mock.call.shutil.rmtree('/$W_1'),
 
             # Package the installer tools.
             mock.call._package_installer_tools(mock.ANY, mock.ANY),
@@ -885,9 +888,9 @@
             iter([app_uuid]), iter([dmg_uuid, pkg_uuid])
         ]
         kwargs[
-            '_package_and_sign_dmg'].return_value = '$O/AppProduct-99.0.9999.99.dmg'
+            '_package_and_sign_dmg'].return_value = '/$O/AppProduct-99.0.9999.99.dmg'
         kwargs[
-            '_package_and_sign_pkg'].return_value = '$O/AppProduct-99.0.9999.99.pkg'
+            '_package_and_sign_pkg'].return_value = '/$O/AppProduct-99.0.9999.99.pkg'
 
         class Config(test_config.TestConfig):
 
@@ -906,37 +909,37 @@
         manager.assert_has_calls([
             # First customize the distribution and sign it.
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99', mock.ANY),
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99', mock.ANY),
 
             # Prepare the app for notarization.
             mock.call.run_command([
                 'zip', '--recurse-paths', '--symlinks', '--quiet',
-                '$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
+                '/$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
             ],
-                                  cwd='$W_1/AppProduct-99.0.9999.99'),
-            mock.call.submit('$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
-            mock.call.shutil.rmtree('$W_2'),
+                                  cwd='/$W_1/AppProduct-99.0.9999.99'),
+            mock.call.submit('/$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
+            mock.call.shutil.rmtree('/$W_2'),
             mock.call.wait_for_results({app_uuid: None}.keys(), mock.ANY),
             mock.call._staple_chrome(
-                self.paths.replace_work('$W_1/AppProduct-99.0.9999.99'),
+                self.paths.replace_work('/$W_1/AppProduct-99.0.9999.99'),
                 mock.ANY),
 
             # Make the DMG, and submit for notarization.
             mock.call._package_and_sign_dmg(mock.ANY, mock.ANY),
-            mock.call.submit('$O/AppProduct-99.0.9999.99.dmg', mock.ANY),
+            mock.call.submit('/$O/AppProduct-99.0.9999.99.dmg', mock.ANY),
 
             # Make the PKG, and submit for notarization.
             mock.call._package_and_sign_pkg(mock.ANY, mock.ANY),
-            mock.call.submit('$O/AppProduct-99.0.9999.99.pkg', mock.ANY),
+            mock.call.submit('/$O/AppProduct-99.0.9999.99.pkg', mock.ANY),
 
             # Wait for notarization results.
             mock.call.wait_for_results({
                 dmg_uuid: None,
                 pkg_uuid: None
             }.keys(), mock.ANY),
-            mock.call.staple('$O/AppProduct-99.0.9999.99.dmg'),
-            mock.call.staple('$O/AppProduct-99.0.9999.99.pkg'),
-            mock.call.shutil.rmtree('$W_1'),
+            mock.call.staple('/$O/AppProduct-99.0.9999.99.dmg'),
+            mock.call.staple('/$O/AppProduct-99.0.9999.99.pkg'),
+            mock.call.shutil.rmtree('/$W_1'),
 
             # Package the installer tools.
             mock.call._package_installer_tools(mock.ANY, mock.ANY),
@@ -957,21 +960,21 @@
         manager.assert_has_calls([
             # First customize the distribution and sign it.
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99', mock.ANY),
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99', mock.ANY),
 
             # Prepare the app for notarization.
             mock.call.run_command([
                 'zip', '--recurse-paths', '--symlinks', '--quiet',
-                '$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
+                '/$W_1/AppProduct-99.0.9999.99.zip', 'App Product.app'
             ],
-                                  cwd='$W_1/AppProduct-99.0.9999.99'),
-            mock.call.submit('$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
-            mock.call.shutil.rmtree('$W_2'),
+                                  cwd='/$W_1/AppProduct-99.0.9999.99'),
+            mock.call.submit('/$W_1/AppProduct-99.0.9999.99.zip', mock.ANY),
+            mock.call.shutil.rmtree('/$W_2'),
             mock.call.wait_for_results({app_uuid: None}.keys(), mock.ANY),
             mock.call._staple_chrome(
-                self.paths.replace_work('$W_1/AppProduct-99.0.9999.99'),
+                self.paths.replace_work('/$W_1/AppProduct-99.0.9999.99'),
                 mock.ANY),
-            mock.call.shutil.rmtree('$W_1'),
+            mock.call.shutil.rmtree('/$W_1'),
 
             # Package the installer tools.
             mock.call._package_installer_tools(mock.ANY, mock.ANY),
@@ -993,12 +996,12 @@
         manager.assert_has_calls([
             # First customize the distribution and sign it.
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99', mock.ANY),
-            mock.call.shutil.rmtree('$W_2'),
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99', mock.ANY),
+            mock.call.shutil.rmtree('/$W_2'),
 
             # Make the DMG.
             mock.call._package_and_sign_dmg(mock.ANY, mock.ANY),
-            mock.call.shutil.rmtree('$W_1'),
+            mock.call.shutil.rmtree('/$W_1'),
 
             # Package the installer tools.
             mock.call._package_installer_tools(mock.ANY, mock.ANY),
@@ -1016,10 +1019,10 @@
         manager.assert_has_calls([
             # First customize the distribution and sign it.
             mock.call._customize_and_sign_chrome(mock.ANY, mock.ANY,
-                                                 '$O/AppProduct-99.0.9999.99',
+                                                 '/$O/AppProduct-99.0.9999.99',
                                                  mock.ANY),
-            mock.call.shutil.rmtree('$W_2'),
-            mock.call.shutil.rmtree('$W_1'),
+            mock.call.shutil.rmtree('/$W_2'),
+            mock.call.shutil.rmtree('/$W_1'),
 
             # Package the installer tools.
             mock.call._package_installer_tools(mock.ANY, mock.ANY),
@@ -1065,38 +1068,38 @@
         manager.assert_has_calls([
             # Customizations.
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99', mock.ANY),
-            mock.call.shutil.rmtree('$W_2'),
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99', mock.ANY),
+            mock.call.shutil.rmtree('/$W_2'),
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99-ForCows-MOO',
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99-ForCows-MOO',
                 mock.ANY),
-            mock.call.shutil.rmtree('$W_3'),
+            mock.call.shutil.rmtree('/$W_3'),
             mock.call._customize_and_sign_chrome(
-                mock.ANY, mock.ANY, '$W_1/AppProduct-99.0.9999.99-ForDogs-ARF',
+                mock.ANY, mock.ANY, '/$W_1/AppProduct-99.0.9999.99-ForDogs-ARF',
                 mock.ANY),
-            mock.call.shutil.rmtree('$W_4'),
+            mock.call.shutil.rmtree('/$W_4'),
             mock.call._customize_and_sign_chrome(
                 mock.ANY, mock.ANY,
-                '$W_1/AppProduct-99.0.9999.99-ForDogcows-MOOF', mock.ANY),
-            mock.call.shutil.rmtree('$W_5'),
+                '/$W_1/AppProduct-99.0.9999.99-ForDogcows-MOOF', mock.ANY),
+            mock.call.shutil.rmtree('/$W_5'),
 
             # Packaging and signing.
             mock.call._package_and_sign_dmg(
-                self.paths.replace_work('$W_1/AppProduct-99.0.9999.99'),
+                self.paths.replace_work('/$W_1/AppProduct-99.0.9999.99'),
                 mock.ANY),
             mock.call._package_and_sign_dmg(
                 self.paths.replace_work(
-                    '$W_1/AppProduct-99.0.9999.99-ForCows-MOO'), mock.ANY),
+                    '/$W_1/AppProduct-99.0.9999.99-ForCows-MOO'), mock.ANY),
             mock.call._package_and_sign_pkg(
                 self.paths.replace_work(
-                    '$W_1/AppProduct-99.0.9999.99-ForDogs-ARF'), mock.ANY),
+                    '/$W_1/AppProduct-99.0.9999.99-ForDogs-ARF'), mock.ANY),
             mock.call._package_and_sign_dmg(
                 self.paths.replace_work(
-                    '$W_1/AppProduct-99.0.9999.99-ForDogcows-MOOF'), mock.ANY),
+                    '/$W_1/AppProduct-99.0.9999.99-ForDogcows-MOOF'), mock.ANY),
             mock.call._package_and_sign_pkg(
                 self.paths.replace_work(
-                    '$W_1/AppProduct-99.0.9999.99-ForDogcows-MOOF'), mock.ANY),
-            mock.call.shutil.rmtree('$W_1'),
+                    '/$W_1/AppProduct-99.0.9999.99-ForDogcows-MOOF'), mock.ANY),
+            mock.call.shutil.rmtree('/$W_1'),
 
             # Finally the installer tools.
             mock.call._package_installer_tools(mock.ANY, mock.ANY),
diff --git a/chrome/installer/mac/signing/signing_test.py b/chrome/installer/mac/signing/signing_test.py
index 02dff33f..347f8db5 100644
--- a/chrome/installer/mac/signing/signing_test.py
+++ b/chrome/installer/mac/signing/signing_test.py
@@ -19,7 +19,7 @@
 class TestSignPart(unittest.TestCase):
 
     def setUp(self):
-        self.paths = model.Paths('$I', '$O', '$W')
+        self.paths = model.Paths('/$I', '/$O', '/$W')
         self.config = test_config.TestConfig()
 
     def test_sign_part(self, run_command):
@@ -27,7 +27,7 @@
         signing.sign_part(self.paths, self.config, part)
         run_command.assert_called_once_with([
             'codesign', '--sign', '[IDENTITY]', '--timestamp', '--requirements',
-            '=designated => identifier "test.signing.app"', '$W/Test.app'
+            '=designated => identifier "test.signing.app"', '/$W/Test.app'
         ])
 
     def test_sign_part_no_notary(self, run_command):
@@ -36,7 +36,7 @@
         signing.sign_part(self.paths, config, part)
         run_command.assert_called_once_with([
             'codesign', '--sign', '[IDENTITY]', '--requirements',
-            '=designated => identifier "test.signing.app"', '$W/Test.app'
+            '=designated => identifier "test.signing.app"', '/$W/Test.app'
         ])
 
     def test_sign_part_no_identifier_requirement(self, run_command):
@@ -44,7 +44,7 @@
             'Test.app', 'test.signing.app', identifier_requirement=False)
         signing.sign_part(self.paths, self.config, part)
         run_command.assert_called_once_with(
-            ['codesign', '--sign', '[IDENTITY]', '--timestamp', '$W/Test.app'])
+            ['codesign', '--sign', '[IDENTITY]', '--timestamp', '/$W/Test.app'])
 
     def test_sign_with_identifier(self, run_command):
         part = model.CodeSignedProduct(
@@ -53,7 +53,7 @@
         run_command.assert_called_once_with([
             'codesign', '--sign', '[IDENTITY]', '--timestamp', '--identifier',
             'test.signing.app', '--requirements',
-            '=designated => identifier "test.signing.app"', '$W/Test.app'
+            '=designated => identifier "test.signing.app"', '/$W/Test.app'
         ])
 
     def test_sign_with_identifier_no_requirement(self, run_command):
@@ -65,7 +65,7 @@
         signing.sign_part(self.paths, self.config, part)
         run_command.assert_called_once_with([
             'codesign', '--sign', '[IDENTITY]', '--timestamp', '--identifier',
-            'test.signing.app', '$W/Test.app'
+            'test.signing.app', '/$W/Test.app'
         ])
 
     def test_sign_part_with_options(self, run_command):
@@ -78,7 +78,7 @@
         run_command.assert_called_once_with([
             'codesign', '--sign', '[IDENTITY]', '--timestamp', '--requirements',
             '=designated => identifier "test.signing.app"', '--options',
-            'restrict,library', '$W/Test.app'
+            'restrict,library', '/$W/Test.app'
         ])
 
     def test_sign_part_with_entitlements(self, run_command):
@@ -90,7 +90,7 @@
         signing.sign_part(self.paths, self.config, part)
         run_command.assert_called_once_with([
             'codesign', '--sign', '[IDENTITY]', '--timestamp', '--entitlements',
-            '$W/entitlements.plist', '$W/Test.app'
+            '/$W/entitlements.plist', '/$W/Test.app'
         ])
 
     def test_verify_part(self, run_command):
@@ -99,9 +99,9 @@
         self.assertEqual(run_command.mock_calls, [
             mock.call([
                 'codesign', '--display', '--verbose=5', '--requirements', '-',
-                '$W/Test.app'
+                '/$W/Test.app'
             ]),
-            mock.call(['codesign', '--verify', '--verbose=6', '$W/Test.app']),
+            mock.call(['codesign', '--verify', '--verbose=6', '/$W/Test.app']),
         ])
 
     def test_verify_part_with_options(self, run_command):
@@ -114,10 +114,10 @@
         self.assertEqual(run_command.mock_calls, [
             mock.call([
                 'codesign', '--display', '--verbose=5', '--requirements', '-',
-                '$W/Test.app'
+                '/$W/Test.app'
             ]),
             mock.call([
                 'codesign', '--verify', '--verbose=6', '--deep',
-                '--ignore-resources', '$W/Test.app'
+                '--ignore-resources', '/$W/Test.app'
             ]),
         ])
diff --git a/chrome/installer/setup/installer_state.cc b/chrome/installer/setup/installer_state.cc
index 6883665..b5e6e41b 100644
--- a/chrome/installer/setup/installer_state.cc
+++ b/chrome/installer/setup/installer_state.cc
@@ -79,6 +79,8 @@
 
   const bool is_uninstall = command_line.HasSwitch(switches::kUninstall);
 
+  // TODO(grt): Infer target_path_ from an existing install in support of
+  // varying install locations; see https://crbug.com/380177.
   target_path_ = GetChromeInstallPath(system_install());
   state_key_ = install_static::GetClientStateKeyPath();
 
diff --git a/chrome/installer/util/BUILD.gn b/chrome/installer/util/BUILD.gn
index 0b770ce..8010633 100644
--- a/chrome/installer/util/BUILD.gn
+++ b/chrome/installer/util/BUILD.gn
@@ -310,7 +310,6 @@
       "experiment_storage_unittest.cc",
       "experiment_unittest.cc",
       "google_update_settings_unittest.cc",
-      "helper_unittest.cc",
       "install_util_unittest.cc",
       "l10n_string_util_unittest.cc",
       "logging_installer_unittest.cc",
diff --git a/chrome/installer/util/helper.cc b/chrome/installer/util/helper.cc
index 1190b20..9019ba94a 100644
--- a/chrome/installer/util/helper.cc
+++ b/chrome/installer/util/helper.cc
@@ -5,56 +5,26 @@
 #include "chrome/installer/util/helper.h"
 
 #include "base/path_service.h"
-#include "base/win/registry.h"
 #include "chrome/install_static/install_util.h"
-#include "chrome/installer/util/install_util.h"
 #include "chrome/installer/util/util_constants.h"
 
-namespace {
-
-base::FilePath GetDefaultChromeInstallPath(bool system_install) {
-  base::FilePath install_path;
-  int key = system_install ? base::DIR_PROGRAM_FILES : base::DIR_LOCAL_APP_DATA;
-  if (base::PathService::Get(key, &install_path)) {
-    install_path =
-        install_path.Append(install_static::GetChromeInstallSubDirectory());
-    install_path = install_path.Append(installer::kInstallBinaryDir);
-  }
-  return install_path;
-}
-
-base::FilePath GetCurrentInstallPathFromRegistry(bool system_install) {
-  base::FilePath install_path;
-  if (!InstallUtil::GetChromeVersion(system_install).IsValid())
-    return install_path;
-
-  std::wstring uninstall_string;
-  base::win::RegKey key(system_install ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
-                        install_static::GetClientStateKeyPath().c_str(),
-                        KEY_QUERY_VALUE | KEY_WOW64_32KEY);
-  key.ReadValue(installer::kUninstallStringField, &uninstall_string);
-
-  // The UninstallString has the format
-  // [InstallPath]/[version]/Installer/setup.exe. In order to get the
-  // [InstallPath], the full path must be pruned of the last 3 components.
-  if (!uninstall_string.empty()) {
-    install_path = base::FilePath(std::move(uninstall_string))
-                       .DirName()
-                       .DirName()
-                       .DirName();
-  }
-  return install_path;
-}
-
-}  // namespace
-
 namespace installer {
 
 base::FilePath GetChromeInstallPath(bool system_install) {
-  base::FilePath install_path =
-      GetCurrentInstallPathFromRegistry(system_install);
-  if (install_path.empty())
-    install_path = GetDefaultChromeInstallPath(system_install);
+  base::FilePath install_path;
+#if defined(_WIN64)
+  // TODO(wfh): Place Chrome binaries into DIR_PROGRAM_FILESX86 until the code
+  // to support moving the binaries is added.
+  int key =
+      system_install ? base::DIR_PROGRAM_FILESX86 : base::DIR_LOCAL_APP_DATA;
+#else
+  int key = system_install ? base::DIR_PROGRAM_FILES : base::DIR_LOCAL_APP_DATA;
+#endif
+  if (base::PathService::Get(key, &install_path)) {
+    install_path =
+        install_path.Append(install_static::GetChromeInstallSubDirectory());
+    install_path = install_path.Append(kInstallBinaryDir);
+  }
   return install_path;
 }
 
diff --git a/chrome/installer/util/helper.h b/chrome/installer/util/helper.h
index 16c4bf7..5dadc32 100644
--- a/chrome/installer/util/helper.h
+++ b/chrome/installer/util/helper.h
@@ -11,14 +11,11 @@
 
 namespace installer {
 
-// This function returns the install path for Chrome depending on whether it's
-// a system wide install or a user specific install.
-// Returns the install path stored at
-// Software\Google\Update\ClientState\{appguid}\UninstallString
-// under HKLM if |system_install| is true, HKCU otherwise. If no path was stored
-// in the registry, returns (%ProgramFiles%\[Company\]Product\Application) if
-// |system_install| is true, otherwise returns user specific location
-// (%LOCALAPPDATA%\[Company\]Product\Application).
+// This function returns the install path for Chrome depending on whether its
+// system wide install or user specific install.
+// system_install: if true, the function returns system wide location
+//                 (ProgramFiles\Google). Otherwise it returns user specific
+//                 location (Document And Settings\<user>\Local Settings...)
 base::FilePath GetChromeInstallPath(bool system_install);
 
 }  // namespace installer
diff --git a/chrome/installer/util/helper_unittest.cc b/chrome/installer/util/helper_unittest.cc
deleted file mode 100644
index f02e9b8..0000000
--- a/chrome/installer/util/helper_unittest.cc
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/installer/util/helper.h"
-
-#include "base/files/file_path.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/optional.h"
-#include "base/path_service.h"
-#include "base/test/scoped_path_override.h"
-#include "base/test/test_reg_util_win.h"
-#include "base/version.h"
-#include "base/win/registry.h"
-#include "chrome/install_static/install_util.h"
-#include "chrome/installer/util/google_update_constants.h"
-#include "chrome/installer/util/util_constants.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace installer {
-
-// Tests GetChromeInstallPath with a boolean parameter which is |true| if the
-// test must use system-level values or |false| it the test must use user-level
-// values.
-class GetChromeInstallPathTest : public testing::TestWithParam<bool> {
- public:
-  GetChromeInstallPathTest() = default;
-
-  void SetUp() override {
-    ASSERT_TRUE(program_files_.CreateUniqueTempDir());
-    ASSERT_TRUE(random_.CreateUniqueTempDir());
-    ASSERT_TRUE(local_app_data_.CreateUniqueTempDir());
-    ASSERT_NO_FATAL_FAILURE(
-        registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE));
-    ASSERT_NO_FATAL_FAILURE(
-        registry_override_manager_.OverrideRegistry(HKEY_CURRENT_USER));
-    program_files_override_.emplace(base::DIR_PROGRAM_FILES,
-                                    program_files_path());
-    local_data_app_override_.emplace(base::DIR_LOCAL_APP_DATA,
-                                     local_app_data_path());
-  }
-
-  base::FilePath random_path() const { return random_.GetPath(); }
-  base::FilePath program_files_path() const { return program_files_.GetPath(); }
-  base::FilePath local_app_data_path() const {
-    return local_app_data_.GetPath();
-  }
-  static bool is_system_level() { return GetParam(); }
-
-  base::FilePath GetExpectedPath(bool system_level) {
-    auto path = system_level ? program_files_path() : local_app_data_path();
-    return path.Append(install_static::GetChromeInstallSubDirectory())
-        .Append(kInstallBinaryDir);
-  }
-
-  static base::win::RegKey GetClientsRegKey() {
-    return base::win::RegKey(
-        is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
-        install_static::GetClientsKeyPath().c_str(),
-        KEY_SET_VALUE | KEY_WOW64_32KEY);
-  }
-
-  static base::win::RegKey GetClientStateRegKey() {
-    return base::win::RegKey(
-        is_system_level() ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER,
-        install_static::GetClientStateKeyPath().c_str(),
-        KEY_SET_VALUE | KEY_WOW64_32KEY);
-  }
-
- private:
-  base::ScopedTempDir program_files_;
-  base::ScopedTempDir random_;
-  base::ScopedTempDir local_app_data_;
-  registry_util::RegistryOverrideManager registry_override_manager_;
-  base::Optional<base::ScopedPathOverride> program_files_override_;
-  base::Optional<base::ScopedPathOverride> local_data_app_override_;
-};
-
-TEST_P(GetChromeInstallPathTest, NoRegistryValue) {
-  EXPECT_EQ(GetChromeInstallPath(is_system_level()),
-            GetExpectedPath(is_system_level()));
-}
-
-TEST_P(GetChromeInstallPathTest, RegistryValueSet) {
-  base::win::RegKey client_state_key(GetClientStateRegKey());
-  ASSERT_EQ(client_state_key.WriteValue(
-                kUninstallStringField,
-                random_path()
-                    .Append(install_static::GetChromeInstallSubDirectory())
-                    .Append(kInstallBinaryDir)
-                    .AppendASCII("1.0.0.0\\Installer\\setup.exe")
-                    .value()
-                    .c_str()),
-            ERROR_SUCCESS);
-
-  base::win::RegKey client_key(GetClientsRegKey());
-  ASSERT_EQ(client_key.WriteValue(google_update::kRegVersionField, L"1.0.0.0"),
-            ERROR_SUCCESS);
-  EXPECT_EQ(GetChromeInstallPath(is_system_level()),
-            random_path()
-                .Append(install_static::GetChromeInstallSubDirectory())
-                .Append(kInstallBinaryDir));
-}
-
-TEST_P(GetChromeInstallPathTest, RegistryValueSetWrongScope) {
-  base::win::RegKey client_state_key(GetClientStateRegKey());
-  ASSERT_EQ(client_state_key.WriteValue(
-                kUninstallStringField,
-                random_path()
-                    .Append(install_static::GetChromeInstallSubDirectory())
-                    .Append(kInstallBinaryDir)
-                    .AppendASCII("1.0.0.0\\Installer\\setup.exe")
-                    .value()
-                    .c_str()),
-            ERROR_SUCCESS);
-
-  base::win::RegKey client_key(GetClientsRegKey());
-  ASSERT_EQ(client_key.WriteValue(google_update::kRegVersionField, L"1.0.0.0"),
-            ERROR_SUCCESS);
-  EXPECT_EQ(GetChromeInstallPath(!is_system_level()),
-            GetExpectedPath(!is_system_level()));
-}
-
-TEST_P(GetChromeInstallPathTest, RegistryValueSetNoProductVersion) {
-  base::win::RegKey client_state_key(GetClientStateRegKey());
-  ASSERT_EQ(client_state_key.WriteValue(
-                kUninstallStringField,
-                random_path()
-                    .Append(install_static::GetChromeInstallSubDirectory())
-                    .Append(kInstallBinaryDir)
-                    .AppendASCII("1.0.0.0\\Installer\\setup.exe")
-                    .value()
-                    .c_str()),
-            ERROR_SUCCESS);
-  EXPECT_EQ(GetChromeInstallPath(is_system_level()),
-            GetExpectedPath(is_system_level()));
-}
-
-INSTANTIATE_TEST_SUITE_P(UserLevelTest,
-                         GetChromeInstallPathTest,
-                         testing::Values(false));
-INSTANTIATE_TEST_SUITE_P(SystemLevelTest,
-                         GetChromeInstallPathTest,
-                         testing::Values(true));
-
-}  // namespace installer
diff --git a/chrome/installer/util/shell_util.cc b/chrome/installer/util/shell_util.cc
index 51f0092..8c53f45 100644
--- a/chrome/installer/util/shell_util.cc
+++ b/chrome/installer/util/shell_util.cc
@@ -872,8 +872,11 @@
 base::string16 GetInstallationSuffixForModeAtLevel(
     const install_static::InstallConstants& mode,
     bool system_install) {
-  // Search based on the existing install location. If no existing install
-  // found, uses the default install location for the mode.
+  // Search based on the default install location for the mode. If we ever
+  // support customizing the install location (https://crbug.com/113987,
+  // https://crbug.com/302491) this will have to change to something else, such
+  // as probing the Omaha keys in the registry to see where the mode is
+  // installed.
   const base::FilePath chrome_exe =
       installer::GetChromeInstallPath(system_install)
           .Append(installer::kChromeExe);
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc
index 51f7952..4e44e14 100644
--- a/chrome/renderer/chrome_content_renderer_client.cc
+++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -86,7 +86,7 @@
 #include "components/page_load_metrics/renderer/metrics_render_frame_observer.h"
 #include "components/paint_preview/buildflags/buildflags.h"
 #include "components/pdf/renderer/pepper_pdf_host.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 #include "components/safe_browsing/buildflags.h"
 #include "components/safe_browsing/content/renderer/threat_dom_details.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
diff --git a/chrome/renderer/chrome_render_frame_observer.cc b/chrome/renderer/chrome_render_frame_observer.cc
index ac6ba14b9..e4857f0 100644
--- a/chrome/renderer/chrome_render_frame_observer.cc
+++ b/chrome/renderer/chrome_render_frame_observer.cc
@@ -22,13 +22,13 @@
 #include "chrome/common/chrome_isolated_world_ids.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/common/open_search_description_document_handler.mojom.h"
-#include "chrome/common/prerender_messages.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/renderer/media/media_feeds.h"
 #include "chrome/renderer/prerender/prerender_helper.h"
 #include "chrome/renderer/web_apps.h"
 #include "components/crash/core/common/crash_key.h"
 #include "components/offline_pages/buildflags/buildflags.h"
+#include "components/prerender/common/prerender_messages.h"
 #include "components/translate/content/renderer/translate_agent.h"
 #include "components/translate/core/common/translate_util.h"
 #include "components/web_cache/renderer/web_cache_impl.h"
@@ -134,7 +134,7 @@
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
   if (!command_line.HasSwitch(switches::kDisableClientSidePhishingDetection))
-    SetClientSidePhishingDetection(true);
+    SetClientSidePhishingDetection();
 #endif
   if (!translate::IsSubFrameTranslationEnabled()) {
     translate_agent_ =
@@ -193,6 +193,120 @@
   return handled;
 }
 
+void ChromeRenderFrameObserver::ReadyToCommitNavigation(
+    WebDocumentLoader* document_loader) {
+  // Execute cache clear operations that were postponed until a navigation
+  // event (including tab reload).
+  if (render_frame()->IsMainFrame() && web_cache_impl_)
+    web_cache_impl_->ExecutePendingClearCache();
+
+  // Let translate_agent do any preparatory work for loading a URL.
+  if (!translate_agent_)
+    return;
+
+  translate_agent_->PrepareForUrl(
+      render_frame()->GetWebFrame()->GetDocument().Url());
+}
+
+void ChromeRenderFrameObserver::DidFinishLoad() {
+  WebLocalFrame* frame = render_frame()->GetWebFrame();
+  // Don't do anything for subframes.
+  if (frame->Parent())
+    return;
+
+  GURL osdd_url = frame->GetDocument().OpenSearchDescriptionURL();
+  if (!osdd_url.is_empty()) {
+    mojo::AssociatedRemote<chrome::mojom::OpenSearchDescriptionDocumentHandler>
+        osdd_handler;
+    render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
+        &osdd_handler);
+    osdd_handler->PageHasOpenSearchDescriptionDocument(
+        frame->GetDocument().Url(), osdd_url);
+  }
+}
+
+void ChromeRenderFrameObserver::DidCreateNewDocument() {
+#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
+  DCHECK(render_frame());
+  if (!render_frame()->IsMainFrame())
+    return;
+
+  DCHECK(render_frame()->GetWebFrame());
+  blink::WebDocumentLoader* doc_loader =
+      render_frame()->GetWebFrame()->GetDocumentLoader();
+  DCHECK(doc_loader);
+
+  if (!doc_loader->HasBeenLoadedAsWebArchive())
+    return;
+
+  // Connect to Mojo service on browser to notify it of the page's archive
+  // properties.
+  mojo::AssociatedRemote<offline_pages::mojom::MhtmlPageNotifier>
+      mhtml_notifier;
+  render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
+      &mhtml_notifier);
+  DCHECK(mhtml_notifier);
+  blink::WebArchiveInfo info = doc_loader->GetArchiveInfo();
+
+  mhtml_notifier->NotifyMhtmlPageLoadAttempted(info.load_result, info.url,
+                                               info.date);
+#endif
+}
+
+void ChromeRenderFrameObserver::DidCommitProvisionalLoad(
+    bool is_same_document_navigation,
+    ui::PageTransition transition) {
+  WebLocalFrame* frame = render_frame()->GetWebFrame();
+
+  // Don't do anything for subframes.
+  if (frame->Parent())
+    return;
+
+  static crash_reporter::CrashKeyString<8> view_count_key("view-count");
+  view_count_key.Set(
+      base::NumberToString(content::RenderView::GetRenderViewCount()));
+
+#if !defined(OS_ANDROID)
+  if (render_frame()->GetEnabledBindings() &
+      content::kWebUIBindingsPolicyMask) {
+    for (const auto& script : webui_javascript_)
+      render_frame()->ExecuteJavaScript(script);
+    webui_javascript_.clear();
+  }
+#endif
+}
+
+void ChromeRenderFrameObserver::DidClearWindowObject() {
+#if !defined(OS_ANDROID)
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kInstantProcess))
+    SearchBoxExtension::Install(render_frame()->GetWebFrame());
+#endif  // !defined(OS_ANDROID)
+}
+
+void ChromeRenderFrameObserver::DidMeaningfulLayout(
+    blink::WebMeaningfulLayout layout_type) {
+  // Don't do any work for subframes.
+  if (!render_frame()->IsMainFrame())
+    return;
+
+  switch (layout_type) {
+    case blink::WebMeaningfulLayout::kFinishedParsing:
+      CapturePageText(PRELIMINARY_CAPTURE);
+      break;
+    case blink::WebMeaningfulLayout::kFinishedLoading:
+      CapturePageText(FINAL_CAPTURE);
+      break;
+    default:
+      break;
+  }
+}
+
+void ChromeRenderFrameObserver::OnDestruct() {
+  delete this;
+}
+
 void ChromeRenderFrameObserver::OnSetIsPrerendering(
     prerender::PrerenderMode mode,
     const std::string& histogram_prefix) {
@@ -210,14 +324,17 @@
   }
 }
 
-void ChromeRenderFrameObserver::RequestReloadImageForContextNode() {
-  WebLocalFrame* frame = render_frame()->GetWebFrame();
-  // TODO(dglazkov): This code is clearly in the wrong place. Need
-  // to investigate what it is doing and fix (http://crbug.com/606164).
-  WebNode context_node = frame->ContextMenuNode();
-  if (!context_node.IsNull()) {
-    frame->ReloadImage(context_node);
-  }
+void ChromeRenderFrameObserver::SetWindowFeatures(
+    blink::mojom::WindowFeaturesPtr window_features) {
+  render_frame()->GetRenderView()->GetWebView()->SetWindowFeatures(
+      content::ConvertMojoWindowFeaturesToWebWindowFeatures(*window_features));
+}
+
+void ChromeRenderFrameObserver::ExecuteWebUIJavaScript(
+    const base::string16& javascript) {
+#if !defined(OS_ANDROID)
+  webui_javascript_.push_back(javascript);
+#endif
 }
 
 void ChromeRenderFrameObserver::RequestImageForContextNode(
@@ -294,6 +411,16 @@
   std::move(callback).Run(image_data, original_size, image_extension);
 }
 
+void ChromeRenderFrameObserver::RequestReloadImageForContextNode() {
+  WebLocalFrame* frame = render_frame()->GetWebFrame();
+  // TODO(dglazkov): This code is clearly in the wrong place. Need
+  // to investigate what it is doing and fix (http://crbug.com/606164).
+  WebNode context_node = frame->ContextMenuNode();
+  if (!context_node.IsNull()) {
+    frame->ReloadImage(context_node);
+  }
+}
+
 void ChromeRenderFrameObserver::GetWebApplicationInfo(
     GetWebApplicationInfoCallback callback) {
   WebLocalFrame* frame = render_frame()->GetWebFrame();
@@ -345,114 +472,17 @@
   std::move(callback).Run(MediaFeeds::GetMediaFeedURL(render_frame()));
 }
 
-void ChromeRenderFrameObserver::SetClientSidePhishingDetection(
-    bool enable_phishing_detection) {
+void ChromeRenderFrameObserver::SetClientSidePhishingDetection() {
 #if BUILDFLAG(SAFE_BROWSING_CSD)
-  phishing_classifier_ =
-      enable_phishing_detection
-          ? safe_browsing::PhishingClassifierDelegate::Create(render_frame(),
-                                                              nullptr)
-          : nullptr;
+  phishing_classifier_ = safe_browsing::PhishingClassifierDelegate::Create(
+      render_frame(), nullptr);
 #endif
 }
 
-void ChromeRenderFrameObserver::ExecuteWebUIJavaScript(
-    const base::string16& javascript) {
-#if !defined(OS_ANDROID)
-  webui_javascript_.push_back(javascript);
-#endif
-}
-
-void ChromeRenderFrameObserver::DidFinishLoad() {
-  WebLocalFrame* frame = render_frame()->GetWebFrame();
-  // Don't do anything for subframes.
-  if (frame->Parent())
-    return;
-
-  GURL osdd_url = frame->GetDocument().OpenSearchDescriptionURL();
-  if (!osdd_url.is_empty()) {
-    mojo::AssociatedRemote<chrome::mojom::OpenSearchDescriptionDocumentHandler>
-        osdd_handler;
-    render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
-        &osdd_handler);
-    osdd_handler->PageHasOpenSearchDescriptionDocument(
-        frame->GetDocument().Url(), osdd_url);
-  }
-}
-
-void ChromeRenderFrameObserver::DidCreateNewDocument() {
-#if BUILDFLAG(ENABLE_OFFLINE_PAGES)
-  DCHECK(render_frame());
-  if (!render_frame()->IsMainFrame())
-    return;
-
-  DCHECK(render_frame()->GetWebFrame());
-  blink::WebDocumentLoader* doc_loader =
-      render_frame()->GetWebFrame()->GetDocumentLoader();
-  DCHECK(doc_loader);
-
-  if (!doc_loader->HasBeenLoadedAsWebArchive())
-    return;
-
-  // Connect to Mojo service on browser to notify it of the page's archive
-  // properties.
-  mojo::AssociatedRemote<offline_pages::mojom::MhtmlPageNotifier>
-      mhtml_notifier;
-  render_frame()->GetRemoteAssociatedInterfaces()->GetInterface(
-      &mhtml_notifier);
-  DCHECK(mhtml_notifier);
-  blink::WebArchiveInfo info = doc_loader->GetArchiveInfo();
-
-  mhtml_notifier->NotifyMhtmlPageLoadAttempted(info.load_result, info.url,
-                                               info.date);
-#endif
-}
-
-void ChromeRenderFrameObserver::ReadyToCommitNavigation(
-    WebDocumentLoader* document_loader) {
-  // Execute cache clear operations that were postponed until a navigation
-  // event (including tab reload).
-  if (render_frame()->IsMainFrame() && web_cache_impl_)
-    web_cache_impl_->ExecutePendingClearCache();
-
-  // Let translate_agent do any preparatory work for loading a URL.
-  if (!translate_agent_)
-    return;
-
-  translate_agent_->PrepareForUrl(
-      render_frame()->GetWebFrame()->GetDocument().Url());
-}
-
-void ChromeRenderFrameObserver::DidCommitProvisionalLoad(
-    bool is_same_document_navigation,
-    ui::PageTransition transition) {
-  WebLocalFrame* frame = render_frame()->GetWebFrame();
-
-  // Don't do anything for subframes.
-  if (frame->Parent())
-    return;
-
-  static crash_reporter::CrashKeyString<8> view_count_key("view-count");
-  view_count_key.Set(
-      base::NumberToString(content::RenderView::GetRenderViewCount()));
-
-#if !defined(OS_ANDROID)
-  if (render_frame()->GetEnabledBindings() &
-      content::kWebUIBindingsPolicyMask) {
-    for (const auto& script : webui_javascript_)
-      render_frame()->ExecuteJavaScript(script);
-    webui_javascript_.clear();
-  }
-#endif
-}
-
-void ChromeRenderFrameObserver::DidClearWindowObject() {
-#if !defined(OS_ANDROID)
-  const base::CommandLine& command_line =
-      *base::CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kInstantProcess))
-    SearchBoxExtension::Install(render_frame()->GetWebFrame());
-#endif  // !defined(OS_ANDROID)
+void ChromeRenderFrameObserver::OnRenderFrameObserverRequest(
+    mojo::PendingAssociatedReceiver<chrome::mojom::ChromeRenderFrame>
+        receiver) {
+  receivers_.Add(this, std::move(receiver));
 }
 
 void ChromeRenderFrameObserver::CapturePageText(TextCaptureType capture_type) {
@@ -517,39 +547,6 @@
 #endif
 }
 
-void ChromeRenderFrameObserver::DidMeaningfulLayout(
-    blink::WebMeaningfulLayout layout_type) {
-  // Don't do any work for subframes.
-  if (!render_frame()->IsMainFrame())
-    return;
-
-  switch (layout_type) {
-    case blink::WebMeaningfulLayout::kFinishedParsing:
-      CapturePageText(PRELIMINARY_CAPTURE);
-      break;
-    case blink::WebMeaningfulLayout::kFinishedLoading:
-      CapturePageText(FINAL_CAPTURE);
-      break;
-    default:
-      break;
-  }
-}
-
-void ChromeRenderFrameObserver::OnDestruct() {
-  delete this;
-}
-
-void ChromeRenderFrameObserver::OnRenderFrameObserverRequest(
-    mojo::PendingAssociatedReceiver<chrome::mojom::ChromeRenderFrame>
-        receiver) {
-  receivers_.Add(this, std::move(receiver));
-}
-
-void ChromeRenderFrameObserver::SetWindowFeatures(
-    blink::mojom::WindowFeaturesPtr window_features) {
-  render_frame()->GetRenderView()->GetWebView()->SetWindowFeatures(
-      content::ConvertMojoWindowFeaturesToWebWindowFeatures(*window_features));
-}
 
 // static
 bool ChromeRenderFrameObserver::NeedsDownscale(
diff --git a/chrome/renderer/chrome_render_frame_observer.h b/chrome/renderer/chrome_render_frame_observer.h
index cf3c336..216e835 100644
--- a/chrome/renderer/chrome_render_frame_observer.h
+++ b/chrome/renderer/chrome_render_frame_observer.h
@@ -12,7 +12,7 @@
 #include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "chrome/common/chrome_render_frame.mojom.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 #include "components/safe_browsing/buildflags.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "mojo/public/cpp/bindings/associated_receiver_set.h"
@@ -93,13 +93,15 @@
       chrome::mojom::ImageFormat image_format,
       RequestImageForContextNodeCallback callback) override;
   void RequestReloadImageForContextNode() override;
-  void SetClientSidePhishingDetection(bool enable_phishing_detection) override;
   void GetWebApplicationInfo(GetWebApplicationInfoCallback callback) override;
 #if defined(OS_ANDROID)
   void SetCCTClientHeader(const std::string& header) override;
 #endif
   void GetMediaFeedURL(GetMediaFeedURLCallback callback) override;
 
+  // Initialize a |phishing_classifier_delegate_|.
+  void SetClientSidePhishingDetection();
+
   void OnRenderFrameObserverRequest(
       mojo::PendingAssociatedReceiver<chrome::mojom::ChromeRenderFrame>
           receiver);
@@ -150,4 +152,4 @@
   DISALLOW_COPY_AND_ASSIGN(ChromeRenderFrameObserver);
 };
 
-#endif  // CHROME_RENDERER_CHROME_RENDER_FRAME_OBSERVER_H_
\ No newline at end of file
+#endif  // CHROME_RENDERER_CHROME_RENDER_FRAME_OBSERVER_H_
diff --git a/chrome/renderer/extensions/platform_keys_natives.cc b/chrome/renderer/extensions/platform_keys_natives.cc
index 831e007c..22551ad 100644
--- a/chrome/renderer/extensions/platform_keys_natives.cc
+++ b/chrome/renderer/extensions/platform_keys_natives.cc
@@ -10,8 +10,8 @@
 
 #include "base/bind.h"
 #include "base/values.h"
-#include "content/public/renderer/v8_value_converter.h"
 #include "extensions/renderer/script_context.h"
+#include "gin/data_object_builder.h"
 #include "third_party/blink/public/platform/web_crypto_algorithm.h"
 #include "third_party/blink/public/platform/web_crypto_algorithm_params.h"
 #include "third_party/blink/public/platform/web_string.h"
@@ -43,14 +43,17 @@
   return false;
 }
 
-std::unique_ptr<base::DictionaryValue> WebCryptoAlgorithmToBaseValue(
-    const blink::WebCryptoAlgorithm& algorithm) {
+v8::Local<v8::Object> WebCryptoAlgorithmToV8Value(
+    const blink::WebCryptoAlgorithm& algorithm,
+    v8::Local<v8::Context> context) {
   DCHECK(!algorithm.IsNull());
+  v8::Context::Scope scope(context);
+  v8::Isolate* isolate = context->GetIsolate();
 
-  std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue);
   const blink::WebCryptoAlgorithmInfo* info =
       blink::WebCryptoAlgorithm::LookupAlgorithmInfo(algorithm.Id());
-  dict->SetKey("name", base::Value(info->name));
+  gin::DataObjectBuilder builder(isolate);
+  builder.Set("name", base::StringPiece(info->name));
 
   const blink::WebCryptoAlgorithm* hash = nullptr;
 
@@ -59,16 +62,15 @@
       const blink::WebCryptoRsaHashedKeyGenParams* rsa_hashed_key_gen =
           algorithm.RsaHashedKeyGenParams();
       if (rsa_hashed_key_gen) {
-        dict->SetKey("modulusLength",
-                     base::Value(static_cast<int>(
-                         rsa_hashed_key_gen->ModulusLengthBits())));
+        builder.Set("modulusLength", rsa_hashed_key_gen->ModulusLengthBits());
+
         const blink::WebVector<unsigned char>& public_exponent =
             rsa_hashed_key_gen->PublicExponent();
-        dict->SetWithoutPathExpansion(
-            "publicExponent",
-            base::Value::CreateWithCopiedBuffer(
-                reinterpret_cast<const char*>(public_exponent.Data()),
-                public_exponent.size()));
+        v8::Local<v8::ArrayBuffer> buffer =
+            v8::ArrayBuffer::New(isolate, public_exponent.size());
+        memcpy(buffer->GetContents().Data(), public_exponent.Data(),
+               public_exponent.size());
+        builder.Set("publicExponent", buffer);
 
         hash = &rsa_hashed_key_gen->GetHash();
         DCHECK(!hash->IsNull());
@@ -85,7 +87,7 @@
       const blink::WebCryptoEcKeyGenParams* ec_key_gen =
           algorithm.EcKeyGenParams();
       if (ec_key_gen) {
-        std::string named_curve;
+        base::StringPiece named_curve;
         switch (ec_key_gen->NamedCurve()) {
           case blink::kWebCryptoNamedCurveP256:
             named_curve = "P-256";
@@ -98,7 +100,7 @@
             break;
         }
         DCHECK(!named_curve.empty());
-        dict->SetKey("namedCurve", base::Value(std::move(named_curve)));
+        builder.Set("namedCurve", named_curve);
       }
 
       const blink::WebCryptoEcdsaParams* ecdsa = algorithm.EcdsaParams();
@@ -117,13 +119,13 @@
     const blink::WebCryptoAlgorithmInfo* hash_info =
         blink::WebCryptoAlgorithm::LookupAlgorithmInfo(hash->Id());
 
-    std::unique_ptr<base::DictionaryValue> hash_dict(new base::DictionaryValue);
-    hash_dict->SetKey("name", base::Value(hash_info->name));
-    dict->SetWithoutPathExpansion("hash", std::move(hash_dict));
+    builder.Set("hash", gin::DataObjectBuilder(isolate)
+                            .Set("name", base::StringPiece(hash_info->name))
+                            .Build());
   }
   // Otherwise, |algorithm| is missing support here or no parameters were
   // required.
-  return dict;
+  return builder.Build();
 }
 
 }  // namespace
@@ -158,15 +160,11 @@
       v8::Local<v8::Object>::Cast(call_info[0]), operation, &exception_code,
       &error_details, call_info.GetIsolate());
 
-  std::unique_ptr<base::DictionaryValue> algorithm_dict;
-  if (!algorithm.IsNull())
-    algorithm_dict = WebCryptoAlgorithmToBaseValue(algorithm);
-
-  if (!algorithm_dict)
+  if (algorithm.IsNull())
     return;
 
-  call_info.GetReturnValue().Set(content::V8ValueConverter::Create()->ToV8Value(
-      algorithm_dict.get(), context()->v8_context()));
+  call_info.GetReturnValue().Set(
+      WebCryptoAlgorithmToV8Value(algorithm, context()->v8_context()));
 }
 
 }  // namespace extensions
diff --git a/chrome/renderer/media/chrome_speech_recognition_client.cc b/chrome/renderer/media/chrome_speech_recognition_client.cc
index 2b35d6d..a255f37 100644
--- a/chrome/renderer/media/chrome_speech_recognition_client.cc
+++ b/chrome/renderer/media/chrome_speech_recognition_client.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "content/public/renderer/render_frame.h"
+#include "media/base/channel_mixer.h"
 #include "media/mojo/mojom/media_types.mojom.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 
@@ -17,13 +18,20 @@
           speech_recognition_context_.BindNewPipeAndPassReceiver();
   speech_recognition_context_->BindRecognizer(
       speech_recognition_recognizer_.BindNewPipeAndPassReceiver(),
-      speech_recognition_client_receiver_.BindNewPipeAndPassRemote());
+      speech_recognition_client_receiver_.BindNewPipeAndPassRemote(),
+      base::BindOnce(&ChromeSpeechRecognitionClient::OnRecognizerBound,
+                     base::Unretained(this)));
   render_frame->GetBrowserInterfaceBroker()->GetInterface(
       std::move(speech_recognition_context_receiver));
   render_frame->GetBrowserInterfaceBroker()->GetInterface(
       caption_host_.BindNewPipeAndPassReceiver());
 }
 
+void ChromeSpeechRecognitionClient::OnRecognizerBound(
+    bool is_multichannel_supported) {
+  is_multichannel_supported_ = is_multichannel_supported;
+}
+
 ChromeSpeechRecognitionClient::~ChromeSpeechRecognitionClient() = default;
 
 void ChromeSpeechRecognitionClient::AddAudio(
@@ -36,14 +44,51 @@
 }
 
 bool ChromeSpeechRecognitionClient::IsSpeechRecognitionAvailable() {
-  return speech_recognition_recognizer_.is_bound() &&
+  return is_browser_requesting_transcription_ &&
+         speech_recognition_recognizer_.is_bound() &&
          speech_recognition_recognizer_.is_connected();
 }
 
 void ChromeSpeechRecognitionClient::OnSpeechRecognitionRecognitionEvent(
     media::mojom::SpeechRecognitionResultPtr result) {
-  caption_host_->OnTranscription(chrome::mojom::TranscriptionResult::New(
-      result->transcription, result->is_final));
+  caption_host_->OnTranscription(
+      chrome::mojom::TranscriptionResult::New(result->transcription,
+                                              result->is_final),
+      base::BindOnce(&ChromeSpeechRecognitionClient::OnTranscriptionCallback,
+                     base::Unretained(this)));
+}
+
+void ChromeSpeechRecognitionClient::OnTranscriptionCallback(bool success) {
+  is_browser_requesting_transcription_ = success;
+}
+
+void ChromeSpeechRecognitionClient::CopyBufferToTempAudioBus(
+    const media::AudioBuffer& buffer) {
+  if (!temp_audio_bus_ ||
+      buffer.channel_count() != temp_audio_bus_->channels() ||
+      buffer.frame_count() != temp_audio_bus_->frames()) {
+    temp_audio_bus_ =
+        media::AudioBus::Create(buffer.channel_count(), buffer.frame_count());
+  }
+
+  buffer.ReadFrames(buffer.frame_count(),
+                    /* source_frame_offset */ 0, /* dest_frame_offset */ 0,
+                    temp_audio_bus_.get());
+}
+
+void ChromeSpeechRecognitionClient::ResetChannelMixer(
+    const media::AudioBuffer& buffer) {
+  if (!monaural_audio_bus_ ||
+      buffer.frame_count() != monaural_audio_bus_->frames()) {
+    monaural_audio_bus_ =
+        media::AudioBus::Create(1 /* channels */, buffer.frame_count());
+  }
+
+  if (buffer.channel_layout() != channel_layout_) {
+    channel_layout_ = buffer.channel_layout();
+    channel_mixer_ = std::make_unique<media::ChannelMixer>(
+        buffer.channel_layout(), media::CHANNEL_LAYOUT_MONO);
+  }
 }
 
 media::mojom::AudioDataS16Ptr
@@ -58,6 +103,21 @@
   signed_buffer->frame_count = buffer->frame_count();
   signed_buffer->sample_rate = buffer->sample_rate();
 
+  // If multichannel audio is not supported by the speech recognition service,
+  // mix the channels into a monaural channel before converting it.
+  if (buffer->channel_count() > 1 && !is_multichannel_supported_) {
+    signed_buffer->channel_count = 1;
+    CopyBufferToTempAudioBus(*buffer);
+    ResetChannelMixer(*buffer);
+    signed_buffer->data.resize(buffer->frame_count());
+    channel_mixer_->Transform(temp_audio_bus_.get(), monaural_audio_bus_.get());
+    monaural_audio_bus_->ToInterleaved<media::SignedInt16SampleTypeTraits>(
+        monaural_audio_bus_->frames(), &signed_buffer->data[0]);
+    return signed_buffer;
+  }
+
+  // If the audio is already in the interleaved signed int 16 format, directly
+  // assign it to the buffer.
   if (buffer->sample_format() == media::SampleFormat::kSampleFormatS16) {
     int16_t* audio_data = reinterpret_cast<int16_t*>(buffer->channel_data()[0]);
     signed_buffer->data.assign(
@@ -67,17 +127,7 @@
   }
 
   // Convert the raw audio to the interleaved signed int 16 sample type.
-  if (!temp_audio_bus_ ||
-      buffer->channel_count() != temp_audio_bus_->channels() ||
-      buffer->frame_count() != temp_audio_bus_->frames()) {
-    temp_audio_bus_ =
-        media::AudioBus::Create(buffer->channel_count(), buffer->frame_count());
-  }
-
-  buffer->ReadFrames(buffer->frame_count(),
-                     /* source_frame_offset */ 0, /* dest_frame_offset */ 0,
-                     temp_audio_bus_.get());
-
+  CopyBufferToTempAudioBus(*buffer);
   signed_buffer->data.resize(buffer->frame_count() * buffer->channel_count());
   temp_audio_bus_->ToInterleaved<media::SignedInt16SampleTypeTraits>(
       temp_audio_bus_->frames(), &signed_buffer->data[0]);
diff --git a/chrome/renderer/media/chrome_speech_recognition_client.h b/chrome/renderer/media/chrome_speech_recognition_client.h
index 5f08b42..1a27698e 100644
--- a/chrome/renderer/media/chrome_speech_recognition_client.h
+++ b/chrome/renderer/media/chrome_speech_recognition_client.h
@@ -19,6 +19,10 @@
 class RenderFrame;
 }  // namespace content
 
+namespace media {
+class ChannelMixer;
+}  // namespace media
+
 class ChromeSpeechRecognitionClient
     : public media::SpeechRecognitionClient,
       public media::mojom::SpeechRecognitionRecognizerClient {
@@ -33,6 +37,10 @@
   void AddAudio(scoped_refptr<media::AudioBuffer> buffer) override;
   bool IsSpeechRecognitionAvailable() override;
 
+  // Callback executed when the recognizer is bound. Sets the flag indicating
+  // whether the speech recognition service supports multichannel audio.
+  void OnRecognizerBound(bool is_multichannel_supported);
+
   // media::mojom::SpeechRecognitionRecognizerClient
   void OnSpeechRecognitionRecognitionEvent(
       media::mojom::SpeechRecognitionResultPtr result) override;
@@ -41,6 +49,16 @@
   media::mojom::AudioDataS16Ptr ConvertToAudioDataS16(
       scoped_refptr<media::AudioBuffer> buffer);
 
+  // Called as a response to sending a transcription to the browser.
+  void OnTranscriptionCallback(bool success);
+  // Recreates the temporary audio bus if the frame count or channel count
+  // changed and reads the frames from the buffer into the temporary audio bus.
+  void CopyBufferToTempAudioBus(const media::AudioBuffer& buffer);
+
+  // Resets the temporary monaural audio bus and the channel mixer used to
+  // combine multiple audio channels.
+  void ResetChannelMixer(const media::AudioBuffer& buffer);
+
   mojo::Remote<media::mojom::SpeechRecognitionContext>
       speech_recognition_context_;
   mojo::Remote<media::mojom::SpeechRecognitionRecognizer>
@@ -52,6 +70,22 @@
   // The temporary audio bus used to convert the raw audio to the appropriate
   // format.
   std::unique_ptr<media::AudioBus> temp_audio_bus_;
+
+  // Whether the browser is still requesting transcriptions.
+  bool is_browser_requesting_transcription_ = true;
+  // The temporary audio bus used to mix multichannel audio into a single
+  // channel.
+  std::unique_ptr<media::AudioBus> monaural_audio_bus_;
+
+  std::unique_ptr<media::ChannelMixer> channel_mixer_;
+
+  // The layout used to instantiate the channel mixer.
+  media::ChannelLayout channel_layout_ =
+      media::ChannelLayout::CHANNEL_LAYOUT_NONE;
+
+  // A flag indicating whether the speech recognition service supports
+  // multichannel audio.
+  bool is_multichannel_supported_ = false;
 };
 
 #endif  // CHROME_RENDERER_MEDIA_CHROME_SPEECH_RECOGNITION_CLIENT_H_
diff --git a/chrome/renderer/net/net_error_helper_core_unittest.cc b/chrome/renderer/net/net_error_helper_core_unittest.cc
index c24b4c7..1220513 100644
--- a/chrome/renderer/net/net_error_helper_core_unittest.cc
+++ b/chrome/renderer/net/net_error_helper_core_unittest.cc
@@ -171,7 +171,7 @@
                                public NetErrorHelperCore::Delegate {
  public:
   NetErrorHelperCoreTest()
-      : timer_(NULL),
+      : timer_(nullptr),
         update_count_(0),
         error_html_update_count_(0),
         reload_count_(0),
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.cc b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
index 4410ede..f72df2d 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.cc
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.cc
@@ -15,7 +15,6 @@
 #include "base/values.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/chrome_features.h"
-#include "chrome/common/prerender_messages.h"
 #include "chrome/common/render_messages.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/grit/renderer_resources.h"
@@ -24,6 +23,7 @@
 #include "chrome/renderer/plugins/plugin_preroller.h"
 #include "chrome/renderer/plugins/plugin_uma.h"
 #include "components/content_settings/renderer/content_settings_agent_impl.h"
+#include "components/prerender/common/prerender_messages.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/untrustworthy_context_menu_params.h"
diff --git a/chrome/renderer/plugins/chrome_plugin_placeholder.h b/chrome/renderer/plugins/chrome_plugin_placeholder.h
index a01632cc..0cb58f0 100644
--- a/chrome/renderer/plugins/chrome_plugin_placeholder.h
+++ b/chrome/renderer/plugins/chrome_plugin_placeholder.h
@@ -13,7 +13,7 @@
 #include "chrome/common/plugin.mojom.h"
 #include "chrome/renderer/plugins/power_saver_info.h"
 #include "components/plugins/renderer/loadable_plugin_placeholder.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/renderer/context_menu_client.h"
 #include "content/public/renderer/render_thread_observer.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chrome/renderer/prerender/prerender_helper.cc b/chrome/renderer/prerender/prerender_helper.cc
index 2097753f..05f6567 100644
--- a/chrome/renderer/prerender/prerender_helper.cc
+++ b/chrome/renderer/prerender/prerender_helper.cc
@@ -6,8 +6,8 @@
 
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
-#include "chrome/common/prerender_messages.h"
 #include "chrome/common/prerender_url_loader_throttle.h"
+#include "components/prerender/common/prerender_messages.h"
 #include "content/public/renderer/document_state.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_thread.h"
@@ -43,7 +43,8 @@
   if (!prerender_helper)
     return nullptr;
 
-  mojo::PendingRemote<chrome::mojom::PrerenderCanceler> canceler;
+  mojo::PendingRemote<components::prerender::common::mojom::PrerenderCanceler>
+      canceler;
   render_frame->GetBrowserInterfaceBroker()->GetInterface(
       canceler.InitWithNewPipeAndPassReceiver());
 
diff --git a/chrome/renderer/prerender/prerender_helper.h b/chrome/renderer/prerender/prerender_helper.h
index 2d9ebe65..8570ba4 100644
--- a/chrome/renderer/prerender/prerender_helper.h
+++ b/chrome/renderer/prerender/prerender_helper.h
@@ -9,7 +9,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/time/time.h"
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "content/public/renderer/render_frame_observer_tracker.h"
 
diff --git a/chrome/renderer/safe_browsing/phishing_classifier.cc b/chrome/renderer/safe_browsing/phishing_classifier.cc
index 2d0492b..35b5f416 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier.cc
@@ -11,7 +11,6 @@
 #include "base/callback.h"
 #include "base/compiler_specific.h"
 #include "base/location.h"
-#include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_util.h"
@@ -49,11 +48,13 @@
 PhishingClassifier::~PhishingClassifier() {
   // The RenderView should have called CancelPendingClassification() before
   // we are destroyed.
-  CheckNoPendingClassification();
+  DCHECK(done_callback_.is_null());
+  DCHECK(!page_text_);
 }
 
 void PhishingClassifier::set_phishing_scorer(const Scorer* scorer) {
-  CheckNoPendingClassification();
+  DCHECK(done_callback_.is_null());
+  DCHECK(!page_text_);
   scorer_ = scorer;
   if (scorer_) {
     url_extractor_.reset(new PhishingUrlFeatureExtractor);
@@ -85,7 +86,8 @@
 
   // The RenderView should have called CancelPendingClassification() before
   // starting a new classification, so DCHECK this.
-  CheckNoPendingClassification();
+  DCHECK(done_callback_.is_null());
+  DCHECK(!page_text_);
   // However, in an opt build, we will go ahead and clean up the pending
   // classification so that we can start in a known state.
   CancelPendingClassification();
@@ -220,15 +222,6 @@
   RunCallback(verdict);
 }
 
-void PhishingClassifier::CheckNoPendingClassification() {
-  DCHECK(done_callback_.is_null());
-  DCHECK(!page_text_);
-  if (!done_callback_.is_null() || page_text_) {
-    LOG(ERROR) << "Classification in progress, missing call to "
-               << "CancelPendingClassification";
-  }
-}
-
 void PhishingClassifier::RunCallback(const ClientPhishingRequest& verdict) {
   std::move(done_callback_).Run(verdict);
   Clear();
diff --git a/chrome/renderer/safe_browsing/phishing_classifier.h b/chrome/renderer/safe_browsing/phishing_classifier.h
index f6f5aad2..309cb15 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier.h
+++ b/chrome/renderer/safe_browsing/phishing_classifier.h
@@ -124,11 +124,6 @@
   // non-phishy verdict.
   void VisualExtractionFinished(bool success);
 
-  // Helper to verify that there is no pending phishing classification.  Dies
-  // in debug builds if the state is not as expected.  This is a no-op in
-  // release builds.
-  void CheckNoPendingClassification();
-
   // Helper method to run the DoneCallback and clear the state.
   void RunCallback(const ClientPhishingRequest& verdict);
 
diff --git a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
index 77db494..f5763a6 100644
--- a/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
+++ b/chrome/renderer/safe_browsing/phishing_classifier_delegate.cc
@@ -12,7 +12,6 @@
 #include "base/callback.h"
 #include "base/debug/stack_trace.h"
 #include "base/lazy_instance.h"
-#include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
 #include "chrome/renderer/safe_browsing/feature_extractor_clock.h"
@@ -185,8 +184,8 @@
   have_page_text_ = true;
 
   GURL stripped_last_load_url(StripRef(last_finished_load_url_));
+  // Check if toplevel URL has changed.
   if (stripped_last_load_url == StripRef(last_url_sent_to_classifier_)) {
-    DVLOG(2) << "Toplevel URL is unchanged, not starting classification.";
     return;
   }
 
@@ -214,8 +213,6 @@
 
 void PhishingClassifierDelegate::ClassificationDone(
     const ClientPhishingRequest& verdict) {
-  DVLOG(2) << "Phishy verdict = " << verdict.is_phishing()
-           << " score = " << verdict.client_score();
   is_phishing_detection_running_ = false;
   if (callback_.is_null())
     return;
@@ -244,7 +241,6 @@
   // classified at all (as opposed to deferring it until we get an IPC or
   // the load completes), we discard the page text since it won't be needed.
   if (!classifier_->is_ready()) {
-    DVLOG(2) << "Not starting classification, no Scorer created.";
     is_phishing_detection_running_ = false;
     // Keep classifier_page_text_, in case a Scorer is set later.
     if (!callback_.is_null())
@@ -257,7 +253,6 @@
     // Skip loads from session history navigation.  However, update the
     // last URL sent to the classifier, so that we'll properly detect
     // same-document navigations.
-    DVLOG(2) << "Not starting classification for back/forward navigation";
     last_url_sent_to_classifier_ = last_finished_load_url_;
     classifier_page_text_.clear();  // we won't need this.
     have_page_text_ = false;
@@ -270,7 +265,6 @@
 
   GURL stripped_last_load_url(StripRef(last_finished_load_url_));
   if (!have_page_text_) {
-    DVLOG(2) << "Not starting classification, there is no page text ready.";
     RecordEvent(SBPhishingClassifierEvent::kPageTextNotLoaded);
     return;
   }
@@ -281,15 +275,11 @@
     // so defer classification for now.  Note: the ref does not affect
     // any of the browser's preclassification checks, so we don't require it
     // to match.
-    DVLOG(2) << "Not starting classification, last url from browser is "
-             << last_url_received_from_browser_ << ", last finished load is "
-             << last_finished_load_url_;
     // Keep classifier_page_text_, in case the browser notifies us later that
     // we should classify the URL.
     return;
   }
 
-  DVLOG(2) << "Starting classification for " << last_finished_load_url_;
   last_url_sent_to_classifier_ = last_finished_load_url_;
   is_classifying_ = true;
   classifier_->BeginClassification(
diff --git a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
index e64fd77..672e41e 100644
--- a/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
+++ b/chrome/renderer/safe_browsing/phishing_dom_feature_extractor_browsertest.cc
@@ -106,9 +106,6 @@
         const std::string frame_domain = it->second;
         full_url = GURL("http://" + it->second).Resolve(partial_url.Utf8());
         url_to_frame_domain_map_[full_url.spec()] = it->second;
-      } else {
-        NOTREACHED() << "Testing input setup is incorrect. "
-                        "Please check url_to_frame_domain_map_ setup.";
       }
     }
     return blink::WebURL(full_url);
diff --git a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc
index 535186b72..5349a31 100644
--- a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc
+++ b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.cc
@@ -15,7 +15,6 @@
 #include "base/i18n/break_iterator.h"
 #include "base/i18n/case_conversion.h"
 #include "base/location.h"
-#include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/utf_string_conversions.h"
@@ -74,11 +73,8 @@
     std::unique_ptr<base::i18n::BreakIterator> i(new base::i18n::BreakIterator(
         text, base::i18n::BreakIterator::BREAK_WORD));
 
-    if (i->Init()) {
+    if (i->Init())
       iterator = std::move(i);
-    } else {
-      DLOG(ERROR) << "failed to open iterator";
-    }
   }
 };
 
@@ -103,7 +99,8 @@
 PhishingTermFeatureExtractor::~PhishingTermFeatureExtractor() {
   // The RenderView should have called CancelPendingExtraction() before
   // we are destroyed.
-  CheckNoPendingExtraction();
+  DCHECK(done_callback_.is_null());
+  DCHECK(!state_.get());
 }
 
 void PhishingTermFeatureExtractor::ExtractFeatures(
@@ -113,7 +110,8 @@
     DoneCallback done_callback) {
   // The RenderView should have called CancelPendingExtraction() before
   // starting a new extraction, so DCHECK this.
-  CheckNoPendingExtraction();
+  DCHECK(done_callback_.is_null());
+  DCHECK(!state_.get());
   // However, in an opt build, we will go ahead and clean up the pending
   // extraction so that we can start in a known state.
   CancelPendingExtraction();
@@ -161,7 +159,6 @@
       base::TimeTicks now = clock_->Now();
       if (now - state_->start_time >=
           base::TimeDelta::FromMilliseconds(kMaxTotalTimeMs)) {
-        DLOG(ERROR) << "Feature extraction took too long, giving up";
         // We expect this to happen infrequently, so record when it does.
         UMA_HISTOGRAM_COUNTS_1M("SBClientPhishing.TermFeatureTimeout", 1);
         RunCallback(false);
@@ -261,15 +258,6 @@
   }
 }
 
-void PhishingTermFeatureExtractor::CheckNoPendingExtraction() {
-  DCHECK(done_callback_.is_null());
-  DCHECK(!state_.get());
-  if (!done_callback_.is_null() || state_.get()) {
-    LOG(ERROR) << "Extraction in progress, missing call to "
-               << "CancelPendingExtraction";
-  }
-}
-
 void PhishingTermFeatureExtractor::RunCallback(bool success) {
   // Record some timing stats that we can use to evaluate feature extraction
   // performance.  These include both successful and failed extractions.
diff --git a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.h b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.h
index d0cc48d..788caec3 100644
--- a/chrome/renderer/safe_browsing/phishing_term_feature_extractor.h
+++ b/chrome/renderer/safe_browsing/phishing_term_feature_extractor.h
@@ -115,11 +115,6 @@
   // Handles a single word in the page text.
   void HandleWord(const base::StringPiece16& word);
 
-  // Helper to verify that there is no pending feature extraction.  Dies in
-  // debug builds if the state is not as expected.  This is a no-op in release
-  // builds.
-  void CheckNoPendingExtraction();
-
   // Runs |done_callback_| and then clears all internal state.
   void RunCallback(bool success);
 
diff --git a/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc b/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc
index 931c520..403d1d06 100644
--- a/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc
+++ b/chrome/renderer/safe_browsing/phishing_url_feature_extractor.cc
@@ -8,7 +8,6 @@
 #include <string>
 #include <vector>
 
-#include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -44,8 +43,8 @@
             host, net::registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
             net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
 
+    // Check if TLD exists for host.
     if (registry_length == 0 || registry_length == std::string::npos) {
-      DVLOG(1) << "Could not find TLD for host: " << host;
       return false;
     }
     DCHECK_LT(registry_length, host.size()) << "Non-zero registry length, but "
@@ -59,8 +58,8 @@
     host.erase(tld_start - 1);
     std::vector<std::string> host_tokens = base::SplitString(
         host, ".", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+    // Check if domain exists for host.
     if (host_tokens.empty()) {
-      DVLOG(1) << "Could not find domain for host: " << host;
       return false;
     }
     if (!features->AddBooleanFeature(features::kUrlDomainToken +
diff --git a/chrome/renderer/safe_browsing/scorer.cc b/chrome/renderer/safe_browsing/scorer.cc
index a04122ad..d396b012 100644
--- a/chrome/renderer/safe_browsing/scorer.cc
+++ b/chrome/renderer/safe_browsing/scorer.cc
@@ -58,14 +58,12 @@
 Scorer* Scorer::Create(const base::StringPiece& model_str) {
   std::unique_ptr<Scorer> scorer(new Scorer());
   ClientSideModel& model = scorer->model_;
+  // Parse the phishing model.
   if (!model.ParseFromArray(model_str.data(), model_str.size())) {
-    DLOG(ERROR) << "Unable to parse phishing model.  This Scorer object is "
-                << "invalid.";
     RecordScorerCreationStatus(SCORER_FAIL_MODEL_PARSE_ERROR);
     return NULL;
   } else if (!model.IsInitialized()) {
-    DLOG(ERROR) << "Unable to parse phishing model.  The model is missing "
-                << "some required fields.  Maybe the .proto file changed?";
+    // The model may be missing some required fields.
     RecordScorerCreationStatus(SCORER_FAIL_MODEL_MISSING_FIELDS);
     return NULL;
   }
diff --git a/chrome/service/cloud_print/cloud_print_url_fetcher.cc b/chrome/service/cloud_print/cloud_print_url_fetcher.cc
index f9f2fd69..7c565da9 100644
--- a/chrome/service/cloud_print/cloud_print_url_fetcher.cc
+++ b/chrome/service/cloud_print/cloud_print_url_fetcher.cc
@@ -129,7 +129,7 @@
 
 CloudPrintURLFetcher::CloudPrintURLFetcher(
     const net::PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
-    : delegate_(NULL),
+    : delegate_(nullptr),
       num_retries_(0),
       type_(REQUEST_MAX),
       partial_traffic_annotation_(partial_traffic_annotation) {}
diff --git a/chrome/service/cloud_print/printer_job_handler_unittest.cc b/chrome/service/cloud_print/printer_job_handler_unittest.cc
index 3bd5b2d..4b7bb28 100644
--- a/chrome/service/cloud_print/printer_job_handler_unittest.cc
+++ b/chrome/service/cloud_print/printer_job_handler_unittest.cc
@@ -630,20 +630,19 @@
   CloudPrintURLFetcher::set_test_factory(nullptr);
 }
 
-MockPrintServerWatcher::MockPrintServerWatcher() : delegate_(NULL) {
+MockPrintServerWatcher::MockPrintServerWatcher() : delegate_(nullptr) {
   ON_CALL(*this, StartWatching(_))
       .WillByDefault(DoAll(SaveArg<0>(&delegate_), Return(true)));
   ON_CALL(*this, StopWatching()).WillByDefault(Return(true));
 }
 
-
-MockPrinterWatcher::MockPrinterWatcher() : delegate_(NULL) {
+MockPrinterWatcher::MockPrinterWatcher() : delegate_(nullptr) {
   ON_CALL(*this, StartWatching(_))
       .WillByDefault(DoAll(SaveArg<0>(&delegate_), Return(true)));
   ON_CALL(*this, StopWatching()).WillByDefault(Return(true));
 }
 
-MockJobSpooler::MockJobSpooler() : delegate_(NULL) {
+MockJobSpooler::MockJobSpooler() : delegate_(nullptr) {
   ON_CALL(*this, Spool(_, _, _, _, _, _, _, _))
       .WillByDefault(DoAll(SaveArg<7>(&delegate_), Return(true)));
 }
diff --git a/chrome/services/speech/BUILD.gn b/chrome/services/speech/BUILD.gn
index ebfdec78..26ea9cb8 100644
--- a/chrome/services/speech/BUILD.gn
+++ b/chrome/services/speech/BUILD.gn
@@ -12,6 +12,8 @@
 
 source_set("lib") {
   sources = [
+    "cloud_speech_recognition_client.cc",
+    "cloud_speech_recognition_client.h",
     "speech_recognition_recognizer_impl.cc",
     "speech_recognition_recognizer_impl.h",
     "speech_recognition_service_impl.cc",
@@ -27,10 +29,32 @@
   deps = [
     ":buildflags",
     "//base",
-    "//services/service_manager/public/cpp",
+    "//components/speech",
+    "//content/browser/speech/proto",
+    "//mojo/public/cpp/bindings",
+    "//net",
+    "//services/network/public/cpp",
+    "//services/network/public/mojom",
   ]
 
   if (enable_soda) {
     deps += [ "//chrome/services/soda/internal" ]
   }
 }
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [ "cloud_speech_recognition_client_unittest.cc" ]
+
+  deps = [
+    ":lib",
+    "//base",
+    "//base/test:test_support",
+    "//chrome/test:test_support",
+    "//components/speech",
+    "//content/browser/speech/proto",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
diff --git a/chrome/services/speech/DEPS b/chrome/services/speech/DEPS
index 6d6606d..8f8d843 100644
--- a/chrome/services/speech/DEPS
+++ b/chrome/services/speech/DEPS
@@ -1,5 +1,11 @@
 include_rules = [
   "+chrome/services/soda/internal",
+  "+chrome/services/speech",
   "+components/soda/constants.h",
+  "+components/speech",
+  "+content/browser/speech",
+  "+google_apis",
   "+media",
+  "+services/network",
+  "+third_party/blink/public/mojom/speech",
 ]
diff --git a/chrome/services/speech/cloud_speech_recognition_client.cc b/chrome/services/speech/cloud_speech_recognition_client.cc
new file mode 100644
index 0000000..611d14d
--- /dev/null
+++ b/chrome/services/speech/cloud_speech_recognition_client.cc
@@ -0,0 +1,211 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/services/speech/cloud_speech_recognition_client.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_util.h"
+#include "content/browser/speech/proto/google_streaming_api.pb.h"
+#include "google_apis/google_api_keys.h"
+#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "net/base/escape.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
+#include "services/network/public/mojom/chunked_data_pipe_getter.mojom.h"
+#include "url/gurl.h"
+
+namespace speech {
+
+// The maximum duration a stream can be open for. The Open Speech API supports 5
+// minutes of continuous recognition.
+constexpr base::TimeDelta kStreamResetDuration =
+    base::TimeDelta::FromSeconds(295);
+
+constexpr char kWebServiceBaseUrl[] =
+    "https://www.google.com/speech-api/full-duplex/v1";
+constexpr char kDownstreamUrl[] = "/down";
+constexpr char kUpstreamUrl[] = "/up";
+
+CloudSpeechRecognitionClient::CloudSpeechRecognitionClient(
+    OnRecognitionEventCallback callback,
+    base::WeakPtr<SpeechRecognitionServiceImpl> speech_recognition_service_impl)
+    : recognition_event_callback_(callback),
+      speech_recognition_service_impl_(
+          std::move(speech_recognition_service_impl)) {
+  ResetUrlLoaderFactory();
+}
+
+CloudSpeechRecognitionClient::~CloudSpeechRecognitionClient() = default;
+
+bool CloudSpeechRecognitionClient::DidAudioPropertyChange(int sample_rate,
+                                                          int channel_count) {
+  return sample_rate != sample_rate_ || channel_count != channel_count_;
+}
+
+void CloudSpeechRecognitionClient::Initialize(const CloudSpeechConfig& config) {
+  channel_count_ = config.channel_count;
+  sample_rate_ = config.sample_rate;
+  language_code_ = config.language_code;
+  is_initialized_ = true;
+  Reset();
+}
+
+void CloudSpeechRecognitionClient::OnDownstreamDataReceived(
+    base::StringPiece new_response_data) {
+  // The downstream response is organized in chunks, whose size is determined
+  // by a 4 bytes prefix, transparently handled by the ChunkedByteBuffer class.
+  // Such chunks are sent by the speech recognition webservice over the HTTP
+  // downstream channel using HTTP chunked transfer (unrelated to our chunks).
+  // This function is called every time an HTTP chunk is received by the
+  // url fetcher. However there isn't any particular matching between our
+  // protocol chunks and HTTP chunks, in the sense that a single HTTP chunk can
+  // contain a portion of one chunk or even more chunks together.
+  chunked_byte_buffer_.Append(new_response_data);
+
+  // A single HTTP chunk can contain more than one data chunk, thus the while.
+  while (chunked_byte_buffer_.HasChunks()) {
+    auto chunk = chunked_byte_buffer_.PopChunk();
+    content::proto::SpeechRecognitionEvent event;
+    if (!event.ParseFromArray(chunk->data(), chunk->size() * sizeof(uint8_t))) {
+      DLOG(ERROR) << "Parsing of the recognition response failed.";
+      return;
+    }
+
+    std::string result;
+    for (const auto& recognition_result : event.result()) {
+      if (recognition_result.has_stability()) {
+        for (const auto& alternative : recognition_result.alternative()) {
+          if (alternative.has_transcript())
+            result += alternative.transcript();
+        }
+      }
+    }
+
+    recognition_event_callback().Run(result, false);
+  }
+}
+
+void CloudSpeechRecognitionClient::Reset() {
+  DCHECK(is_initialized_);
+
+  // Return if the URL loader factory has not been set.
+  if (!url_loader_factory_)
+    return;
+
+  last_reset_ = base::Time::Now();
+  const std::string request_key = base::UnguessableToken::Create().ToString();
+
+  // Setup downstream fetcher.
+  GURL downstream_url(base::StringPrintf(
+      "%s%s?key=%s&pair=%s&output=pb", kWebServiceBaseUrl, kDownstreamUrl,
+      net::EscapeQueryParamValue(google_apis::GetAPIKey(), true).c_str(),
+      net::EscapeQueryParamValue(request_key, true).c_str()));
+
+  net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("cloud_speech_recognition",
+                                          R"(
+        semantics {
+          sender: "Speech Recognition"
+          description:
+            "Chrome provides transcription from output audio by using the "
+            "Google speech recognition web service. Audio is sent to Google's "
+            "servers (upstream) and text is returned (downstream). This "
+            "network request (downstream) sends an id for getting the text "
+            "response. Then the (upstream) request sends the audio data along "
+            "with the id. When the server has finished processing the audio "
+            "data and produced a text response, it replies to this request."
+          trigger:
+            "Generally triggered in direct response to a user playing a "
+            "media with audio."
+          data: "A unique random id for this speech recognition request and "
+            "the audio output stream."
+          destination: GOOGLE_OWNED_SERVICE
+        }
+        policy {
+          cookies_allowed: NO
+          setting:
+            "The Live Caption feature can be enabled/disabled in the Chrome "
+            "accessibility settings menu. The feature is disabled by default."
+          chrome_policy {
+            AudioCaptureAllowed {
+              policy_options {mode: MANDATORY}
+              AudioCaptureAllowed: false
+            }
+          }
+          chrome_policy {
+            AudioCaptureAllowedUrls {
+              policy_options {mode: MANDATORY}
+              AudioCaptureAllowedUrls: {}
+            }
+          }
+        })");
+  auto downstream_request = std::make_unique<network::ResourceRequest>();
+  downstream_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+  downstream_request->url = downstream_url;
+  downstream_loader_ = std::make_unique<speech::DownstreamLoader>(
+      std::move(downstream_request), traffic_annotation,
+      url_loader_factory_.get(), this);
+
+  // Setup upstream fetcher.
+  GURL upstream_url(base::StringPrintf(
+      "%s%s?key=%s&pair=%s&output=pb&lang=%s&pFilter=0&maxAlternatives=1&app="
+      "chrome&continuous&interim",
+      kWebServiceBaseUrl, kUpstreamUrl,
+      net::EscapeQueryParamValue(google_apis::GetAPIKey(), true).c_str(),
+      net::EscapeQueryParamValue(request_key, true).c_str(),
+      net::EscapeQueryParamValue(language_code_, true).c_str()));
+
+  auto upstream_request = std::make_unique<network::ResourceRequest>();
+  upstream_request->url = upstream_url;
+  upstream_request->method = "POST";
+  upstream_request->credentials_mode = network::mojom::CredentialsMode::kOmit;
+  upstream_request->headers.SetHeader(
+      net::HttpRequestHeaders::kContentType,
+      "audio/l16; rate=" + base::NumberToString(sample_rate_));
+  upstream_loader_ = std::make_unique<speech::UpstreamLoader>(
+      std::move(upstream_request), traffic_annotation,
+      url_loader_factory_.get(), this);
+}
+
+void CloudSpeechRecognitionClient::AddAudio(base::span<const char> chunk) {
+  DCHECK(is_initialized_);
+  if (base::Time::Now() - last_reset_ > kStreamResetDuration) {
+    Reset();
+  }
+
+  upstream_loader_->AppendChunkToUpload(std::string(chunk.data(), chunk.size()),
+                                        false);
+}
+
+void CloudSpeechRecognitionClient::SetUrlLoaderFactoryForTesting(
+    mojo::PendingRemote<network::mojom::URLLoaderFactory> factory) {
+  url_loader_factory_ =
+      mojo::Remote<network::mojom::URLLoaderFactory>(std::move(factory));
+}
+
+void CloudSpeechRecognitionClient::ResetUrlLoaderFactory() {
+  downstream_loader_.reset();
+  upstream_loader_.reset();
+  url_loader_factory_.reset();
+
+  if (!speech_recognition_service_impl_)
+    return;
+
+  url_loader_factory_ = mojo::Remote<network::mojom::URLLoaderFactory>(
+      speech_recognition_service_impl_->GetUrlLoaderFactory());
+
+  url_loader_factory_.set_disconnect_handler(
+      base::BindOnce(&CloudSpeechRecognitionClient::ResetUrlLoaderFactory,
+                     base::Unretained(this)));
+
+  if (!is_initialized_)
+    return;
+
+  Reset();
+}
+
+}  // namespace speech
diff --git a/chrome/services/speech/cloud_speech_recognition_client.h b/chrome/services/speech/cloud_speech_recognition_client.h
new file mode 100644
index 0000000..350c2d8
--- /dev/null
+++ b/chrome/services/speech/cloud_speech_recognition_client.h
@@ -0,0 +1,107 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_SERVICES_SPEECH_CLOUD_SPEECH_RECOGNITION_CLIENT_H_
+#define CHROME_SERVICES_SPEECH_CLOUD_SPEECH_RECOGNITION_CLIENT_H_
+
+#include "base/callback.h"
+#include "base/containers/span.h"
+#include "base/memory/weak_ptr.h"
+#include "base/strings/string_piece.h"
+#include "base/unguessable_token.h"
+#include "chrome/services/speech/speech_recognition_service_impl.h"
+#include "components/speech/downstream_loader.h"
+#include "components/speech/downstream_loader_client.h"
+#include "components/speech/upstream_loader.h"
+#include "components/speech/upstream_loader_client.h"
+#include "content/browser/speech/chunked_byte_buffer.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace speech {
+
+// Encapsulates the configuration parameters used to initialize the stream.
+struct CloudSpeechConfig {
+  int sample_rate;
+  int channel_count;
+  std::string language_code;
+};
+
+// Streams audio to the Open Speech API to generate transcriptions. This is a
+// temporary solution that will enable testing and experimentation of the Live
+// Caption feature while the Speech On-Device API (SODA) is under development.
+// Much of this implementation overlaps with that of the SpeechRecognitionEngine
+// used by the WebSpeech API. This code is intentionally kept separate from the
+// WebSpeech API implementation to reduce code churn once this client is removed
+// and replaced with the SodaClient.
+class CloudSpeechRecognitionClient : public speech::UpstreamLoaderClient,
+                                     public speech::DownstreamLoaderClient {
+ public:
+  using OnRecognitionEventCallback =
+      base::RepeatingCallback<void(const std::string& result,
+                                   const bool is_final)>;
+
+  explicit CloudSpeechRecognitionClient(
+      OnRecognitionEventCallback callback,
+      base::WeakPtr<SpeechRecognitionServiceImpl>
+          speech_recognition_service_impl);
+  ~CloudSpeechRecognitionClient() override;
+
+  // Checks whether the sample rate or channel count differs from the values
+  // used to initialize the stream.
+  bool DidAudioPropertyChange(int sample_rate, int channel_count);
+
+  // Initializes the stream instance with the provided config.
+  void Initialize(const CloudSpeechConfig& config);
+
+  // speech::DownstreamLoaderClient
+  void OnDownstreamDataReceived(base::StringPiece new_response_data) override;
+  void OnDownstreamDataComplete(bool success, int response_code) override {}
+
+  // speech::UpstreamLoaderClient
+  void OnUpstreamDataComplete(bool success, int response_code) override {}
+
+  // Resets the stream instance.
+  void Reset();
+
+  // Feeds raw audio to the Open Speech API.
+  void AddAudio(base::span<const char> chunk);
+
+  void SetUrlLoaderFactoryForTesting(
+      mojo::PendingRemote<network::mojom::URLLoaderFactory> factory);
+
+  // Returns a flag indicating whether the stream has been initialized.
+  bool IsInitialized() { return is_initialized_; }
+
+  OnRecognitionEventCallback recognition_event_callback() {
+    return recognition_event_callback_;
+  }
+
+ private:
+  friend class speech::UpstreamLoader;
+  friend class speech::DownstreamLoader;
+  void ResetUrlLoaderFactory();
+
+  bool is_initialized_ = false;
+  int sample_rate_ = 0;
+  int channel_count_ = 0;
+  std::string language_code_;
+
+  // Stores the last time the stream was reset.
+  base::Time last_reset_;
+
+  OnRecognitionEventCallback recognition_event_callback_;
+
+  std::unique_ptr<speech::UpstreamLoader> upstream_loader_;
+  std::unique_ptr<speech::DownstreamLoader> downstream_loader_;
+
+  // Remote owned by the SpeechRecognitionServiceImpl.
+  mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_;
+  base::WeakPtr<SpeechRecognitionServiceImpl> speech_recognition_service_impl_;
+
+  content::ChunkedByteBuffer chunked_byte_buffer_;
+};
+
+}  // namespace speech
+
+#endif  // CHROME_SERVICES_SPEECH_CLOUD_SPEECH_RECOGNITION_CLIENT_H_
diff --git a/chrome/services/speech/cloud_speech_recognition_client_unittest.cc b/chrome/services/speech/cloud_speech_recognition_client_unittest.cc
new file mode 100644
index 0000000..c97645bc
--- /dev/null
+++ b/chrome/services/speech/cloud_speech_recognition_client_unittest.cc
@@ -0,0 +1,484 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/services/speech/cloud_speech_recognition_client.h"
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/containers/queue.h"
+#include "base/containers/span.h"
+#include "base/numerics/safe_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/sys_byteorder.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "chrome/services/speech/speech_recognition_service_impl.h"
+#include "chrome/test/base/testing_browser_process.h"
+#include "content/browser/speech/proto/google_streaming_api.pb.h"
+#include "content/public/test/browser_task_environment.h"
+#include "media/base/bind_to_current_loop.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/bindings/remote.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"
+#include "third_party/blink/public/mojom/speech/speech_recognition_error.mojom.h"
+#include "third_party/blink/public/mojom/speech/speech_recognition_result.mojom.h"
+
+using base::checked_cast;
+using base::HostToNet32;
+
+namespace speech {
+
+// The number of bytes in the dummy audio.
+constexpr uint32_t kDummyAudioBytes = 4000;
+
+class SpeechRecognitionServiceImplMock : public SpeechRecognitionServiceImpl {
+ public:
+  explicit SpeechRecognitionServiceImplMock(
+      mojo::PendingReceiver<media::mojom::SpeechRecognitionService> receiver);
+
+  mojo::PendingRemote<network::mojom::URLLoaderFactory> GetUrlLoaderFactory()
+      override;
+  std::vector<network::TestURLLoaderFactory::PendingRequest>*
+  GetPendingRequests();
+  int GetNumPending();
+
+  void ResetNetwork();
+
+  // private:
+  // Instantiate a TestURLLoaderFactory which we can use to respond and unpause
+  // network requests.
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  mojo::Receiver<network::mojom::URLLoaderFactory> test_factory_receiver_;
+};
+
+class CloudSpeechRecognitionClientUnitTest : public testing::Test {
+ public:
+  CloudSpeechRecognitionClientUnitTest();
+
+  // testing::Test methods.
+  void SetUp() override;
+
+ protected:
+  void OnRecognitionEvent(const std::string& result, const bool is_final);
+
+  void InjectDummyAudio();
+
+  void InitializeUpstreamPipeIfNecessary();
+
+  // Reads and returns all pending upload data from |upstream_data_pipe_|,
+  // initializing the pipe from |GetUpstreamRequest()|, if needed.
+  std::string ConsumeChunkedUploadData(uint32_t expected_num_bytes);
+
+  const network::TestURLLoaderFactory::PendingRequest* GetUpstreamRequest();
+  const network::TestURLLoaderFactory::PendingRequest* GetDownstreamRequest();
+
+  void ProvideMockResponseStartDownstreamIfNeeded();
+  void ProvideMockStringResponseDownstream(const std::string& response_string);
+  void ProvideMockProtoResultDownstream(
+      const content::proto::SpeechRecognitionEvent& result);
+  void ProvideMockResultDownstream(std::vector<std::string> result_strings);
+  static std::string SerializeProtobufResponse(
+      const content::proto::SpeechRecognitionEvent& msg);
+  void ExpectResultsReceived(const std::vector<std::string>& expected_results);
+
+  std::unique_ptr<CloudSpeechRecognitionClient> client_under_test_;
+  std::unique_ptr<SpeechRecognitionServiceImplMock>
+      speech_recognition_service_impl_;
+  mojo::Remote<media::mojom::SpeechRecognitionService> remote_;
+
+  mojo::ScopedDataPipeProducerHandle downstream_data_pipe_;
+  mojo::Remote<network::mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter_;
+  mojo::ScopedDataPipeConsumerHandle upstream_data_pipe_;
+  base::queue<std::string> results_;
+  content::BrowserTaskEnvironment task_environment_{
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+};
+
+SpeechRecognitionServiceImplMock::SpeechRecognitionServiceImplMock(
+    mojo::PendingReceiver<media::mojom::SpeechRecognitionService> receiver)
+    : SpeechRecognitionServiceImpl(std::move(receiver)),
+      test_factory_receiver_(&test_url_loader_factory_) {
+  TestingBrowserProcess::GetGlobal()->SetSharedURLLoaderFactory(
+      base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+          &test_url_loader_factory_));
+}
+
+mojo::PendingRemote<network::mojom::URLLoaderFactory>
+SpeechRecognitionServiceImplMock::GetUrlLoaderFactory() {
+  return test_factory_receiver_.BindNewPipeAndPassRemote();
+}
+
+std::vector<network::TestURLLoaderFactory::PendingRequest>*
+SpeechRecognitionServiceImplMock::GetPendingRequests() {
+  return test_url_loader_factory_.pending_requests();
+}
+
+int SpeechRecognitionServiceImplMock::GetNumPending() {
+  return test_url_loader_factory_.NumPending();
+}
+
+void SpeechRecognitionServiceImplMock::ResetNetwork() {
+  test_factory_receiver_.reset();
+}
+
+CloudSpeechRecognitionClientUnitTest::CloudSpeechRecognitionClientUnitTest() =
+    default;
+
+void CloudSpeechRecognitionClientUnitTest::SetUp() {
+  client_under_test_ = std::make_unique<CloudSpeechRecognitionClient>(
+      media::BindToCurrentLoop(
+          base::Bind(&CloudSpeechRecognitionClientUnitTest::OnRecognitionEvent,
+                     base::Unretained(this))),
+      nullptr);
+
+  speech_recognition_service_impl_ =
+      std::make_unique<SpeechRecognitionServiceImplMock>(
+          remote_.BindNewPipeAndPassReceiver());
+
+  client_under_test_->SetUrlLoaderFactoryForTesting(
+      speech_recognition_service_impl_->GetUrlLoaderFactory());
+
+  CloudSpeechConfig config;
+  config.sample_rate = 48000;
+  config.channel_count = 2;
+  config.language_code = "en-US";
+  client_under_test_->Initialize(config);
+
+  // Run the loop to guarantee that the upstream and downstream loaders have
+  // started.
+  while (!GetUpstreamRequest() || !GetDownstreamRequest()) {
+    task_environment_.RunUntilIdle();
+  }
+}
+
+void CloudSpeechRecognitionClientUnitTest::OnRecognitionEvent(
+    const std::string& result,
+    const bool is_final) {
+  results_.push(result);
+}
+
+void CloudSpeechRecognitionClientUnitTest::InjectDummyAudio() {
+  DCHECK(client_under_test_.get());
+  char dummy_audio_buffer_data[kDummyAudioBytes] = {'\0'};
+  client_under_test_->AddAudio(base::span<char>(
+      &dummy_audio_buffer_data[0], sizeof(dummy_audio_buffer_data)));
+}
+
+void CloudSpeechRecognitionClientUnitTest::InitializeUpstreamPipeIfNecessary() {
+  if (!upstream_data_pipe_.get()) {
+    if (!chunked_data_pipe_getter_) {
+      const network::TestURLLoaderFactory::PendingRequest* upstream_request =
+          GetUpstreamRequest();
+      EXPECT_TRUE(upstream_request);
+      EXPECT_TRUE(upstream_request->request.request_body);
+      EXPECT_EQ(1u, upstream_request->request.request_body->elements()->size());
+      EXPECT_EQ(
+          network::mojom::DataElementType::kChunkedDataPipe,
+          (*upstream_request->request.request_body->elements())[0].type());
+      network::TestURLLoaderFactory::PendingRequest* mutable_upstream_request =
+          const_cast<network::TestURLLoaderFactory::PendingRequest*>(
+              upstream_request);
+      chunked_data_pipe_getter_.Bind((*mutable_upstream_request->request
+                                           .request_body->elements_mutable())[0]
+                                         .ReleaseChunkedDataPipeGetter());
+    }
+
+    constexpr size_t kDataPipeCapacity = 256;
+    const MojoCreateDataPipeOptions data_pipe_options{
+        sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1,
+        kDataPipeCapacity};
+    mojo::ScopedDataPipeProducerHandle producer_end;
+    mojo::ScopedDataPipeConsumerHandle consumer_end;
+    CHECK_EQ(
+        MOJO_RESULT_OK,
+        mojo::CreateDataPipe(&data_pipe_options, &producer_end, &consumer_end));
+    chunked_data_pipe_getter_->StartReading(std::move(producer_end));
+    upstream_data_pipe_ = std::move(consumer_end);
+  }
+}
+
+std::string CloudSpeechRecognitionClientUnitTest::ConsumeChunkedUploadData(
+    uint32_t expected_num_bytes) {
+  std::string result;
+  InitializeUpstreamPipeIfNecessary();
+
+  EXPECT_TRUE(upstream_data_pipe_.is_valid());
+
+  std::string out;
+  while (true) {
+    task_environment_.RunUntilIdle();
+
+    const void* data;
+    uint32_t num_bytes = 0;
+    MojoResult result = upstream_data_pipe_->BeginReadData(
+        &data, &num_bytes, MOJO_READ_DATA_FLAG_NONE);
+
+    expected_num_bytes -= num_bytes;
+    if (result == MOJO_RESULT_OK) {
+      out.append(static_cast<const char*>(data), num_bytes);
+      upstream_data_pipe_->EndReadData(num_bytes);
+      continue;
+    }
+
+    if (result == MOJO_RESULT_SHOULD_WAIT) {
+      if (expected_num_bytes > 0) {
+        continue;
+      } else {
+        break;
+      }
+    }
+
+    LOG(INFO) << "Mojo pipe unexpectedly closed with result:" << result;
+    break;
+  }
+
+  return out;
+}
+
+// Returns the latest upstream request.
+const network::TestURLLoaderFactory::PendingRequest*
+CloudSpeechRecognitionClientUnitTest::GetUpstreamRequest() {
+  auto* pending_requests =
+      speech_recognition_service_impl_->GetPendingRequests();
+  for (int i = pending_requests->size() - 1; i >= 0; i--) {
+    const auto& pending_request = (*pending_requests)[i];
+    if (pending_request.request.url.spec().find("/up") != std::string::npos)
+      return &pending_request;
+  }
+
+  return nullptr;
+}
+
+// Returns the latest downstream request.
+const network::TestURLLoaderFactory::PendingRequest*
+CloudSpeechRecognitionClientUnitTest::GetDownstreamRequest() {
+  auto* pending_requests =
+      speech_recognition_service_impl_->GetPendingRequests();
+  for (int i = pending_requests->size() - 1; i >= 0; i--) {
+    const auto& pending_request = (*pending_requests)[i];
+    if (pending_request.request.url.spec().find("/down") != std::string::npos)
+      return &pending_request;
+  }
+
+  return nullptr;
+}
+
+void CloudSpeechRecognitionClientUnitTest::
+    ProvideMockResponseStartDownstreamIfNeeded() {
+  if (downstream_data_pipe_.get())
+    return;
+  const network::TestURLLoaderFactory::PendingRequest* downstream_request =
+      GetDownstreamRequest();
+  ASSERT_TRUE(downstream_request);
+
+  auto head = network::mojom::URLResponseHead::New();
+  std::string headers("HTTP/1.1 200 OK\n\n");
+  head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(
+      net::HttpUtil::AssembleRawHeaders(headers));
+  downstream_request->client->OnReceiveResponse(std::move(head));
+
+  constexpr size_t kDataPipeCapacity = 256;
+  const MojoCreateDataPipeOptions data_pipe_options{
+      sizeof(MojoCreateDataPipeOptions), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1,
+      kDataPipeCapacity};
+  mojo::ScopedDataPipeProducerHandle producer_end;
+  mojo::ScopedDataPipeConsumerHandle consumer_end;
+  CHECK_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(&data_pipe_options,
+                                                &producer_end, &consumer_end));
+  downstream_request->client->OnStartLoadingResponseBody(
+      std::move(consumer_end));
+  downstream_data_pipe_ = std::move(producer_end);
+}
+
+void CloudSpeechRecognitionClientUnitTest::ProvideMockStringResponseDownstream(
+    const std::string& response_string) {
+  ProvideMockResponseStartDownstreamIfNeeded();
+  uint32_t written = 0;
+  while (written < response_string.size()) {
+    uint32_t write_bytes = response_string.size() - written;
+    MojoResult result = downstream_data_pipe_->WriteData(
+        response_string.data() + written, &write_bytes,
+        MOJO_WRITE_DATA_FLAG_NONE);
+    if (result == MOJO_RESULT_OK) {
+      written += write_bytes;
+      continue;
+    }
+
+    if (result == MOJO_RESULT_SHOULD_WAIT) {
+      task_environment_.RunUntilIdle();
+      continue;
+    }
+
+    FAIL() << "Mojo write failed unexpectedly with result:" << result;
+    return;
+  }
+
+  // Flush the mojo pipe.
+  task_environment_.RunUntilIdle();
+}
+
+void CloudSpeechRecognitionClientUnitTest::ProvideMockProtoResultDownstream(
+    const content::proto::SpeechRecognitionEvent& result) {
+  ProvideMockResponseStartDownstreamIfNeeded();
+  ASSERT_TRUE(downstream_data_pipe_.get());
+  ASSERT_TRUE(downstream_data_pipe_.is_valid());
+
+  ProvideMockStringResponseDownstream(SerializeProtobufResponse(result));
+}
+
+void CloudSpeechRecognitionClientUnitTest::ProvideMockResultDownstream(
+    std::vector<std::string> result_strings) {
+  std::vector<blink::mojom::SpeechRecognitionResultPtr> results;
+  results.push_back(blink::mojom::SpeechRecognitionResult::New());
+  blink::mojom::SpeechRecognitionResultPtr& result = results.back();
+  result->is_provisional = false;
+
+  for (std::string result_string : result_strings) {
+    result->hypotheses.push_back(blink::mojom::SpeechRecognitionHypothesis::New(
+        base::UTF8ToUTF16(result_string), 0.1F));
+  }
+
+  content::proto::SpeechRecognitionEvent proto_event;
+  proto_event.set_status(
+      content::proto::SpeechRecognitionEvent::STATUS_SUCCESS);
+  content::proto::SpeechRecognitionResult* proto_result =
+      proto_event.add_result();
+  proto_result->set_final(!result->is_provisional);
+  proto_result->set_stability(1.0);
+  for (const auto& hypothesis : result->hypotheses) {
+    content::proto::SpeechRecognitionAlternative* proto_alternative =
+        proto_result->add_alternative();
+    proto_alternative->set_confidence(hypothesis->confidence);
+    proto_alternative->set_transcript(base::UTF16ToUTF8(hypothesis->utterance));
+  }
+
+  ProvideMockProtoResultDownstream(proto_event);
+}
+
+std::string CloudSpeechRecognitionClientUnitTest::SerializeProtobufResponse(
+    const content::proto::SpeechRecognitionEvent& msg) {
+  std::string msg_string;
+  msg.SerializeToString(&msg_string);
+
+  // Prepend 4 byte prefix length indication to the protobuf message as
+  // envisaged by the google streaming recognition webservice protocol.
+  uint32_t prefix = HostToNet32(checked_cast<uint32_t>(msg_string.size()));
+  msg_string.insert(0, reinterpret_cast<char*>(&prefix), sizeof(prefix));
+
+  return msg_string;
+}
+
+void CloudSpeechRecognitionClientUnitTest::ExpectResultsReceived(
+    const std::vector<std::string>& expected_results) {
+  ASSERT_GE(1U, results_.size());
+  std::string expected_transcription;
+  for (std::string result : expected_results) {
+    expected_transcription += result;
+  }
+
+  ASSERT_TRUE(expected_transcription == results_.front());
+  results_.pop();
+}
+
+TEST_F(CloudSpeechRecognitionClientUnitTest, StreamingRecognition) {
+  ASSERT_TRUE(client_under_test_->IsInitialized());
+  ASSERT_TRUE(GetUpstreamRequest());
+  ASSERT_TRUE(GetDownstreamRequest());
+  ASSERT_EQ("", ConsumeChunkedUploadData(0));
+
+  InjectDummyAudio();
+  ASSERT_FALSE(ConsumeChunkedUploadData(kDummyAudioBytes).empty());
+
+  // Simulate a protobuf message streamed from the server containing a single
+  // result with two hypotheses.
+  std::vector<std::string> result_strings;
+  result_strings.push_back("hypothesis 1");
+  result_strings.push_back("hypothesis 2");
+
+  ProvideMockResultDownstream(result_strings);
+  ExpectResultsReceived(result_strings);
+}
+
+TEST_F(CloudSpeechRecognitionClientUnitTest, DidAudioPropertyChange) {
+  ASSERT_FALSE(client_under_test_->DidAudioPropertyChange(48000, 2));
+  ASSERT_TRUE(client_under_test_->DidAudioPropertyChange(48000, 1));
+  ASSERT_TRUE(client_under_test_->DidAudioPropertyChange(44100, 2));
+  ASSERT_TRUE(client_under_test_->DidAudioPropertyChange(44100, 1));
+}
+
+// Verifies that invalid response strings are handled appropriately.
+TEST_F(CloudSpeechRecognitionClientUnitTest, InvalidResponseString) {
+  ASSERT_TRUE(client_under_test_->IsInitialized());
+  ASSERT_TRUE(GetUpstreamRequest());
+  ASSERT_TRUE(GetDownstreamRequest());
+  ASSERT_EQ("", ConsumeChunkedUploadData(0));
+
+  InjectDummyAudio();
+  ASSERT_FALSE(ConsumeChunkedUploadData(kDummyAudioBytes).empty());
+
+  ProvideMockStringResponseDownstream("INVALID RESPONSE STRING");
+  ASSERT_TRUE(results_.empty());
+}
+
+// Verifies that the client gracefully recovers from network crashes.
+TEST_F(CloudSpeechRecognitionClientUnitTest, NetworkReset) {
+  ASSERT_TRUE(client_under_test_->IsInitialized());
+  ASSERT_TRUE(GetUpstreamRequest());
+  ASSERT_TRUE(GetDownstreamRequest());
+  ASSERT_EQ("", ConsumeChunkedUploadData(0));
+
+  InjectDummyAudio();
+  ASSERT_FALSE(ConsumeChunkedUploadData(kDummyAudioBytes).empty());
+
+  // Simulate a network crash by resetting the URL loader factory receiver.
+  speech_recognition_service_impl_->ResetNetwork();
+  InjectDummyAudio();
+  ASSERT_FALSE(ConsumeChunkedUploadData(kDummyAudioBytes).empty());
+  ASSERT_TRUE(GetUpstreamRequest());
+  ASSERT_TRUE(GetDownstreamRequest());
+
+  // Simulate a protobuf message streamed from the server containing a single
+  // result with one hypothesis.
+  std::vector<std::string> result_strings;
+  result_strings.push_back("hypothesis 1");
+
+  ProvideMockResultDownstream(result_strings);
+  ExpectResultsReceived(result_strings);
+}
+
+// Verifies that the stream is reset after 295 seconds. The Open Speech API
+// supports a maximum recognition time of 5 minutes, so we must reset the stream
+// with a new request key before then.
+TEST_F(CloudSpeechRecognitionClientUnitTest, StreamReset) {
+  ASSERT_TRUE(client_under_test_->IsInitialized());
+  ASSERT_TRUE(GetUpstreamRequest());
+  ASSERT_TRUE(GetDownstreamRequest());
+  ASSERT_EQ("", ConsumeChunkedUploadData(0));
+
+  std::string UploadUrlBeforeReset = GetUpstreamRequest()->request.url.spec();
+  std::string DownloadUrlBeforeReset =
+      GetDownstreamRequest()->request.url.spec();
+
+  // Fast forward by 325 seconds to trigger a reset.
+  task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(325));
+  InjectDummyAudio();
+  ASSERT_EQ(2, speech_recognition_service_impl_->GetNumPending());
+
+  std::string UploadUrlAfterReset = GetUpstreamRequest()->request.url.spec();
+  std::string DownloadUrlAfterReset =
+      GetDownstreamRequest()->request.url.spec();
+
+  // The URLs after the reset should contain a different request key.
+  ASSERT_NE(UploadUrlBeforeReset, UploadUrlAfterReset);
+  ASSERT_NE(DownloadUrlBeforeReset, DownloadUrlAfterReset);
+}
+
+}  // namespace speech
diff --git a/chrome/services/speech/speech_recognition_recognizer_impl.cc b/chrome/services/speech/speech_recognition_recognizer_impl.cc
index 54f5244..1af1e59 100644
--- a/chrome/services/speech/speech_recognition_recognizer_impl.cc
+++ b/chrome/services/speech/speech_recognition_recognizer_impl.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/containers/span.h"
 #include "components/soda/constants.h"
 #include "media/base/audio_buffer.h"
 #include "media/base/audio_sample_types.h"
@@ -22,6 +23,8 @@
 
 namespace speech {
 
+constexpr char kInvalidAudioDataError[] = "Invalid audio data received.";
+
 namespace {
 
 #if BUILDFLAG(ENABLE_SODA)
@@ -47,13 +50,23 @@
 
 void SpeechRecognitionRecognizerImpl::Create(
     mojo::PendingReceiver<media::mojom::SpeechRecognitionRecognizer> receiver,
-    mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient>
-        remote) {
+    mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient> remote,
+    base::WeakPtr<SpeechRecognitionServiceImpl>
+        speech_recognition_service_impl) {
   mojo::MakeSelfOwnedReceiver(
-      base::WrapUnique(new SpeechRecognitionRecognizerImpl(std::move(remote))),
+      std::make_unique<SpeechRecognitionRecognizerImpl>(
+          std::move(remote), std::move(speech_recognition_service_impl)),
       std::move(receiver));
 }
 
+bool SpeechRecognitionRecognizerImpl::IsMultichannelSupported() {
+#if BUILDFLAG(ENABLE_SODA)
+  return true;
+#else
+  return false;
+#endif  // BUILDFLAG(ENABLE_SODA)
+}
+
 void SpeechRecognitionRecognizerImpl::OnRecognitionEvent(
     const std::string& result,
     const bool is_final) {
@@ -62,13 +75,17 @@
 }
 
 SpeechRecognitionRecognizerImpl::SpeechRecognitionRecognizerImpl(
-    mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient> remote)
+    mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient> remote,
+    base::WeakPtr<SpeechRecognitionServiceImpl> speech_recognition_service_impl)
     : client_remote_(std::move(remote)) {
   recognition_event_callback_ = media::BindToCurrentLoop(
       base::Bind(&SpeechRecognitionRecognizerImpl::OnRecognitionEvent,
                  weak_factory_.GetWeakPtr()));
 #if BUILDFLAG(ENABLE_SODA)
   soda_client_ = std::make_unique<soda::SodaClient>(GetSodaBinaryPath());
+#else
+  cloud_client_ = std::make_unique<CloudSpeechRecognitionClient>(
+      recognition_event_callback(), std::move(speech_recognition_service_impl));
 #endif  // BUILDFLAG(ENABLE_SODA)
 }
 
@@ -77,13 +94,27 @@
   int channel_count = buffer->channel_count;
   int frame_count = buffer->frame_count;
   int sample_rate = buffer->sample_rate;
-  int num_samples;
-  int data_size;
-  if (channel_count <= 0 || channel_count > media::limits::kMaxChannels ||
-      sample_rate <= 0 || frame_count <= 0 ||
+  size_t num_samples = 0;
+  size_t buffer_size = 0;
+
+  // Verify the channel count.
+  if (channel_count <= 0 || channel_count > media::limits::kMaxChannels) {
+    mojo::ReportBadMessage(kInvalidAudioDataError);
+    return;
+  }
+
+  // Verify and calculate the number of samples.
+  if (sample_rate <= 0 || frame_count <= 0 ||
       !base::CheckMul(frame_count, channel_count).AssignIfValid(&num_samples) ||
-      !base::CheckMul(num_samples, sizeof(int16_t)).AssignIfValid(&data_size)) {
-    mojo::ReportBadMessage("Invalid audio data received.");
+      num_samples != buffer->data.size()) {
+    mojo::ReportBadMessage(kInvalidAudioDataError);
+    return;
+  }
+
+  // Verify and calculate the buffer size.
+  if (!base::CheckMul(buffer->data.size(), sizeof(buffer->data[0]))
+           .AssignIfValid(&buffer_size)) {
+    mojo::ReportBadMessage(kInvalidAudioDataError);
     return;
   }
 
@@ -103,7 +134,21 @@
   }
 
   soda_client_->AddAudio(reinterpret_cast<char*>(buffer->data.data()),
-                         data_size);
+                         buffer_size);
+#else
+  DCHECK(cloud_client_);
+  if (!cloud_client_->IsInitialized() ||
+      cloud_client_->DidAudioPropertyChange(sample_rate, channel_count)) {
+    // Initialize the stream.
+    CloudSpeechConfig config;
+    config.sample_rate = sample_rate;
+    config.channel_count = channel_count;
+    config.language_code = "en-US";
+    cloud_client_->Initialize(config);
+  }
+
+  cloud_client_->AddAudio(base::span<const char>(
+      reinterpret_cast<char*>(buffer->data.data()), buffer_size));
 #endif  // BUILDFLAG(ENABLE_SODA)
 }
 
diff --git a/chrome/services/speech/speech_recognition_recognizer_impl.h b/chrome/services/speech/speech_recognition_recognizer_impl.h
index 9814d36..01934e0 100644
--- a/chrome/services/speech/speech_recognition_recognizer_impl.h
+++ b/chrome/services/speech/speech_recognition_recognizer_impl.h
@@ -9,8 +9,8 @@
 #include <string>
 
 #include "base/memory/weak_ptr.h"
-#include "build/branding_buildflags.h"
 #include "chrome/services/speech/buildflags.h"
+#include "chrome/services/speech/cloud_speech_recognition_client.h"
 #include "media/mojo/mojom/speech_recognition_service.mojom.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -20,6 +20,7 @@
 }  // namespace soda
 
 namespace speech {
+class SpeechRecognitionServiceImpl;
 
 class SpeechRecognitionRecognizerImpl
     : public media::mojom::SpeechRecognitionRecognizer {
@@ -27,23 +28,27 @@
   using OnRecognitionEventCallback =
       base::RepeatingCallback<void(const std::string& result,
                                    const bool is_final)>;
-
+  SpeechRecognitionRecognizerImpl(
+      mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient>
+          remote,
+      base::WeakPtr<SpeechRecognitionServiceImpl>
+          speech_recognition_service_impl);
   ~SpeechRecognitionRecognizerImpl() override;
 
   static void Create(
       mojo::PendingReceiver<media::mojom::SpeechRecognitionRecognizer> receiver,
       mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient>
-          remote);
+          remote,
+      base::WeakPtr<SpeechRecognitionServiceImpl>
+          speech_recognition_service_impl);
+
+  static bool IsMultichannelSupported();
 
   OnRecognitionEventCallback recognition_event_callback() const {
     return recognition_event_callback_;
   }
 
  private:
-  explicit SpeechRecognitionRecognizerImpl(
-      mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient>
-          remote);
-
   // Convert the audio buffer into the appropriate format and feed the raw audio
   // into the speech recognition instance.
   void SendAudioToSpeechRecognitionService(
@@ -61,6 +66,8 @@
   std::unique_ptr<soda::SodaClient> soda_client_;
 #endif  // BUILDFLAG(ENABLE_SODA)
 
+  std::unique_ptr<CloudSpeechRecognitionClient> cloud_client_;
+
   // The callback that is eventually executed on a speech recognition event
   // which passes the transcribed audio back to the caller via the speech
   // recognition event client remote.
diff --git a/chrome/services/speech/speech_recognition_service_impl.cc b/chrome/services/speech/speech_recognition_service_impl.cc
index 7fc6f723..e9c6239 100644
--- a/chrome/services/speech/speech_recognition_service_impl.cc
+++ b/chrome/services/speech/speech_recognition_service_impl.cc
@@ -19,12 +19,43 @@
   speech_recognition_contexts_.Add(this, std::move(context));
 }
 
+void SpeechRecognitionServiceImpl::SetUrlLoaderFactory(
+    mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory) {
+  url_loader_factory_ = mojo::Remote<network::mojom::URLLoaderFactory>(
+      std::move(url_loader_factory));
+  url_loader_factory_.set_disconnect_handler(
+      base::BindOnce(&SpeechRecognitionServiceImpl::DisconnectHandler,
+                     base::Unretained(this)));
+}
+
+void SpeechRecognitionServiceImpl::BindSpeechRecognitionServiceClient(
+    mojo::PendingRemote<media::mojom::SpeechRecognitionServiceClient> client) {
+  client_ = mojo::Remote<media::mojom::SpeechRecognitionServiceClient>(
+      std::move(client));
+}
+
+mojo::PendingRemote<network::mojom::URLLoaderFactory>
+SpeechRecognitionServiceImpl::GetUrlLoaderFactory() {
+  mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_factory_remote;
+  url_loader_factory_->Clone(
+      pending_factory_remote.InitWithNewPipeAndPassReceiver());
+
+  return pending_factory_remote;
+}
+
 void SpeechRecognitionServiceImpl::BindRecognizer(
     mojo::PendingReceiver<media::mojom::SpeechRecognitionRecognizer> receiver,
-    mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient>
-        client) {
-  SpeechRecognitionRecognizerImpl::Create(std::move(receiver),
-                                          std::move(client));
+    mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient> client,
+    BindRecognizerCallback callback) {
+  SpeechRecognitionRecognizerImpl::Create(
+      std::move(receiver), std::move(client), weak_factory_.GetWeakPtr());
+  std::move(callback).Run(
+      SpeechRecognitionRecognizerImpl::IsMultichannelSupported());
+}
+
+void SpeechRecognitionServiceImpl::DisconnectHandler() {
+  if (client_.is_bound())
+    client_->OnNetworkServiceDisconnect();
 }
 
 }  // namespace speech
diff --git a/chrome/services/speech/speech_recognition_service_impl.h b/chrome/services/speech/speech_recognition_service_impl.h
index 4677116..233c78a 100644
--- a/chrome/services/speech/speech_recognition_service_impl.h
+++ b/chrome/services/speech/speech_recognition_service_impl.h
@@ -5,10 +5,12 @@
 #ifndef CHROME_SERVICES_SPEECH_SPEECH_RECOGNITION_SERVICE_IMPL_H_
 #define CHROME_SERVICES_SPEECH_SPEECH_RECOGNITION_SERVICE_IMPL_H_
 
+#include "base/memory/weak_ptr.h"
 #include "media/mojo/mojom/speech_recognition_service.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
+#include "services/network/url_loader_factory.h"
 
 namespace speech {
 
@@ -23,20 +25,37 @@
   // media::mojom::SpeechRecognitionService
   void BindContext(mojo::PendingReceiver<media::mojom::SpeechRecognitionContext>
                        context) override;
+  void SetUrlLoaderFactory(mojo::PendingRemote<network::mojom::URLLoaderFactory>
+                               url_loader_factory) override;
+  void BindSpeechRecognitionServiceClient(
+      mojo::PendingRemote<media::mojom::SpeechRecognitionServiceClient> client)
+      override;
+
+  virtual mojo::PendingRemote<network::mojom::URLLoaderFactory>
+  GetUrlLoaderFactory();
 
   // media::mojom::SpeechRecognitionContext
   void BindRecognizer(
       mojo::PendingReceiver<media::mojom::SpeechRecognitionRecognizer> receiver,
       mojo::PendingRemote<media::mojom::SpeechRecognitionRecognizerClient>
-          client) override;
+          client,
+      BindRecognizerCallback callback) override;
 
- private:
+ protected:
+  void DisconnectHandler();
+
   mojo::Receiver<media::mojom::SpeechRecognitionService> receiver_;
 
   // The set of receivers used to receive messages from the renderer clients.
   mojo::ReceiverSet<media::mojom::SpeechRecognitionContext>
       speech_recognition_contexts_;
 
+  mojo::Remote<network::mojom::URLLoaderFactory> url_loader_factory_;
+
+  mojo::Remote<media::mojom::SpeechRecognitionServiceClient> client_;
+
+  base::WeakPtrFactory<SpeechRecognitionServiceImpl> weak_factory_{this};
+
   DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionServiceImpl);
 };
 
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index e772fe62..ed9a841 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -1960,6 +1960,8 @@
         "../browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc",
         "../browser/ui/views/location_bar/location_bar_view_browsertest.cc",
         "../browser/ui/views/location_bar/location_icon_view_browsertest.cc",
+        "../browser/ui/views/location_bar/permission_chip_browsertest.cc",
+        "../browser/ui/views/location_bar/permission_chip_prompt_browsertest.cc",
         "../browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc",
         "../browser/ui/views/media_router/cast_dialog_view_browsertest.cc",
         "../browser/ui/views/media_router/media_router_dialog_controller_views_browsertest.cc",
@@ -2010,6 +2012,7 @@
         "../browser/ui/views/payments/profile_list_view_controller_browsertest.cc",
         "../browser/ui/views/payments/shipping_address_editor_view_controller_browsertest.cc",
         "../browser/ui/views/payments/shipping_option_view_controller_browsertest.cc",
+        "../browser/ui/views/permission_bubble/permission_prompt_bubble_view_browsertest.cc",
         "../browser/ui/views/profiles/profile_menu_view_browsertest.cc",
         "../browser/ui/views/qrcode_generator/qrcode_generator_bubble_browsertest.cc",
         "../browser/ui/views/safe_browsing/password_reuse_modal_warning_dialog_browsertest.cc",
@@ -3170,9 +3173,6 @@
     "../browser/mac/keystone_glue_unittest.mm",
     "../browser/media/android/router/media_router_android_unittest.cc",
     "../browser/media/cast_mirroring_service_host_unittest.cc",
-    "../browser/media/feeds/media_feeds_converter_unittest.cc",
-    "../browser/media/feeds/media_feeds_fetcher_unittest.cc",
-    "../browser/media/feeds/media_feeds_service_unittest.cc",
     "../browser/media/history/media_history_keyed_service_unittest.cc",
     "../browser/media/history/media_history_store_unittest.cc",
     "../browser/media/media_engagement_contents_observer_unittest.cc",
@@ -3584,6 +3584,9 @@
       "../browser/component_updater/soda_component_installer_unittest.cc",
       "../browser/content_settings/generated_cookie_prefs_unittest.cc",
       "../browser/device_identity/device_oauth2_token_service_unittest.cc",
+      "../browser/media/feeds/media_feeds_converter_unittest.cc",
+      "../browser/media/feeds/media_feeds_fetcher_unittest.cc",
+      "../browser/media/feeds/media_feeds_service_unittest.cc",
       "../browser/nearby_sharing/fast_initiation_manager_unittest.cc",
       "../browser/nearby_sharing/nearby_process_manager_unittest.cc",
       "../browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc",
@@ -3908,9 +3911,6 @@
       "../browser/translate/translate_manager_render_view_host_android_unittest.cc",
     ]
 
-    if (enable_password_change_in_leaked_dialog) {
-      sources += [ "../browser/password_manager/credential_leak_password_change_controller_android_unittest.cc" ]
-    }
     deps += [
       "//base:base_java",
       "//chrome:chrome_android_core",
@@ -4289,6 +4289,7 @@
       "//chrome/browser/resource_coordinator/tab_ranker:tab_features_test_helper",
       "//chrome/services/sharing:unit_tests",
       "//chrome/services/sharing/nearby_decoder:unit_tests",
+      "//chrome/services/speech:unit_tests",
       "//components/chrome_cleaner/test:test_name_helper",
       "//components/feature_engagement/test:test_support",
       "//components/safety_check:test_support",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java
index 5d823c3..d4db49bc 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeBrowserTestRule.java
@@ -4,10 +4,12 @@
 
 package org.chromium.chrome.test;
 
+import android.accounts.Account;
+
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
 
-import org.chromium.chrome.test.util.browser.signin.SigninTestUtil;
+import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
 import org.chromium.content_public.browser.test.NativeLibraryTestRule;
 
 /**
@@ -15,14 +17,11 @@
  * initializing the AccountManagerFacade.
  */
 public class ChromeBrowserTestRule extends NativeLibraryTestRule {
-    private void setUp() {
-        SigninTestUtil.setUpAuthForTesting();
-        loadNativeLibraryAndInitBrowserProcess();
-    }
+    private final AccountManagerTestRule mAccountManagerTestRule = new AccountManagerTestRule();
 
     @Override
     public Statement apply(final Statement base, Description description) {
-        return super.apply(new Statement() {
+        Statement statement = super.apply(new Statement() {
             @Override
             public void evaluate() throws Throwable {
                 /**
@@ -30,17 +29,17 @@
                  * UI thread).  After loading the library, this will initialize the browser process
                  * if necessary.
                  */
-                setUp();
-                try {
-                    base.evaluate();
-                } finally {
-                    tearDown();
-                }
+                loadNativeLibraryAndInitBrowserProcess();
+                base.evaluate();
             }
         }, description);
+        return mAccountManagerTestRule.apply(statement, description);
     }
 
-    private void tearDown() {
-        SigninTestUtil.tearDownAuthForTesting();
+    /**
+     * Add and sign in an account with the default name.
+     */
+    public Account addAndSignInTestAccount() {
+        return mAccountManagerTestRule.addAndSignInTestAccount();
     }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
index a156e15..716c4f8c3 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeJUnit4ClassRunner.java
@@ -18,7 +18,6 @@
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.StrictModeContext;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
 import org.chromium.base.test.util.RestrictionSkipCheck;
 import org.chromium.base.test.util.SkipCheck;
 import org.chromium.chrome.browser.ChromeVersionInfo;
@@ -53,7 +52,7 @@
     }
 
     @Override
-    protected List<PreTestHook> getPreTestHooks() {
+    protected List<TestHook> getPreTestHooks() {
         return addToList(super.getPreTestHooks(), Policies.getRegistrationHook());
     }
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/tests/FirstRunControllerTest.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/tests/FirstRunControllerTest.java
index 849ee5f..a113086 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/tests/FirstRunControllerTest.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/pagecontroller/tests/FirstRunControllerTest.java
@@ -15,7 +15,7 @@
 import org.junit.runner.RunWith;
 
 import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.params.ParameterizedCommandLineFlags.Switches;
+import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.test.pagecontroller.controllers.first_run.TOSController;
 import org.chromium.chrome.test.pagecontroller.controllers.ntp.NewTabPageController;
@@ -45,7 +45,7 @@
                           TOSController.getInstance().isCurrentPageThis());
     }
 
-    @Switches(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
+    @CommandLineFlags.Add(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE)
     @Test
     public void testDisableFre() {
         Assert.assertTrue(ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE + " should work.",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
index df15c95..e8f69e9 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/AccountManagerTestRule.java
@@ -6,8 +6,6 @@
 
 import android.accounts.Account;
 
-import androidx.annotation.Nullable;
-
 import org.junit.rules.TestRule;
 import org.junit.runner.Description;
 import org.junit.runners.model.Statement;
@@ -19,17 +17,28 @@
 import org.chromium.components.signin.test.util.FakeProfileDataSource;
 
 /**
- * JUnit4 rule for overriding behaviour of {@link AccountManagerFacade} for tests.
+ * This test rule mocks AccountManagerFacade and manages sign-in/sign-out.
+ *
+ * When the user does not invoke any sign-in functions with this rule, the rule will not
+ * invoke any native code, therefore it is safe to use it in Robolectric tests just as
+ * a simple AccountManagerFacade mock.
  */
 public class AccountManagerTestRule implements TestRule {
-    private final FakeAccountManagerFacade mFakeAccountManagerFacade;
+    private static final String TEST_ACCOUNT_EMAIL = "test@gmail.com";
 
-    public AccountManagerTestRule(@Nullable FakeProfileDataSource fakeProfileDataSource) {
-        mFakeAccountManagerFacade = new FakeAccountManagerFacade(fakeProfileDataSource);
-    }
+    private final FakeAccountManagerFacade mFakeAccountManagerFacade;
+    private boolean mIsSignedIn = false;
 
     public AccountManagerTestRule() {
-        this(null);
+        this(new FakeAccountManagerFacade(null));
+    }
+
+    public AccountManagerTestRule(FakeProfileDataSource fakeProfileDataSource) {
+        this(new FakeAccountManagerFacade(fakeProfileDataSource));
+    }
+
+    public AccountManagerTestRule(FakeAccountManagerFacade fakeAccountManagerFacade) {
+        mFakeAccountManagerFacade = fakeAccountManagerFacade;
     }
 
     @Override
@@ -41,6 +50,9 @@
                 try {
                     statement.evaluate();
                 } finally {
+                    if (mIsSignedIn) {
+                        signOut();
+                    }
                     AccountManagerFacadeProvider.resetInstanceForTests();
                 }
             }
@@ -48,13 +60,6 @@
     }
 
     /**
-     * Sets the boolean for whether the account cache has already been populated.
-     */
-    public void setIsCachePopulated(boolean isCachePopulated) {
-        mFakeAccountManagerFacade.setIsCachePopulated(isCachePopulated);
-    }
-
-    /**
      * Add an account to the fake AccountManagerFacade.
      * @return The account added.
      */
@@ -81,4 +86,28 @@
         mFakeAccountManagerFacade.setProfileData(accountName, profileData);
         return account;
     }
+
+    /**
+     * Add and sign in an account with the default name.
+     *
+     * This method invokes native code. It shouldn't be called in a Robolectric test.
+     */
+    public Account addAndSignInTestAccount() {
+        assert !mIsSignedIn : "An account is already signed in!";
+        Account account = addAccount(TEST_ACCOUNT_EMAIL);
+        SigninTestUtil.signIn(account);
+        mIsSignedIn = true;
+        return account;
+    }
+
+    /**
+     * Sign out from the current account.
+     *
+     * This method invokes native code. It shouldn't be called in a Robolectric test.
+     */
+    private void signOut() {
+        assert mIsSignedIn : "No account is signed in!";
+        SigninTestUtil.signOut();
+        mIsSignedIn = false;
+    }
 }
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
index 03222ee..1ff1bac 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/signin/SigninTestUtil.java
@@ -196,7 +196,7 @@
         }
     }
 
-    private static void signOut() {
+    static void signOut() {
         ThreadUtils.assertOnBackgroundThread();
         CallbackHelper callbackHelper = new CallbackHelper();
         TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/chrome/test/base/ui_test_utils.cc b/chrome/test/base/ui_test_utils.cc
index 287c71c4..33aacb3 100644
--- a/chrome/test/base/ui_test_utils.cc
+++ b/chrome/test/base/ui_test_utils.cc
@@ -453,9 +453,9 @@
 
 void GetCookieCallback(base::RepeatingClosure callback,
                        net::CookieList* cookies,
-                       const net::CookieStatusList& cookie_list,
-                       const net::CookieStatusList& excluded_cookies) {
-  *cookies = net::cookie_util::StripStatuses(cookie_list);
+                       const net::CookieAccessResultList& cookie_list,
+                       const net::CookieAccessResultList& excluded_cookies) {
+  *cookies = net::cookie_util::StripAccessResults(cookie_list);
   callback.Run();
 }
 
diff --git a/chrome/test/chromedriver/chrome/chrome_impl.cc b/chrome/test/chromedriver/chrome/chrome_impl.cc
index 73865e5..7aca4824 100644
--- a/chrome/test/chromedriver/chrome/chrome_impl.cc
+++ b/chrome/test/chromedriver/chrome/chrome_impl.cc
@@ -282,13 +282,21 @@
 
   base::DictionaryValue params;
   params.SetInteger("windowId", window->id);
-  if (window->state != "normal") {
-    params.SetString("bounds.windowState", "normal");
+  const std::string normal = "normal";
+  if (window->state != normal) {
+    params.SetString("bounds.windowState", normal);
     status = devtools_websocket_client_->SendCommand("Browser.setWindowBounds",
                                                      params);
     if (status.IsError())
       return status;
     base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
+
+    status = GetWindowBounds(window->id, window);
+    if (status.IsError())
+      return status;
+
+    if (window->state != normal)
+      return MakeFailedStatus(normal, window->state);
   }
 
   std::string desired_state;
diff --git a/chrome/test/chromedriver/chrome/devtools_client_impl.cc b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
index 49df1f3..54d5332 100644
--- a/chrome/test/chromedriver/chrome/devtools_client_impl.cc
+++ b/chrome/test/chromedriver/chrome/devtools_client_impl.cc
@@ -86,7 +86,7 @@
       id_(id),
       frontend_closer_func_(base::Bind(&FakeCloseFrontends)),
       parser_func_(base::Bind(&internal::ParseInspectorMessage)),
-      unnotified_event_(NULL),
+      unnotified_event_(nullptr),
       next_id_(1),
       stack_count_(0) {
   socket_->SetId(id_);
@@ -106,7 +106,7 @@
       id_(id),
       frontend_closer_func_(frontend_closer_func),
       parser_func_(base::Bind(&internal::ParseInspectorMessage)),
-      unnotified_event_(NULL),
+      unnotified_event_(nullptr),
       next_id_(1),
       stack_count_(0) {
   socket_->SetId(id_);
@@ -122,7 +122,7 @@
       id_(session_id),
       frontend_closer_func_(base::BindRepeating(&FakeCloseFrontends)),
       parser_func_(base::BindRepeating(&internal::ParseInspectorMessage)),
-      unnotified_event_(NULL),
+      unnotified_event_(nullptr),
       next_id_(1),
       stack_count_(0) {
   parent->children_[session_id] = this;
@@ -143,7 +143,7 @@
       id_(id),
       frontend_closer_func_(frontend_closer_func),
       parser_func_(parser_func),
-      unnotified_event_(NULL),
+      unnotified_event_(nullptr),
       next_id_(1),
       stack_count_(0) {
   socket_->SetId(id_);
diff --git a/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc b/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc
index c6f68d52..ae1e4a87 100644
--- a/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc
+++ b/chrome/test/chromedriver/chrome/javascript_dialog_manager_unittest.cc
@@ -86,7 +86,7 @@
 
 class FakeDevToolsClient : public StubDevToolsClient {
  public:
-  FakeDevToolsClient() : listener_(NULL), closing_count_(0) {}
+  FakeDevToolsClient() : listener_(nullptr), closing_count_(0) {}
   ~FakeDevToolsClient() override {}
 
   void set_closing_count(int closing_count) {
diff --git a/chrome/test/chromedriver/chrome/network_conditions_override_manager.cc b/chrome/test/chromedriver/chrome/network_conditions_override_manager.cc
index eedb2b2..42c340c 100644
--- a/chrome/test/chromedriver/chrome/network_conditions_override_manager.cc
+++ b/chrome/test/chromedriver/chrome/network_conditions_override_manager.cc
@@ -11,8 +11,7 @@
 
 NetworkConditionsOverrideManager::NetworkConditionsOverrideManager(
     DevToolsClient* client)
-    : client_(client),
-      overridden_network_conditions_(NULL) {
+    : client_(client), overridden_network_conditions_(nullptr) {
   client_->AddListener(this);
 }
 
diff --git a/chrome/test/chromedriver/test/run_py_tests.py b/chrome/test/chromedriver/test/run_py_tests.py
index fdf9f19..2de06f1 100755
--- a/chrome/test/chromedriver/test/run_py_tests.py
+++ b/chrome/test/chromedriver/test/run_py_tests.py
@@ -127,9 +127,6 @@
     # already tested by other test cases.
     'ChromeDriverTest.testGetCurrentWindowHandle',
     'ChromeDriverTest.testStartStop',
-    # Both https://crbug.com/867511:
-    'ChromeDriverTest.testWindowFullScreen',
-    'ChromeDriverTest.testWindowMaximize',
     # LaunchApp is an obsolete API.
     'ChromeExtensionsCapabilityTest.testCanLaunchApp',
     # PerfTest takes a long time, requires extra setup, and adds little value
@@ -139,8 +136,6 @@
     'HeadlessInvalidCertificateTest.*',
     # Similar issues with HeadlessChromeDriverTest.
     'HeadlessChromeDriverTest.*',
-    # Flaky: https://crbug.com/899919
-    'SessionHandlingTest.testGetSessions',
     # Flaky due to occasional timeout in starting Chrome
     'ZChromeStartRetryCountTest.testChromeStartRetryCount',
 ]
@@ -1464,6 +1459,10 @@
     self.assertNotEqual(old_rect_list, new_rect_list)
 
     self._driver.SetWindowRect(*old_rect_list)
+    for i in range(10):
+      if old_rect_list == self._driver.GetWindowRect():
+        break
+      time.sleep(0.1)
     self.assertEquals(old_rect_list, self._driver.GetWindowRect())
 
   def testConsoleLogSources(self):
diff --git a/chrome/test/data/chromeos/app_mode/webstore/downloads/hpanhkopkhnkpcmnedlnjmkfafmlamak-2.0.0.crx b/chrome/test/data/chromeos/app_mode/webstore/downloads/hpanhkopkhnkpcmnedlnjmkfafmlamak-2.0.0.crx
index 0eb278c..0202ee6 100644
--- a/chrome/test/data/chromeos/app_mode/webstore/downloads/hpanhkopkhnkpcmnedlnjmkfafmlamak-2.0.0.crx
+++ b/chrome/test/data/chromeos/app_mode/webstore/downloads/hpanhkopkhnkpcmnedlnjmkfafmlamak-2.0.0.crx
Binary files differ
diff --git a/chrome/test/data/chromeos/oobe_webui_browsertest.js b/chrome/test/data/chromeos/oobe_webui_browsertest.js
index 3dcc2ddc..d610957 100644
--- a/chrome/test/data/chromeos/oobe_webui_browsertest.js
+++ b/chrome/test/data/chromeos/oobe_webui_browsertest.js
@@ -139,7 +139,7 @@
 
 // Fails on chromeos, http://crbug.com/665315
 TEST_F('OobeWebUITest', 'DISABLED_OobeUpdate', function() {
-  Oobe.getInstance().showScreen({'id':'update'});
+  Oobe.getInstance().showScreen({'id':'oobe-update'});
 });
 
 // Fails on chromeos, http://crbug.com/665315
diff --git a/chrome/test/data/extensions/permissions_increase/updates.json b/chrome/test/data/extensions/permissions_increase/updates.json
new file mode 100644
index 0000000..850c002
--- /dev/null
+++ b/chrome/test/data/extensions/permissions_increase/updates.json
@@ -0,0 +1,32 @@
+)]}'
+{
+  "response": {
+    "protocol": "3.1",
+    "app": [
+      {
+        "appid": "pgdpcfcocojkjfbgpiianjngphoopgmo",
+        "updatecheck": {
+          "status": "ok",
+          "manifest": {
+            "version": "2",
+            "packages": {
+              "package": [
+                {
+                  "size": 1103,
+                  "hash_sha256": "dc0b73d9daa1236d0ecd7a0370729e99fb9dbfccf97cea2d2bbf02fb584b2853",
+                  "name": "v2.crx",
+                  "fp": "1.dc0b73d9daa1236d0ecd7a0370729e99fb9dbfccf97cea2d2bbf02fb584b2853"
+                }
+              ]
+            }
+          },
+          "urls": {
+            "url": [
+              {"codebase": "http://localhost/autoupdate/"}
+            ]
+          }
+        }
+      }
+    ]
+  }
+}
diff --git a/chrome/test/data/extensions/permissions_increase/v2.crx b/chrome/test/data/extensions/permissions_increase/v2.crx
new file mode 100644
index 0000000..ffb119b
--- /dev/null
+++ b/chrome/test/data/extensions/permissions_increase/v2.crx
Binary files differ
diff --git a/chrome/test/data/media/bigbuck-player.html b/chrome/test/data/media/bigbuck-player.html
index e35aba565..0a596f2 100644
--- a/chrome/test/data/media/bigbuck-player.html
+++ b/chrome/test/data/media/bigbuck-player.html
@@ -13,5 +13,11 @@
   document.getElementById('fullscreen').addEventListener('click', _ => {
     document.getElementById('video').webkitRequestFullscreen();
   });
+
+  if ('HTMLPortalElement' in self) {
+    let portal = document.createElement('portal');
+    portal.src = "picture-in-picture/iframe-content.html";
+    document.body.appendChild(portal);
+  }
 </script>
 </html>
diff --git a/chrome/test/data/pdf/basic_test.js b/chrome/test/data/pdf/basic_test.js
index 690a067..1c2391b 100644
--- a/chrome/test/data/pdf/basic_test.js
+++ b/chrome/test/data/pdf/basic_test.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.
 
-import {getFilenameFromURL, shouldIgnoreKeyEvents} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer.js';
+import {getFilenameFromURL, shouldIgnoreKeyEvents} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer_utils.js';
 import {$} from 'chrome://resources/js/util.m.js';
 import {pressAndReleaseKeyOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
 
diff --git a/chrome/test/data/webrtc/peerconnection_getstats.js b/chrome/test/data/webrtc/peerconnection_getstats.js
index 77aedd2..edc93322 100644
--- a/chrome/test/data/webrtc/peerconnection_getstats.js
+++ b/chrome/test/data/webrtc/peerconnection_getstats.js
@@ -477,7 +477,7 @@
 let kRTCDataChannelStats = new RTCStats(null, {
   label: 'string',
   protocol: 'string',
-  datachannelid: 'number',
+  dataChannelIdentifier: 'number',
   state: 'string',
   messagesSent: 'number',
   bytesSent: 'number',
diff --git a/chrome/test/data/webui/cr_elements/cr_input_test.js b/chrome/test/data/webui/cr_elements/cr_input_test.js
index 7d899e7..b95cf5a58 100644
--- a/chrome/test/data/webui/cr_elements/cr_input_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_input_test.js
@@ -5,7 +5,7 @@
 // clang-format off
 // #import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
-// #import {eventToPromise, whenAttributeIs} from '../test_util.m.js';
+// #import {eventToPromise, isChildVisible, whenAttributeIs} from '../test_util.m.js';
 // #import {assertEquals, assertNotEquals, assertThrows, assertTrue, assertFalse} from '../chai_assert.js';
 // clang-format on
 
@@ -375,4 +375,22 @@
     assertTrue(input.matches(':focus'));
     assertEquals('', window.getSelection().toString());
   });
+
+  test('slots', function() {
+    /* #ignore */ PolymerTest.clearBody();
+    document.body.innerHTML = `
+      <cr-input>
+        <div slot="inline-prefix" id="inline-prefix">One</div>
+        <div slot="suffix" id="suffix">Two</div>
+        <div slot="inline-suffix" id="inline-suffix">Three</div>
+      </cr-input>
+    `;
+    Polymer.dom.flush();
+    crInput =
+        /** @type {!CrInputElement} */ (document.querySelector('cr-input'));
+    assertTrue(test_util.isChildVisible(crInput, '#inline-prefix', true));
+    assertTrue(test_util.isChildVisible(crInput, '#suffix', true));
+    assertTrue(test_util.isChildVisible(crInput, '#inline-suffix', true));
+  });
+
 });
diff --git a/chrome/test/data/webui/extensions/item_test.js b/chrome/test/data/webui/extensions/item_test.js
index dbf4616e..5f4dcca2 100644
--- a/chrome/test/data/webui/extensions/item_test.js
+++ b/chrome/test/data/webui/extensions/item_test.js
@@ -375,7 +375,7 @@
 
   test(assert(extension_item_tests.TestNames.RemoveButton), function() {
     expectFalse(item.$['remove-button'].hidden);
-    item.set('data.controlledInfo', {type: 'POLICY', text: 'policy'});
+    item.set('data.mustRemainInstalled', true);
     flush();
     expectTrue(item.$['remove-button'].hidden);
   });
diff --git a/chrome/test/data/webui/interventions_internals_browsertest.js b/chrome/test/data/webui/interventions_internals_browsertest.js
index dc3ab33..ae2fb81 100644
--- a/chrome/test/data/webui/interventions_internals_browsertest.js
+++ b/chrome/test/data/webui/interventions_internals_browsertest.js
@@ -85,8 +85,8 @@
 
     window.testPageHandler = new TestPageHandler();
 
-    getBlacklistedStatus = function(blacklisted) {
-      return (blacklisted ? 'Blacklisted' : 'Not blacklisted');
+    getBlocklistedStatus = function(blocklisted) {
+      return (blocklisted ? 'Blocklisted' : 'Not blocklisted');
     };
   },
 };
@@ -483,84 +483,84 @@
       mocha.run();
     });
 
-TEST_F('InterventionsInternalsUITest', 'AddNewBlacklistedHost', function() {
-  test('AddNewBlacklistedHost', () => {
+TEST_F('InterventionsInternalsUITest', 'AddNewBlocklistedHost', function() {
+  test('AddNewBlocklistedHost', () => {
     let pageImpl = new InterventionsInternalPageImpl(null);
     let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
     let expectedHost = 'example.com';
-    pageImpl.onBlacklistedHost(expectedHost, time);
+    pageImpl.onBlocklistedHost(expectedHost, time);
 
-    let blacklistedTable = $('blacklisted-hosts-table');
-    let row = blacklistedTable.querySelector('.blacklisted-host-row');
+    let blocklistedTable = $('blocklisted-hosts-table');
+    let row = blocklistedTable.querySelector('.blocklisted-host-row');
 
     let expectedTime = getTimeFormat(time);
 
     expectEquals(
-        expectedHost, row.querySelector('.host-blacklisted').textContent);
+        expectedHost, row.querySelector('.host-blocklisted').textContent);
     expectEquals(
-        expectedTime, row.querySelector('.host-blacklisted-time').textContent);
+        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
   });
 
   mocha.run();
 });
 
-TEST_F('InterventionsInternalsUITest', 'HostAlreadyBlacklisted', function() {
-  test('HostAlreadyBlacklisted', () => {
+TEST_F('InterventionsInternalsUITest', 'HostAlreadyBlocklisted', function() {
+  test('HostAlreadyBlocklisted', () => {
     let pageImpl = new InterventionsInternalPageImpl(null);
     let time0 = 758675653000;   // Jan 15 1994 23:14:13 UTC
     let time1 = 1507221689240;  // Oct 05 2017 16:41:29 UTC
     let expectedHost = 'example.com';
 
-    pageImpl.onBlacklistedHost(expectedHost, time0);
+    pageImpl.onBlocklistedHost(expectedHost, time0);
 
-    let blacklistedTable = $('blacklisted-hosts-table');
-    let row = blacklistedTable.querySelector('.blacklisted-host-row');
+    let blocklistedTable = $('blocklisted-hosts-table');
+    let row = blocklistedTable.querySelector('.blocklisted-host-row');
     let expectedTime = getTimeFormat(time0);
     expectEquals(
-        expectedHost, row.querySelector('.host-blacklisted').textContent);
+        expectedHost, row.querySelector('.host-blocklisted').textContent);
     expectEquals(
-        expectedTime, row.querySelector('.host-blacklisted-time').textContent);
+        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
 
-    pageImpl.onBlacklistedHost(expectedHost, time1);
+    pageImpl.onBlocklistedHost(expectedHost, time1);
 
     // The row remains the same.
     expectEquals(
-        expectedHost, row.querySelector('.host-blacklisted').textContent);
+        expectedHost, row.querySelector('.host-blocklisted').textContent);
     expectEquals(
-        expectedTime, row.querySelector('.host-blacklisted-time').textContent);
+        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
   });
 
   mocha.run();
 });
 
-TEST_F('InterventionsInternalsUITest', 'UpdateUserBlacklisted', function() {
-  test('UpdateUserBlacklistedDisplayCorrectly', () => {
+TEST_F('InterventionsInternalsUITest', 'UpdateUserBlocklisted', function() {
+  test('UpdateUserBlocklistedDisplayCorrectly', () => {
     let pageImpl = new InterventionsInternalPageImpl(null);
-    let state = $('user-blacklisted-status-value');
+    let state = $('user-blocklisted-status-value');
 
-    pageImpl.onUserBlacklistedStatusChange(true /* blacklisted */);
+    pageImpl.onUserBlocklistedStatusChange(true /* blocklisted */);
     expectEquals(
-        getBlacklistedStatus(true /* blacklisted */), state.textContent);
+        getBlocklistedStatus(true /* blocklisted */), state.textContent);
 
-    pageImpl.onUserBlacklistedStatusChange(false /* blacklisted */);
+    pageImpl.onUserBlocklistedStatusChange(false /* blocklisted */);
     expectEquals(
-        getBlacklistedStatus(false /* blacklisted */), state.textContent);
+        getBlocklistedStatus(false /* blocklisted */), state.textContent);
   });
 
   mocha.run();
 });
 
-TEST_F('InterventionsInternalsUITest', 'OnBlacklistCleared', function() {
-  test('OnBlacklistClearedRemovesAllBlacklistedHostInTable', () => {
+TEST_F('InterventionsInternalsUITest', 'OnBlocklistCleared', function() {
+  test('OnBlocklistClearedRemovesAllBlocklistedHostInTable', () => {
     let pageImpl = new InterventionsInternalPageImpl(null);
-    let state = $('user-blacklisted-status-value');
+    let state = $('user-blocklisted-status-value');
     let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
 
-    pageImpl.onBlacklistCleared(time);
-    let actualClearedTime = $('blacklist-last-cleared-time').textContent;
+    pageImpl.onBlocklistCleared(time);
+    let actualClearedTime = $('blocklist-last-cleared-time').textContent;
     expectEquals(getTimeFormat(time), actualClearedTime);
-    let blacklistedTable = $('blacklisted-hosts-table');
-    let rows = blacklistedTable.querySelectorAll('.blacklisted-host-row');
+    let blocklistedTable = $('blocklisted-hosts-table');
+    let rows = blocklistedTable.querySelectorAll('.blocklisted-host-row');
     expectEquals(0, rows.length);
   });
 
@@ -568,9 +568,9 @@
 });
 
 TEST_F(
-    'InterventionsInternalsUITest', 'ClearLogMessageOnBlacklistCleared',
+    'InterventionsInternalsUITest', 'ClearLogMessageOnBlocklistCleared',
     function() {
-      test('ClearLogsTableOnBlacklistCleared', () => {
+      test('ClearLogsTableOnBlocklistCleared', () => {
         let pageImpl = new InterventionsInternalPageImpl(null);
         let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
         let log = {
@@ -583,12 +583,12 @@
 
         pageImpl.logNewMessage(log);
         expectGT($('message-logs-table').rows.length, 1 /* header row */);
-        pageImpl.onBlacklistCleared(time);
-        let expectedNumberOfRows = 2;  // header row and clear blacklist log.
+        pageImpl.onBlocklistCleared(time);
+        let expectedNumberOfRows = 2;  // header row and clear blocklist log.
         let rows = $('message-logs-table').rows;
         expectEquals(expectedNumberOfRows, rows.length);
         expectEquals(
-            'Blacklist Cleared',
+            'Blocklist Cleared',
             rows[1].querySelector('.log-description').textContent);
       });
 
@@ -609,18 +609,18 @@
   mocha.run();
 });
 
-TEST_F('InterventionsInternalsUITest', 'OnBlacklistIgnoreChange', function() {
-  test('OnBlacklistIgnoreChangeDisable', () => {
+TEST_F('InterventionsInternalsUITest', 'OnBlocklistIgnoreChange', function() {
+  test('OnBlocklistIgnoreChangeDisable', () => {
     let pageImpl = new InterventionsInternalPageImpl(null);
-    pageImpl.onIgnoreBlacklistDecisionStatusChanged(true /* ignored */);
-    expectEquals('Enable Blacklist', $('ignore-blacklist-button').textContent);
+    pageImpl.onIgnoreBlocklistDecisionStatusChanged(true /* ignored */);
+    expectEquals('Enable Blocklist', $('ignore-blocklist-button').textContent);
     expectEquals(
-        'Blacklist decisions are ignored.',
-        $('blacklist-ignored-status').textContent);
+        'Blocklist decisions are ignored.',
+        $('blocklist-ignored-status').textContent);
 
-    pageImpl.onIgnoreBlacklistDecisionStatusChanged(false /* ignored */);
-    expectEquals('Ignore Blacklist', $('ignore-blacklist-button').textContent);
-    expectEquals('', $('blacklist-ignored-status').textContent);
+    pageImpl.onIgnoreBlocklistDecisionStatusChanged(false /* ignored */);
+    expectEquals('Ignore Blocklist', $('ignore-blocklist-button').textContent);
+    expectEquals('', $('blocklist-ignored-status').textContent);
   });
 
   mocha.run();
diff --git a/chrome/test/data/webui/new_tab_page/app_test.js b/chrome/test/data/webui/new_tab_page/app_test.js
index 1f7297a7..eec813e 100644
--- a/chrome/test/data/webui/new_tab_page/app_test.js
+++ b/chrome/test/data/webui/new_tab_page/app_test.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {$$, BackgroundManager, BackgroundSelectionType, BrowserProxy} from 'chrome://new-tab-page/new_tab_page.js';
+import {isMac} from 'chrome://resources/js/cr.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {assertNotStyle, assertStyle, createTestProxy, createTheme} from 'chrome://test/new_tab_page/test_support.js';
 import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
@@ -152,6 +153,34 @@
     assertTrue(!!app.shadowRoot.querySelector('ntp-voice-search-overlay'));
   });
 
+  test('keyboard shortcut opens voice search overlay', async () => {
+    // Act.
+    window.dispatchEvent(new KeyboardEvent('keydown', {
+      ctrlKey: true,
+      shiftKey: true,
+      code: 'Period',
+    }));
+    await flushTasks();
+
+    // Assert.
+    assertTrue(!!app.shadowRoot.querySelector('ntp-voice-search-overlay'));
+  });
+
+  if (isMac) {
+    test('keyboard shortcut opens voice search overlay on mac', async () => {
+      // Act.
+      window.dispatchEvent(new KeyboardEvent('keydown', {
+        metaKey: true,
+        shiftKey: true,
+        code: 'Period',
+      }));
+      await flushTasks();
+
+      // Assert.
+      assertTrue(!!app.shadowRoot.querySelector('ntp-voice-search-overlay'));
+    });
+  }
+
   test('setting background image shows image, disallows doodle', async () => {
     // Arrange.
     const theme = createTheme();
diff --git a/chrome/test/data/webui/print_preview/header_test.js b/chrome/test/data/webui/print_preview/header_test.js
index ed7d86d..cbcaf70 100644
--- a/chrome/test/data/webui/print_preview/header_test.js
+++ b/chrome/test/data/webui/print_preview/header_test.js
@@ -2,8 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationType, Error, State} from 'chrome://print/print_preview.js';
+import {Destination, DestinationConnectionStatus, DestinationOrigin, DestinationType, Error, PrintPreviewPluralStringProxyImpl, State} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
+import {TestPluralStringProxy} from 'chrome://test/test_plural_string_proxy.js';
 import {fakeDataBind} from 'chrome://test/test_util.m.js';
 
 window.header_test = {};
@@ -19,9 +20,17 @@
   /** @type {?PrintPreviewHeaderElement} */
   let header = null;
 
+  /** @type {TestPluralStringProxy} */
+  let pluralString = null;
+
   /** @override */
   setup(function() {
     PolymerTest.clearBody();
+
+    pluralString = new TestPluralStringProxy();
+    PrintPreviewPluralStringProxyImpl.instance_ = pluralString;
+    pluralString.text = '1 sheet of paper';
+
     const model = document.createElement('print-preview-model');
     document.body.appendChild(model);
 
@@ -51,15 +60,39 @@
 
   // Tests that the 4 different messages (non-virtual printer singular and
   // plural, virtual printer singular and plural) all show up as expected.
-  test(assert(header_test.TestNames.HeaderPrinterTypes), function() {
+  test(assert(header_test.TestNames.HeaderPrinterTypes), async function() {
     const summary = header.$$('.summary');
-    assertEquals('1 sheet of paper', summary.textContent.trim());
-    header.sheetCount = 3;
-    assertEquals('3 sheets of paper', summary.textContent.trim());
-    setPdfDestination();
-    assertEquals('3 pages', summary.textContent.trim());
-    header.sheetCount = 1;
-    assertEquals('1 page', summary.textContent.trim());
+    {
+      const {messageName, itemCount} =
+          await pluralString.whenCalled('getPluralString');
+      assertEquals('1 sheet of paper', summary.textContent.trim());
+      assertEquals('printPreviewSheetSummaryLabel', messageName);
+      assertEquals(1, itemCount);
+    }
+    {
+      pluralString.resetResolver('getPluralString');
+      header.sheetCount = 3;
+      const {messageName, itemCount} =
+          await pluralString.whenCalled('getPluralString');
+      assertEquals('printPreviewSheetSummaryLabel', messageName);
+      assertEquals(3, itemCount);
+    }
+    {
+      pluralString.resetResolver('getPluralString');
+      setPdfDestination();
+      const {messageName, itemCount} =
+          await pluralString.whenCalled('getPluralString');
+      assertEquals('printPreviewPageSummaryLabel', messageName);
+      assertEquals(3, itemCount);
+    }
+    {
+      pluralString.resetResolver('getPluralString');
+      header.sheetCount = 1;
+      const {messageName, itemCount} =
+          await pluralString.whenCalled('getPluralString');
+      assertEquals('printPreviewPageSummaryLabel', messageName);
+      assertEquals(1, itemCount);
+    }
     // Verify the chrome://print case of a zero length document does not show
     // the summary.
     header.sheetCount = 0;
@@ -68,8 +101,9 @@
 
   // Tests that the correct message is shown for non-READY states, and that
   // the print button is disabled appropriately.
-  test(assert(header_test.TestNames.HeaderChangesForState), function() {
+  test(assert(header_test.TestNames.HeaderChangesForState), async function() {
     const summary = header.$$('.summary');
+    await pluralString.whenCalled('getPluralString');
     assertEquals('1 sheet of paper', summary.textContent.trim());
 
     header.state = State.NOT_READY;
diff --git a/chrome/test/data/webui/print_preview/policy_test.js b/chrome/test/data/webui/print_preview/policy_test.js
index 8f130b4..8f162dbc 100644
--- a/chrome/test/data/webui/print_preview/policy_test.js
+++ b/chrome/test/data/webui/print_preview/policy_test.js
@@ -2,12 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import {BackgroundGraphicsModeRestriction, NativeLayer, NativeLayerImpl, PluginProxy} from 'chrome://print/print_preview.js';
+import {BackgroundGraphicsModeRestriction, NativeLayer, NativeLayerImpl, PluginProxy, PrintPreviewPluralStringProxyImpl} from 'chrome://print/print_preview.js';
 import {assert} from 'chrome://resources/js/assert.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {NativeLayerStub} from 'chrome://test/print_preview/native_layer_stub.js';
 import {PDFPluginStub} from 'chrome://test/print_preview/plugin_stub.js';
 import {getCddTemplate, getDefaultInitialSettings} from 'chrome://test/print_preview/print_preview_test_utils.js';
+import {TestPluralStringProxy} from 'chrome://test/test_plural_string_proxy.js';
 
 window.policy_tests = {};
 policy_tests.suiteName = 'PolicyTest';
@@ -19,6 +20,17 @@
   SheetsPolicy: 'sheets policy',
 };
 
+class PolicyTestPluralStringProxy extends TestPluralStringProxy {
+  /** override */
+  getPluralString(messageName, itemCount) {
+    if (messageName === 'sheetsLimitErrorMessage') {
+      this.methodCalled('getPluralString', {messageName, itemCount});
+    }
+    return Promise.resolve(this.text);
+  }
+}
+
+
 suite(policy_tests.suiteName, function() {
   /** @type {?PrintPreviewAppElement} */
   let page = null;
@@ -255,6 +267,10 @@
   });
 
   test(assert(policy_tests.TestNames.SheetsPolicy), async () => {
+    const pluralString = new PolicyTestPluralStringProxy();
+    PrintPreviewPluralStringProxyImpl.instance_ = pluralString;
+    pluralString.text = 'Exceeds limit of 1 sheet of paper';
+
     const tests = [
       {
         // No policy.
@@ -262,7 +278,7 @@
         pages: [1, 2, 3],
         expectedDisabled: false,
         expectedHidden: true,
-        expectedErrorMessage: '',
+        expectedNonEmptyErrorMessage: false,
       },
       {
         // Policy is set, actual pages are not calculated yet.
@@ -270,7 +286,7 @@
         pages: [],
         expectedDisabled: true,
         expectedHidden: true,
-        expectedErrorMessage: '',
+        expectedNonEmptyErrorMessage: false,
       },
       {
         // Policy is set, but the limit is not hit.
@@ -278,7 +294,7 @@
         pages: [1, 2],
         expectedDisabled: false,
         expectedHidden: true,
-        expectedErrorMessage: '',
+        expectedNonEmptyErrorMessage: false,
       },
       {
         // Policy is set, the limit is hit, singular form is used.
@@ -286,20 +302,25 @@
         pages: [1, 2],
         expectedDisabled: true,
         expectedHidden: false,
-        expectedErrorMessage: 'Exceeds limit of 1 sheet of paper',
+        expectedNonEmptyErrorMessage: true,
       },
       {
         // Policy is set, the limit is hit, plural form is used.
         maxSheets: 2,
-        pages: [1, 2, 3],
+        pages: [1, 2, 3, 4],
         expectedDisabled: true,
         expectedHidden: false,
-        expectedErrorMessage: 'Exceeds limit of 2 sheets of paper',
+        expectedNonEmptyErrorMessage: true,
       }
     ];
     for (const subtestParams of tests) {
       await doValuePolicySetup('sheets', subtestParams.maxSheets);
+      pluralString.resetResolver('getPluralString');
       page.setSetting('pages', subtestParams.pages);
+      if (subtestParams.expectedNonEmptyErrorMessage) {
+        const {_, itemCount} = await pluralString.whenCalled('getPluralString');
+        assertEquals(subtestParams.maxSheets, itemCount);
+      }
       const printButton = page.$$('print-preview-sidebar')
                               .$$('print-preview-button-strip')
                               .$$('cr-button.action-button');
@@ -308,10 +329,9 @@
                                .$$('div.error-message');
       assertEquals(subtestParams.expectedDisabled, printButton.disabled);
       assertEquals(subtestParams.expectedHidden, errorMessage.hidden);
-      if (!errorMessage.hidden) {
-        assertEquals(
-            subtestParams.expectedErrorMessage, errorMessage.innerText);
-      }
+      assertEquals(
+          subtestParams.expectedNonEmptyErrorMessage,
+          !errorMessage.hidden && !!errorMessage.innerText);
     }
   });
 });
diff --git a/chrome/test/data/webui/settings/autofill_page_test.js b/chrome/test/data/webui/settings/autofill_page_test.js
index 6a53367..938dd3d 100644
--- a/chrome/test/data/webui/settings/autofill_page_test.js
+++ b/chrome/test/data/webui/settings/autofill_page_test.js
@@ -5,7 +5,7 @@
 // clang-format off
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {AutofillManagerImpl, PaymentsManagerImpl} from 'chrome://settings/lazy_load.js';
-import {CrSettingsPrefs, MultiStorePasswordUiEntry, OpenWindowProxyImpl, PasswordManagerImpl, Router, routes, SettingsPluralStringProxyImpl} from 'chrome://settings/settings.js';
+import {CrSettingsPrefs, MultiStoreExceptionEntry, MultiStorePasswordUiEntry, OpenWindowProxyImpl, PasswordManagerImpl, Router, routes, SettingsPluralStringProxyImpl} from 'chrome://settings/settings.js';
 import {FakeSettingsPrivate} from 'chrome://test/settings/fake_settings_private.m.js';
 import {AutofillManagerExpectations, createAddressEntry, createCreditCardEntry, createExceptionEntry, createPasswordEntry, PaymentsManagerExpectations, TestAutofillManager, TestPaymentsManager} from 'chrome://test/settings/passwords_and_autofill_fake_data.js';
 import {makeCompromisedCredential} from 'chrome://test/settings/passwords_and_autofill_fake_data.js';
@@ -207,11 +207,16 @@
     return createPrefs(true, true).then(function(prefs) {
       const element = createAutofillElement(prefs);
 
-      const list = [createExceptionEntry(), createExceptionEntry()];
+      const list = [
+        createExceptionEntry({url: 'one.com', id: 0}),
+        createExceptionEntry({url: 'two.com', id: 1})
+      ];
       passwordManager.lastCallback.addExceptionListChangedListener(list);
       flush();
 
-      assertEquals(list, element.$$('#passwordSection').passwordExceptions);
+      assertDeepEquals(
+          list.map(entry => new MultiStoreExceptionEntry(entry)),
+          element.$$('#passwordSection').passwordExceptions);
 
       // The callback is coming from the manager, so the element shouldn't
       // have additional calls to the manager after the base expectations.
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/plugin_vm_detail_view_test.js b/chrome/test/data/webui/settings/chromeos/app_management/plugin_vm_detail_view_test.js
index e97067f3..0ff5cb0 100644
--- a/chrome/test/data/webui/settings/chromeos/app_management/plugin_vm_detail_view_test.js
+++ b/chrome/test/data/webui/settings/chromeos/app_management/plugin_vm_detail_view_test.js
@@ -27,8 +27,13 @@
     fakeHandler = setupFakeHandler();
     replaceStore();
 
+    loadTimeData.overrideValues({
+      showPluginVmCameraPermissions: true,
+    });
+
     const permissions = {};
-    const permissionIds = [PluginVmPermissionType.PRINTING];
+    const permissionIds =
+        [PluginVmPermissionType.PRINTING, PluginVmPermissionType.CAMERA];
     for (const permissionId of permissionIds) {
       permissions[permissionId] = app_management.util.createPermission(
           permissionId, PermissionValueType.kBool, Bool.kTrue,
@@ -76,6 +81,7 @@
     };
 
     await checkToggle('PRINTING');
+    await checkToggle('CAMERA');
   });
 
   test('Pin to shelf toggle', async function() {
diff --git a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
index 3b4e271..a1050d6 100644
--- a/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
+++ b/chrome/test/data/webui/settings/chromeos/crostini_page_test.js
@@ -377,7 +377,7 @@
 
       test('DiskResizeOpensWhenClicked', async function() {
         assertTrue(!!subpage.$$('#showDiskResizeButton'));
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo',
             {succeeded: true, canResize: true, isUserChosenSize: true});
         subpage.$$('#showDiskResizeButton').click();
@@ -675,9 +675,13 @@
 
       async function clickShowDiskResize(userChosen) {
         console.log('Awaiting getDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
-            'getCrostiniDiskInfo',
-            {succeeded: true, canResize: true, isUserChosenSize: userChosen});
+        await crostiniBrowserProxy.resolvePromises('getCrostiniDiskInfo', {
+          succeeded: true,
+          canResize: true,
+          isUserChosenSize: userChosen,
+          ticks: ticks,
+          defaultIndex: 2
+        });
         subpage.$$('#showDiskResizeButton').click();
         console.log('Awaiting flushAsync');
         await flushAsync();
@@ -698,7 +702,7 @@
 
       test('ResizeUnsupported', async function() {
         console.log(`Starting test ${this.test.title}`);
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', {succeeded: true, canResize: false});
         assertFalse(isVisible(subpage.$$('#showDiskResizeButton')));
         assertEquals(
@@ -709,7 +713,7 @@
 
       test('ResizeButtonAndSubtextCorrectlySet', async function() {
         console.log(`Starting test ${this.test.title}`);
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', resizeableData);
         const button = subpage.$$('#showDiskResizeButton');
         const subtext = subpage.$$('#diskSizeDescription');
@@ -723,7 +727,7 @@
 
       test('ReserveSizeButtonAndSubtextCorrectlySet', async function() {
         console.log(`Starting test ${this.test.title}`);
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', sparseDiskData);
         const button = subpage.$$('#showDiskResizeButton');
         const subtext = subpage.$$('#diskSizeDescription');
@@ -743,7 +747,7 @@
         await clickShowDiskResize(true);
         const diskInfo = resizeableData;
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', diskInfo);
 
         assertTrue(isVisible(dialog.$$('#recommended-size')));
@@ -757,7 +761,7 @@
         const diskInfo = resizeableData;
         diskInfo.isLowSpaceAvailable = true;
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', diskInfo);
 
         assertFalse(isVisible(dialog.$$('#recommended-size')));
@@ -769,7 +773,7 @@
         console.log(`Starting test ${this.test.title}`);
         await clickShowDiskResize(true);
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', {succeeded: false, isUserChosenSize: true});
 
         // We failed, should have a retry button.
@@ -789,7 +793,7 @@
 
         // And failure page again.
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.rejectPromise('getCrostiniDiskInfo');
+        await crostiniBrowserProxy.rejectPromises('getCrostiniDiskInfo');
         button = dialog.$$('#retry');
         assertTrue(isVisible(button));
         assertVisibleBlockIs('#error');
@@ -804,7 +808,7 @@
         console.log(`Starting test ${this.test.title}`);
         await clickShowDiskResize(true);
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo',
             {succeeded: true, canResize: false, isUserChosenSize: true});
         assertVisibleBlockIs('#unsupported');
@@ -817,7 +821,7 @@
         console.log(`Starting test ${this.test.title}`);
         await clickShowDiskResize(true);
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', resizeableData);
         assertVisibleBlockIs('#resize-block');
 
@@ -834,7 +838,7 @@
         console.log(`Starting test ${this.test.title}`);
         await clickShowDiskResize(true);
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', resizeableData);
         const button = dialog.$$('#resize');
         button.click();
@@ -852,12 +856,12 @@
         console.log(`Starting test ${this.test.title}`);
         await clickShowDiskResize(true);
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', resizeableData);
         const button = dialog.$$('#resize');
         button.click();
         console.log('Awaiting resizeCrostiniDisk');
-        await crostiniBrowserProxy.resolvePromise('resizeCrostiniDisk', false);
+        await crostiniBrowserProxy.resolvePromises('resizeCrostiniDisk', false);
         assertFalse(button.disabled);
         assertFalse(isVisible(dialog.$$('#done')));
         assertFalse(isVisible(dialog.$$('#resizing')));
@@ -870,12 +874,12 @@
         console.log(`Starting test ${this.test.title}`);
         await clickShowDiskResize(true);
         console.log('Awaiting getCrostiniDiskInfo');
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', resizeableData);
         const button = dialog.$$('#resize');
         button.click();
         console.log('Awaiting resizeCrostiniDisk');
-        await crostiniBrowserProxy.resolvePromise('resizeCrostiniDisk', true);
+        await crostiniBrowserProxy.resolvePromises('resizeCrostiniDisk', true);
         // Dialog should close itself.
         console.log('Awaiting close');
         await test_util.eventToPromise('close', dialog);
@@ -884,7 +888,7 @@
 
       test('DiskResizeConfirmationDialogShownAndAccepted', async function() {
         console.log(`Starting test ${this.test.title}`);
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', sparseDiskData);
         console.log('Awaiting show');
         await clickShowDiskResize(false);
@@ -929,7 +933,7 @@
 
       test('DiskResizeConfirmationDialogShownAndCanceled', async function() {
         console.log(`Starting test ${this.test.title}`);
-        await crostiniBrowserProxy.resolvePromise(
+        await crostiniBrowserProxy.resolvePromises(
             'getCrostiniDiskInfo', sparseDiskData);
         console.log('Awaiting click show');
         await clickShowDiskResize(false);
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index 6a4b718d..a0d8d92 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -527,7 +527,7 @@
   mocha.grep('\\bMainPage\\b').run();
 });
 
-TEST_F('OSSettingsCrostiniPageTest', 'DISABLED_SubPageDefault', function() {
+TEST_F('OSSettingsCrostiniPageTest', 'SubPageDefault', function() {
   mocha.grep('\\bSubPageDefault\\b').run();
 });
 
@@ -535,7 +535,7 @@
   mocha.grep('\\bSubPagePortForwarding\\b').run();
 });
 
-TEST_F('OSSettingsCrostiniPageTest', 'DISABLED_DiskResize', function() {
+TEST_F('OSSettingsCrostiniPageTest', 'DiskResize', function() {
   mocha.grep('\\bDiskResize\\b').run();
 });
 
diff --git a/chrome/test/data/webui/settings/chromeos/test_crostini_browser_proxy.js b/chrome/test/data/webui/settings/chromeos/test_crostini_browser_proxy.js
index c36b596..01092f3 100644
--- a/chrome/test/data/webui/settings/chromeos/test_crostini_browser_proxy.js
+++ b/chrome/test/data/webui/settings/chromeos/test_crostini_browser_proxy.js
@@ -40,17 +40,29 @@
   }
 
   getNewPromiseFor(name) {
-    return new Promise((resolve, reject) => {
-      this.methodCalls_[name] = {name, resolve, reject};
-    });
+    if (name in this.methodCalls_) {
+      return new Promise((resolve, reject) => {
+        this.methodCalls_[name].push({name, resolve, reject});
+      });
+    } else {
+      return new Promise((resolve, reject) => {
+        this.methodCalls_[name] = [{name, resolve, reject}];
+      });
+    }
   }
 
-  async resolvePromise(name, ...args) {
-    await this.methodCalls_[name].resolve(...args);
+  async resolvePromises(name, ...args) {
+    for (const o of this.methodCalls_[name]) {
+      await o.resolve(...args);
+    }
+    this.methodCalls_[name] = [];
   }
 
-  async rejectPromise(name, ...args) {
-    await this.methodCalls_[name].reject(...args);
+  async rejectPromises(name, ...args) {
+    for (const o of this.methodCalls_[name]) {
+      await o.reject(...args);
+    }
+    this.methodCalls_[name] = [];
   }
 
   /** @override */
diff --git a/chrome/test/data/webui/settings/multi_store_exception_entry_test.js b/chrome/test/data/webui/settings/multi_store_exception_entry_test.js
index 772d856..0623259 100644
--- a/chrome/test/data/webui/settings/multi_store_exception_entry_test.js
+++ b/chrome/test/data/webui/settings/multi_store_exception_entry_test.js
@@ -11,9 +11,9 @@
 
 suite('MultiStoreExceptionEntry', function() {
   test('verifyIds', function() {
-    const deviceEntry = createExceptionEntry('g.com', 0);
+    const deviceEntry = createExceptionEntry({url: 'g.com', id: 0});
     deviceEntry.fromAccountStore = false;
-    const accountEntry = createExceptionEntry('g.com', 1);
+    const accountEntry = createExceptionEntry({url: 'g.com', id: 1});
     accountEntry.fromAccountStore = true;
 
     const multiStoreDeviceEntry = new MultiStoreExceptionEntry(deviceEntry);
diff --git a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js
index 97e9257..9dacdea 100644
--- a/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js
+++ b/chrome/test/data/webui/settings/passwords_and_autofill_fake_data.js
@@ -6,7 +6,7 @@
 import {assertNotReached} from 'chrome://resources/js/assert.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {AutofillManager, PaymentsManager} from 'chrome://settings/lazy_load.js';
-import {MultiStorePasswordUiEntry} from 'chrome://settings/settings.js';
+import {MultiStoreExceptionEntry, MultiStorePasswordUiEntry} from 'chrome://settings/settings.js';
 
 import {assertEquals} from '../chai_assert.js';
 
@@ -18,7 +18,7 @@
  * password manager native code. If no |id| is passed, it is set to a default,
  * value so this should probably not be done in tests with multiple entries
  * (|id| is unique). If no |frontendId| is passed, it is set to the same value
- * as |id|.
+ * set for |id|.
  * @param {{ url: (string|undefined),
  *            username: (string|undefined),
  *            federationText: (string|undefined),
@@ -31,24 +31,23 @@
 export function createPasswordEntry(params) {
   // Generate fake data if param is undefined.
   params = params || {};
-  params.url = params.url !== undefined ? params.url : 'www.foo.com';
-  params.username = params.username || 'user';
-  params.id = params.id !== undefined ? params.id : 42;
-  params.frontendId =
-      params.frontendId !== undefined ? params.frontendId : params.id;
-  params.fromAccountStore = params.fromAccountStore || false;
+  const url = params.url !== undefined ? params.url : 'www.foo.com';
+  const username = params.username !== undefined ? params.username : 'user';
+  const id = params.id !== undefined ? params.id : 42;
+  const frontendId = params.frontendId !== undefined ? params.frontendId : id;
+  const fromAccountStore = params.fromAccountStore || false;
 
   return {
     urls: {
-      origin: 'http://' + params.url + '/login',
-      shown: params.url,
-      link: 'http://' + params.url + '/login',
+      origin: 'http://' + url + '/login',
+      shown: url,
+      link: 'http://' + url + '/login',
     },
-    username: params.username,
+    username: username,
     federationText: params.federationText,
-    id: params.id,
-    frontendId: params.frontendId,
-    fromAccountStore: params.fromAccountStore,
+    id: id,
+    frontendId: frontendId,
+    fromAccountStore: fromAccountStore,
   };
 }
 
@@ -100,14 +99,23 @@
 }
 
 /**
- * Creates a single item for the list of password exceptions.
- * @param {string=} url
- * @param {number=} id
+ * Creates a single item for the list of password exceptions. If no |id| is
+ * passed, it is set to a default, value so this should probably not be done in
+ * tests with multiple entries (|id| is unique). If no |frontendId| is passed,
+ * it is set to the same value set for |id|.
+ * @param {{ url: (string|undefined),
+ *           id: (number|undefined),
+ *           frontendId: (number|undefined),
+ *           fromAccountStore: (boolean|undefined)
+ *         }=} params
  * @return {chrome.passwordsPrivate.ExceptionEntry}
  */
-export function createExceptionEntry(url, id) {
-  url = url || patternMaker_('www.xxxxxx.com', 16);
-  id = id || 0;
+export function createExceptionEntry(params) {
+  params = params || {};
+  const url = params.url !== undefined ? params.url : 'www.foo.com';
+  const id = params.id !== undefined ? params.id : 42;
+  const frontendId = params.frontendId !== undefined ? params.frontendId : id;
+  const fromAccountStore = params.fromAccountStore || false;
   return {
     urls: {
       origin: 'http://' + url + '/login',
@@ -115,12 +123,54 @@
       link: 'http://' + url + '/login',
     },
     id: id,
-    frontendId: id,
-    fromAccountStore: false,
+    frontendId: frontendId,
+    fromAccountStore: fromAccountStore,
   };
 }
 
 /**
+ * Creates a multi-store password item with the same mock data as
+ * createExceptionEntry(), so it can be used for verifying deduplication result.
+ * At least one of |accountId| and |deviceId| must be set.
+ * @param {!{ url: (string|undefined),
+ *           accountId: (number|undefined),
+ *           deviceId: (number|undefined),
+ *         }} params
+ * @return {MultiStoreExceptionEntry}
+ */
+export function createMultiStoreExceptionEntry(params) {
+  const dummyFrontendId = 42;
+  let deviceEntry, accountEntry;
+  if (params.deviceId !== undefined) {
+    deviceEntry = createExceptionEntry({
+      url: params.url,
+      id: params.deviceId,
+      frontendId: dummyFrontendId,
+      fromAccountStore: false
+    });
+  }
+  if (params.accountId !== undefined) {
+    accountEntry = createExceptionEntry({
+      url: params.url,
+      id: params.accountId,
+      frontendId: dummyFrontendId,
+      fromAccountStore: true
+    });
+  }
+
+  if (deviceEntry) {
+    return new MultiStoreExceptionEntry(deviceEntry, accountEntry);
+  }
+  if (accountEntry) {
+    return new MultiStoreExceptionEntry(accountEntry);
+  }
+
+  assertNotReached();
+  return new MultiStoreExceptionEntry(createExceptionEntry());
+}
+
+
+/**
  * Creates a new fake address entry for testing.
  * @return {!chrome.autofillPrivate.AddressEntry}
  */
diff --git a/chrome/test/data/webui/settings/passwords_section_test.js b/chrome/test/data/webui/settings/passwords_section_test.js
index d8d9a58..6807141 100644
--- a/chrome/test/data/webui/settings/passwords_section_test.js
+++ b/chrome/test/data/webui/settings/passwords_section_test.js
@@ -9,8 +9,8 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 import {getToastManager} from 'chrome://settings/lazy_load.js';
-import {MultiStorePasswordUiEntry, PasswordManagerImpl, PasswordManagerProxy, ProfileInfoBrowserProxyImpl, Router, routes, SettingsPluralStringProxyImpl} from 'chrome://settings/settings.js';
-import {createExceptionEntry, createMultiStorePasswordEntry, createPasswordEntry, makeCompromisedCredential, makePasswordCheckStatus, PasswordSectionElementFactory} from 'chrome://test/settings/passwords_and_autofill_fake_data.js';
+import {MultiStoreExceptionEntry, MultiStorePasswordUiEntry, PasswordManagerImpl, PasswordManagerProxy, ProfileInfoBrowserProxyImpl, Router, routes, SettingsPluralStringProxyImpl} from 'chrome://settings/settings.js';
+import {createExceptionEntry, createMultiStoreExceptionEntry, createMultiStorePasswordEntry, createPasswordEntry, makeCompromisedCredential, makePasswordCheckStatus, PasswordSectionElementFactory} from 'chrome://test/settings/passwords_and_autofill_fake_data.js';
 import {runCancelExportTest, runExportFlowErrorRetryTest, runExportFlowErrorTest, runExportFlowFastTest, runExportFlowSlowTest, runFireCloseEventAfterExportCompleteTest,runStartExportTest} from 'chrome://test/settings/passwords_export_test.js';
 import {getSyncAllPrefs, simulateStoredAccounts, simulateSyncStatus} from 'chrome://test/settings/sync_test_util.m.js';
 import {TestPasswordManagerProxy} from 'chrome://test/settings/test_password_manager_proxy.js';
@@ -46,7 +46,7 @@
 }
 
 /**
- * Convenience version of validateMultiStorePasswordList for when store
+ * Convenience version of validateMultiStorePasswordList() for when store
  * duplicates don't exist.
  * @param {!Element} passwordsSection The passwords section element that will
  *     be checked.
@@ -65,11 +65,10 @@
  * Helper method that validates a that elements in the exception list match
  * the expected data.
  * @param {!Array<!Element>} nodes The nodes that will be checked.
- * @param {!Array<!chrome.passwordsPrivate.ExceptionEntry>} exceptionList The
- *     expected data.
+ * @param {!Array<!MultiStoreExceptionEntry>} exceptionList The expected data.
  * @private
  */
-function validateExceptionList(nodes, exceptionList) {
+function validateMultiStoreExceptionList(nodes, exceptionList) {
   assertEquals(exceptionList.length, nodes.length);
   for (let index = 0; index < exceptionList.length; ++index) {
     const node = nodes[index];
@@ -84,6 +83,19 @@
 }
 
 /**
+ * Convenience version of validateMultiStoreExceptionList() for when store
+ * duplicates do not exist.
+ * @param {!Array<!Element>} nodes The nodes that will be checked.
+ * @param {!Array<!chrome.passwordsPrivate.ExceptionEntry>} exceptionList The
+ *     expected data.
+ * @private
+ */
+function validateExceptionList(nodes, exceptionList) {
+  validateMultiStoreExceptionList(
+      nodes, exceptionList.map(entry => new MultiStoreExceptionEntry(entry)));
+}
+
+/**
  * Returns all children of an element that has children added by a dom-repeat.
  * @param {!Element} element
  * @return {!Array<!Element>}
@@ -573,12 +585,12 @@
 
   test('verifyFilterPasswordExceptions', function() {
     const exceptionList = [
-      createExceptionEntry('docsshoW.google.com'),
-      createExceptionEntry('showmail.com'),
-      createExceptionEntry('google.com'),
-      createExceptionEntry('inbox.google.com'),
-      createExceptionEntry('mapsshow.google.com'),
-      createExceptionEntry('plus.google.comshow'),
+      createExceptionEntry({url: 'docsshoW.google.com', id: 0}),
+      createExceptionEntry({url: 'showmail.com', id: 1}),
+      createExceptionEntry({url: 'google.com', id: 2}),
+      createExceptionEntry({url: 'inbox.google.com', id: 3}),
+      createExceptionEntry({url: 'mapsshow.google.com', id: 4}),
+      createExceptionEntry({url: 'plus.google.comshow', id: 5}),
     ];
 
     const passwordsSection = elementFactory.createPasswordsSection(
@@ -587,10 +599,10 @@
     flush();
 
     const expectedExceptionList = [
-      createExceptionEntry('docsshoW.google.com'),
-      createExceptionEntry('showmail.com'),
-      createExceptionEntry('mapsshow.google.com'),
-      createExceptionEntry('plus.google.comshow'),
+      createExceptionEntry({url: 'docsshoW.google.com', id: 0}),
+      createExceptionEntry({url: 'showmail.com', id: 1}),
+      createExceptionEntry({url: 'mapsshow.google.com', id: 4}),
+      createExceptionEntry({url: 'plus.google.comshow', id: 5}),
     ];
 
     validateExceptionList(
@@ -610,12 +622,12 @@
 
   test('verifyPasswordExceptions', function() {
     const exceptionList = [
-      createExceptionEntry('docs.google.com'),
-      createExceptionEntry('mail.com'),
-      createExceptionEntry('google.com'),
-      createExceptionEntry('inbox.google.com'),
-      createExceptionEntry('maps.google.com'),
-      createExceptionEntry('plus.google.com'),
+      createExceptionEntry({url: 'docs.google.com', id: 0}),
+      createExceptionEntry({url: 'mail.com', id: 1}),
+      createExceptionEntry({url: 'google.com', id: 2}),
+      createExceptionEntry({url: 'inbox.google.com', id: 3}),
+      createExceptionEntry({url: 'maps.google.com', id: 4}),
+      createExceptionEntry({url: 'plus.google.com', id: 5}),
     ];
 
     const passwordsSection = elementFactory.createPasswordsSection(
@@ -628,15 +640,57 @@
     assertTrue(passwordsSection.$.noExceptionsLabel.hidden);
   });
 
+  // Test verifies that exceptions duplicated across stores get properly merged
+  // in the UI.
+  test('verifyPasswordExceptionsWithMultiStore', function() {
+    // Entries with duplicates.
+    const accountException1 = createExceptionEntry(
+        {url: '1.com', frontendId: 1, id: 10, fromAccountStore: true});
+    const deviceException1 = createExceptionEntry(
+        {url: '1.com', frontendId: 1, id: 11, fromAccountStore: false});
+    const accountException2 = createExceptionEntry(
+        {url: '2.com', frontendId: 2, id: 20, fromAccountStore: true});
+    const deviceException2 = createExceptionEntry(
+        {url: '2.com', frontendId: 2, id: 21, fromAccountStore: false});
+    // Entries without duplicate.
+    const deviceException3 = createExceptionEntry(
+        {url: '3.com', frontendId: 3, id: 3, fromAccountStore: false});
+    const accountException4 = createExceptionEntry(
+        {url: '4.com', frontendId: 4, id: 4, fromAccountStore: true});
+
+    // Shuffle entries a little.
+    const passwordsSection =
+        elementFactory.createPasswordsSection(passwordManager, [], [
+          deviceException3, accountException1, deviceException2,
+          accountException4, deviceException1, accountException2
+        ]);
+
+    // Expected list keeping relative order.
+    const expectedList = [
+      createMultiStoreExceptionEntry({url: '3.com', deviceId: 3}),
+      createMultiStoreExceptionEntry(
+          {url: '1.com', accountId: 10, deviceId: 11}),
+      createMultiStoreExceptionEntry(
+          {url: '2.com', accountId: 20, deviceId: 21}),
+      createMultiStoreExceptionEntry({url: '4.com', accountId: 4}),
+    ];
+
+    validateMultiStoreExceptionList(
+        getDomRepeatChildren(passwordsSection.$.passwordExceptionsList),
+        expectedList);
+
+    assertTrue(passwordsSection.$.noExceptionsLabel.hidden);
+  });
+
   // Test verifies that removing an exception will update the elements.
   test('verifyPasswordExceptionRemove', function() {
     const exceptionList = [
-      createExceptionEntry('docs.google.com'),
-      createExceptionEntry('mail.com'),
-      createExceptionEntry('google.com'),
-      createExceptionEntry('inbox.google.com'),
-      createExceptionEntry('maps.google.com'),
-      createExceptionEntry('plus.google.com'),
+      createExceptionEntry({url: 'docs.google.com', id: 0}),
+      createExceptionEntry({url: 'mail.com', id: 1}),
+      createExceptionEntry({url: 'google.com', id: 2}),
+      createExceptionEntry({url: 'inbox.google.com', id: 3}),
+      createExceptionEntry({url: 'maps.google.com', id: 4}),
+      createExceptionEntry({url: 'plus.google.com', id: 5}),
     ];
 
     const passwordsSection = elementFactory.createPasswordsSection(
@@ -653,21 +707,28 @@
     assertFalse(exceptionsListContainsUrl(exceptionList, 'mail.com'));
     flush();
 
+    const expectedExceptionList = [
+      createExceptionEntry({url: 'docs.google.com', id: 0}),
+      createExceptionEntry({url: 'google.com', id: 2}),
+      createExceptionEntry({url: 'inbox.google.com', id: 3}),
+      createExceptionEntry({url: 'maps.google.com', id: 4}),
+      createExceptionEntry({url: 'plus.google.com', id: 5})
+    ];
     validateExceptionList(
         getDomRepeatChildren(passwordsSection.$.passwordExceptionsList),
-        exceptionList);
+        expectedExceptionList);
   });
 
   // Test verifies that pressing the 'remove' button will trigger a remove
   // event. Does not actually remove any exceptions.
   test('verifyPasswordExceptionRemoveButton', function() {
     const exceptionList = [
-      createExceptionEntry('docs.google.com'),
-      createExceptionEntry('mail.com'),
-      createExceptionEntry('google.com'),
-      createExceptionEntry('inbox.google.com'),
-      createExceptionEntry('maps.google.com'),
-      createExceptionEntry('plus.google.com'),
+      createExceptionEntry({url: 'docs.google.com', id: 0}),
+      createExceptionEntry({url: 'mail.com', id: 1}),
+      createExceptionEntry({url: 'google.com', id: 2}),
+      createExceptionEntry({url: 'inbox.google.com', id: 3}),
+      createExceptionEntry({url: 'maps.google.com', id: 4}),
+      createExceptionEntry({url: 'plus.google.com', id: 5}),
     ];
 
     const passwordsSection = elementFactory.createPasswordsSection(
@@ -687,12 +748,12 @@
     // called on |passwordManager| and continues recursively until no more items
     // exist.
     function removeNextRecursive() {
-      passwordManager.resetResolver('removeException');
+      passwordManager.resetResolver('removeExceptions');
       clickRemoveButton();
-      return passwordManager.whenCalled('removeException').then(id => {
+      return passwordManager.whenCalled('removeExceptions').then(ids => {
         // Verify that the event matches the expected value.
         assertTrue(item < exceptionList.length);
-        assertEquals(id, exceptionList[item].id);
+        assertDeepEquals(ids, [exceptionList[item].id]);
 
         if (++item < exceptionList.length) {
           return removeNextRecursive();
@@ -704,6 +765,28 @@
     return removeNextRecursive();
   });
 
+  // Test verifies that pressing the 'remove' button for a duplicated exception
+  // will remove both the device and account copies.
+  test('verifyDuplicatedExceptionRemoveButton', async function() {
+    // Create a duplicated exception that will be merged into a single entry.
+    const deviceCopy =
+        createPasswordEntry({frontendId: 42, id: 0, fromAccountStore: false});
+    const accountCopy =
+        createPasswordEntry({frontendId: 42, id: 1, fromAccountStore: true});
+
+    const passwordsSection = elementFactory.createPasswordsSection(
+        passwordManager, [], [deviceCopy, accountCopy]);
+
+    const [mergedEntry] =
+        getDomRepeatChildren(passwordsSection.$.passwordExceptionsList);
+    mergedEntry.querySelector('#removeExceptionButton').click();
+
+    // Verify both ids get passed to the proxy.
+    const ids = await passwordManager.whenCalled('removeExceptions');
+    assertTrue(ids.includes(deviceCopy.id));
+    assertTrue(ids.includes(accountCopy.id));
+  });
+
   test('verifyFederatedPassword', function() {
     const item = createMultiStorePasswordEntry(
         {federationText: 'with chromium.org', username: 'bart', deviceId: 42});
diff --git a/chrome/test/data/webui/settings/test_password_manager_proxy.js b/chrome/test/data/webui/settings/test_password_manager_proxy.js
index 369cdd8..9179876 100644
--- a/chrome/test/data/webui/settings/test_password_manager_proxy.js
+++ b/chrome/test/data/webui/settings/test_password_manager_proxy.js
@@ -56,6 +56,7 @@
       'removeSavedPassword',
       'removeSavedPasswords',
       'removeException',
+      'removeExceptions',
     ]);
 
     /** @private {!PasswordManagerExpectations} */
@@ -142,6 +143,12 @@
   }
 
   /** @override */
+  removeExceptions(ids) {
+    this.actual_.removed.exceptions += ids.length;
+    this.methodCalled('removeExceptions', ids);
+  }
+
+  /** @override */
   requestPlaintextPassword(id, reason) {
     this.methodCalled('requestPlaintextPassword', {id, reason});
     return Promise.resolve(this.plaintextPassword_);
diff --git a/chrome/test/data/webui/tab_strip/BUILD.gn b/chrome/test/data/webui/tab_strip/BUILD.gn
index 9c2b6a64..06f97065 100644
--- a/chrome/test/data/webui/tab_strip/BUILD.gn
+++ b/chrome/test/data/webui/tab_strip/BUILD.gn
@@ -11,17 +11,14 @@
                     "js_module_root=../../chrome/test/data/webui/",
                     "js_module_root=./gen/chrome/test/data/webui/",
                   ]
-
-  # TODO(crbug.com/1000989): Add JS type checking for all commented out targets.
   deps = [
-    #":alert_indicator_test",
-    #":alert_indicators_test",
+    ":alert_indicator_test",
+    ":alert_indicators_test",
     ":drag_manager_test",
-
-    #":tab_group_test",
-    #":tab_list_test",
-    #":tab_swiper_test",
-    #":tab_test",
+    ":tab_group_test",
+    ":tab_list_test",
+    ":tab_swiper_test",
+    ":tab_test",
     ":test_tab_strip_embedder_proxy",
     ":test_tabs_api_proxy",
   ]
@@ -41,6 +38,24 @@
   ]
 }
 
+js_library("alert_indicator_test") {
+  deps = [
+    "..:chai_assert",
+    "//chrome/browser/resources/tab_strip:alert_indicator",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
+js_library("alert_indicators_test") {
+  deps = [
+    "..:chai_assert",
+    "//chrome/browser/resources/tab_strip:alert_indicator",
+    "//chrome/browser/resources/tab_strip:alert_indicators",
+    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
 js_library("drag_manager_test") {
   deps = [
     ":test_tabs_api_proxy",
@@ -54,3 +69,59 @@
   ]
   externs_list = [ "$externs_path/mocha-2.5.js" ]
 }
+
+js_library("tab_group_test") {
+  deps = [
+    ":test_tab_strip_embedder_proxy",
+    "..:chai_assert",
+    "//chrome/browser/resources/tab_strip:tab",
+    "//chrome/browser/resources/tab_strip:tab_group",
+    "//chrome/browser/resources/tab_strip:tab_strip_embedder_proxy",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
+js_library("tab_list_test") {
+  deps = [
+    ":test_tab_strip_embedder_proxy",
+    ":test_tabs_api_proxy",
+    "..:chai_assert",
+    "..:test_util.m",
+    "//chrome/browser/resources/tab_strip:tab",
+    "//chrome/browser/resources/tab_strip:tab_group",
+    "//chrome/browser/resources/tab_strip:tab_list",
+    "//chrome/browser/resources/tab_strip:tab_strip_embedder_proxy",
+    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
+    "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/js:load_time_data.m",
+    "//ui/webui/resources/js/cr/ui:focus_outline_manager.m",
+  ]
+  externs_list = [
+    "$externs_path/mocha-2.5.js",
+    "$externs_path/pending.js",
+  ]
+}
+
+js_library("tab_swiper_test") {
+  deps = [
+    ":test_tabs_api_proxy",
+    "..:chai_assert",
+    "..:test_util.m",
+    "//chrome/browser/resources/tab_strip:tab_swiper",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
+
+js_library("tab_test") {
+  deps = [
+    ":test_tab_strip_embedder_proxy",
+    ":test_tabs_api_proxy",
+    "..:chai_assert",
+    "//chrome/browser/resources/tab_strip:tab",
+    "//chrome/browser/resources/tab_strip:tab_strip_embedder_proxy",
+    "//chrome/browser/resources/tab_strip:tabs_api_proxy",
+    "//ui/webui/resources/js:icon.m",
+    "//ui/webui/resources/js:load_time_data.m",
+  ]
+  externs_list = [ "$externs_path/mocha-2.5.js" ]
+}
diff --git a/chrome/test/data/webui/tab_strip/alert_indicator_test.js b/chrome/test/data/webui/tab_strip/alert_indicator_test.js
index 8f16818..fc1f761b 100644
--- a/chrome/test/data/webui/tab_strip/alert_indicator_test.js
+++ b/chrome/test/data/webui/tab_strip/alert_indicator_test.js
@@ -2,16 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://tab-strip/alert_indicator.js';
+import {AlertIndicatorElement} from 'chrome://tab-strip/alert_indicator.js';
+
+import {assertEquals, assertFalse, assertNotEquals} from '../chai_assert.js';
 
 suite('AlertIndicator', () => {
+  /** @type {!AlertIndicatorElement} */
   let alertIndicatorElement;
+
+  /** @type {CSSStyleDeclaration} */
   let alertIndicatorStyle;
 
   setup(() => {
     document.body.innerHTML = '';
 
-    alertIndicatorElement = document.createElement('tabstrip-alert-indicator');
+    alertIndicatorElement = /** @type {!AlertIndicatorElement} */ (
+        document.createElement('tabstrip-alert-indicator'));
     document.body.appendChild(alertIndicatorElement);
 
     alertIndicatorStyle = window.getComputedStyle(alertIndicatorElement);
diff --git a/chrome/test/data/webui/tab_strip/alert_indicators_test.js b/chrome/test/data/webui/tab_strip/alert_indicators_test.js
index 6f97abb9..536630d 100644
--- a/chrome/test/data/webui/tab_strip/alert_indicators_test.js
+++ b/chrome/test/data/webui/tab_strip/alert_indicators_test.js
@@ -2,24 +2,28 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://tab-strip/alert_indicators.js';
-
+import {AlertIndicatorElement} from 'chrome://tab-strip/alert_indicator.js';
+import {AlertIndicatorsElement} from 'chrome://tab-strip/alert_indicators.js';
 import {TabAlertState} from 'chrome://tab-strip/tabs_api_proxy.js';
 
+import {assertEquals} from '../chai_assert.js';
+
 suite('AlertIndicators', () => {
+  /** @type {!AlertIndicatorsElement} */
   let alertIndicatorsElement;
 
+  /** @return {!NodeList<!AlertIndicatorElement>} */
   const getAlertIndicators = () => {
-    return alertIndicatorsElement.shadowRoot.querySelectorAll(
-        'tabstrip-alert-indicator');
+    return /** @type {!NodeList<!AlertIndicatorElement>} */ (
+        alertIndicatorsElement.shadowRoot.querySelectorAll(
+            'tabstrip-alert-indicator'));
   };
 
   setup(() => {
     document.body.innerHTML = '';
 
-    alertIndicatorsElement =
-        document.createElement('tabstrip-alert-indicators');
-    alertIndicatorsElement.onAlertIndicatorCountChange = () => {};
+    alertIndicatorsElement = /** @type {!AlertIndicatorsElement} */
+        (document.createElement('tabstrip-alert-indicators'));
     document.body.appendChild(alertIndicatorsElement);
   });
 
diff --git a/chrome/test/data/webui/tab_strip/tab_group_test.js b/chrome/test/data/webui/tab_strip/tab_group_test.js
index be281e9c..dad79eb6 100644
--- a/chrome/test/data/webui/tab_strip/tab_group_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_group_test.js
@@ -3,15 +3,21 @@
 // found in the LICENSE file.
 
 import 'chrome://tab-strip/tab.js';
-import 'chrome://tab-strip/tab_group.js';
+import {TabGroupElement} from 'chrome://tab-strip/tab_group.js';
 
 import {TabStripEmbedderProxyImpl} from 'chrome://tab-strip/tab_strip_embedder_proxy.js';
+
+import {assertEquals} from '../chai_assert.js';
+
 import {TestTabStripEmbedderProxy} from './test_tab_strip_embedder_proxy.js';
 
 suite('TabGroup', () => {
   const groupId = 'my-group-id';
 
+  /** @type {!TabGroupElement} */
   let tabGroupElement;
+
+  /** @type {!TestTabStripEmbedderProxy} */
   let testTabStripEmbedderProxy;
 
   setup(() => {
@@ -19,7 +25,8 @@
     TabStripEmbedderProxyImpl.instance_ = testTabStripEmbedderProxy;
 
     document.body.innerHTML = '';
-    tabGroupElement = document.createElement('tabstrip-tab-group');
+    tabGroupElement = /** @type {!TabGroupElement} */ (
+        document.createElement('tabstrip-tab-group'));
     tabGroupElement.dataset.groupId = groupId;
     tabGroupElement.appendChild(document.createElement('tabstrip-tab'));
     document.body.appendChild(tabGroupElement);
diff --git a/chrome/test/data/webui/tab_strip/tab_list_test.js b/chrome/test/data/webui/tab_strip/tab_list_test.js
index 4d80ece..bd2ffff 100644
--- a/chrome/test/data/webui/tab_strip/tab_list_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_list_test.js
@@ -5,22 +5,29 @@
 import {webUIListenerCallback} from 'chrome://resources/js/cr.m.js';
 import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
-import {setScrollAnimationEnabledForTesting} from 'chrome://tab-strip/tab_list.js';
+import {TabElement} from 'chrome://tab-strip/tab.js';
+import {TabGroupElement} from 'chrome://tab-strip/tab_group.js';
+import {setScrollAnimationEnabledForTesting, TabListElement} from 'chrome://tab-strip/tab_list.js';
 import {TabStripEmbedderProxyImpl} from 'chrome://tab-strip/tab_strip_embedder_proxy.js';
-import {TabsApiProxyImpl} from 'chrome://tab-strip/tabs_api_proxy.js';
+import {TabData, TabsApiProxyImpl} from 'chrome://tab-strip/tabs_api_proxy.js';
 
+import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
 import {eventToPromise} from '../test_util.m.js';
 
 import {TestTabStripEmbedderProxy} from './test_tab_strip_embedder_proxy.js';
 import {TestTabsApiProxy} from './test_tabs_api_proxy.js';
 
 suite('TabList', () => {
-  let callbackRouter;
-  let optionsCalled;
+  /** @type {!TabListElement} */
   let tabList;
+
+  /** @type {!TestTabStripEmbedderProxy} */
   let testTabStripEmbedderProxy;
+
+  /** @type {!TestTabsApiProxy} */
   let testTabsApiProxy;
 
+  /** @type {!Array<!TabData>} */
   const tabs = [
     {
       active: true,
@@ -48,28 +55,42 @@
     },
   ];
 
+  /**
+   * @param {!TabData} tab
+   * @param {number} index
+   */
   function pinTabAt(tab, index) {
     const changeInfo = {index: index, pinned: true};
     const updatedTab = Object.assign({}, tab, changeInfo);
     webUIListenerCallback('tab-updated', updatedTab);
   }
 
+  /**
+   * @param {!TabData} tab
+   * @param {number} index
+   */
   function unpinTabAt(tab, index) {
     const changeInfo = {index: index, pinned: false};
     const updatedTab = Object.assign({}, tab, changeInfo);
     webUIListenerCallback('tab-updated', updatedTab);
   }
 
+  /** @return {!NodeList<!TabElement>} */
   function getUnpinnedTabs() {
-    return tabList.shadowRoot.querySelectorAll('#unpinnedTabs tabstrip-tab');
+    return /** @type {!NodeList<!TabElement>} */ (
+        tabList.shadowRoot.querySelectorAll('#unpinnedTabs tabstrip-tab'));
   }
 
+  /** @return {!NodeList<!TabElement>} */
   function getPinnedTabs() {
-    return tabList.shadowRoot.querySelectorAll('#pinnedTabs tabstrip-tab');
+    return /** @type {!NodeList<!TabElement>} */ (
+        tabList.shadowRoot.querySelectorAll('#pinnedTabs tabstrip-tab'));
   }
 
+  /** @return {!NodeList<!TabGroupElement>} */
   function getTabGroups() {
-    return tabList.shadowRoot.querySelectorAll('tabstrip-tab-group');
+    return /** @type {!NodeList<!TabGroupElement>} */ (
+        tabList.shadowRoot.querySelectorAll('tabstrip-tab-group'));
   }
 
   setup(() => {
@@ -79,7 +100,6 @@
     testTabsApiProxy = new TestTabsApiProxy();
     testTabsApiProxy.setTabs(tabs);
     TabsApiProxyImpl.instance_ = testTabsApiProxy;
-    callbackRouter = testTabsApiProxy.callbackRouter;
 
     testTabStripEmbedderProxy = new TestTabStripEmbedderProxy();
     testTabStripEmbedderProxy.setColors({
@@ -95,7 +115,8 @@
 
     setScrollAnimationEnabledForTesting(false);
 
-    tabList = document.createElement('tabstrip-tab-list');
+    tabList = /** @type {!TabListElement} */ (
+        document.createElement('tabstrip-tab-list'));
     document.body.appendChild(tabList);
 
     return testTabsApiProxy.whenCalled('getTabs');
@@ -224,17 +245,20 @@
   });
 
   test('PlacesTabElement', () => {
-    const pinnedTab = document.createElement('tabstrip-tab');
+    const pinnedTab =
+        /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
     tabList.placeTabElement(pinnedTab, 0, true, undefined);
     assertEquals(pinnedTab, getPinnedTabs()[0]);
 
-    const unpinnedUngroupedTab = document.createElement('tabstrip-tab');
+    const unpinnedUngroupedTab =
+        /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
     tabList.placeTabElement(unpinnedUngroupedTab, 1, false, undefined);
     let unpinnedTabs = getUnpinnedTabs();
     assertEquals(4, unpinnedTabs.length);
     assertEquals(unpinnedUngroupedTab, unpinnedTabs[0]);
 
-    const groupedTab = document.createElement('tabstrip-tab');
+    const groupedTab =
+        /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
     tabList.placeTabElement(groupedTab, 1, false, 'group0');
     unpinnedTabs = getUnpinnedTabs();
     assertEquals(5, unpinnedTabs.length);
@@ -305,7 +329,8 @@
   });
 
   test('PlacesTabGroupElement', () => {
-    const tabGroupElement = document.createElement('tabstrip-tab-group');
+    const tabGroupElement = /** @type {!TabGroupElement} */ (
+        document.createElement('tabstrip-tab-group'));
     tabList.placeTabGroupElement(tabGroupElement, 2);
 
     const tabGroupElements = getTabGroups();
diff --git a/chrome/test/data/webui/tab_strip/tab_swiper_test.js b/chrome/test/data/webui/tab_strip/tab_swiper_test.js
index b66fa3e..a7219c3 100644
--- a/chrome/test/data/webui/tab_strip/tab_swiper_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_swiper_test.js
@@ -4,21 +4,23 @@
 
 import {SWIPE_FINISH_THRESHOLD_PX, SWIPE_START_THRESHOLD_PX, TabSwiper, TRANSLATE_ANIMATION_THRESHOLD_PX} from 'chrome://tab-strip/tab_swiper.js';
 
+import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
 import {eventToPromise} from '../test_util.m.js';
 
 import {TestTabsApiProxy} from './test_tabs_api_proxy.js';
 
 suite('TabSwiper', () => {
+  /** @type {!HTMLElement} */
   let tabElement;
-  let tabSwiper;
 
-  const tab = {id: 1001};
+  /** @type {!TabSwiper} */
+  let tabSwiper;
 
   setup(() => {
     document.body.innerHTML = '';
 
-    tabElement = document.createElement('div');
-    tabElement.tab = tab;
+    tabElement =
+        /** @type {!HTMLElement} */ (document.createElement('div'));
     document.body.appendChild(tabElement);
 
     tabSwiper = new TabSwiper(tabElement);
@@ -58,8 +60,8 @@
     pointerState.clientY = startY - (SWIPE_START_THRESHOLD_PX + 1);
     tabElement.dispatchEvent(new PointerEvent('pointermove', pointerState));
     assertTrue(
-        parseInt(tabElStyle.maxWidth) > 0 &&
-        parseInt(tabElStyle.maxWidth) < tabWidth);
+        parseInt(tabElStyle.maxWidth, 10) > 0 &&
+        parseInt(tabElStyle.maxWidth, 10) < tabWidth);
     assertTrue(
         parseFloat(tabElStyle.opacity) > 0 &&
         parseFloat(tabElStyle.opacity) < 1);
diff --git a/chrome/test/data/webui/tab_strip/tab_test.js b/chrome/test/data/webui/tab_strip/tab_test.js
index 19558c7..39fab62 100644
--- a/chrome/test/data/webui/tab_strip/tab_test.js
+++ b/chrome/test/data/webui/tab_strip/tab_test.js
@@ -2,30 +2,53 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-import 'chrome://tab-strip/tab.js';
-
 import {getFavicon} from 'chrome://resources/js/icon.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {TabElement} from 'chrome://tab-strip/tab.js';
 import {TabStripEmbedderProxy, TabStripEmbedderProxyImpl} from 'chrome://tab-strip/tab_strip_embedder_proxy.js';
-import {CloseTabAction, TabNetworkState, TabsApiProxyImpl} from 'chrome://tab-strip/tabs_api_proxy.js';
+import {CloseTabAction, TabData, TabNetworkState, TabsApiProxyImpl} from 'chrome://tab-strip/tabs_api_proxy.js';
+
+import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js';
 
 import {TestTabStripEmbedderProxy} from './test_tab_strip_embedder_proxy.js';
 import {TestTabsApiProxy} from './test_tabs_api_proxy.js';
 
 suite('Tab', function() {
+  /** @type {!TestTabsApiProxy} */
   let testTabsApiProxy;
+
+  /** @type {!TestTabStripEmbedderProxy} */
   let testTabStripEmbedderProxy;
+
+  /** @type {!TabElement} */
   let tabElement;
 
+  /** @type {!TabData} */
   const tab = {
     active: false,
     alertStates: [],
+    blocked: false,
+    crashed: false,
     id: 1001,
+    index: 0,
+    isDefaultFavicon: false,
     networkState: TabNetworkState.NONE,
     pinned: false,
+    shouldHideThrobber: false,
+    showIcon: true,
     title: 'My title',
+    url: 'http://foo',
   };
 
+  /**
+   * Convenience function for creating a typed TabData object.
+   * @param {!Object=} overrides
+   * @return {!TabData}
+   */
+  function createTabData(overrides) {
+    return /** @type {!TabData} */ (Object.assign({}, tab, overrides));
+  }
+
   const strings = {
     closeTab: 'Close tab',
     loadingTab: 'Loading...',
@@ -49,8 +72,9 @@
     testTabsApiProxy = new TestTabsApiProxy();
     TabsApiProxyImpl.instance_ = testTabsApiProxy;
 
-    tabElement = document.createElement('tabstrip-tab');
-    tabElement.tab = tab;
+    tabElement =
+        /** @type {!TabElement} */ (document.createElement('tabstrip-tab'));
+    tabElement.tab = createTabData({});
     document.body.appendChild(tabElement);
   });
 
@@ -151,19 +175,19 @@
   });
 
   test('toggles an [active] attribute when active', () => {
-    tabElement.tab = Object.assign({}, tab, {active: true});
+    tabElement.tab = createTabData({active: true});
     assertTrue(tabElement.hasAttribute('active'));
-    tabElement.tab = Object.assign({}, tab, {active: false});
+    tabElement.tab = createTabData({active: false});
     assertFalse(tabElement.hasAttribute('active'));
   });
 
   test('sets [aria-selected] attribute when active', () => {
-    tabElement.tab = Object.assign({}, tab, {active: true});
+    tabElement.tab = createTabData({active: true});
     assertEquals(
         'true',
         tabElement.shadowRoot.querySelector('#tab').getAttribute(
             'aria-selected'));
-    tabElement.tab = Object.assign({}, tab, {active: false});
+    tabElement.tab = createTabData({active: false});
     assertEquals(
         'false',
         tabElement.shadowRoot.querySelector('#tab').getAttribute(
@@ -177,13 +201,13 @@
     const faviconContainerStyle = window.getComputedStyle(
         tabElement.shadowRoot.querySelector('#faviconContainer'));
 
-    tabElement.tab = Object.assign({}, tab, {showIcon: true});
+    tabElement.tab = createTabData({showIcon: true});
     assertEquals(
         faviconContainerStyle.maxWidth,
         faviconContainerStyle.getPropertyValue('--favicon-size').trim());
     assertEquals(faviconContainerStyle.opacity, '1');
 
-    tabElement.tab = Object.assign({}, tab, {showIcon: false});
+    tabElement.tab = createTabData({showIcon: false});
     assertEquals(faviconContainerStyle.maxWidth, '0px');
     assertEquals(faviconContainerStyle.opacity, '0');
   });
@@ -193,13 +217,13 @@
     const expectedSize = '100px';
     tabElement.style.setProperty('--tabstrip-pinned-tab-size', expectedSize);
 
-    tabElement.tab = Object.assign({}, tab, {pinned: true});
+    tabElement.tab = createTabData({pinned: true});
     assertEquals(expectedSize, tabElementStyle.width);
     assertEquals(expectedSize, tabElementStyle.height);
 
     tabElement.style.setProperty('--tabstrip-tab-width', '100px');
     tabElement.style.setProperty('--tabstrip-tab-height', '150px');
-    tabElement.tab = Object.assign({}, tab, {pinned: false});
+    tabElement.tab = createTabData({pinned: false});
     assertEquals('100px', tabElementStyle.width);
     assertEquals('150px', tabElementStyle.height);
   });
@@ -212,32 +236,29 @@
       assertEquals(color, spinnerStyle.backgroundColor);
 
       // Also assert it becomes hidden when network state is NONE
-      tabElement.tab =
-          Object.assign({}, tab, {networkState: TabNetworkState.NONE});
+      tabElement.tab = createTabData({networkState: TabNetworkState.NONE});
       assertEquals('none', spinnerStyle.display);
     }
 
     tabElement.style.setProperty(
         '--tabstrip-tab-loading-spinning-color', 'rgb(255, 0, 0)');
-    tabElement.tab =
-        Object.assign({}, tab, {networkState: TabNetworkState.LOADING});
+    tabElement.tab = createTabData({networkState: TabNetworkState.LOADING});
     assertSpinnerVisible('rgb(255, 0, 0)');
 
     tabElement.style.setProperty(
         '--tabstrip-tab-waiting-spinning-color', 'rgb(0, 255, 0)');
-    tabElement.tab =
-        Object.assign({}, tab, {networkState: TabNetworkState.WAITING});
+    tabElement.tab = createTabData({networkState: TabNetworkState.WAITING});
     assertSpinnerVisible('rgb(0, 255, 0)');
   });
 
   test('shows blocked indicator when tab is blocked', () => {
     const blockIndicatorStyle = window.getComputedStyle(
         tabElement.shadowRoot.querySelector('#blocked'));
-    tabElement.tab = Object.assign({}, tab, {blocked: true});
+    tabElement.tab = createTabData({blocked: true});
     assertEquals('block', blockIndicatorStyle.display);
-    tabElement.tab = Object.assign({}, tab, {blocked: true, active: true});
+    tabElement.tab = createTabData({blocked: true, active: true});
     assertEquals('none', blockIndicatorStyle.display);
-    tabElement.tab = Object.assign({}, tab, {blocked: false});
+    tabElement.tab = createTabData({blocked: false});
     assertEquals('none', blockIndicatorStyle.display);
   });
 
@@ -253,18 +274,18 @@
         const crashedIconStyle = window.getComputedStyle(
             tabElement.shadowRoot.querySelector('#crashedIcon'));
 
-        tabElement.tab = Object.assign({}, tab, {crashed: true});
+        tabElement.tab = createTabData({crashed: true});
         assertEquals(faviconStyle.opacity, '0');
         assertEquals(crashedIconStyle.opacity, '1');
 
-        tabElement.tab = Object.assign({}, tab, {crashed: false});
+        tabElement.tab = createTabData({crashed: false});
         assertEquals(faviconStyle.opacity, '1');
         assertEquals(crashedIconStyle.opacity, '0');
       });
 
   test('clicking on the element activates the tab', () => {
     tabElement.shadowRoot.querySelector('#tab').click();
-    return testTabsApiProxy.whenCalled('activateTab', tabId => {
+    return testTabsApiProxy.whenCalled('activateTab').then(tabId => {
       assertEquals(tabId, tab.id);
     });
   });
@@ -275,7 +296,7 @@
   });
 
   test('sets the loading title while loading', () => {
-    const loadingTabWithoutTitle = Object.assign({}, tab, {
+    const loadingTabWithoutTitle = createTabData({
       networkState: TabNetworkState.WAITING,
       shouldHideThrobber: false,
     });
@@ -287,7 +308,7 @@
   });
 
   test('exposes the tab ID to an attribute', () => {
-    tabElement.tab = Object.assign({}, tab, {id: 1001});
+    tabElement.tab = createTabData({id: 1001});
     assertEquals('1001', tabElement.getAttribute('data-tab-id'));
   });
 
@@ -313,7 +334,7 @@
 
   test('sets the favicon to the favicon URL', () => {
     const expectedFaviconUrl = 'data:mock-favicon';
-    tabElement.tab = Object.assign({}, tab, {favIconUrl: expectedFaviconUrl});
+    tabElement.tab = createTabData({favIconUrl: expectedFaviconUrl});
     const faviconElement = tabElement.shadowRoot.querySelector('#favicon');
     assertEquals(
         faviconElement.style.backgroundImage, `url("${expectedFaviconUrl}")`);
@@ -322,7 +343,7 @@
   test(
       'sets the favicon to the default favicon URL if there is none provided',
       () => {
-        const updatedTab = Object.assign({}, tab);
+        const updatedTab = createTabData();
         delete updatedTab.favIconUrl;
         tabElement.tab = updatedTab;
         const faviconElement = tabElement.shadowRoot.querySelector('#favicon');
@@ -330,7 +351,7 @@
       });
 
   test('removes the favicon if the tab is waiting', () => {
-    tabElement.tab = Object.assign({}, tab, {
+    tabElement.tab = createTabData({
       favIconUrl: 'data:mock-favicon',
       networkState: TabNetworkState.WAITING,
     });
@@ -341,7 +362,7 @@
   test(
       'removes the favicon if the tab is loading with a default favicon',
       () => {
-        tabElement.tab = Object.assign({}, tab, {
+        tabElement.tab = createTabData({
           favIconUrl: 'data:mock-favicon',
           hasDefaultFavicon: true,
           networkState: TabNetworkState.WAITING,
@@ -400,14 +421,14 @@
     const titleTextElement = tabElement.shadowRoot.querySelector('#titleText');
     assertEquals(titleTextElement.getAttribute('aria-label'), tab.title);
 
-    tabElement.tab = Object.assign({}, tab, {
+    tabElement.tab = createTabData({
       crashed: true,
       title: 'My tab',
     });
     assertEquals(
         titleTextElement.getAttribute('aria-label'), 'My tab has crashed');
 
-    tabElement.tab = Object.assign({}, tab, {
+    tabElement.tab = createTabData({
       crashed: false,
       networkState: TabNetworkState.ERROR,
       title: 'My tab',
diff --git a/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js b/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
index e4246658..47bb99f 100644
--- a/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
+++ b/chrome/test/data/webui/tab_strip/test_tabs_api_proxy.js
@@ -73,7 +73,7 @@
     this.methodCalled('moveTab', [tabId, newIndex]);
   }
 
-  /** @param {!Array<!TabGroupVisualData>} groupVisualData */
+  /** @param {!Object<!TabGroupVisualData>} groupVisualData */
   setGroupVisualData(groupVisualData) {
     this.groupVisualData_ = groupVisualData;
   }
diff --git a/chrome/test/mini_installer/variable_expander.py b/chrome/test/mini_installer/variable_expander.py
index 04a6dba..f9be0137 100644
--- a/chrome/test/mini_installer/variable_expander.py
+++ b/chrome/test/mini_installer/variable_expander.py
@@ -157,46 +157,31 @@
         previous_version_mini_installer_path)
     windows_major_ver, windows_minor_ver, _, _, _ = win32api.GetVersionEx()
     self._variable_mapping = {
-        'CHROMEDRIVER_PATH':
-        chromedriver_path,
-        'QUIET':
-        '-q' if quiet else '',
-        'OUTPUT_DIR':
-        '"--output-dir=%s"' % output_dir if output_dir else '',
-        'LOCAL_APPDATA':
-        shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA, None, 0),
-        'LOG_FILE':
-        '',
-        'MINI_INSTALLER':
-        mini_installer_abspath,
-        'MINI_INSTALLER_FILE_VERSION':
-        _GetFileVersion(mini_installer_abspath),
-        'MINI_INSTALLER_BITNESS':
-        _GetFileBitness(mini_installer_abspath),
+        'CHROMEDRIVER_PATH': chromedriver_path,
+        'QUIET': '-q' if quiet else '',
+        'OUTPUT_DIR': '"--output-dir=%s"' % output_dir if output_dir else '',
+        'LOCAL_APPDATA': shell.SHGetFolderPath(0, shellcon.CSIDL_LOCAL_APPDATA,
+                                               None, 0),
+        'LOG_FILE': '',
+        'MINI_INSTALLER': mini_installer_abspath,
+        'MINI_INSTALLER_FILE_VERSION': _GetFileVersion(mini_installer_abspath),
+        'MINI_INSTALLER_BITNESS': _GetFileBitness(mini_installer_abspath),
         'PREVIOUS_VERSION_MINI_INSTALLER':
-        previous_version_mini_installer_abspath,
-        'PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION':
-        _GetFileVersion(previous_version_mini_installer_abspath),
-        'PROGRAM_FILES':
-        shell.SHGetFolderPath(0, shellcon.CSIDL_PROGRAM_FILES, None, 0),
-        'USER_SPECIFIC_REGISTRY_SUFFIX':
-        _GetUserSpecificRegistrySuffix(),
-        'VERSION_SERVER_2003':
-        '(5, 2)',
-        'VERSION_VISTA':
-        '(6, 0)',
-        'VERSION_WIN10':
-        '(10, 0)',
-        'VERSION_WIN7':
-        '(6, 1)',
-        'VERSION_WIN8':
-        '(6, 2)',
-        'VERSION_WIN8_1':
-        '(6, 3)',
-        'VERSION_XP':
-        '(5, 1)',
-        'WINDOWS_VERSION':
-        '(%s, %s)' % (windows_major_ver, windows_minor_ver)
+            previous_version_mini_installer_abspath,
+        'PREVIOUS_VERSION_MINI_INSTALLER_FILE_VERSION': _GetFileVersion(
+            previous_version_mini_installer_abspath),
+        'PROGRAM_FILES': shell.SHGetFolderPath(0,
+                                               shellcon.CSIDL_PROGRAM_FILESX86,
+                                               None, 0),
+        'USER_SPECIFIC_REGISTRY_SUFFIX': _GetUserSpecificRegistrySuffix(),
+        'VERSION_SERVER_2003': '(5, 2)',
+        'VERSION_VISTA': '(6, 0)',
+        'VERSION_WIN10': '(10, 0)',
+        'VERSION_WIN7': '(6, 1)',
+        'VERSION_WIN8': '(6, 2)',
+        'VERSION_WIN8_1': '(6, 3)',
+        'VERSION_XP': '(5, 1)',
+        'WINDOWS_VERSION': '(%s, %s)' % (windows_major_ver, windows_minor_ver)
     }
 
     mini_installer_product_name = _GetProductName(mini_installer_abspath)
diff --git a/chrome/utility/image_writer/image_writer_unittest.cc b/chrome/utility/image_writer/image_writer_unittest.cc
index bab93243..55881c8 100644
--- a/chrome/utility/image_writer/image_writer_unittest.cc
+++ b/chrome/utility/image_writer/image_writer_unittest.cc
@@ -70,7 +70,7 @@
 // the write completes.
 class VerifyingHandler : public MockHandler {
  public:
-  VerifyingHandler() : image_writer_(NULL), verified_(false) {}
+  VerifyingHandler() : image_writer_(nullptr), verified_(false) {}
 
   void SendSucceeded() override {
     MockHandler::SendSucceeded();
diff --git a/chrome/utility/importer/nss_decryptor_system_nss.cc b/chrome/utility/importer/nss_decryptor_system_nss.cc
index 67ccc83c..a9f6611 100644
--- a/chrome/utility/importer/nss_decryptor_system_nss.cc
+++ b/chrome/utility/importer/nss_decryptor_system_nss.cc
@@ -14,7 +14,7 @@
 #include "base/strings/sys_string_conversions.h"
 #include "crypto/nss_util.h"
 
-NSSDecryptor::NSSDecryptor() : is_nss_initialized_(false), db_slot_(NULL) {}
+NSSDecryptor::NSSDecryptor() : is_nss_initialized_(false), db_slot_(nullptr) {}
 NSSDecryptor::~NSSDecryptor() {
   if (db_slot_) {
     // Deliberately leave the user db open, just in case we need to open more
diff --git a/chromecast/base/serializers.h b/chromecast/base/serializers.h
index 110ccc92..d2a35238 100644
--- a/chromecast/base/serializers.h
+++ b/chromecast/base/serializers.h
@@ -17,11 +17,13 @@
 
 namespace chromecast {
 
+// Deprecated: use base::JSONReader::Read instead.
 // Helper function which deserializes JSON |text| into a base::Value. If |text|
 // is empty, is not valid JSON, or if some other deserialization error occurs,
 // the return value will hold the NULL pointer.
 std::unique_ptr<base::Value> DeserializeFromJson(const std::string& text);
 
+// Deprecated: use base::JSONWriter::Write instead.
 // Helper function which serializes |value| into a JSON string. If a
 // serialization error occurs,the return value will be base::nullopt.
 // Dereferencing the result is equivalent to DCHECK()-ing that serialization
diff --git a/chromecast/browser/webview/web_content_controller.h b/chromecast/browser/webview/web_content_controller.h
index 342461e..de9009b 100644
--- a/chromecast/browser/webview/web_content_controller.h
+++ b/chromecast/browser/webview/web_content_controller.h
@@ -64,6 +64,17 @@
   void AttachTo(aura::Window* window, int window_id);
 
  protected:
+  // content::WebContentsObserver
+  void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
+  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
+                              content::RenderFrameHost* new_host) override;
+  void MainFrameWasResized(bool width_changed) override;
+  void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
+                        const gfx::Size& frame_size) override;
+  void RenderViewCreated(content::RenderViewHost* render_view_host) override;
+  void RenderViewDeleted(content::RenderViewHost* render_view_host) override;
+
   static void RegisterRenderWidgetInputObserverFromRenderFrameHost(
       WebContentController* web_content_controller,
       content::RenderFrameHost* render_frame_host);
@@ -111,17 +122,6 @@
   // exo::SurfaceObserver
   void OnSurfaceDestroying(exo::Surface* surface) override;
 
-  // content::WebContentsObserver
-  void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
-  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
-  void RenderFrameHostChanged(content::RenderFrameHost* old_host,
-                              content::RenderFrameHost* new_host) override;
-  void MainFrameWasResized(bool width_changed) override;
-  void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
-                        const gfx::Size& frame_size) override;
-  void RenderViewCreated(content::RenderViewHost* render_view_host) override;
-  void RenderViewDeleted(content::RenderViewHost* render_view_host) override;
-
   // JsClientInstance::Observer
   void OnJsClientInstanceRegistered(int process_id,
                                     int routing_id,
diff --git a/chromecast/browser/webview/webview_controller.cc b/chromecast/browser/webview/webview_controller.cc
index 34ddb413..b1e9043 100644
--- a/chromecast/browser/webview/webview_controller.cc
+++ b/chromecast/browser/webview/webview_controller.cc
@@ -42,6 +42,14 @@
   WebviewController* controller_;
 };
 
+void UpdateWebkitPreferences(content::RenderViewHost* render_view_host) {
+  content::WebPreferences prefs = render_view_host->GetWebkitPreferences();
+  // Allow Webviews to show scrollbars. These are globally disabled since Cast
+  // Apps are not expected to be scrollable.
+  prefs.hide_scrollbars = false;
+  render_view_host->UpdateWebkitPreferences(prefs);
+}
+
 }  // namespace
 
 WebviewController::WebviewController(content::BrowserContext* browser_context,
@@ -165,6 +173,12 @@
   }
 }
 
+void WebviewController::RenderViewCreated(
+    content::RenderViewHost* render_view_host) {
+  WebContentController::RenderViewCreated(render_view_host);
+  UpdateWebkitPreferences(render_view_host);
+}
+
 void WebviewController::SendNavigationEvent(
     WebviewNavigationThrottle* throttle,
     content::NavigationHandle* navigation_handle) {
diff --git a/chromecast/browser/webview/webview_controller.h b/chromecast/browser/webview/webview_controller.h
index 4f60dd7f..ddebfa4 100644
--- a/chromecast/browser/webview/webview_controller.h
+++ b/chromecast/browser/webview/webview_controller.h
@@ -80,6 +80,9 @@
   // content::WebContentsObserver
   void DidFirstVisuallyNonEmptyPaint() override;
 
+  // WebContentController
+  void RenderViewCreated(content::RenderViewHost* render_view_host) override;
+
   const bool enabled_for_dev_;
   std::unique_ptr<content::WebContents> contents_;
   std::unique_ptr<CastWebContents> cast_web_contents_;
diff --git a/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc b/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc
index 8c346f94..06970a8 100644
--- a/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc
+++ b/chromecast/media/cma/backend/mixer/post_processors/post_processor_unittest.cc
@@ -245,7 +245,10 @@
     pp->ProcessFrames(&data_in[i], kBufSizeFrames, 1.0, 0.0);
   }
   clock_t stop_clock = clock();
-  LOG(INFO) << "At " << sample_rate
+  const ::testing::TestInfo* const test_info =
+      ::testing::UnitTest::GetInstance()->current_test_info();
+  LOG(INFO) << test_info->test_suite_name() << "." << test_info->name()
+            << " At " << sample_rate
             << " frames per second CPU usage: " << std::defaultfloat
             << 100.0 * (stop_clock - start_clock) /
                    (CLOCKS_PER_SEC * effective_duration)
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 6524b89..9cc4a29f 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-13272.0.0
\ No newline at end of file
+13274.0.0
\ No newline at end of file
diff --git a/chromeos/components/BUILD.gn b/chromeos/components/BUILD.gn
index bfdf700..1a91679 100644
--- a/chromeos/components/BUILD.gn
+++ b/chromeos/components/BUILD.gn
@@ -35,7 +35,6 @@
 group("closure_compile") {
   testonly = true
   deps = [
-    "//chromeos/components/camera_app_ui:closure_compile",
     "//chromeos/components/help_app_ui:closure_compile",
     "//chromeos/components/media_app_ui:closure_compile",
     "//chromeos/components/multidevice/debug_webui/resources:closure_compile",
diff --git a/chromeos/components/camera_app_ui/BUILD.gn b/chromeos/components/camera_app_ui/BUILD.gn
deleted file mode 100644
index 44365f15..0000000
--- a/chromeos/components/camera_app_ui/BUILD.gn
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//mojo/public/tools/bindings/mojom.gni")
-import("//third_party/closure_compiler/compile_js.gni")
-
-assert(is_chromeos, "Camera App is Chrome OS only")
-
-static_library("camera_app_ui") {
-  sources = [
-    "camera_app_helper_impl.cc",
-    "camera_app_helper_impl.h",
-    "camera_app_ui.cc",
-    "camera_app_ui.h",
-    "url_constants.cc",
-    "url_constants.h",
-  ]
-
-  deps = [
-    ":mojo_bindings",
-    ":mojo_bindings_js",
-    "//ash/public/cpp",
-    "//chromeos/components/web_applications",
-    "//chromeos/constants",
-    "//chromeos/resources:camera_app_resources",
-    "//chromeos/strings",
-    "//chromeos/system",
-    "//content/public/browser",
-    "//content/public/common",
-    "//media/capture:capture_lib",
-    "//mojo/public/cpp/bindings",
-    "//mojo/public/cpp/platform",
-    "//mojo/public/js:resources_grit",
-    "//ui/resources:webui_resources_grd_grit",
-    "//ui/webui",
-  ]
-}
-
-group("closure_compile") {
-  testonly = true
-  deps = [
-    "resources:closure_compile",
-  ]
-}
-
-mojom("mojo_bindings") {
-  sources = [ "camera_app_helper.mojom" ]
-
-  deps = [ "//components/arc/mojom:camera_intent" ]
-}
diff --git a/chromeos/components/camera_app_ui/DEPS b/chromeos/components/camera_app_ui/DEPS
deleted file mode 100644
index 7d83b5e..0000000
--- a/chromeos/components/camera_app_ui/DEPS
+++ /dev/null
@@ -1,6 +0,0 @@
-include_rules = [
-  "+ash/public/cpp",
-  "+content/public/browser",
-  "+ui/aura",
-  "+ui/webui",
-]
diff --git a/chromeos/components/camera_app_ui/OWNERS b/chromeos/components/camera_app_ui/OWNERS
deleted file mode 100644
index 29ab2a0..0000000
--- a/chromeos/components/camera_app_ui/OWNERS
+++ /dev/null
@@ -1,12 +0,0 @@
-henryhsu@chromium.org
-inker@chromium.org
-jcliang@chromium.org
-shik@chromium.org
-wtlee@chromium.org
-yuli@chromium.org
-
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
-
-# TEAM: chromeos-camera@chromium.org
-# COMPONENT: Platform>Apps>Camera
diff --git a/chromeos/components/camera_app_ui/camera_app_ui.cc b/chromeos/components/camera_app_ui/camera_app_ui.cc
deleted file mode 100644
index 9ffe7d4..0000000
--- a/chromeos/components/camera_app_ui/camera_app_ui.cc
+++ /dev/null
@@ -1,79 +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 "chromeos/components/camera_app_ui/camera_app_ui.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "chromeos/components/camera_app_ui/url_constants.h"
-#include "chromeos/grit/chromeos_camera_app_resources.h"
-#include "chromeos/grit/chromeos_camera_app_resources_map.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/browser/web_ui_data_source.h"
-#include "mojo/public/js/grit/mojo_bindings_resources.h"
-
-namespace chromeos {
-
-namespace {
-
-const struct {
-  const char* path;
-  int id;
-} kGritResourceMap[] = {
-    {"src/js/browser_proxy/browser_proxy.js", IDR_CAMERA_WEBUI_BROWSER_PROXY},
-    {"src/js/mojo/camera_intent.mojom-lite.js",
-     IDR_CAMERA_CAMERA_INTENT_MOJOM_LITE_JS},
-    {"src/js/mojo/image_capture.mojom-lite.js",
-     IDR_CAMERA_IMAGE_CAPTURE_MOJOM_LITE_JS},
-    {"src/js/mojo/camera_common.mojom-lite.js",
-     IDR_CAMERA_CAMERA_COMMON_MOJOM_LITE_JS},
-    {"src/js/mojo/camera_metadata.mojom-lite.js",
-     IDR_CAMERA_CAMERA_METADATA_MOJOM_LITE_JS},
-    {"src/js/mojo/camera_metadata_tags.mojom-lite.js",
-     IDR_CAMERA_CAMERA_METADATA_TAGS_MOJOM_LITE_JS},
-    {"src/js/mojo/camera_app.mojom-lite.js", IDR_CAMERA_APP_MOJOM_LITE_JS},
-    {"src/js/mojo/mojo_bindings_lite.js", IDR_MOJO_MOJO_BINDINGS_LITE_JS},
-};
-
-content::WebUIDataSource* CreateCameraAppUIHTMLSource() {
-  content::WebUIDataSource* source =
-      content::WebUIDataSource::Create(kChromeUICameraAppHost);
-
-  // Add all settings resources.
-  for (size_t i = 0; i < kChromeosCameraAppResourcesSize; i++) {
-    source->AddResourcePath(kChromeosCameraAppResources[i].name,
-                            kChromeosCameraAppResources[i].value);
-  }
-
-  for (const auto& res : kGritResourceMap) {
-    source->AddResourcePath(res.path, res.id);
-  }
-
-  source->UseStringsJs();
-
-  return source;
-}
-
-}  // namespace
-
-///////////////////////////////////////////////////////////////////////////////
-//
-// CameraAppUI
-//
-///////////////////////////////////////////////////////////////////////////////
-
-CameraAppUI::CameraAppUI(content::WebUI* web_ui)
-    : ui::MojoWebUIController(web_ui) {
-  content::BrowserContext* browser_context =
-      web_ui->GetWebContents()->GetBrowserContext();
-
-  // Set up the data source.
-  content::WebUIDataSource* source = CreateCameraAppUIHTMLSource();
-  content::WebUIDataSource::Add(browser_context, source);
-}
-
-CameraAppUI::~CameraAppUI() = default;
-
-}  // namespace chromeos
diff --git a/chromeos/components/camera_app_ui/camera_app_ui.h b/chromeos/components/camera_app_ui/camera_app_ui.h
deleted file mode 100644
index 64bb1c2..0000000
--- a/chromeos/components/camera_app_ui/camera_app_ui.h
+++ /dev/null
@@ -1,24 +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 CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_UI_H_
-#define CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_UI_H_
-
-#include "base/macros.h"
-#include "ui/webui/mojo_web_ui_controller.h"
-
-namespace chromeos {
-
-class CameraAppUI : public ui::MojoWebUIController {
- public:
-  explicit CameraAppUI(content::WebUI* web_ui);
-  ~CameraAppUI() override;
-
- private:
-  DISALLOW_COPY_AND_ASSIGN(CameraAppUI);
-};
-
-}  // namespace chromeos
-
-#endif  // CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_UI_H_
diff --git a/chromeos/components/camera_app_ui/resources/pwa.html b/chromeos/components/camera_app_ui/resources/pwa.html
deleted file mode 100644
index 9c99cdde..0000000
--- a/chromeos/components/camera_app_ui/resources/pwa.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<!-- Copyright 2020 The Chromium Authors. All rights reserved.
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file. -->
-<!-- TODO(crbug/896575): Delete when manifest URL installs are implemented. -->
-<!DOCTYPE html>
-<link rel="manifest" href="manifest.json">
diff --git a/chromeos/components/camera_app_ui/url_constants.cc b/chromeos/components/camera_app_ui/url_constants.cc
deleted file mode 100644
index 98812144..0000000
--- a/chromeos/components/camera_app_ui/url_constants.cc
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromeos/components/camera_app_ui/url_constants.h"
-
-namespace chromeos {
-
-const char kChromeUICameraAppHost[] = "camera-app";
-
-}  // namespace chromeos
diff --git a/chromeos/components/camera_app_ui/url_constants.h b/chromeos/components/camera_app_ui/url_constants.h
deleted file mode 100644
index 87238fb9..0000000
--- a/chromeos/components/camera_app_ui/url_constants.h
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMEOS_COMPONENTS_CAMERA_APP_UI_URL_CONSTANTS_H_
-#define CHROMEOS_COMPONENTS_CAMERA_APP_UI_URL_CONSTANTS_H_
-
-namespace chromeos {
-
-extern const char kChromeUICameraAppHost[];
-
-}  // namespace chromeos
-
-#endif  // CHROMEOS_COMPONENTS_CAMERA_APP_UI_URL_CONSTANTS_H_
diff --git a/chromeos/components/print_management/resources/manifest.json b/chromeos/components/print_management/resources/manifest.json
index c5225a34..fff3cbd 100644
--- a/chromeos/components/print_management/resources/manifest.json
+++ b/chromeos/components/print_management/resources/manifest.json
@@ -3,7 +3,7 @@
     "short_name": "Print Management",
     "start_url": "/",
     "display": "standalone",
-    "theme_color": "#4285F4",
+    "theme_color": "#ffffff",
     "background_color": "#ffffff",
     "scope": "./",
     "icons": [
diff --git a/chromeos/components/quick_answers/result_loader.cc b/chromeos/components/quick_answers/result_loader.cc
index faa64030..b7ac5f61 100644
--- a/chromeos/components/quick_answers/result_loader.cc
+++ b/chromeos/components/quick_answers/result_loader.cc
@@ -91,12 +91,10 @@
     std::unique_ptr<QuickAnswer> quick_answer) {
   // Record quick answer result.
   base::TimeDelta duration = base::TimeTicks::Now() - fetch_start_time_;
-  if (!quick_answer) {
-    RecordLoadingStatus(LoadStatus::kNoResult, duration);
-  } else {
-    RecordLoadingStatus(LoadStatus::kSuccess, duration);
-    RecordResult(quick_answer->result_type, duration);
-  }
+  RecordLoadingStatus(
+      quick_answer ? LoadStatus::kSuccess : LoadStatus::kNoResult, duration);
+  RecordResult(quick_answer ? quick_answer->result_type : ResultType::kNoResult,
+               duration);
   delegate_->OnQuickAnswerReceived(std::move(quick_answer));
 }
 }  // namespace quick_answers
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 3d3cd3c..49140e71 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -229,7 +229,7 @@
 // Enable or disable Unified Input Logic for FST decoder in the IME extension
 // on Chrome OS.
 const base::Feature kImeInputLogicFst{"ImeInputLogicFst",
-                                      base::FEATURE_DISABLED_BY_DEFAULT};
+                                      base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enable or disable Unified Input Logic for Mozc decoder in the IME extension
 // on Chrome OS.
@@ -273,9 +273,10 @@
 const base::Feature kParentalControlsSettings{
     "ChromeOSParentalControlsSettings", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Enables the option to share the camera with PluginVm or not
-const base::Feature kPluginVmShowCameraSetting{
-    "PluginVmShowCameraSetting", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether the camera permissions should be shown in the Plugin
+// VM app settings.
+const base::Feature kPluginVmShowCameraPermissions{
+    "PluginVmShowCameraPermissions", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Controls whether to show printer statuses.
 const base::Feature kPrinterStatus{"PrinterStatus",
@@ -372,7 +373,7 @@
 // state will vary. See config in
 // chrome/browser/chromeos/sync/split_settings_sync_field_trial.cc
 const base::Feature kSplitSettingsSync{"SplitSettingsSync",
-                                       base::FEATURE_ENABLED_BY_DEFAULT};
+                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Enables a settings UI toggle that controls Suggested Content status. Also
 // enables a corresponding notice in the Launcher about Suggested Content.
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 9cbd53d..891b8834 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -123,7 +123,7 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kParentalControlsSettings;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
-extern const base::Feature kPluginVmShowCameraSetting;
+extern const base::Feature kPluginVmShowCameraPermissions;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 extern const base::Feature kPrintJobManagementApp;
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
diff --git a/chromeos/printing/uri.h b/chromeos/printing/uri.h
index d6656c38..97ab8b4 100644
--- a/chromeos/printing/uri.h
+++ b/chromeos/printing/uri.h
@@ -217,6 +217,7 @@
     kInvalidUTF8Character,      // error when tried to parse UTF-8 character
     kInvalidScheme,             // invalid Scheme format or no ':' in input
     kInvalidPortNumber,
+    kRelativePathsNotAllowed,  // non-empty Path that does not start with '/'
     kEmptySegmentInPath,
     kEmptyParameterNameInQuery
   };
diff --git a/chromeos/printing/uri_impl.cc b/chromeos/printing/uri_impl.cc
index 8a9dc78..98428f61 100644
--- a/chromeos/printing/uri_impl.cc
+++ b/chromeos/printing/uri_impl.cc
@@ -347,13 +347,19 @@
 }
 
 bool Uri::Pim::ParsePath(const Iter& begin, const Iter& end) {
+  // Path must be empty or start with '/'.
+  if (begin < end && *begin != '/') {
+    parser_error_.status = ParserStatus::kRelativePathsNotAllowed;
+    parser_error_.parsed_chars = 0;
+    parser_error_.parsed_strings = 0;
+    return false;
+  }
   // This holds Path's segments.
   std::vector<std::string> path;
   // This stores offset from begin of every segment.
   std::vector<size_t> strings_positions;
   // Parsing...
   for (Iter it1 = begin; it1 < end;) {
-    DCHECK_EQ(*it1, '/');
     if (++it1 == end)  // omit '/' character
       break;
     Iter it2 = std::find(it1, end, '/');
@@ -449,7 +455,7 @@
   }
   // The Path is terminated by the first question mark ("?") or number
   // sign ("#") character, or by the end of the URI.
-  if (it1 < end && *it1 == '/') {
+  if (it1 < end) {
     auto it2 = FindFirstOf(it1, end, "?#");
     if (!ParsePath(it1, it2)) {
       parser_error_.parsed_chars += it1 - begin;
diff --git a/chromeos/resources/BUILD.gn b/chromeos/resources/BUILD.gn
index 1e0da57..60b3e89b 100644
--- a/chromeos/resources/BUILD.gn
+++ b/chromeos/resources/BUILD.gn
@@ -40,31 +40,6 @@
   ]
 }
 
-# Resources used by chrome://camera-app.
-grit("camera_app_resources") {
-  source = "../components/camera_app_ui/resources/camera_app_resources.grd"
-
-  outputs = [
-    "grit/chromeos_camera_app_resources.h",
-    "grit/chromeos_camera_app_resources_map.cc",
-    "grit/chromeos_camera_app_resources_map.h",
-    "chromeos_camera_app_resources.pak",
-  ]
-  output_dir = "$root_gen_dir/chromeos"
-
-  grit_flags = [
-    "-E",
-    "root_gen_dir=" + rebase_path(root_gen_dir, root_build_dir),
-  ]
-
-  deps = [
-    "//chromeos/components/camera_app_ui:mojo_bindings_js",
-    "//media/capture/video/chromeos/mojom:cros_camera_js",
-    "//mojo/public/js:bindings_lite",
-    "//third_party/blink/public/mojom:mojom_platform_js",
-  ]
-}
-
 # Resources used by chrome://help-app, and parts of the sandboxed app it hosts
 # that do not come from the app bundle (below).
 grit("help_app_resources") {
diff --git a/chromeos/services/assistant/public/cpp/assistant_enums.h b/chromeos/services/assistant/public/cpp/assistant_enums.h
index 16104c6..7c23368 100644
--- a/chromeos/services/assistant/public/cpp/assistant_enums.h
+++ b/chromeos/services/assistant/public/cpp/assistant_enums.h
@@ -14,8 +14,6 @@
   // The Assistant service is not ready yet.
   NOT_READY = 0,
   // The Assistant service is ready.
-  READY,
-  // The Assistant service is ready.
   // TODO(b/142428671): This is set when the Assistant backend signals it is
   // ready to handle queries, where |READY| is signaled when it is started.
   // If this signal turns out to be reliable it should replace |READY| and be
diff --git a/chromeos/services/assistant/service.cc b/chromeos/services/assistant/service.cc
index 14bc921..b3efdd3ed 100644
--- a/chromeos/services/assistant/service.cc
+++ b/chromeos/services/assistant/service.cc
@@ -80,9 +80,8 @@
   switch (state) {
     case State::STOPPED:
     case State::STARTING:
-      return AssistantStatus::NOT_READY;
     case State::STARTED:
-      return AssistantStatus::READY;
+      return AssistantStatus::NOT_READY;
     case State::RUNNING:
       return AssistantStatus::NEW_READY;
   }
diff --git a/chromeos/services/assistant/service_unittest.cc b/chromeos/services/assistant/service_unittest.cc
index 4e18e3c..21b9039 100644
--- a/chromeos/services/assistant/service_unittest.cc
+++ b/chromeos/services/assistant/service_unittest.cc
@@ -291,12 +291,14 @@
   EXPECT_EQ(client()->status(), AssistantStatus::NOT_READY);
 }
 
-TEST_F(AssistantServiceTest, ShouldSetClientStatusToReadyWhenStarted) {
+TEST_F(AssistantServiceTest, ShouldKeepClientStatusNotReadyWhenStarted) {
+  // Note: even though we've started, we are not ready to handle the queries
+  // until LibAssistant tells us we are.
   assistant_manager()->SetStateAndInformObservers(
       AssistantManagerService::State::STARTED);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(client()->status(), AssistantStatus::READY);
+  EXPECT_EQ(client()->status(), AssistantStatus::NOT_READY);
 }
 
 TEST_F(AssistantServiceTest, ShouldSetClientStatusToNewReadyWhenRunning) {
diff --git a/chromeos/services/device_sync/cryptauth_v2_device_manager_impl.cc b/chromeos/services/device_sync/cryptauth_v2_device_manager_impl.cc
index 3bf70fd..e09006d 100644
--- a/chromeos/services/device_sync/cryptauth_v2_device_manager_impl.cc
+++ b/chromeos/services/device_sync/cryptauth_v2_device_manager_impl.cc
@@ -294,6 +294,21 @@
 
   RecordDeviceSyncResult(device_sync_result);
 
+  // TODO(https://crbug.com/1092113): This is a workaround for the SyncMetadata
+  // 404 errors returned by the server when it cannot find an enrolled device
+  // with the same Instance ID. Theoretically, this should never occur assuming
+  // that 1) we never run a v2 DeviceSync until the device has successfully
+  // enrolled using v2 Enrollment and 2) the Instance ID does not rotate.
+  // Without this mitigation, the user will unsuccessfully try to sync until the
+  // next enrollment, which could be up to 30 days. Remove this code when the
+  // root cause is uncovered.
+  if (device_sync_result.result_code() ==
+      CryptAuthDeviceSyncResult::ResultCode::
+          kErrorSyncMetadataApiCallEndpointNotFound) {
+    scheduler_->RequestEnrollment(cryptauthv2::ClientMetadata::FAILURE_RECOVERY,
+                                  base::nullopt /* session_id */);
+  }
+
   scheduler_->HandleDeviceSyncResult(device_sync_result);
 
   base::Optional<base::TimeDelta> time_to_next_attempt = GetTimeToNextAttempt();
diff --git a/chromeos/services/device_sync/cryptauth_v2_device_manager_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_v2_device_manager_impl_unittest.cc
index b54203e..4153e41 100644
--- a/chromeos/services/device_sync/cryptauth_v2_device_manager_impl_unittest.cc
+++ b/chromeos/services/device_sync/cryptauth_v2_device_manager_impl_unittest.cc
@@ -209,6 +209,7 @@
   }
 
   CryptAuthV2DeviceManager* device_manager() { return device_manager_.get(); }
+  FakeCryptAuthScheduler* scheduler() { return &fake_scheduler_; }
 
  private:
   // Adds the ClientMetadata from the latest DeviceSync request to a list of
@@ -455,6 +456,27 @@
   TimeoutWaitingForClientAppMetadataAndVerifyResult();
 }
 
+// TODO(https://crbug.com/1092113): Remove when bug is resolved.
+TEST_F(DeviceSyncCryptAuthV2DeviceManagerImplTest,
+       ScheduleEnrollmentAfterSyncMetadataEndpointNotFoundError) {
+  CreateAndStartDeviceManager();
+  RequestDeviceSyncThroughSchedulerAndVerify(
+      cryptauthv2::ClientMetadata::PERIODIC, base::nullopt /* session_id */);
+  SucceedGetClientAppMetadataRequest();
+
+  EXPECT_FALSE(scheduler()->IsWaitingForEnrollmentResult());
+
+  // Fail SyncMetadata request with 404 error.
+  FinishDeviceSyncAttemptAndVerifyResult(
+      0u /* expected_device_sync_instance_index */,
+      CryptAuthDeviceSyncResult(CryptAuthDeviceSyncResult::ResultCode::
+                                    kErrorSyncMetadataApiCallEndpointNotFound,
+                                false /* did_device_registry_change */,
+                                base::nullopt /* client_directive */));
+
+  EXPECT_TRUE(scheduler()->IsWaitingForEnrollmentResult());
+}
+
 }  // namespace device_sync
 
 }  // namespace chromeos
diff --git a/chromeos/services/device_sync/fake_cryptauth_scheduler.cc b/chromeos/services/device_sync/fake_cryptauth_scheduler.cc
index 85d7da1..594d3a3 100644
--- a/chromeos/services/device_sync/fake_cryptauth_scheduler.cc
+++ b/chromeos/services/device_sync/fake_cryptauth_scheduler.cc
@@ -21,7 +21,6 @@
 void FakeCryptAuthScheduler::RequestEnrollment(
     const cryptauthv2::ClientMetadata::InvocationReason& invocation_reason,
     const base::Optional<std::string>& session_id) {
-  DCHECK(HasEnrollmentSchedulingStarted());
   is_waiting_for_enrollment_result_ = true;
 
   cryptauthv2::ClientMetadata client_metadata;
@@ -37,7 +36,6 @@
 void FakeCryptAuthScheduler::RequestDeviceSync(
     const cryptauthv2::ClientMetadata::InvocationReason& invocation_reason,
     const base::Optional<std::string>& session_id) {
-  DCHECK(HasDeviceSyncSchedulingStarted());
   is_waiting_for_device_sync_result_ = true;
 
   cryptauthv2::ClientMetadata client_metadata;
diff --git a/chromeos/services/tts/BUILD.gn b/chromeos/services/tts/BUILD.gn
index e74177d..e2feb37 100644
--- a/chromeos/services/tts/BUILD.gn
+++ b/chromeos/services/tts/BUILD.gn
@@ -42,6 +42,7 @@
   bundled_header = "\"chromeos/services/tts/chrome_tts.h\""
 
   functions = [
+    "GoogleTtsSetLogger",
     "GoogleTtsInit",
     "GoogleTtsShutdown",
     "GoogleTtsInstallVoice",
diff --git a/chromeos/services/tts/chrome_tts.h b/chromeos/services/tts/chrome_tts.h
index 6f7bb98..4ab10f017 100644
--- a/chromeos/services/tts/chrome_tts.h
+++ b/chromeos/services/tts/chrome_tts.h
@@ -8,6 +8,8 @@
 #include <cstddef>
 #include <cstdint>
 
+void GoogleTtsSetLogger(void (*logger_func)(int severity, const char* message));
+
 bool GoogleTtsInit(const char* pipeline_path, const char* path_prefix);
 
 void GoogleTtsShutdown();
diff --git a/chromeos/services/tts/tts_service.cc b/chromeos/services/tts/tts_service.cc
index 363e2b7..0e94f34 100644
--- a/chromeos/services/tts/tts_service.cc
+++ b/chromeos/services/tts/tts_service.cc
@@ -12,6 +12,23 @@
 namespace chromeos {
 namespace tts {
 
+// Simple helper to bridge logging in the shared library to Chrome's logging.
+void HandleLibraryLogging(int severity, const char* message) {
+  switch (severity) {
+    case logging::LOG_INFO:
+      // Suppressed.
+      break;
+    case logging::LOG_WARNING:
+      LOG(WARNING) << message;
+      break;
+    case logging::LOG_ERROR:
+      LOG(ERROR) << message;
+      break;
+    default:
+      break;
+  }
+}
+
 // TtsService is mostly glue code that adapts the TtsStream interface into a
 // form needed by libchrometts.so. As is convention with shared objects, the
 // lifetime of all arguments passed to the library is scoped to the function.
@@ -24,6 +41,8 @@
   bool loaded = libchrometts_.Load(kLibchromettsPath);
   if (!loaded)
     LOG(ERROR) << "Unable to load libchrometts.so: " << dlerror();
+  else
+    libchrometts_.GoogleTtsSetLogger(HandleLibraryLogging);
 }
 
 TtsService::~TtsService() = default;
diff --git a/components/arc/arc_features.cc b/components/arc/arc_features.cc
index 86fe498c9..156bf610c 100644
--- a/components/arc/arc_features.cc
+++ b/components/arc/arc_features.cc
@@ -56,7 +56,7 @@
 // Note, that we keep the original feature name to preserve
 // corresponding metrics.
 const base::Feature kNativeBridgeToggleFeature{
-    "ArcNativeBridgeExperiment", base::FEATURE_ENABLED_BY_DEFAULT};
+    "ArcNativeBridgeExperiment", base::FEATURE_DISABLED_BY_DEFAULT};
 
 // Controls ARC picture-in-picture feature. If this is enabled, then Android
 // will control which apps can enter PIP. If this is disabled, then ARC PIP
diff --git a/components/arc/mojom/BUILD.gn b/components/arc/mojom/BUILD.gn
index c541f80..0778d56 100644
--- a/components/arc/mojom/BUILD.gn
+++ b/components/arc/mojom/BUILD.gn
@@ -69,6 +69,7 @@
       ":camera_intent",
       ":media",
       ":notifications",
+      "//components/chromeos_camera/common:camera_app_helper",
       "//media/capture/video/chromeos/mojom:cros_camera",
       "//mojo/public/mojom/base",
       "//printing/mojom",
diff --git a/components/arc/session/arc_property_util.cc b/components/arc/session/arc_property_util.cc
index 6181019..0a4ca1a4 100644
--- a/components/arc/session/arc_property_util.cc
+++ b/components/arc/session/arc_property_util.cc
@@ -305,7 +305,16 @@
   if (single_file)
     base::DeleteFile(dest_path, /*recursive=*/false);
 
-  for (const char* file : {"default.prop", "build.prop", "vendor_build.prop"}) {
+  // default.prop may not exist. Silently skip it if not found.
+  for (const auto& pair : {std::pair<const char*, bool>{"default.prop", true},
+                           {"build.prop", false},
+                           {"vendor_build.prop", false}}) {
+    const char* file = pair.first;
+    const bool is_optional = pair.second;
+
+    if (is_optional && !base::PathExists(source_path.Append(file)))
+      continue;
+
     if (!ExpandPropertyFile(source_path.Append(file),
                             single_file ? dest_path : dest_path.Append(file),
                             &config,
diff --git a/components/arc/session/arc_property_util_unittest.cc b/components/arc/session/arc_property_util_unittest.cc
index 7cf60e89..1583bc1 100644
--- a/components/arc/session/arc_property_util_unittest.cc
+++ b/components/arc/session/arc_property_util_unittest.cc
@@ -342,6 +342,19 @@
       base::ReadFileToString(dest_dir.Append("default.prop"), &content));
   EXPECT_EQ(std::string(kDefaultProp) + "\n", content);
 
+  // If default.prop does not exist in the source path, it should still process
+  // the other files, while also ensuring that default.prop is removed from the
+  // destination path.
+  base::DeleteFile(dest_dir.Append("default.prop"), /*recursive=*/false);
+
+  EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_dir, false));
+
+  EXPECT_TRUE(base::ReadFileToString(dest_dir.Append("build.prop"), &content));
+  EXPECT_EQ(std::string(kBuildProp) + "\n", content);
+  EXPECT_TRUE(
+      base::ReadFileToString(dest_dir.Append("vendor_build.prop"), &content));
+  EXPECT_EQ(std::string(kVendorBuildProp) + "\n", content);
+
   // Finally, test the case where source is valid but the dest is not.
   EXPECT_FALSE(
       ExpandPropertyFiles(source_dir, base::FilePath("/nonexistent"), false));
@@ -405,6 +418,15 @@
                                kVendorBuildProp),
             content);
 
+  // If default.prop does not exist in the source path, it should still process
+  // the other files.
+  base::DeleteFile(source_dir.Append("default.prop"),
+                   /*recursive=*/false);
+  EXPECT_TRUE(ExpandPropertyFiles(source_dir, dest_prop_file, true));
+  EXPECT_TRUE(base::ReadFileToString(dest_prop_file, &content));
+  EXPECT_EQ(base::StringPrintf("%s\n%s\n", kBuildProp, kVendorBuildProp),
+            content);
+
   // Finally, test the case where source is valid but the dest is not.
   EXPECT_FALSE(
       ExpandPropertyFiles(source_dir, base::FilePath("/nonexistent"), true));
diff --git a/components/autofill/android/autofill_provider_android.cc b/components/autofill/android/autofill_provider_android.cc
index 7612937..a8710cac 100644
--- a/components/autofill/android/autofill_provider_android.cc
+++ b/components/autofill/android/autofill_provider_android.cc
@@ -19,6 +19,7 @@
 #include "ui/gfx/geometry/rect_f.h"
 
 using base::android::AttachCurrentThread;
+using base::android::ConvertJavaStringToUTF16;
 using base::android::ConvertUTF16ToJavaString;
 using base::android::ConvertUTF8ToJavaString;
 using base::android::JavaRef;
@@ -141,6 +142,16 @@
   }
 }
 
+void AutofillProviderAndroid::OnAcceptDataListSuggestion(JNIEnv* env,
+                                                         jobject jcaller,
+                                                         jstring value) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (auto* handler = handler_.get()) {
+    RendererShouldAcceptDataListSuggestion(
+        handler, ConvertJavaStringToUTF16(env, value));
+  }
+}
+
 void AutofillProviderAndroid::OnTextFieldDidChange(
     AutofillHandlerProxy* handler,
     const FormData& form,
@@ -314,6 +325,18 @@
   FireSuccessfulSubmission(pending_submission_source_);
 }
 
+void AutofillProviderAndroid::OnHidePopup(AutofillHandlerProxy* handler) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  if (handler == handler_.get()) {
+    JNIEnv* env = AttachCurrentThread();
+    ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+    if (obj.is_null())
+      return;
+
+    Java_AutofillProvider_hidePopup(env, obj);
+  }
+}
+
 void AutofillProviderAndroid::Reset(AutofillHandlerProxy* handler) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (handler == handler_.get()) {
diff --git a/components/autofill/android/autofill_provider_android.h b/components/autofill/android/autofill_provider_android.h
index 270a05ee..178f58e 100644
--- a/components/autofill/android/autofill_provider_android.h
+++ b/components/autofill/android/autofill_provider_android.h
@@ -67,11 +67,13 @@
   void OnFormsSeen(AutofillHandlerProxy* handler,
                    const std::vector<FormData>& forms,
                    const base::TimeTicks timestamp) override;
+  void OnHidePopup(AutofillHandlerProxy* handler) override;
 
   void Reset(AutofillHandlerProxy* handler) override;
 
   // Methods called by Java.
   void OnAutofillAvailable(JNIEnv* env, jobject jcaller, jobject form_data);
+  void OnAcceptDataListSuggestion(JNIEnv* env, jobject jcaller, jstring value);
 
  private:
   void FireSuccessfulSubmission(mojom::SubmissionSource source);
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
index a7d05d3..aa203050 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java
@@ -137,6 +137,11 @@
                 nativeAutofillProvider, AutofillProvider.this, formData);
     }
 
+    protected void acceptDataListSuggestion(long nativeAutofillProvider, String value) {
+        AutofillProviderJni.get().onAcceptDataListSuggestion(
+                nativeAutofillProvider, AutofillProvider.this, value);
+    }
+
     /**
      * Invoked when current query need to be reset.
      */
@@ -149,9 +154,15 @@
     @CalledByNative
     protected abstract void onDidFillAutofillFormData();
 
+    @CalledByNative
+    protected abstract void hidePopup();
+
     @NativeMethods
     interface Natives {
         void onAutofillAvailable(
                 long nativeAutofillProviderAndroid, AutofillProvider caller, FormData formData);
+
+        void onAcceptDataListSuggestion(
+                long nativeAutofillProviderAndroid, AutofillProvider caller, String value);
     }
 }
diff --git a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java
index d5bc3b4..a705abd 100644
--- a/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java
+++ b/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java
@@ -419,6 +419,9 @@
                 focusOnForm, focusField, x, y, width, height, false /*causedByValueChange*/);
     }
 
+    @Override
+    protected void hidePopup() {}
+
     private void notifyViewExitBeforeDestoryRequest() {
         if (mRequest == null) return;
         FocusField focusField = mRequest.getFocusField();
diff --git a/components/autofill/content/renderer/BUILD.gn b/components/autofill/content/renderer/BUILD.gn
index 82ce0f34..6ee2bee9 100644
--- a/components/autofill/content/renderer/BUILD.gn
+++ b/components/autofill/content/renderer/BUILD.gn
@@ -80,6 +80,7 @@
     "//components/autofill/content/renderer",
     "//services/service_manager/public/cpp",
     "//skia",
+    "//testing/gmock",
     "//testing/gtest",
     "//third_party/blink/public:blink",
   ]
diff --git a/components/autofill/content/renderer/form_autofill_util.cc b/components/autofill/content/renderer/form_autofill_util.cc
index 5b6b24e..35f247f2 100644
--- a/components/autofill/content/renderer/form_autofill_util.cc
+++ b/components/autofill/content/renderer/form_autofill_util.cc
@@ -1470,11 +1470,6 @@
     FormData* form,
     FormFieldData* field) {
   form->url = GetCanonicalOriginForDocument(document);
-  if (IsAutofillFieldMetadataEnabled() && !document.Body().IsNull()) {
-    SCOPED_UMA_HISTOGRAM_TIMER(
-        "PasswordManager.ButtonTitlePerformance.NoFormTag");
-    form->button_titles = InferButtonTitlesForForm(document.Body());
-  }
   if (document.GetFrame() && document.GetFrame()->Top()) {
     form->main_frame_origin = document.GetFrame()->Top()->GetSecurityOrigin();
   } else {
@@ -1611,7 +1606,7 @@
   return StripAuthAndParams(full_origin);
 }
 
-GURL GetOriginWithoutAuthForDocument(const WebDocument& document) {
+GURL GetDocumentUrlWithoutAuth(const WebDocument& document) {
   GURL::Replacements rep;
   rep.ClearUsername();
   rep.ClearPassword();
@@ -1675,6 +1670,11 @@
   return identifier;
 }
 
+FormRendererId GetFormRendererId(const blink::WebFormElement& form) {
+  return form.IsNull() ? FormRendererId()
+                       : FormRendererId(form.UniqueRendererFormId());
+}
+
 base::i18n::TextDirection GetTextDirectionForElement(
     const blink::WebFormControlElement& element) {
   // Use 'text-align: left|right' if set or 'direction' otherwise.
@@ -1868,11 +1868,6 @@
   form->action = GetCanonicalActionForForm(form_element);
   form->is_action_empty =
       form_element.Action().IsNull() || form_element.Action().IsEmpty();
-  if (IsAutofillFieldMetadataEnabled()) {
-    SCOPED_UMA_HISTOGRAM_TIMER(
-        "PasswordManager.ButtonTitlePerformance.HasFormTag");
-    form->button_titles = InferButtonTitlesForForm(form_element);
-  }
   if (frame->Top()) {
     form->main_frame_origin = frame->Top()->GetSecurityOrigin();
   } else {
@@ -2213,6 +2208,41 @@
   return FindChildTextWithIgnoreList(node, std::set<WebNode>());
 }
 
+ButtonTitleList GetButtonTitles(const WebFormElement& web_form,
+                                const WebDocument& document,
+                                ButtonTitlesCache* button_titles_cache) {
+  DCHECK(button_titles_cache);
+  if (!IsAutofillFieldMetadataEnabled() && web_form.IsNull())
+    return ButtonTitleList();
+
+  // True if the cache has no entry for |web_form|.
+  bool cache_miss = true;
+  // Iterator pointing to the entry for |web_form| if the entry for |web_form|
+  // is found.
+  ButtonTitlesCache::iterator form_position;
+  std::tie(form_position, cache_miss) = button_titles_cache->emplace(
+      GetFormRendererId(web_form), ButtonTitleList());
+  if (!cache_miss)
+    return form_position->second;
+
+  ButtonTitleList button_titles;
+  DCHECK(!web_form.IsNull() || !document.IsNull());
+  if (web_form.IsNull()) {
+    const WebElement& body = document.Body();
+    if (!body.IsNull()) {
+      SCOPED_UMA_HISTOGRAM_TIMER(
+          "PasswordManager.ButtonTitlePerformance.NoFormTag");
+      button_titles = InferButtonTitlesForForm(body);
+    }
+  } else {
+    SCOPED_UMA_HISTOGRAM_TIMER(
+        "PasswordManager.ButtonTitlePerformance.HasFormTag");
+    button_titles = InferButtonTitlesForForm(web_form);
+  }
+  form_position->second = std::move(button_titles);
+  return form_position->second;
+}
+
 base::string16 FindChildTextWithIgnoreListForTesting(
     const WebNode& node,
     const std::set<WebNode>& divs_to_skip) {
@@ -2226,10 +2256,6 @@
   return InferLabelForElement(element, stop_words, label, label_source);
 }
 
-ButtonTitleList InferButtonTitlesForTesting(const WebElement& form_element) {
-  return InferButtonTitlesForForm(form_element);
-}
-
 WebFormElement FindFormByUniqueRendererId(WebDocument doc,
                                           FormRendererId form_renderer_id) {
   for (const auto& form : doc.Forms()) {
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index c7fcb0a..1a33e640 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -10,6 +10,7 @@
 #include <set>
 #include <vector>
 
+#include "base/containers/flat_map.h"
 #include "base/i18n/rtl.h"
 #include "base/macros.h"
 #include "base/strings/string16.h"
@@ -45,6 +46,10 @@
 
 namespace form_util {
 
+// Mapping from a form element's render id to results of button titles
+// heuristics for a given form element.
+using ButtonTitlesCache = base::flat_map<FormRendererId, ButtonTitleList>;
+
 // A bit field mask to extract data from WebFormControlElement.
 // Copied to components/autofill/ios/browser/resources/autofill_controller.js.
 enum ExtractMask {
@@ -99,7 +104,7 @@
 // strip unnecessary data (e.g. query params and HTTP credentials).
 GURL GetCanonicalActionForForm(const blink::WebFormElement& form);
 GURL GetCanonicalOriginForDocument(const blink::WebDocument& document);
-GURL GetOriginWithoutAuthForDocument(const blink::WebDocument& document);
+GURL GetDocumentUrlWithoutAuth(const blink::WebDocument& document);
 
 // Returns true if |element| is a month input element.
 bool IsMonthInput(const blink::WebInputElement* element);
@@ -133,6 +138,10 @@
 // attribute.
 base::string16 GetFormIdentifier(const blink::WebFormElement& form);
 
+// Returns the |unique_renderer_id| of a given |WebFormElement|. If
+// |WebFormElement::IsNull()|, returns a null renderer ID.
+FormRendererId GetFormRendererId(const blink::WebFormElement& form);
+
 // Returns text alignment for |element|.
 base::i18n::TextDirection GetTextDirectionForElement(
     const blink::WebFormControlElement& element);
@@ -283,6 +292,15 @@
 // Whitespace is trimmed from text accumulated at descendant nodes.
 base::string16 FindChildText(const blink::WebNode& node);
 
+// Returns the button titles for |web_form| (or unowned buttons in |document| if
+// |web_form| is null). |button_titles_cache| can be used to spare recomputation
+// if called multiple times for the same form. Button titles computation for
+// unowned buttons is enabled only in Dev and Canary (crbug.com/1086446),
+// otherwise the method returns an empty list.
+ButtonTitleList GetButtonTitles(const blink::WebFormElement& web_form,
+                                const blink::WebDocument& document,
+                                ButtonTitlesCache* button_titles_cache);
+
 // Exposed for testing purpose
 base::string16 FindChildTextWithIgnoreListForTesting(
     const blink::WebNode& node,
@@ -291,8 +309,6 @@
                                     const std::vector<base::char16>& stop_words,
                                     base::string16* label,
                                     FormFieldData::LabelSource* label_source);
-ButtonTitleList InferButtonTitlesForTesting(
-    const blink::WebElement& form_element);
 
 // Returns form by unique renderer id. Return null element if there is no form
 // with given form renderer id.
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
index 62ed5150..34575e7 100644
--- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -4,12 +4,15 @@
 
 #include "components/autofill/content/renderer/form_autofill_util.h"
 
+#include "base/metrics/field_trial.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
 #include "components/autofill/core/common/renderer_id.h"
 #include "content/public/test/render_view_test.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_vector.h"
@@ -138,6 +141,14 @@
 // TODO(crbug.com/796918): Should be "label" or "label-"
 const char kDivTableExample6Expected[] = "";
 
+void VerifyButtonTitleCache(const WebFormElement& form_target,
+                            const ButtonTitleList& expected_button_titles,
+                            const ButtonTitlesCache& actual_cache) {
+  EXPECT_THAT(actual_cache,
+              testing::ElementsAre(testing::Pair(GetFormRendererId(form_target),
+                                                 expected_button_titles)));
+}
+
 class FormAutofillUtilsTest : public content::RenderViewTest {
  public:
   FormAutofillUtilsTest() {}
@@ -272,8 +283,8 @@
   }
 }
 
-TEST_F(FormAutofillUtilsTest, InferButtonTitleForFormTest) {
-  const char kHtml[] =
+TEST_F(FormAutofillUtilsTest, GetButtonTitles) {
+  constexpr char kHtml[] =
       "<form id='target'>"
       "  <input type='button' value='Clear field'>"
       "  <input type='button' value='Clear field'>"
@@ -294,8 +305,11 @@
   ASSERT_FALSE(target.IsNull());
   const WebFormElement& form_target = target.ToConst<WebFormElement>();
   ASSERT_FALSE(form_target.IsNull());
+  ButtonTitlesCache cache;
 
-  autofill::ButtonTitleList actual = InferButtonTitlesForTesting(form_target);
+  autofill::ButtonTitleList actual =
+      GetButtonTitles(form_target, web_frame->GetDocument(), &cache);
+
   autofill::ButtonTitleList expected = {
       {base::UTF8ToUTF16("Clear field"),
        ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE},
@@ -309,9 +323,11 @@
       {base::UTF8ToUTF16("Join"), ButtonTitleType::DIV},
       {base::UTF8ToUTF16("Start"), ButtonTitleType::SPAN}};
   EXPECT_EQ(expected, actual);
+
+  VerifyButtonTitleCache(form_target, expected, cache);
 }
 
-TEST_F(FormAutofillUtilsTest, InferButtonTitleForFormTest_TooLongTitle) {
+TEST_F(FormAutofillUtilsTest, GetButtonTitles_TooLongTitle) {
   std::string title;
   for (int i = 0; i < 300; ++i)
     title += "a";
@@ -330,8 +346,10 @@
   ASSERT_FALSE(target.IsNull());
   const WebFormElement& form_target = target.ToConst<WebFormElement>();
   ASSERT_FALSE(form_target.IsNull());
+  ButtonTitlesCache cache;
 
-  autofill::ButtonTitleList actual = InferButtonTitlesForTesting(form_target);
+  autofill::ButtonTitleList actual =
+      GetButtonTitles(form_target, web_frame->GetDocument(), &cache);
 
   int total_length = 0;
   for (auto title : actual) {
@@ -341,8 +359,14 @@
   EXPECT_EQ(200, total_length);
 }
 
-TEST_F(FormAutofillUtilsTest, InferButtonTitle_Formless) {
-  const char kNoFormHtml[] =
+TEST_F(FormAutofillUtilsTest, GetButtonTitles_Formless) {
+  // Button titles computation and crowdsourcing for <form>less forms are
+  // enabled only if |AutofillFieldMetadata| (Dev and Canary) is enabled.
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.Init();
+  base::FieldTrialList::CreateFieldTrial("AutofillFieldMetadata", "Enabled");
+
+  constexpr char kNoFormHtml[] =
       "<div class='reg-form'>"
       "  <input type='button' value='\n Show\t password '>"
       "  <button>Sign Up</button>"
@@ -358,10 +382,12 @@
   LoadHTML(kNoFormHtml);
   WebLocalFrame* web_frame = GetMainFrame();
   ASSERT_NE(nullptr, web_frame);
-  const WebElement& body = web_frame->GetDocument().Body();
-  ASSERT_FALSE(body.IsNull());
+  WebFormElement form_target;
+  ASSERT_FALSE(web_frame->GetDocument().Body().IsNull());
+  ButtonTitlesCache cache;
 
-  autofill::ButtonTitleList actual = InferButtonTitlesForTesting(body);
+  autofill::ButtonTitleList actual =
+      GetButtonTitles(form_target, web_frame->GetDocument(), &cache);
   autofill::ButtonTitleList expected = {
       {base::UTF8ToUTF16("Show password"),
        ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE},
@@ -370,6 +396,42 @@
       {base::UTF8ToUTF16("Register"),
        ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE}};
   EXPECT_EQ(expected, actual);
+
+  VerifyButtonTitleCache(form_target, expected, cache);
+}
+
+TEST_F(FormAutofillUtilsTest, GetButtonTitles_Formless_DisabledByDefault) {
+  // Button titles computation and crowdsourcing for <form>less forms should be
+  // disabled if |AutofillFieldMetadata| is disabled.
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.Init();
+  base::FieldTrialList::CreateFieldTrial("AutofillFieldMetadata", "Disabled");
+
+  constexpr char kNoFormHtml[] =
+      "<div class='reg-form'>"
+      "  <input type='button' value='\n Show\t password '>"
+      "  <button>Sign Up</button>"
+      "  <button type='button'>Register</button>"
+      "</div>"
+      "<form id='ignored-form'>"
+      "  <input type='button' value='Ignore this'>"
+      "  <button>Ignore this</button>"
+      "  <a id='Submit' value='Ignore this'>"
+      "  <div name='BTN'>Ignore this</div>"
+      "</form>";
+
+  LoadHTML(kNoFormHtml);
+  WebLocalFrame* web_frame = GetMainFrame();
+  ASSERT_NE(nullptr, web_frame);
+  WebFormElement form_target;
+  ASSERT_FALSE(web_frame->GetDocument().Body().IsNull());
+  ButtonTitlesCache cache;
+
+  autofill::ButtonTitleList actual =
+      GetButtonTitles(form_target, web_frame->GetDocument(), &cache);
+
+  EXPECT_TRUE(actual.empty());
+  EXPECT_TRUE(cache.empty());
 }
 
 TEST_F(FormAutofillUtilsTest, IsEnabled) {
diff --git a/components/autofill/content/renderer/html_based_username_detector.cc b/components/autofill/content/renderer/html_based_username_detector.cc
index 9929ea02..1006ccd 100644
--- a/components/autofill/content/renderer/html_based_username_detector.cc
+++ b/components/autofill/content/renderer/html_based_username_detector.cc
@@ -284,13 +284,6 @@
   }
 }
 
-// Returns the |unique_renderer_id| of a given |WebFormElement|. If
-// |WebFormElement::IsNull()| return a null renderer ID.
-FormRendererId GetFormRendererId(WebFormElement form) {
-  return form.IsNull() ? FormRendererId()
-                       : FormRendererId(form.UniqueRendererFormId());
-}
-
 }  // namespace
 
 const std::vector<FieldRendererId>& GetPredictionsFieldBasedOnHtmlAttributes(
@@ -311,8 +304,8 @@
   bool cache_miss = true;
   // Iterator pointing to the entry for |form| if the entry for |form| is found.
   UsernameDetectorCache::iterator form_position;
-  std::tie(form_position, cache_miss) = username_detector_cache->insert(
-      std::make_pair(GetFormRendererId(form), std::vector<FieldRendererId>()));
+  std::tie(form_position, cache_miss) = username_detector_cache->emplace(
+      form_util::GetFormRendererId(form), std::vector<FieldRendererId>());
 
   if (cache_miss) {
     std::vector<FieldRendererId> username_predictions;
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index 87c1bbd..877b32d 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -24,7 +24,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
-#include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/password_form_conversion_utils.h"
 #include "components/autofill/content/renderer/password_generation_agent.h"
 #include "components/autofill/content/renderer/prefilled_values_detector.h"
@@ -257,9 +256,9 @@
 // Annotate |fields| with field signatures and form signature as HTML
 // attributes.
 void AnnotateFieldsWithSignatures(
-    std::vector<blink::WebFormControlElement>* fields,
+    std::vector<blink::WebFormControlElement>& fields,
     const blink::WebString& form_signature) {
-  for (blink::WebFormControlElement& control_element : *fields) {
+  for (blink::WebFormControlElement& control_element : fields) {
     FieldSignature field_signature = CalculateFieldSignatureByNameAndType(
         control_element.NameForAutofill().Utf16(),
         control_element.FormControlTypeForAutofill().Utf8());
@@ -272,37 +271,6 @@
   }
 }
 
-// Annotate |forms| and all fields in the |frame| with form and field signatures
-// as HTML attributes.
-void AnnotateFormsAndFieldsWithSignatures(WebLocalFrame* frame,
-                                          WebVector<WebFormElement>* forms) {
-  for (WebFormElement& form : *forms) {
-    std::unique_ptr<FormData> form_data(
-        CreateFormDataFromWebForm(form, /*field_data_manager=*/nullptr,
-                                  /*username_detector_cache=*/nullptr));
-    WebString form_signature;
-    if (form_data) {
-      form_signature = GetFormSignatureAsWebString(*form_data);
-      form.SetAttribute(WebString::FromASCII(kDebugAttributeForFormSignature),
-                        form_signature);
-    }
-    std::vector<WebFormControlElement> form_fields =
-        form_util::ExtractAutofillableElementsInForm(form);
-    AnnotateFieldsWithSignatures(&form_fields, form_signature);
-  }
-
-  std::vector<WebFormControlElement> unowned_elements =
-      form_util::GetUnownedAutofillableFormFieldElements(
-          frame->GetDocument().All(), nullptr);
-  std::unique_ptr<FormData> form_data(CreateFormDataFromUnownedInputElements(
-      *frame, /*field_data_manager=*/nullptr,
-      /*username_detector_cache=*/nullptr));
-  WebString form_signature;
-  if (form_data)
-    form_signature = GetFormSignatureAsWebString(*form_data);
-  AnnotateFieldsWithSignatures(&unowned_elements, form_signature);
-}
-
 // Returns true iff there is a password field in |frame|.
 bool HasPasswordField(const WebLocalFrame& frame) {
   static base::NoDestructor<WebString> kPassword("password");
@@ -1015,6 +983,31 @@
   gatekeeper_.OnUserGesture();
 }
 
+void PasswordAutofillAgent::AnnotateFormsAndFieldsWithSignatures(
+    WebVector<WebFormElement>& forms) {
+  for (WebFormElement& form : forms) {
+    std::unique_ptr<FormData> form_data = GetFormDataFromWebForm(form);
+    WebString form_signature;
+    if (form_data) {
+      form_signature = GetFormSignatureAsWebString(*form_data);
+      form.SetAttribute(WebString::FromASCII(kDebugAttributeForFormSignature),
+                        form_signature);
+    }
+    std::vector<WebFormControlElement> form_fields =
+        form_util::ExtractAutofillableElementsInForm(form);
+    AnnotateFieldsWithSignatures(form_fields, form_signature);
+  }
+
+  std::vector<WebFormControlElement> unowned_elements =
+      form_util::GetUnownedAutofillableFormFieldElements(
+          render_frame()->GetWebFrame()->GetDocument().All(), nullptr);
+  std::unique_ptr<FormData> form_data = GetFormDataFromUnownedInputElements();
+  WebString form_signature;
+  if (form_data)
+    form_signature = GetFormSignatureAsWebString(*form_data);
+  AnnotateFieldsWithSignatures(unowned_elements, form_signature);
+}
+
 void PasswordAutofillAgent::SendPasswordForms(bool only_visible) {
   std::unique_ptr<RendererSavePasswordProgressLogger> logger;
   if (logging_state_active_) {
@@ -1046,7 +1039,7 @@
   WebVector<WebFormElement> forms = frame->GetDocument().Forms();
 
   if (IsShowAutofillSignaturesEnabled())
-    AnnotateFormsAndFieldsWithSignatures(frame, &forms);
+    AnnotateFormsAndFieldsWithSignatures(forms);
   if (logger)
     logger->LogNumber(Logger::STRING_NUMBER_OF_ALL_FORMS, forms.size());
 
@@ -1131,7 +1124,7 @@
       password_forms_data.back().url =
           form_util::GetCanonicalOriginForDocument(frame->GetDocument());
       password_forms_data.back().full_url =
-          form_util::GetOriginWithoutAuthForDocument(frame->GetDocument());
+          form_util::GetDocumentUrlWithoutAuth(frame->GetDocument());
     }
     if (!password_forms_data.empty()) {
       sent_request_to_store_ = true;
@@ -1382,7 +1375,8 @@
 std::unique_ptr<FormData> PasswordAutofillAgent::GetFormDataFromWebForm(
     const WebFormElement& web_form) {
   return CreateFormDataFromWebForm(web_form, field_data_manager_.get(),
-                                   &username_detector_cache_);
+                                   &username_detector_cache_,
+                                   &button_titles_cache_);
 }
 
 std::unique_ptr<FormData>
@@ -1398,7 +1392,8 @@
   if (!web_frame)
     return nullptr;
   return CreateFormDataFromUnownedInputElements(
-      *web_frame, field_data_manager_.get(), &username_detector_cache_);
+      *web_frame, field_data_manager_.get(), &username_detector_cache_,
+      &button_titles_cache_);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index 011425f9..1714ab48 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -20,6 +20,7 @@
 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
 #include "components/autofill/content/renderer/autofill_agent.h"
 #include "components/autofill/content/renderer/field_data_manager.h"
+#include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/form_tracker.h"
 #include "components/autofill/content/renderer/html_based_username_detector.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
@@ -99,10 +100,6 @@
   kMaxValue = kNoFillableElementsFound,
 };
 
-// Names of HTML attributes to show form and field signatures for debugging.
-extern const char kDebugAttributeForFormSignature[];
-extern const char kDebugAttributeForFieldSignature[];
-
 class FieldDataManager;
 class RendererSavePasswordProgressLogger;
 class PasswordGenerationAgent;
@@ -345,6 +342,12 @@
     DISALLOW_COPY_AND_ASSIGN(PasswordValueGatekeeper);
   };
 
+  // Annotate |forms| and all fields in the current frame with form and field
+  // signatures as HTML attributes. Used by
+  // chrome://flags/#enable-show-autofill-signatures only.
+  void AnnotateFormsAndFieldsWithSignatures(
+      blink::WebVector<blink::WebFormElement>& forms);
+
   // Scans the given frame for password forms and sends them up to the browser.
   // If |only_visible| is true, only forms visible in the layout are sent.
   void SendPasswordForms(bool only_visible);
@@ -513,10 +516,6 @@
   // Records the username typed before suggestions preview.
   base::string16 username_query_prefix_;
 
-  // The HTML based username detector's cache which maps form elements to
-  // username predictions.
-  UsernameDetectorCache username_detector_cache_;
-
   // This notifier is used to avoid sending redundant messages to the password
   // manager driver mojo interface.
   FocusStateNotifier focus_state_notifier_;
@@ -543,6 +542,14 @@
   // structure. Replace FormData with a smaller structure.
   std::map<FormRendererId, FormStructureInfo> forms_structure_cache_;
 
+  // The HTML based username detector's cache which maps form elements to
+  // username predictions.
+  UsernameDetectorCache username_detector_cache_;
+
+  // Stores the mapping from a form element's ID to results of button titles
+  // heuristics for that form.
+  form_util::ButtonTitlesCache button_titles_cache_;
+
   // Flag to prevent that multiple PasswordManager.FirstRendererFillingResult
   // UMA metrics are recorded per page load. This is reset on
   // DidCommitProvisionalLoad() but only for non-same-document-navigations.
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index a216162b..93824ca 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -9,7 +9,6 @@
 #include "base/no_destructor.h"
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
-#include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/html_based_username_detector.h"
 #include "components/autofill/core/common/password_form.h"
 #include "components/autofill/core/common/renderer_id.h"
@@ -128,7 +127,8 @@
 std::unique_ptr<FormData> CreateFormDataFromWebForm(
     const WebFormElement& web_form,
     const FieldDataManager* field_data_manager,
-    UsernameDetectorCache* username_detector_cache) {
+    UsernameDetectorCache* username_detector_cache,
+    form_util::ButtonTitlesCache* button_titles_cache) {
   if (web_form.IsNull())
     return nullptr;
 
@@ -136,7 +136,7 @@
   form_data->url =
       form_util::GetCanonicalOriginForDocument(web_form.GetDocument());
   form_data->full_url =
-      form_util::GetOriginWithoutAuthForDocument(web_form.GetDocument());
+      form_util::GetDocumentUrlWithoutAuth(web_form.GetDocument());
   form_data->is_gaia_with_skip_save_password_form =
       IsGaiaWithSkipSavePasswordForm(web_form) ||
       IsGaiaReauthenticationForm(web_form);
@@ -153,6 +153,8 @@
   }
   form_data->username_predictions = GetUsernamePredictions(
       control_elements.ReleaseVector(), *form_data, username_detector_cache);
+  form_data->button_titles = form_util::GetButtonTitles(
+      web_form, web_form.GetDocument(), button_titles_cache);
 
   return form_data;
 }
@@ -160,7 +162,8 @@
 std::unique_ptr<FormData> CreateFormDataFromUnownedInputElements(
     const WebLocalFrame& frame,
     const FieldDataManager* field_data_manager,
-    UsernameDetectorCache* username_detector_cache) {
+    UsernameDetectorCache* username_detector_cache,
+    form_util::ButtonTitlesCache* button_titles_cache) {
   std::vector<WebElement> fieldsets;
   std::vector<WebFormControlElement> control_elements =
       form_util::GetUnownedFormFieldElements(frame.GetDocument().All(),
@@ -179,9 +182,12 @@
   form_data->url =
       form_util::GetCanonicalOriginForDocument(frame.GetDocument());
   form_data->full_url =
-      form_util::GetOriginWithoutAuthForDocument(frame.GetDocument());
+      form_util::GetDocumentUrlWithoutAuth(frame.GetDocument());
   form_data->username_predictions = GetUsernamePredictions(
       control_elements, *form_data, username_detector_cache);
+  form_data->button_titles = form_util::GetButtonTitles(
+      WebFormElement(), frame.GetDocument(), button_titles_cache);
+
   return form_data;
 }
 
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.h b/components/autofill/content/renderer/password_form_conversion_utils.h
index 8701d51..07a2ad0 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.h
+++ b/components/autofill/content/renderer/password_form_conversion_utils.h
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/strings/string_piece.h"
+#include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/html_based_username_detector.h"
 #include "components/autofill/core/common/password_form.h"
 #include "third_party/blink/public/platform/web_string.h"
@@ -42,14 +43,16 @@
 std::unique_ptr<FormData> CreateFormDataFromWebForm(
     const blink::WebFormElement& web_form,
     const FieldDataManager* field_data_manager,
-    UsernameDetectorCache* username_detector_cache);
+    UsernameDetectorCache* username_detector_cache,
+    form_util::ButtonTitlesCache* button_titles_cache);
 
 // Same as CreateFormDataFromWebForm() but for input elements that are
 // not enclosed in <form> element.
 std::unique_ptr<FormData> CreateFormDataFromUnownedInputElements(
     const blink::WebLocalFrame& frame,
     const FieldDataManager* field_data_manager,
-    UsernameDetectorCache* username_detector_cache);
+    UsernameDetectorCache* username_detector_cache,
+    form_util::ButtonTitlesCache* button_titles_cache);
 
 // The "Realm" for the sign-on. This is scheme, host, port.
 std::string GetSignOnRealm(const GURL& origin);
diff --git a/components/autofill/core/browser/autofill_handler_proxy.cc b/components/autofill/core/browser/autofill_handler_proxy.cc
index be318a2..a246c8c8d 100644
--- a/components/autofill/core/browser/autofill_handler_proxy.cc
+++ b/components/autofill/core/browser/autofill_handler_proxy.cc
@@ -88,7 +88,9 @@
 
 void AutofillHandlerProxy::OnDidEndTextFieldEditing() {}
 
-void AutofillHandlerProxy::OnHidePopup() {}
+void AutofillHandlerProxy::OnHidePopup() {
+  provider_->OnHidePopup(this);
+}
 
 void AutofillHandlerProxy::SelectFieldOptionsDidChange(const FormData& form) {}
 
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 864444a7..38dcf82 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -96,7 +96,6 @@
 using features::kAutofillEnforceMinRequiredFieldsForQuery;
 using features::kAutofillEnforceMinRequiredFieldsForUpload;
 using features::kAutofillRestrictUnownedFieldsToFormlessCheckout;
-using mojom::ButtonTitleType;
 using mojom::SubmissionIndicatorEvent;
 using mojom::SubmissionSource;
 
@@ -7656,8 +7655,9 @@
   // Create a form with name and address fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -7699,8 +7699,9 @@
   // Create a form with address fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -7741,8 +7742,9 @@
   // Create a form with name and contact fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -7783,8 +7785,9 @@
   // Create a form with contact fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -7824,8 +7827,9 @@
   // Create a form with name fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -7865,8 +7869,9 @@
   // Create a form with name, address, and email fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -7916,8 +7921,9 @@
   // Create a form with address and email fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -7964,8 +7970,9 @@
   // Create a form with name fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -8015,8 +8022,9 @@
   // Create a form with name, address, and phone fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -8064,8 +8072,9 @@
   // Create a form with name, address, phone, and email fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
@@ -8116,8 +8125,9 @@
   // Create a form with address, phone, and email fields.
   FormData form;
   form.name = ASCIIToUTF16("MyForm");
-  form.button_titles = {std::make_pair(
-      ASCIIToUTF16("Submit"), ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.url = GURL("http://myform.com/form.html");
   form.action = GURL("http://myform.com/submit.html");
   form.main_frame_origin =
diff --git a/components/autofill/core/browser/autofill_metrics.cc b/components/autofill/core/browser/autofill_metrics.cc
index ac12335f..401c9b7b 100644
--- a/components/autofill/core/browser/autofill_metrics.cc
+++ b/components/autofill/core/browser/autofill_metrics.cc
@@ -1602,7 +1602,9 @@
     const std::vector<std::unique_ptr<CreditCard>>& server_cards,
     base::TimeDelta disused_data_threshold) {
   size_t num_local_cards = 0;
+  size_t num_local_cards_with_nickname = 0;
   size_t num_masked_cards = 0;
+  size_t num_masked_cards_with_nickname = 0;
   size_t num_unmasked_cards = 0;
   size_t num_disused_local_cards = 0;
   size_t num_disused_masked_cards = 0;
@@ -1634,6 +1636,8 @@
             days_since_last_use);
         num_local_cards += 1;
         num_disused_local_cards += disused_delta;
+        if (card->HasValidNickname())
+          num_local_cards_with_nickname += 1;
         break;
       case CreditCard::MASKED_SERVER_CARD:
         UMA_HISTOGRAM_COUNTS_1000(
@@ -1644,6 +1648,8 @@
             days_since_last_use);
         num_masked_cards += 1;
         num_disused_masked_cards += disused_delta;
+        if (card->HasValidNickname())
+          num_masked_cards_with_nickname += 1;
         break;
       case CreditCard::FULL_SERVER_CARD:
         UMA_HISTOGRAM_COUNTS_1000(
@@ -1670,10 +1676,15 @@
   UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount", num_cards);
   UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Local",
                             num_local_cards);
+  UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Local.WithNickname",
+                            num_local_cards_with_nickname);
   UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Server",
                             num_server_cards);
   UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Server.Masked",
                             num_masked_cards);
+  UMA_HISTOGRAM_COUNTS_1000(
+      "Autofill.StoredCreditCardCount.Server.Masked.WithNickname",
+      num_masked_cards_with_nickname);
   UMA_HISTOGRAM_COUNTS_1000("Autofill.StoredCreditCardCount.Server.Unmasked",
                             num_unmasked_cards);
 
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index ad36b11..b019d34 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -3634,6 +3634,67 @@
       "Autofill.DaysSinceLastUse.StoredCreditCard.Server.Unmasked", 200, 3);
 }
 
+TEST_F(AutofillMetricsTest, LogStoredCreditCardWithNicknameMetrics) {
+  std::vector<std::unique_ptr<CreditCard>> local_cards;
+  std::vector<std::unique_ptr<CreditCard>> server_cards;
+  local_cards.reserve(2);
+  server_cards.reserve(4);
+
+  // Create cards with and without nickname of each record type: 1 of each for
+  // local, 2 of each for masked.
+  const std::vector<CreditCard::RecordType> record_types{
+      CreditCard::LOCAL_CARD, CreditCard::MASKED_SERVER_CARD};
+  int num_cards_of_type = 0;
+  for (auto record_type : record_types) {
+    num_cards_of_type += 1;
+    for (int i = 0; i < num_cards_of_type; ++i) {
+      // Create a card with a nickname.
+      CreditCard card_with_nickname = test::GetRandomCreditCard(record_type);
+      card_with_nickname.SetNickname(ASCIIToUTF16("Valid nickname"));
+
+      // Create a card that doesn't have a nickname.
+      CreditCard card_without_nickname = test::GetRandomCreditCard(record_type);
+      // Set nickname to empty.
+      card_without_nickname.SetNickname(ASCIIToUTF16(""));
+
+      // Add the cards to the personal data manager in the appropriate way.
+      auto& repo =
+          (record_type == CreditCard::LOCAL_CARD) ? local_cards : server_cards;
+      repo.push_back(
+          std::make_unique<CreditCard>(std::move(card_with_nickname)));
+      repo.push_back(
+          std::make_unique<CreditCard>(std::move(card_without_nickname)));
+    }
+  }
+
+  // Log the stored credit card metrics for the cards configured above.
+  base::HistogramTester histogram_tester;
+  AutofillMetrics::LogStoredCreditCardMetrics(local_cards, server_cards,
+                                              base::TimeDelta::FromDays(180));
+
+  // Validate the count metrics.
+  histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount", 1);
+  histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Local", 1);
+  histogram_tester.ExpectTotalCount(
+      "Autofill.StoredCreditCardCount.Local.WithNickname", 1);
+  histogram_tester.ExpectTotalCount("Autofill.StoredCreditCardCount.Server", 1);
+  histogram_tester.ExpectTotalCount(
+      "Autofill.StoredCreditCardCount.Server.Masked", 1);
+  histogram_tester.ExpectTotalCount(
+      "Autofill.StoredCreditCardCount.Server.Masked.WithNickname", 1);
+  histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount", 6, 1);
+  histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Local", 2,
+                                     1);
+  histogram_tester.ExpectBucketCount(
+      "Autofill.StoredCreditCardCount.Local.WithNickname", 1, 1);
+  histogram_tester.ExpectBucketCount("Autofill.StoredCreditCardCount.Server", 4,
+                                     1);
+  histogram_tester.ExpectBucketCount(
+      "Autofill.StoredCreditCardCount.Server.Masked", 4, 1);
+  histogram_tester.ExpectBucketCount(
+      "Autofill.StoredCreditCardCount.Server.Masked.WithNickname", 2, 1);
+}
+
 // Test that we correctly log when Profile Autofill is enabled at startup.
 TEST_F(AutofillMetricsTest, AutofillProfileIsEnabledAtStartup) {
   base::HistogramTester histogram_tester;
diff --git a/components/autofill/core/browser/autofill_provider.cc b/components/autofill/core/browser/autofill_provider.cc
index 9fc3b8c0..8cea5630 100644
--- a/components/autofill/core/browser/autofill_provider.cc
+++ b/components/autofill/core/browser/autofill_provider.cc
@@ -19,4 +19,10 @@
       requestId, AutofillDriver::FORM_DATA_ACTION_FILL, formData);
 }
 
-}  // namespace autofil
+void AutofillProvider::RendererShouldAcceptDataListSuggestion(
+    AutofillHandlerProxy* handler,
+    const base::string16& value) {
+  handler->driver()->RendererShouldAcceptDataListSuggestion(value);
+}
+
+}  // namespace autofill
diff --git a/components/autofill/core/browser/autofill_provider.h b/components/autofill/core/browser/autofill_provider.h
index 09f87a9..6eae408 100644
--- a/components/autofill/core/browser/autofill_provider.h
+++ b/components/autofill/core/browser/autofill_provider.h
@@ -67,11 +67,18 @@
                            const std::vector<FormData>& forms,
                            const base::TimeTicks timestamp) = 0;
 
+  virtual void OnHidePopup(AutofillHandlerProxy* handler) = 0;
+
   virtual void Reset(AutofillHandlerProxy* handler) = 0;
 
   void SendFormDataToRenderer(AutofillHandlerProxy* handler,
                               int requestId,
                               const FormData& formData);
+
+  // Notifies the renderer should accept the datalist suggestion given by
+  // |value| and fill the associated input field.
+  void RendererShouldAcceptDataListSuggestion(AutofillHandlerProxy* handler,
+                                              const base::string16& value);
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/data_model/credit_card.cc b/components/autofill/core/browser/data_model/credit_card.cc
index 86e54707..599f8d6 100644
--- a/components/autofill/core/browser/data_model/credit_card.cc
+++ b/components/autofill/core/browser/data_model/credit_card.cc
@@ -817,11 +817,12 @@
                          : network + ASCIIToUTF16("  ") + obfuscated_string;
 }
 
-base::string16 CreditCard::CardIdentifierStringForAutofillDisplay() const {
+base::string16 CreditCard::CardIdentifierStringForAutofillDisplay(
+    base::string16 customized_nickname) const {
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableSurfacingServerCardNickname) &&
-      HasValidNickname()) {
-    return NicknameAndLastFourDigits();
+      (HasValidNickname() || !customized_nickname.empty())) {
+    return NicknameAndLastFourDigits(customized_nickname);
   }
   // Return a Google-specific string for Google-issued cards.
   if (base::FeatureList::IsEnabled(features::kAutofillEnableGoogleIssuedCard) &&
@@ -832,10 +833,11 @@
 }
 
 base::string16 CreditCard::CardIdentifierStringAndDescriptiveExpiration(
-    const std::string& app_locale) const {
+    const std::string& app_locale,
+    base::string16 customized_nickname) const {
   return l10n_util::GetStringFUTF16(
       IDS_AUTOFILL_CREDIT_CARD_TWO_LINE_LABEL_FROM_NAME,
-      CardIdentifierStringForAutofillDisplay(),
+      CardIdentifierStringForAutofillDisplay(customized_nickname),
       GetInfo(AutofillType(CREDIT_CARD_EXP_DATE_2_DIGIT_YEAR), app_locale));
 }
 
@@ -958,15 +960,17 @@
   return ::autofill::NetworkForFill(network_);
 }
 
-base::string16 CreditCard::NicknameAndLastFourDigits() const {
+base::string16 CreditCard::NicknameAndLastFourDigits(
+    base::string16 customized_nickname) const {
   // Should call HasValidNickname() to check valid nickname before calling this.
-  DCHECK(HasValidNickname());
+  DCHECK(HasValidNickname() || !customized_nickname.empty());
   const base::string16 digits = LastFourDigits();
   // If digits are empty, return nickname.
   if (digits.empty())
-    return nickname_;
+    return customized_nickname.empty() ? nickname_ : customized_nickname;
 
-  return nickname_ + ASCIIToUTF16("  ") +
+  return (customized_nickname.empty() ? nickname_ : customized_nickname) +
+         ASCIIToUTF16("  ") +
          internal::GetObfuscatedStringForCardDigits(digits);
 }
 
diff --git a/components/autofill/core/browser/data_model/credit_card.h b/components/autofill/core/browser/data_model/credit_card.h
index b73bd3e..e74ced4 100644
--- a/components/autofill/core/browser/data_model/credit_card.h
+++ b/components/autofill/core/browser/data_model/credit_card.h
@@ -260,14 +260,16 @@
   // available and valid;  otherwise, formatted as 'IssuerNetwork - ****2345'.
   // Google-issued cards have their own specific identifier, instead of
   // displaying the issuer network name.
-  base::string16 CardIdentifierStringForAutofillDisplay() const;
+  base::string16 CardIdentifierStringForAutofillDisplay(
+      base::string16 customized_nickname = base::string16()) const;
   // A label for this card formatted as 'Nickname - ****2345, expires on MM/YY'
   // if nickname experiment is turned on and nickname is available; otherwise,
   // formatted as 'IssuerNetwork - ****2345, expires on MM/YY'.
   // This label is used as a second line label when the cardholder
   // name/expiration date field is selected.
   base::string16 CardIdentifierStringAndDescriptiveExpiration(
-      const std::string& app_locale) const;
+      const std::string& app_locale,
+      base::string16 customized_nickname = base::string16()) const;
   // A label for this card formatted as 'Expires on MM/YY'.
   // This label is used as a second line label when the autofill dropdown
   // uses a two line layout and the credit card number is selected.
@@ -314,7 +316,8 @@
 
   // A label for this card formatted as 'Nickname - ****2345'. Always call
   // HasValidNickname() before calling this.
-  base::string16 NicknameAndLastFourDigits() const;
+  base::string16 NicknameAndLastFourDigits(
+      base::string16 customized_nickname = base::string16()) const;
 
   // Sets the name_on_card_ value based on the saved name parts.
   void SetNameOnCardFromSeparateParts();
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index b4a3788..78b90e2 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -61,7 +61,6 @@
 
 namespace autofill {
 
-using mojom::ButtonTitleType;
 using mojom::SubmissionIndicatorEvent;
 
 namespace {
@@ -359,32 +358,6 @@
   return HTML_TYPE_UNRECOGNIZED;
 }
 
-// Helper function for explicit conversion between |ButtonTitleType| defined in
-// "autofill_types.mojom.h" and "server.proto".
-AutofillUploadContents_ButtonTitle_ButtonTitleType ToServerButtonTitleType(
-    ButtonTitleType input) {
-  switch (input) {
-    case ButtonTitleType::NONE:
-      return AutofillUploadContents::ButtonTitle::NONE;
-    case ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE:
-      return AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_SUBMIT_TYPE;
-    case ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE:
-      return AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_BUTTON_TYPE;
-    case ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE:
-      return AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_SUBMIT_TYPE;
-    case ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE:
-      return AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_BUTTON_TYPE;
-    case ButtonTitleType::HYPERLINK:
-      return AutofillUploadContents::ButtonTitle::HYPERLINK;
-    case ButtonTitleType::DIV:
-      return AutofillUploadContents::ButtonTitle::DIV;
-    case ButtonTitleType::SPAN:
-      return AutofillUploadContents::ButtonTitle::SPAN;
-  }
-  NOTREACHED();
-  return AutofillUploadContents::ButtonTitle::NONE;
-}
-
 std::ostream& operator<<(
     std::ostream& out,
     const autofill::AutofillQueryResponseContents& response) {
@@ -483,6 +456,15 @@
                           RandomizedEncoder::FORM_NAME, form.name_attribute(),
                           metadata->mutable_name());
   }
+
+  for (const ButtonTitleInfo& e : form.button_titles()) {
+    auto* button_title = metadata->add_button_title();
+    DCHECK(!e.first.empty());
+    EncodeRandomizedValue(encoder, form_signature, kNullFieldSignature,
+                          RandomizedEncoder::FORM_BUTTON_TITLES, e.first,
+                          button_title->mutable_title());
+    button_title->set_type(static_cast<ButtonTitleType>(e.second));
+  }
   auto full_source_url = form.full_source_url().spec();
   if (encoder.AnonymousUrlCollectionIsEnabled() && !full_source_url.empty()) {
     EncodeRandomizedValue(encoder, form_signature, kNullFieldSignature,
@@ -728,7 +710,7 @@
     for (const ButtonTitleInfo& e : button_titles_) {
       auto* button_title = upload->add_button_title();
       button_title->set_title(base::UTF16ToUTF8(e.first));
-      button_title->set_type(ToServerButtonTitleType(e.second));
+      button_title->set_type(static_cast<ButtonTitleType>(e.second));
     }
   }
 
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h
index 76af1b4..af54af4 100644
--- a/components/autofill/core/browser/form_structure.h
+++ b/components/autofill/core/browser/form_structure.h
@@ -241,6 +241,8 @@
 
   const url::Origin& main_frame_origin() const { return main_frame_origin_; }
 
+  const ButtonTitleList& button_titles() const { return button_titles_; }
+
   bool has_author_specified_types() const {
     return has_author_specified_types_;
   }
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc
index 0e23ab2..37d392c8 100644
--- a/components/autofill/core/browser/form_structure_unittest.cc
+++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -39,7 +39,6 @@
 using features::kAutofillEnforceMinRequiredFieldsForHeuristics;
 using features::kAutofillEnforceMinRequiredFieldsForQuery;
 using features::kAutofillEnforceMinRequiredFieldsForUpload;
-using mojom::ButtonTitleType;
 using mojom::SubmissionIndicatorEvent;
 using mojom::SubmissionSource;
 
@@ -2507,44 +2506,43 @@
 }
 
 TEST_F(FormStructureTest, ButtonTitleType_Match) {
-  // Statically assert that the mojo ButtonTitleType enum matches the
-  // corresponding entries the in proto AutofillUploadContents::ButtonTitle
-  // ButtonTitleType enum.
-  static_assert(AutofillUploadContents::ButtonTitle::NONE ==
-                    static_cast<int>(ButtonTitleType::NONE),
-                "NONE enumerator does not match!");
+  // Statically assert that the mojom::ButtonTitleType enum matches the
+  // corresponding entries in the proto - ButtonTitleType enum.
+  static_assert(
+      ButtonTitleType::NONE == static_cast<int>(mojom::ButtonTitleType::NONE),
+      "NONE enumerator does not match!");
 
   static_assert(
-      AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_SUBMIT_TYPE ==
-          static_cast<int>(ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE),
+      ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE ==
+          static_cast<int>(mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE),
       "BUTTON_ELEMENT_SUBMIT_TYPE enumerator does not match!");
 
   static_assert(
-      AutofillUploadContents::ButtonTitle::BUTTON_ELEMENT_BUTTON_TYPE ==
-          static_cast<int>(ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE),
+      ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE ==
+          static_cast<int>(mojom::ButtonTitleType::BUTTON_ELEMENT_BUTTON_TYPE),
       "BUTTON_ELEMENT_BUTTON_TYPE enumerator does not match!");
 
   static_assert(
-      AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_SUBMIT_TYPE ==
-          static_cast<int>(ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE),
+      ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE ==
+          static_cast<int>(mojom::ButtonTitleType::INPUT_ELEMENT_SUBMIT_TYPE),
       "INPUT_ELEMENT_SUBMIT_TYPE enumerator does not match!");
 
   static_assert(
-      AutofillUploadContents::ButtonTitle::INPUT_ELEMENT_BUTTON_TYPE ==
-          static_cast<int>(ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE),
+      ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE ==
+          static_cast<int>(mojom::ButtonTitleType::INPUT_ELEMENT_BUTTON_TYPE),
       "INPUT_ELEMENT_BUTTON_TYPE enumerator does not match!");
 
-  static_assert(AutofillUploadContents::ButtonTitle::HYPERLINK ==
-                    static_cast<int>(ButtonTitleType::HYPERLINK),
+  static_assert(ButtonTitleType::HYPERLINK ==
+                    static_cast<int>(mojom::ButtonTitleType::HYPERLINK),
                 "HYPERLINK enumerator does not match!");
 
-  static_assert(AutofillUploadContents::ButtonTitle::DIV ==
-                    static_cast<int>(ButtonTitleType::DIV),
-                "DIV enumerator does not match!");
+  static_assert(
+      ButtonTitleType::DIV == static_cast<int>(mojom::ButtonTitleType::DIV),
+      "DIV enumerator does not match!");
 
-  static_assert(AutofillUploadContents::ButtonTitle::SPAN ==
-                    static_cast<int>(ButtonTitleType::SPAN),
-                "SPAN enumerator does not match!");
+  static_assert(
+      ButtonTitleType::SPAN == static_cast<int>(mojom::ButtonTitleType::SPAN),
+      "SPAN enumerator does not match!");
 }
 
 TEST_F(FormStructureTest, EncodeUploadRequest_WithMatchingValidities) {
@@ -4518,6 +4516,9 @@
   FormData form;
   form.id_attribute = ASCIIToUTF16("form-id");
   form.url = GURL("http://www.foo.com/");
+  form.button_titles = {
+      std::make_pair(ASCIIToUTF16("Submit"),
+                     mojom::ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE)};
   form.full_url = GURL("http://www.foo.com/?foo=bar");
   for (const auto& f : kFieldMetadata) {
     FormFieldData field;
@@ -4571,6 +4572,18 @@
                            RandomizedEncoder::FORM_URL, full_url));
   ASSERT_EQ(static_cast<size_t>(upload.field_size()),
             base::size(kFieldMetadata));
+
+  ASSERT_EQ(1, upload.randomized_form_metadata().button_title().size());
+  EXPECT_EQ(upload.randomized_form_metadata()
+                .button_title()[0]
+                .title()
+                .encoded_bits(),
+            encoder.EncodeForTesting(form_signature, FieldSignature(),
+                                     RandomizedEncoder::FORM_BUTTON_TITLES,
+                                     form.button_titles[0].first));
+  EXPECT_EQ(ButtonTitleType::BUTTON_ELEMENT_SUBMIT_TYPE,
+            upload.randomized_form_metadata().button_title()[0].type());
+
   for (int i = 0; i < upload.field_size(); ++i) {
     const auto& metadata = upload.field(i).randomized_field_metadata();
     const auto& field = *form_structure.field(i);
diff --git a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
index 5efca8c..8fdc391 100644
--- a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
+++ b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.cc
@@ -72,6 +72,15 @@
   }
 }
 
+// static
+AutofillSaveCardInfoBarDelegateMobile*
+AutofillSaveCardInfoBarDelegateMobile::FromInfobarDelegate(
+    infobars::InfoBarDelegate* delegate) {
+  return delegate->GetIdentifier() == AUTOFILL_CC_INFOBAR_DELEGATE_MOBILE
+             ? static_cast<AutofillSaveCardInfoBarDelegateMobile*>(delegate)
+             : nullptr;
+}
+
 void AutofillSaveCardInfoBarDelegateMobile::OnLegalMessageLinkClicked(
     GURL url) {
   infobar()->owner()->OpenURL(url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
diff --git a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h
index 6472101..d4dce31 100644
--- a/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h
+++ b/components/autofill/core/browser/payments/autofill_save_card_infobar_delegate_mobile.h
@@ -39,6 +39,11 @@
 
   ~AutofillSaveCardInfoBarDelegateMobile() override;
 
+  // Returns |delegate| as an AutofillSaveCardInfoBarDelegateMobile, or nullptr
+  // if it is of another type.
+  static AutofillSaveCardInfoBarDelegateMobile* FromInfobarDelegate(
+      infobars::InfoBarDelegate* delegate);
+
   bool upload() const { return upload_; }
   int issuer_icon_id() const { return issuer_icon_id_; }
   const base::string16& card_label() const { return card_label_; }
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index c313b05..19b262a 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -2062,12 +2062,17 @@
                               ? Suggestion::PREFIX_MATCH
                               : Suggestion::SUBSTRING_MATCH;
 
+      // Possibly there is a nickname to be shared between the card and its
+      // duplicates.
+      base::string16 shared_nickname =
+          GetDisplayNicknameForCreditCard(*credit_card);
+
       // If the value is the card number, the label is the expiration date.
       // Otherwise the label is the card number, or if that is empty the
       // cardholder name. The label should never repeat the value.
       if (type.GetStorableType() == CREDIT_CARD_NUMBER) {
-        suggestion->value =
-            credit_card->CardIdentifierStringForAutofillDisplay();
+        suggestion->value = credit_card->CardIdentifierStringForAutofillDisplay(
+            shared_nickname);
 
 #if defined(OS_ANDROID) || defined(OS_IOS)
         suggestion->label = credit_card->GetInfo(
@@ -2091,7 +2096,8 @@
         suggestion->label =
             base::FeatureList::IsEnabled(features::kAutofillKeyboardAccessory)
                 ? credit_card->ObfuscatedLastFourDigits()
-                : credit_card->CardIdentifierStringForAutofillDisplay();
+                : credit_card->CardIdentifierStringForAutofillDisplay(
+                      shared_nickname);
 #elif defined(OS_IOS)
         // E.g. "••••1234"".
         suggestion->label = credit_card->ObfuscatedLastFourDigits();
@@ -2646,4 +2652,22 @@
                                            /*opted_in=*/true);
 }
 
+base::string16 PersonalDataManager::GetDisplayNicknameForCreditCard(
+    const CreditCard& card) const {
+  // Always prefer a local nickname if available.
+  if (card.HasValidNickname() && card.record_type() == CreditCard::LOCAL_CARD)
+    return card.nickname();
+  // Either the card a) has no nickname or b) is a server card and we would
+  // prefer to use the nickname of a local card.
+  std::vector<CreditCard*> candidates = GetCreditCards();
+  for (CreditCard* candidate : candidates) {
+    if (candidate->guid() != card.guid() && candidate->HasSameNumberAs(card) &&
+        candidate->HasValidNickname()) {
+      return candidate->nickname();
+    }
+  }
+  // Fall back to nickname of |card|, which may be empty.
+  return card.nickname();
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index 1e787a4d..42d68aa 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -752,6 +752,12 @@
   // migrating from using email to Gaia ID as th account identifier.
   void MigrateUserOptedInWalletSyncTransportIfNeeded();
 
+  // Return a nickname for the |card| to display. This is generally the nickname
+  // stored in |card|, unless |card| exists as a local and a server copy. In
+  // this case, we prefer the nickname of the local if it is defined. If only
+  // one copy has a nickname, take that.
+  base::string16 GetDisplayNicknameForCreditCard(const CreditCard& card) const;
+
   // Stores the |app_locale| supplied on construction.
   const std::string app_locale_;
 
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index e4c14cb..d764b180 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -3218,7 +3218,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NAME_FULL),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /*include_server_cards=*/true);
   ASSERT_EQ(3U, suggestions.size());
 
@@ -3267,7 +3267,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NAME_FULL),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /*include_server_cards=*/true);
   ASSERT_EQ(5U, suggestions.size());
 
@@ -3321,7 +3321,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NAME_FULL),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /*include_server_cards=*/true);
   ASSERT_EQ(0U, suggestions.size());
 }
@@ -3371,7 +3371,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NAME_FULL),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /*include_server_cards=*/true);
   ASSERT_EQ(0U, suggestions.size());
 }
@@ -3436,7 +3436,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NAME_FULL),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /* include_server_cards= */ true);
   ASSERT_EQ(3U, suggestions.size());
 
@@ -3596,7 +3596,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NUMBER),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /*include_server_cards=*/true);
   ASSERT_EQ(1U, suggestions.size());
   EXPECT_EQ(base::UTF8ToUTF16(std::string("Amex  ") +
@@ -3650,7 +3650,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NAME_FULL),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /*include_server_cards=*/true);
   ASSERT_EQ(3U, suggestions.size());
   EXPECT_EQ(base::ASCIIToUTF16("John Dillinger"), suggestions[0].value);
@@ -3658,7 +3658,7 @@
   EXPECT_EQ(base::ASCIIToUTF16("Bonnie Parker"), suggestions[2].value);
 
   suggestions = personal_data_->GetCreditCardSuggestions(
-      AutofillType(CREDIT_CARD_NUMBER), /* field_contents= */ base::string16(),
+      AutofillType(CREDIT_CARD_NUMBER), /*field_contents=*/base::string16(),
       /*include_server_cards=*/true);
   ASSERT_EQ(3U, suggestions.size());
   EXPECT_EQ(base::UTF8ToUTF16(std::string("Visa  ") +
@@ -3697,7 +3697,7 @@
   std::vector<Suggestion> suggestions =
       personal_data_->GetCreditCardSuggestions(
           AutofillType(CREDIT_CARD_NAME_FULL),
-          /* field_contents= */ base::string16(),
+          /*field_contents=*/base::string16(),
           /*include_server_cards=*/true);
   ASSERT_EQ(3U, suggestions.size());
 
@@ -3712,7 +3712,7 @@
 
   suggestions = personal_data_->GetCreditCardSuggestions(
       AutofillType(CREDIT_CARD_NAME_FULL),
-      /* field_contents= */ base::string16(), /*include_server_cards=*/true);
+      /*field_contents=*/base::string16(), /*include_server_cards=*/true);
   ASSERT_EQ(3U, suggestions.size());
 }
 
@@ -7772,4 +7772,129 @@
   EXPECT_THAT(all_upi_ids, testing::ElementsAre(upi_id));
 }
 
+struct ShareNicknameTestParam {
+  std::string local_nickname;
+  std::string server_nickname;
+  std::string expected_nickname;
+};
+
+const ShareNicknameTestParam kShareNicknameTestParam[] = {
+    {"", "", ""},
+    {"", "server nickname", "server nickname"},
+    {"local nickname", "", "local nickname"},
+    {"local nickname", "server nickname", "local nickname"},
+};
+
+class PersonalDataManagerTestForSharingNickname
+    : public PersonalDataManagerTest,
+      public testing::WithParamInterface<ShareNicknameTestParam> {
+ public:
+  PersonalDataManagerTestForSharingNickname()
+      : local_nickname_(base::UTF8ToUTF16(GetParam().local_nickname)),
+        server_nickname_(base::UTF8ToUTF16(GetParam().server_nickname)),
+        expected_nickname_(base::UTF8ToUTF16(GetParam().expected_nickname)) {}
+
+  CreditCard GetLocalCard() {
+    CreditCard local_card("287151C8-6AB1-487C-9095-28E80BE5DA15",
+                          test::kEmptyOrigin);
+    test::SetCreditCardInfo(&local_card, "Clyde Barrow",
+                            "378282246310005" /* American Express */, "04",
+                            "2999", "1");
+    local_card.set_use_count(3);
+    local_card.set_use_date(AutofillClock::Now() -
+                            base::TimeDelta::FromDays(1));
+    local_card.SetNickname(local_nickname_);
+    return local_card;
+  }
+
+  CreditCard GetServerCard() {
+    CreditCard full_server_card(CreditCard::FULL_SERVER_CARD, "c789");
+    test::SetCreditCardInfo(&full_server_card, "Clyde Barrow",
+                            "378282246310005" /* American Express */, "04",
+                            "2999", "1");
+    full_server_card.SetNickname(server_nickname_);
+    return full_server_card;
+  }
+
+  base::string16 local_nickname_;
+  base::string16 server_nickname_;
+  base::string16 expected_nickname_;
+
+ protected:
+  void SetUp() override {
+    PersonalDataManagerTest::SetUp();
+    EnableWalletCardImport();
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kAutofillEnableSurfacingServerCardNickname);
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(,
+                         PersonalDataManagerTestForSharingNickname,
+                         testing::ValuesIn(kShareNicknameTestParam));
+
+TEST_P(PersonalDataManagerTestForSharingNickname,
+       VerifySuggestion_DuplicateCards) {
+  ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
+  CreditCard local_card = GetLocalCard();
+  personal_data_->AddCreditCard(local_card);
+
+  SetServerCards({GetServerCard()});
+
+  personal_data_->Refresh();
+  WaitForOnPersonalDataChanged();
+  ASSERT_EQ(2U, personal_data_->GetCreditCards().size());
+
+  // Verifies the suggestion shows the right text.
+  std::vector<Suggestion> suggestions =
+      personal_data_->GetCreditCardSuggestions(
+          AutofillType(CREDIT_CARD_NUMBER),
+          /*field_contents=*/base::string16(),
+          /*include_server_cards=*/true);
+  ASSERT_EQ(1U, suggestions.size());
+  EXPECT_EQ(suggestions[0].value,
+            (expected_nickname_.empty() ? base::ASCIIToUTF16("Amex")
+                                        : expected_nickname_) +
+                base::UTF8ToUTF16("  ") +
+                local_card.ObfuscatedLastFourDigits());
+}
+
+TEST_P(PersonalDataManagerTestForSharingNickname,
+       VerifySuggestion_UnrelatedCards) {
+  ASSERT_EQ(0U, personal_data_->GetCreditCards().size());
+  CreditCard local_card = GetLocalCard();
+  personal_data_->AddCreditCard(local_card);
+
+  std::vector<CreditCard> server_cards;
+  CreditCard server_card = GetServerCard();
+  // Make sure the cards are different by giving a different card number.
+  server_card.SetNumber(base::ASCIIToUTF16("371449635398431"));
+  server_cards.emplace_back(server_card);
+  SetServerCards(server_cards);
+
+  personal_data_->Refresh();
+  WaitForOnPersonalDataChanged();
+  ASSERT_EQ(2U, personal_data_->GetCreditCards().size());
+
+  // Verifies the suggestion shows the right text.
+  std::vector<Suggestion> suggestions =
+      personal_data_->GetCreditCardSuggestions(
+          AutofillType(CREDIT_CARD_NUMBER),
+          /*field_contents=*/base::string16(),
+          /*include_server_cards=*/true);
+  ASSERT_EQ(2U, suggestions.size());
+  EXPECT_THAT(
+      std::vector<base::string16>({suggestions[0].value, suggestions[1].value}),
+      testing::UnorderedElementsAre(
+          (server_nickname_.empty() ? base::ASCIIToUTF16("Amex")
+                                    : server_nickname_) +
+              base::UTF8ToUTF16("  ") + server_card.ObfuscatedLastFourDigits(),
+          (local_nickname_.empty() ? base::ASCIIToUTF16("Amex")
+                                   : local_nickname_) +
+              base::UTF8ToUTF16("  ") + local_card.ObfuscatedLastFourDigits()));
+}
+
 }  // namespace autofill
diff --git a/components/autofill/core/browser/proto/server.proto b/components/autofill/core/browser/proto/server.proto
index a36839bd..fab70ed 100644
--- a/components/autofill/core/browser/proto/server.proto
+++ b/components/autofill/core/browser/proto/server.proto
@@ -117,6 +117,20 @@
   optional bytes encoded_bits = 2;
 }
 
+// Describes how the button is implemented in HTML source. Corresponds to
+// the mojo ButtonTitleType enum defined in
+// components/autofill/core/common/mojom/autofill_types.mojom.h
+enum ButtonTitleType {
+  NONE = 0;
+  BUTTON_ELEMENT_SUBMIT_TYPE = 1;  // <button type='submit'>
+  BUTTON_ELEMENT_BUTTON_TYPE = 2;  // <button type='button'>
+  INPUT_ELEMENT_SUBMIT_TYPE = 3;   // <input type='submit'>
+  INPUT_ELEMENT_BUTTON_TYPE = 4;   // <input type='button'>
+  HYPERLINK = 5;                   // e.g. <a class='button'>
+  DIV = 6;                         // e.g. <div id='submit'>
+  SPAN = 7;                        // e.g. <span name='btn'>
+}
+
 // The collection of autofill field metadata to be sent using randomization.
 message AutofillRandomizedFormMetadata {
   // Form element id. Example: <form id="XXXXXXXX">
@@ -130,6 +144,18 @@
 
   // Location of form as URL.
   optional AutofillRandomizedValue url = 4;
+
+  // Information about a button's title (sync with another ButtonTitle in this
+  // proto).
+  message ButtonTitle {
+    // Text showed on the button.
+    optional AutofillRandomizedValue title = 1;
+
+    // Describes how the button is implemented in HTML source.
+    optional ButtonTitleType type = 2;
+  }
+  // Titles of form's buttons. Example: <input type="submit" value="XXXXX">
+  repeated ButtonTitle button_title = 5;
 }
 
 // The collection of autofill field metadata to be sent using randomization.
@@ -386,24 +412,13 @@
   // Form-level metadata observed by the client, randomized.
   optional AutofillRandomizedFormMetadata randomized_form_metadata = 32;
 
-  // Information about a button's title.
+  // Information about a button's title (sync with another ButtonTitle in this
+  // proto).
   message ButtonTitle {
     // Text showed on the button.
     optional string title = 1;
 
-    // Describes how the button is implemented in HTML source. Corresponds to
-    // the mojo ButtonTitleType enum defined in
-    // components/autofill/core/common/mojom/autofill_types.mojom.h
-    enum ButtonTitleType {
-      NONE = 0;
-      BUTTON_ELEMENT_SUBMIT_TYPE = 1;  // <button type='submit'>
-      BUTTON_ELEMENT_BUTTON_TYPE = 2;  // <button type='button'>
-      INPUT_ELEMENT_SUBMIT_TYPE = 3;   // <input type='submit'>
-      INPUT_ELEMENT_BUTTON_TYPE = 4;   // <input type='button'>
-      HYPERLINK = 5;                   // e.g. <a class='button'>
-      DIV = 6;                         // e.g. <div id='submit'>
-      SPAN = 7;                        // e.g. <span name='btn'>
-    }
+    // Describes how the button is implemented in HTML source.
     optional ButtonTitleType type = 2;
   }
   // Titles of form's buttons.
diff --git a/components/autofill/core/browser/randomized_encoder.cc b/components/autofill/core/browser/randomized_encoder.cc
index 116e169..4a3a467 100644
--- a/components/autofill/core/browser/randomized_encoder.cc
+++ b/components/autofill/core/browser/randomized_encoder.cc
@@ -204,6 +204,7 @@
 const char RandomizedEncoder::FORM_ACTION[] = "form-action";
 const char RandomizedEncoder::FORM_URL[] = "form-url";
 const char RandomizedEncoder::FORM_CSS_CLASS[] = "form-css-class";
+const char RandomizedEncoder::FORM_BUTTON_TITLES[] = "button-titles";
 
 const char RandomizedEncoder::FIELD_ID[] = "field-id";
 const char RandomizedEncoder::FIELD_NAME[] = "field-name";
diff --git a/components/autofill/core/browser/randomized_encoder.h b/components/autofill/core/browser/randomized_encoder.h
index 70d7b42..aefd5e6 100644
--- a/components/autofill/core/browser/randomized_encoder.h
+++ b/components/autofill/core/browser/randomized_encoder.h
@@ -33,6 +33,7 @@
   static const char FORM_ACTION[];
   static const char FORM_URL[];
   static const char FORM_CSS_CLASS[];
+  static const char FORM_BUTTON_TITLES[];
 
   // Field-level data-type identifiers.
   static const char FIELD_ID[];
diff --git a/components/autofill/core/browser/test_autofill_provider.cc b/components/autofill/core/browser/test_autofill_provider.cc
index ef5137b..2102a197 100644
--- a/components/autofill/core/browser/test_autofill_provider.cc
+++ b/components/autofill/core/browser/test_autofill_provider.cc
@@ -50,6 +50,8 @@
                                        const std::vector<FormData>& forms,
                                        const base::TimeTicks timestamp) {}
 
+void TestAutofillProvider::OnHidePopup(AutofillHandlerProxy* handler) {}
+
 void TestAutofillProvider::Reset(AutofillHandlerProxy* handler) {}
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/test_autofill_provider.h b/components/autofill/core/browser/test_autofill_provider.h
index a7fc221..7a21e59c 100644
--- a/components/autofill/core/browser/test_autofill_provider.h
+++ b/components/autofill/core/browser/test_autofill_provider.h
@@ -48,6 +48,7 @@
   void OnFormsSeen(AutofillHandlerProxy* handler,
                    const std::vector<FormData>& forms,
                    const base::TimeTicks timestamp) override;
+  void OnHidePopup(AutofillHandlerProxy* handler) override;
   void Reset(AutofillHandlerProxy* handler) override;
 };
 
diff --git a/components/blacklist/README.md b/components/blacklist/README.md
index d08198a..5d354e7 100644
--- a/components/blacklist/README.md
+++ b/components/blacklist/README.md
@@ -1,11 +1,11 @@
-# Blacklist component #
+# Blocklist component #
 
-The goal of the blacklist component is to provide various blacklists that allow
+The goal of the blocklist component is to provide various blocklists that allow
 different policies for features to consume. Currently, the only implemented
-blacklist is the opt out blacklist.
+blocklist is the opt out blocklist.
 
-## Opt out blacklist ##
-The opt out blacklist makes decisions based on user history actions. Each user
+## Opt out blocklist ##
+The opt out blocklist makes decisions based on user history actions. Each user
 action is evaluated based on action type, time of the evaluation, host name of
 the action (can be any string representation), and previous action history.
 
@@ -14,15 +14,15 @@
 performing the action, the user interaction should be determined to be an opt
 out (the user did not like the action) or a non-opt out (the user was not
 opposed to the action). The action, type, host name, and whether it was an opt
-out should be reported back to the blacklist to build user action history.
+out should be reported back to the blocklist to build user action history.
 
 For example, a feature may wish to show an InfoBar (or different types of
 InfoBars) displaying information about the page a user is on. After querying the
-opt out blacklist for action eligibility, an InfoBar may be allowed to be shown.
+opt out blocklist for action eligibility, an InfoBar may be allowed to be shown.
 If it is shown, the user may interact with it in a number of ways. If the user
 dismisses the InfoBar, that could be considered an opt out; if the user does
 not dismiss the InfoBar that could be considered a non-opt out. All of the
-information related to that action should be reported to the blacklist.
+information related to that action should be reported to the blocklist.
 
 ### Supported evaluation policies ###
 In general, policies follow a specific form: the most recent _n_ actions are
@@ -33,8 +33,8 @@
 
 * Session policy: This policy only applies across all types and host names, but
 is limited to actions that happened within the current session. The beginning of
-a session is defined as the creation of the blacklist object or when the
-blacklist is cleared (see below for details on clearing the blacklist).
+a session is defined as the creation of the blocklist object or when the
+blocklist is cleared (see below for details on clearing the blocklist).
 
 * Persistent policy: This policy applies across all sessions, types and host
 names.
@@ -51,8 +51,8 @@
 specifies a set of enabled types and versions for each type. This allows
 removing past versions of types to be removed from the backing store.
 
-### Clearing the blacklist ###
+### Clearing the blocklist ###
 Because many actions should be cleared when user clears history, the opt out
-blacklist allows clearing history in certain time ranges. All entries are
+blocklist allows clearing history in certain time ranges. All entries are
 cleared for the specified time range, and the data in memory is repopulated
 from the backing store.
diff --git a/components/blacklist/opt_out_blacklist/BUILD.gn b/components/blacklist/opt_out_blacklist/BUILD.gn
index d2c01ceb3..b7d8cf32 100644
--- a/components/blacklist/opt_out_blacklist/BUILD.gn
+++ b/components/blacklist/opt_out_blacklist/BUILD.gn
@@ -8,6 +8,7 @@
     "opt_out_blacklist.h",
     "opt_out_blacklist_data.cc",
     "opt_out_blacklist_data.h",
+    "opt_out_blacklist_delegate.h",
     "opt_out_blacklist_item.cc",
     "opt_out_blacklist_item.h",
     "opt_out_store.h",
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist.cc b/components/blacklist/opt_out_blacklist/opt_out_blacklist.cc
index fb86725..0aeeedd 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist.cc
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist.cc
@@ -14,82 +14,82 @@
 #include "components/blacklist/opt_out_blacklist/opt_out_blacklist_item.h"
 #include "components/blacklist/opt_out_blacklist/opt_out_store.h"
 
-namespace blacklist {
+namespace blocklist {
 
-OptOutBlacklist::OptOutBlacklist(std::unique_ptr<OptOutStore> opt_out_store,
+OptOutBlocklist::OptOutBlocklist(std::unique_ptr<OptOutStore> opt_out_store,
                                  base::Clock* clock,
-                                 OptOutBlacklistDelegate* blacklist_delegate)
+                                 OptOutBlocklistDelegate* blocklist_delegate)
     : loaded_(false),
       opt_out_store_(std::move(opt_out_store)),
       clock_(clock),
-      blacklist_delegate_(blacklist_delegate) {
+      blocklist_delegate_(blocklist_delegate) {
   DCHECK(clock_);
-  DCHECK(blacklist_delegate_);
+  DCHECK(blocklist_delegate_);
 }
 
-OptOutBlacklist::~OptOutBlacklist() = default;
+OptOutBlocklist::~OptOutBlocklist() = default;
 
-void OptOutBlacklist::Init() {
+void OptOutBlocklist::Init() {
   DCHECK(!loaded_);
-  DCHECK(!blacklist_data_);
+  DCHECK(!blocklist_data_);
   base::TimeDelta duration;
   size_t history = 0;
   int threshold = 0;
 
-  std::unique_ptr<BlacklistData::Policy> session_policy;
+  std::unique_ptr<BlocklistData::Policy> session_policy;
   if (ShouldUseSessionPolicy(&duration, &history, &threshold)) {
     session_policy =
-        std::make_unique<BlacklistData::Policy>(duration, history, threshold);
+        std::make_unique<BlocklistData::Policy>(duration, history, threshold);
   }
 
-  std::unique_ptr<BlacklistData::Policy> persistent_policy;
+  std::unique_ptr<BlocklistData::Policy> persistent_policy;
   if (ShouldUsePersistentPolicy(&duration, &history, &threshold)) {
     persistent_policy =
-        std::make_unique<BlacklistData::Policy>(duration, history, threshold);
+        std::make_unique<BlocklistData::Policy>(duration, history, threshold);
   }
 
   size_t max_hosts = 0;
-  std::unique_ptr<BlacklistData::Policy> host_policy;
+  std::unique_ptr<BlocklistData::Policy> host_policy;
   if (ShouldUseHostPolicy(&duration, &history, &threshold, &max_hosts)) {
     host_policy =
-        std::make_unique<BlacklistData::Policy>(duration, history, threshold);
+        std::make_unique<BlocklistData::Policy>(duration, history, threshold);
   }
 
-  std::unique_ptr<BlacklistData::Policy> type_policy;
+  std::unique_ptr<BlocklistData::Policy> type_policy;
   if (ShouldUseTypePolicy(&duration, &history, &threshold)) {
     type_policy =
-        std::make_unique<BlacklistData::Policy>(duration, history, threshold);
+        std::make_unique<BlocklistData::Policy>(duration, history, threshold);
   }
 
-  auto blacklist_data = std::make_unique<BlacklistData>(
+  auto blocklist_data = std::make_unique<BlocklistData>(
       std::move(session_policy), std::move(persistent_policy),
       std::move(host_policy), std::move(type_policy), max_hosts,
       GetAllowedTypes());
 
   if (opt_out_store_) {
-    opt_out_store_->LoadBlackList(
-        std::move(blacklist_data),
-        base::BindOnce(&OptOutBlacklist::LoadBlackListDone,
+    opt_out_store_->LoadBlockList(
+        std::move(blocklist_data),
+        base::BindOnce(&OptOutBlocklist::LoadBlockListDone,
                        weak_factory_.GetWeakPtr()));
   } else {
-    LoadBlackListDone(std::move(blacklist_data));
+    LoadBlockListDone(std::move(blocklist_data));
   }
 }
 
-base::Time OptOutBlacklist::AddEntry(const std::string& host_name,
+base::Time OptOutBlocklist::AddEntry(const std::string& host_name,
                                      bool opt_out,
                                      int type) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   base::Time now = clock_->Now();
 
-  // If the |blacklist_data| has been loaded from |opt_out_store_|,  synchronous
+  // If the |blocklist_data| has been loaded from |opt_out_store_|,  synchronous
   // operations will be accurate. Otherwise, queue the task to run
   // asynchronously.
   if (loaded_) {
     AddEntrySync(host_name, opt_out, type, now);
   } else {
-    QueuePendingTask(base::BindOnce(&OptOutBlacklist::AddEntrySync,
+    QueuePendingTask(base::BindOnce(&OptOutBlocklist::AddEntrySync,
                                     base::Unretained(this), host_name, opt_out,
                                     type, now));
   }
@@ -97,28 +97,28 @@
   return now;
 }
 
-void OptOutBlacklist::AddEntrySync(const std::string& host_name,
+void OptOutBlocklist::AddEntrySync(const std::string& host_name,
                                    bool opt_out,
                                    int type,
                                    base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(loaded_);
 
-  bool host_was_blacklisted =
-      blacklist_data_->IsHostBlacklisted(host_name, time);
-  bool user_was_blacklisted = blacklist_data_->IsUserOptedOutInGeneral(time);
-  blacklist_data_->AddEntry(host_name, opt_out, type, time, false);
+  bool host_was_blocklisted =
+      blocklist_data_->IsHostBlocklisted(host_name, time);
+  bool user_was_blocklisted = blocklist_data_->IsUserOptedOutInGeneral(time);
+  blocklist_data_->AddEntry(host_name, opt_out, type, time, false);
 
-  if (!host_was_blacklisted &&
-      blacklist_data_->IsHostBlacklisted(host_name, time)) {
-    // Notify |blacklist_delegate_| about a new blacklisted host.
-    blacklist_delegate_->OnNewBlacklistedHost(host_name, time);
+  if (!host_was_blocklisted &&
+      blocklist_data_->IsHostBlocklisted(host_name, time)) {
+    // Notify |blocklist_delegate_| about a new blocklisted host.
+    blocklist_delegate_->OnNewBlocklistedHost(host_name, time);
   }
 
-  if (user_was_blacklisted != blacklist_data_->IsUserOptedOutInGeneral(time)) {
-    // Notify |blacklist_delegate_| about a new blacklisted host.
-    blacklist_delegate_->OnUserBlacklistedStatusChange(
-        blacklist_data_->IsUserOptedOutInGeneral(time));
+  if (user_was_blocklisted != blocklist_data_->IsUserOptedOutInGeneral(time)) {
+    // Notify |blocklist_delegate_| about a new blocklisted host.
+    blocklist_delegate_->OnUserBlocklistedStatusChange(
+        blocklist_data_->IsUserOptedOutInGeneral(time));
   }
 
   if (!opt_out_store_)
@@ -126,96 +126,96 @@
   opt_out_store_->AddEntry(opt_out, host_name, type, time);
 }
 
-BlacklistReason OptOutBlacklist::IsLoadedAndAllowed(
+BlocklistReason OptOutBlocklist::IsLoadedAndAllowed(
     const std::string& host_name,
     int type,
-    bool ignore_long_term_black_list_rules,
-    std::vector<BlacklistReason>* passed_reasons) const {
+    bool ignore_long_term_block_list_rules,
+    std::vector<BlocklistReason>* passed_reasons) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   if (!loaded_)
-    return BlacklistReason::kBlacklistNotLoaded;
-  passed_reasons->push_back(BlacklistReason::kBlacklistNotLoaded);
+    return BlocklistReason::kBlocklistNotLoaded;
+  passed_reasons->push_back(BlocklistReason::kBlocklistNotLoaded);
 
-  return blacklist_data_->IsAllowed(host_name, type,
-                                    ignore_long_term_black_list_rules,
+  return blocklist_data_->IsAllowed(host_name, type,
+                                    ignore_long_term_block_list_rules,
                                     clock_->Now(), passed_reasons);
 }
 
-void OptOutBlacklist::ClearBlackList(base::Time begin_time,
+void OptOutBlocklist::ClearBlockList(base::Time begin_time,
                                      base::Time end_time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK_LE(begin_time, end_time);
-  // If the |blacklist_data| has been loaded from |opt_out_store_|,
+  // If the |blocklist_data| has been loaded from |opt_out_store_|,
   // synchronous operations will be accurate. Otherwise, queue the task to run
   // asynchronously.
   if (loaded_) {
-    ClearBlackListSync(begin_time, end_time);
+    ClearBlockListSync(begin_time, end_time);
   } else {
-    QueuePendingTask(base::BindOnce(&OptOutBlacklist::ClearBlackListSync,
+    QueuePendingTask(base::BindOnce(&OptOutBlocklist::ClearBlockListSync,
                                     base::Unretained(this), begin_time,
                                     end_time));
   }
 }
 
-void OptOutBlacklist::ClearBlackListSync(base::Time begin_time,
+void OptOutBlocklist::ClearBlockListSync(base::Time begin_time,
                                          base::Time end_time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(loaded_);
   DCHECK_LE(begin_time, end_time);
 
   // Clear the in-memory rules entirely.
-  blacklist_data_->ClearData();
+  blocklist_data_->ClearData();
   loaded_ = false;
 
-  // Notify |blacklist_delegate_| that the blacklist is cleared.
-  blacklist_delegate_->OnBlacklistCleared(clock_->Now());
+  // Notify |blocklist_delegate_| that the blocklist is cleared.
+  blocklist_delegate_->OnBlocklistCleared(clock_->Now());
 
-  // Delete relevant entries and reload the blacklist into memory.
+  // Delete relevant entries and reload the blocklist into memory.
   if (opt_out_store_) {
-    opt_out_store_->ClearBlackList(begin_time, end_time);
-    opt_out_store_->LoadBlackList(
-        std::move(blacklist_data_),
-        base::BindOnce(&OptOutBlacklist::LoadBlackListDone,
+    opt_out_store_->ClearBlockList(begin_time, end_time);
+    opt_out_store_->LoadBlockList(
+        std::move(blocklist_data_),
+        base::BindOnce(&OptOutBlocklist::LoadBlockListDone,
                        weak_factory_.GetWeakPtr()));
   } else {
-    LoadBlackListDone(std::move(blacklist_data_));
+    LoadBlockListDone(std::move(blocklist_data_));
   }
 }
 
-void OptOutBlacklist::QueuePendingTask(base::OnceClosure callback) {
+void OptOutBlocklist::QueuePendingTask(base::OnceClosure callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!loaded_);
   DCHECK(!callback.is_null());
   pending_callbacks_.push(std::move(callback));
 }
 
-void OptOutBlacklist::LoadBlackListDone(
-    std::unique_ptr<BlacklistData> blacklist_data) {
+void OptOutBlocklist::LoadBlockListDone(
+    std::unique_ptr<BlocklistData> blocklist_data) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  DCHECK(blacklist_data);
+  DCHECK(blocklist_data);
   DCHECK(!loaded_);
-  DCHECK(!blacklist_data_);
+  DCHECK(!blocklist_data_);
   loaded_ = true;
-  blacklist_data_ = std::move(blacklist_data);
+  blocklist_data_ = std::move(blocklist_data);
 
-  // Notify |blacklist_delegate_| on current user blacklisted status.
-  blacklist_delegate_->OnUserBlacklistedStatusChange(
-      blacklist_data_->IsUserOptedOutInGeneral(clock_->Now()));
+  // Notify |blocklist_delegate_| on current user blocklisted status.
+  blocklist_delegate_->OnUserBlocklistedStatusChange(
+      blocklist_data_->IsUserOptedOutInGeneral(clock_->Now()));
 
-  // Notify the |blacklist_delegate_| on historical blacklisted hosts.
-  for (const auto& entry : blacklist_data_->black_list_item_host_map()) {
-    if (blacklist_data_->IsHostBlacklisted(entry.first, clock_->Now())) {
-      blacklist_delegate_->OnNewBlacklistedHost(
+  // Notify the |blocklist_delegate_| on historical blocklisted hosts.
+  for (const auto& entry : blocklist_data_->block_list_item_host_map()) {
+    if (blocklist_data_->IsHostBlocklisted(entry.first, clock_->Now())) {
+      blocklist_delegate_->OnNewBlocklistedHost(
           entry.first, entry.second.most_recent_opt_out_time().value());
     }
   }
 
-  // Run all pending tasks. |loaded_| may change if ClearBlackList is queued.
+  // Run all pending tasks. |loaded_| may change if ClearBlockList is queued.
   while (pending_callbacks_.size() > 0 && loaded_) {
     std::move(pending_callbacks_.front()).Run();
     pending_callbacks_.pop();
   }
 }
 
-}  // namespace blacklist
+}  // namespace blocklist
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist.h b/components/blacklist/opt_out_blacklist/opt_out_blacklist.h
index c378356..556226d 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist.h
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist.h
@@ -25,35 +25,35 @@
 class Clock;
 }
 
-namespace blacklist {
+namespace blocklist {
 
-class BlacklistData;
-class OptOutBlacklistDelegate;
+class BlocklistData;
+class OptOutBlocklistDelegate;
 class OptOutStore;
 
-class OptOutBlacklist {
+class OptOutBlocklist {
  public:
-  // |opt_out_store| is the backing store to retrieve and store blacklist
+  // |opt_out_store| is the backing store to retrieve and store blocklist
   // information, and can be null. When |opt_out_store| is null, the in-memory
   // data will be immediately loaded to empty. If |opt_out_store| is non-null,
   // it will be used to load the in-memory map asynchronously.
-  // |blacklist_delegate| is a single object listening for blacklist events, and
+  // |blocklist_delegate| is a single object listening for blocklist events, and
   // it is guaranteed to outlive the life time of |this|.
-  OptOutBlacklist(std::unique_ptr<OptOutStore> opt_out_store,
+  OptOutBlocklist(std::unique_ptr<OptOutStore> opt_out_store,
                   base::Clock* clock,
-                  OptOutBlacklistDelegate* blacklist_delegate);
-  virtual ~OptOutBlacklist();
+                  OptOutBlocklistDelegate* blocklist_delegate);
+  virtual ~OptOutBlocklist();
 
-  // Creates the BlacklistData that backs the blacklist.
+  // Creates the BlocklistData that backs the blocklist.
   void Init();
 
-  // Asynchronously deletes all entries in the in-memory blacklist. Informs
+  // Asynchronously deletes all entries in the in-memory blocklist. Informs
   // the backing store to delete entries between |begin_time| and |end_time|,
   // and reloads entries into memory from the backing store. If the embedder
-  // passed in a null store, resets all history in the in-memory blacklist.
-  void ClearBlackList(base::Time begin_time, base::Time end_time);
+  // passed in a null store, resets all history in the in-memory blocklist.
+  void ClearBlockList(base::Time begin_time, base::Time end_time);
 
-  // Asynchronously adds a new navigation to to the in-memory blacklist and
+  // Asynchronously adds a new navigation to to the in-memory blocklist and
   // backing store. |opt_out| is whether the user opted out of the action. If
   // the in memory map has reached the max number of hosts allowed, and
   // |host_name| is a new host, a host will be evicted based on recency of the
@@ -62,47 +62,47 @@
   base::Time AddEntry(const std::string& host_name, bool opt_out, int type);
 
   // Synchronously determines if the action should be allowed for |host_name|
-  // and |type|. Returns the reason the blacklist disallowed the action, or
+  // and |type|. Returns the reason the blocklist disallowed the action, or
   // kAllowed if the action is allowed. Record checked reasons in
-  // |passed_reasons|. |ignore_long_term_black_list_rules| will cause session,
+  // |passed_reasons|. |ignore_long_term_block_list_rules| will cause session,
   // type, and host rules, but the session rule will still be queried.
-  BlacklistReason IsLoadedAndAllowed(
+  BlocklistReason IsLoadedAndAllowed(
       const std::string& host_name,
       int type,
-      bool ignore_long_term_black_list_rules,
-      std::vector<BlacklistReason>* passed_reasons) const;
+      bool ignore_long_term_block_list_rules,
+      std::vector<BlocklistReason>* passed_reasons) const;
 
  protected:
   // Whether the session rule should be enabled. |duration| specifies how long a
-  // user remains blacklisted. |history| specifies how many entries should be
+  // user remains blocklisted. |history| specifies how many entries should be
   // evaluated; |threshold| specifies how many opt outs would cause
-  // blacklisting. I.e., the most recent |history| are looked at and if
+  // blocklisting. I.e., the most recent |history| are looked at and if
   // |threshold| (or more) of them are opt outs, the user is considered
-  // blacklisted unless the most recent opt out was longer than |duration| ago.
+  // blocklisted unless the most recent opt out was longer than |duration| ago.
   // This rule only considers entries within this session (it does not use the
-  // data that was persisted in previous sessions). When the blacklist is
+  // data that was persisted in previous sessions). When the blocklist is
   // cleared, this rule is reset as if it were a new session. Queried in Init().
   virtual bool ShouldUseSessionPolicy(base::TimeDelta* duration,
                                       size_t* history,
                                       int* threshold) const = 0;
 
   // Whether the persistent rule should be enabled. |duration| specifies how
-  // long a user remains blacklisted. |history| specifies how many entries
+  // long a user remains blocklisted. |history| specifies how many entries
   // should be evaluated; |threshold| specifies how many opt outs would cause
-  // blacklisting. I.e., the most recent |history| are looked at and if
+  // blocklisting. I.e., the most recent |history| are looked at and if
   // |threshold| (or more) of them are opt outs, the user is considered
-  // blacklisted unless the most recent opt out was longer than |duration| ago.
+  // blocklisted unless the most recent opt out was longer than |duration| ago.
   // Queried in Init().
   virtual bool ShouldUsePersistentPolicy(base::TimeDelta* duration,
                                          size_t* history,
                                          int* threshold) const = 0;
 
   // Whether the host rule should be enabled. |duration| specifies how long a
-  // host remains blacklisted. |history| specifies how many entries should be
+  // host remains blocklisted. |history| specifies how many entries should be
   // evaluated per host; |threshold| specifies how many opt outs would cause
-  // blacklisting. I.e., the most recent |history| entries per host are looked
+  // blocklisting. I.e., the most recent |history| entries per host are looked
   // at and if |threshold| (or more) of them are opt outs, the host is
-  // considered blacklisted unless the most recent opt out was longer than
+  // considered blocklisted unless the most recent opt out was longer than
   // |duration| ago. |max_hosts| will limit the number of hosts stored in this
   // class when non-zero.
   // Queried in Init().
@@ -112,22 +112,22 @@
                                    size_t* max_hosts) const = 0;
 
   // Whether the type rule should be enabled.  |duration| specifies how long a
-  // type remains blacklisted. |history| specifies how many entries should be
+  // type remains blocklisted. |history| specifies how many entries should be
   // evaluated per type; |threshold| specifies how many opt outs would cause
-  // blacklisting.
+  // blocklisting.
   // I.e., the most recent |history| entries per type are looked at and if
   // |threshold| (or more) of them are opt outs, the type is considered
-  // blacklisted unless the most recent opt out was longer than |duration| ago.
+  // blocklisted unless the most recent opt out was longer than |duration| ago.
   // Queried in Init().
   virtual bool ShouldUseTypePolicy(base::TimeDelta* duration,
                                    size_t* history,
                                    int* threshold) const = 0;
 
   // The allowed types and what version they are. Should be empty unless the
-  // caller will not be using the blacklist in the session. It is used to remove
+  // caller will not be using the blocklist in the session. It is used to remove
   // stale entries from the database and to DCHECK that other methods are not
   // using disallowed types. Queried in Init().
-  virtual BlacklistData::AllowedTypesAndVersions GetAllowedTypes() const = 0;
+  virtual BlocklistData::AllowedTypesAndVersions GetAllowedTypes() const = 0;
 
  private:
   // Synchronous version of AddEntry method. |time| is the time
@@ -138,27 +138,27 @@
                     int type,
                     base::Time time);
 
-  // Synchronous version of ClearBlackList method.
-  void ClearBlackListSync(base::Time begin_time, base::Time end_time);
+  // Synchronous version of ClearBlockList method.
+  void ClearBlockListSync(base::Time begin_time, base::Time end_time);
 
-  // Callback passed to the backing store when loading black list information.
-  // Takes ownership of |blacklist_data|.
-  void LoadBlackListDone(std::unique_ptr<BlacklistData> blacklist_data);
+  // Callback passed to the backing store when loading block list information.
+  // Takes ownership of |blocklist_data|.
+  void LoadBlockListDone(std::unique_ptr<BlocklistData> blocklist_data);
 
-  // Called while waiting for the blacklist to be loaded from the backing
+  // Called while waiting for the blocklist to be loaded from the backing
   // store.
-  // Enqueues a task to run when when loading blacklist information has
+  // Enqueues a task to run when when loading blocklist information has
   // completed. Maintains the order that tasks were called in.
   void QueuePendingTask(base::OnceClosure callback);
 
-  // An in-memory representation of the various rules of the blacklist. This is
+  // An in-memory representation of the various rules of the blocklist. This is
   // null while reading from the backing store.
-  std::unique_ptr<BlacklistData> blacklist_data_;
+  std::unique_ptr<BlocklistData> blocklist_data_;
 
-  // Whether the blacklist is done being loaded from the backing store.
+  // Whether the blocklist is done being loaded from the backing store.
   bool loaded_;
 
-  // The backing store of the blacklist information.
+  // The backing store of the blocklist information.
   std::unique_ptr<OptOutStore> opt_out_store_;
 
   // Callbacks to be run after loading information from the backing store has
@@ -167,17 +167,17 @@
 
   base::Clock* clock_;
 
-  // The delegate listening to this blacklist. |blacklist_delegate_| lifetime is
+  // The delegate listening to this blocklist. |blocklist_delegate_| lifetime is
   // guaranteed to outlive |this|.
-  OptOutBlacklistDelegate* blacklist_delegate_;
+  OptOutBlocklistDelegate* blocklist_delegate_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 
-  base::WeakPtrFactory<OptOutBlacklist> weak_factory_{this};
+  base::WeakPtrFactory<OptOutBlocklist> weak_factory_{this};
 
-  DISALLOW_COPY_AND_ASSIGN(OptOutBlacklist);
+  DISALLOW_COPY_AND_ASSIGN(OptOutBlocklist);
 };
 
-}  // namespace blacklist
+}  // namespace blocklist
 
 #endif  // COMPONENTS_BLACKLIST_OPT_OUT_BLACKLIST_OPT_OUT_BLACKLIST_H_
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc b/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc
index d6577ca..86390e7 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.cc
@@ -6,9 +6,9 @@
 
 #include "base/memory/ptr_util.h"
 
-namespace blacklist {
+namespace blocklist {
 
-BlacklistData::BlacklistData(std::unique_ptr<Policy> session_policy,
+BlocklistData::BlocklistData(std::unique_ptr<Policy> session_policy,
                              std::unique_ptr<Policy> persistent_policy,
                              std::unique_ptr<Policy> host_policy,
                              std::unique_ptr<Policy> type_policy,
@@ -22,46 +22,46 @@
       allowed_types_(std::move(allowed_types)) {
   DCHECK_GE(100u, max_hosts);
 }
-BlacklistData::~BlacklistData() {}
+BlocklistData::~BlocklistData() = default;
 
-void BlacklistData::ClearData() {
-  session_black_list_item_.reset();
-  persistent_black_list_item_.reset();
-  black_list_item_host_map_.clear();
-  black_list_item_type_map_.clear();
+void BlocklistData::ClearData() {
+  session_block_list_item_.reset();
+  persistent_block_list_item_.reset();
+  block_list_item_host_map_.clear();
+  block_list_item_type_map_.clear();
 }
 
-void BlacklistData::AddEntry(const std::string& host_name,
+void BlocklistData::AddEntry(const std::string& host_name,
                              bool opt_out,
                              int type,
                              base::Time time,
                              bool is_from_persistent_storage) {
   // Add to the session based rule if it is enabled.
   if (session_policy_ && !is_from_persistent_storage) {
-    if (!session_black_list_item_) {
-      session_black_list_item_ = std::make_unique<OptOutBlacklistItem>(
+    if (!session_block_list_item_) {
+      session_block_list_item_ = std::make_unique<OptOutBlocklistItem>(
           session_policy_->history, session_policy_->threshold,
           session_policy_->duration);
     }
-    session_black_list_item_->AddEntry(opt_out, time);
+    session_block_list_item_->AddEntry(opt_out, time);
   }
 
   // Add to the persistent rule if it is enabled.
   if (persistent_policy_) {
-    if (!persistent_black_list_item_) {
-      persistent_black_list_item_ = std::make_unique<OptOutBlacklistItem>(
+    if (!persistent_block_list_item_) {
+      persistent_block_list_item_ = std::make_unique<OptOutBlocklistItem>(
           persistent_policy_->history, persistent_policy_->threshold,
           persistent_policy_->duration);
     }
-    persistent_black_list_item_->AddEntry(opt_out, time);
+    persistent_block_list_item_->AddEntry(opt_out, time);
   }
 
   // Add to the host rule if it is enabled. Remove hosts if there are more than
   // |max_hosts_| in the map.
   if (host_policy_) {
-    auto item = black_list_item_host_map_.find(host_name);
-    if (item == black_list_item_host_map_.end()) {
-      auto value = black_list_item_host_map_.emplace(
+    auto item = block_list_item_host_map_.find(host_name);
+    if (item == block_list_item_host_map_.end()) {
+      auto value = block_list_item_host_map_.emplace(
           std::piecewise_construct, std::forward_as_tuple(host_name),
           std::forward_as_tuple(host_policy_->history, host_policy_->threshold,
                                 host_policy_->duration));
@@ -69,14 +69,14 @@
       item = value.first;
     }
     item->second.AddEntry(opt_out, time);
-    if (max_hosts_ > 0 && black_list_item_host_map_.size() > max_hosts_)
+    if (max_hosts_ > 0 && block_list_item_host_map_.size() > max_hosts_)
       EvictOldestHost();
   }
 
   if (type_policy_) {
-    auto item = black_list_item_type_map_.find(type);
-    if (item == black_list_item_type_map_.end()) {
-      auto value = black_list_item_type_map_.emplace(
+    auto item = block_list_item_type_map_.find(type);
+    if (item == block_list_item_type_map_.end()) {
+      auto value = block_list_item_type_map_.emplace(
           std::piecewise_construct, std::forward_as_tuple(type),
           std::forward_as_tuple(type_policy_->history, type_policy_->threshold,
                                 type_policy_->duration));
@@ -87,38 +87,38 @@
   }
 }
 
-BlacklistReason BlacklistData::IsAllowed(
+BlocklistReason BlocklistData::IsAllowed(
     const std::string& host_name,
     int type,
-    bool ignore_long_term_black_list_rules,
+    bool ignore_long_term_block_list_rules,
     base::Time time,
-    std::vector<BlacklistReason>* passed_reasons) const {
+    std::vector<BlocklistReason>* passed_reasons) const {
   // Check the session rule.
   if (session_policy_) {
-    if (session_black_list_item_ &&
-        session_black_list_item_->IsBlackListed(time)) {
-      return BlacklistReason::kUserOptedOutInSession;
+    if (session_block_list_item_ &&
+        session_block_list_item_->IsBlockListed(time)) {
+      return BlocklistReason::kUserOptedOutInSession;
     }
-    passed_reasons->push_back(BlacklistReason::kUserOptedOutInSession);
+    passed_reasons->push_back(BlocklistReason::kUserOptedOutInSession);
   }
 
   // Check whether the persistent rules should be checked this time.
-  if (ignore_long_term_black_list_rules)
-    return BlacklistReason::kAllowed;
+  if (ignore_long_term_block_list_rules)
+    return BlocklistReason::kAllowed;
 
   // Check the persistent rule.
   if (persistent_policy_) {
     if (IsUserOptedOutInGeneral(time)) {
-      return BlacklistReason::kUserOptedOutInGeneral;
+      return BlocklistReason::kUserOptedOutInGeneral;
     }
-    passed_reasons->push_back(BlacklistReason::kUserOptedOutInGeneral);
+    passed_reasons->push_back(BlocklistReason::kUserOptedOutInGeneral);
   }
 
   // Check the host rule.
   if (host_policy_) {
-    if (IsHostBlacklisted(host_name, time))
-      return BlacklistReason::kUserOptedOutOfHost;
-    passed_reasons->push_back(BlacklistReason::kUserOptedOutOfHost);
+    if (IsHostBlocklisted(host_name, time))
+      return BlocklistReason::kUserOptedOutOfHost;
+    passed_reasons->push_back(BlocklistReason::kUserOptedOutOfHost);
   }
 
   // Only allowed types should be recorded.
@@ -126,22 +126,22 @@
 
   // Check the type rule.
   if (type_policy_) {
-    auto item = black_list_item_type_map_.find(type);
-    if (item != black_list_item_type_map_.end() &&
-        item->second.IsBlackListed(time)) {
-      return BlacklistReason::kUserOptedOutOfType;
+    auto item = block_list_item_type_map_.find(type);
+    if (item != block_list_item_type_map_.end() &&
+        item->second.IsBlockListed(time)) {
+      return BlocklistReason::kUserOptedOutOfType;
     }
-    passed_reasons->push_back(BlacklistReason::kUserOptedOutOfType);
+    passed_reasons->push_back(BlocklistReason::kUserOptedOutOfType);
   }
 
-  return BlacklistReason::kAllowed;
+  return BlocklistReason::kAllowed;
 }
 
-void BlacklistData::EvictOldestHost() {
-  DCHECK_LT(max_hosts_, black_list_item_host_map_.size());
+void BlocklistData::EvictOldestHost() {
+  DCHECK_LT(max_hosts_, block_list_item_host_map_.size());
   base::Optional<base::Time> oldest_opt_out;
   std::string key_to_delete;
-  for (auto& item : black_list_item_host_map_) {
+  for (auto& item : block_list_item_host_map_) {
     base::Optional<base::Time> most_recent_opt_out =
         item.second.most_recent_opt_out_time();
     if (!most_recent_opt_out) {
@@ -155,19 +155,19 @@
       key_to_delete = item.first;
     }
   }
-  black_list_item_host_map_.erase(key_to_delete);
+  block_list_item_host_map_.erase(key_to_delete);
 }
 
-bool BlacklistData::IsHostBlacklisted(const std::string& host_name,
+bool BlocklistData::IsHostBlocklisted(const std::string& host_name,
                                       base::Time time) const {
-  auto item = black_list_item_host_map_.find(host_name);
-  return item != black_list_item_host_map_.end() &&
-         item->second.IsBlackListed(time);
+  auto item = block_list_item_host_map_.find(host_name);
+  return item != block_list_item_host_map_.end() &&
+         item->second.IsBlockListed(time);
 }
 
-bool BlacklistData::IsUserOptedOutInGeneral(base::Time time) const {
-  return persistent_black_list_item_ &&
-         persistent_black_list_item_->IsBlackListed(time);
+bool BlocklistData::IsUserOptedOutInGeneral(base::Time time) const {
+  return persistent_block_list_item_ &&
+         persistent_block_list_item_->IsBlockListed(time);
 }
 
-}  // namespace blacklist
+}  // namespace blocklist
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h b/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h
index 5740d793..4ae7ad03 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h
@@ -17,15 +17,15 @@
 #include "base/time/time.h"
 #include "components/blacklist/opt_out_blacklist/opt_out_blacklist_item.h"
 
-namespace blacklist {
+namespace blocklist {
 
-// The various reasons the Blacklist may tell that the user is blacklisted.
+// The various reasons the Blocklist may tell that the user is blocklisted.
 // This should remain synchronized with enums.xml
-enum class BlacklistReason {
-  // The blacklist may not be loaded very early in the session or when the user
-  // has cleared the blacklist history (usually by clearing their browsing
+enum class BlocklistReason {
+  // The blocklist may not be loaded very early in the session or when the user
+  // has cleared the blocklist history (usually by clearing their browsing
   // history).
-  kBlacklistNotLoaded = 0,
+  kBlocklistNotLoaded = 0,
   kUserOptedOutInSession = 1,
   kUserOptedOutInGeneral = 2,
   kUserOptedOutOfHost = 3,
@@ -37,21 +37,21 @@
 
 // This class describes all of the data used to determine whether an action is
 // allowed based on four possible rules: Session: if the user has opted out
-// of j of the last k entries this session, the action will be blacklisted for a
+// of j of the last k entries this session, the action will be blocklisted for a
 // set duration. Persistent: if the user has opted out of j of the last k
-// entries, the action will be blacklisted for a set duration. Host: if the user
+// entries, the action will be blocklisted for a set duration. Host: if the user
 // has opted out of threshold of the last history entries for a specific host,
-// the action will be blacklisted for a set duration. Type: if the user has
+// the action will be blocklisted for a set duration. Type: if the user has
 // opted out of j of the last k entries for a specific type, the action will be
-// blacklisted for a set duration. This is the in-memory version of the black
+// blocklisted for a set duration. This is the in-memory version of the block
 // list policy. This object is moved from the embedder thread to a background
 // thread, It is not safe to access concurrently on two threads.
-class BlacklistData {
+class BlocklistData {
  public:
-  // A struct describing the general blacklisting pattern used by all of the
-  // blacklisting rules.
+  // A struct describing the general blocklisting pattern used by all of the
+  // blocklisting rules.
   // The most recent |history| entries are looked at and if |threshold| (or
-  // more) of them are opt outs, new actions are considered blacklisted unless
+  // more) of them are opt outs, new actions are considered blocklisted unless
   // the most recent opt out was longer than |duration| ago.
   struct Policy {
     Policy(base::TimeDelta duration, size_t history, int threshold)
@@ -59,16 +59,16 @@
 
     ~Policy() = default;
 
-    // Specifies how long the blacklisting rule lasts after the most recent opt
+    // Specifies how long the blocklisting rule lasts after the most recent opt
     // out.
     const base::TimeDelta duration;
     // Amount of entries evaluated for the rule.
     const size_t history;
-    // The number of opt outs that will trigger blacklisting for the rule.
+    // The number of opt outs that will trigger blocklisting for the rule.
     const int threshold;
   };
 
-  // A map of types that are allowed to be used in the blacklist as well as the
+  // A map of types that are allowed to be used in the blocklist as well as the
   // version that those types are in. Versioning allows removals from persistent
   // memory at session start.
   using AllowedTypesAndVersions = std::map<int, int>;
@@ -83,15 +83,15 @@
   // memory. |allowed_types| contains the action types that are allowed in the
   // session and their corresponding versions. Conversioning is used to clear
   // stale data from the persistent storage.
-  BlacklistData(std::unique_ptr<Policy> session_policy,
+  BlocklistData(std::unique_ptr<Policy> session_policy,
                 std::unique_ptr<Policy> persistent_policy,
                 std::unique_ptr<Policy> host_policy,
                 std::unique_ptr<Policy> type_policy,
                 size_t max_hosts,
                 AllowedTypesAndVersions allowed_types);
-  ~BlacklistData();
+  ~BlocklistData();
 
-  // Adds a new entry for all rules to use when evaluating blacklisting state.
+  // Adds a new entry for all rules to use when evaluating blocklisting state.
   // |is_from_persistent_storage| is used to delineate between data added from
   // this session, and previous sessions.
   void AddEntry(const std::string& host_name,
@@ -101,15 +101,15 @@
                 bool is_from_persistent_storage);
 
   // Whether the user is opted out when considering all enabled rules. if
-  // |ignore_long_term_black_list_rules| is true, this will only check the
+  // |ignore_long_term_block_list_rules| is true, this will only check the
   // session rule. For every reason that is checked, but does not trigger
-  // blacklisting, a new reason will be appended to the end |passed_reasons|.
+  // blocklisting, a new reason will be appended to the end |passed_reasons|.
   // |time| is the time that decision should be evaluated at (usually now).
-  BlacklistReason IsAllowed(const std::string& host_name,
+  BlocklistReason IsAllowed(const std::string& host_name,
                             int type,
-                            bool ignore_long_term_black_list_rules,
+                            bool ignore_long_term_block_list_rules,
                             base::Time time,
-                            std::vector<BlacklistReason>* passed_reasons) const;
+                            std::vector<BlocklistReason>* passed_reasons) const;
 
   // This clears all data in all rules.
   void ClearData();
@@ -121,22 +121,22 @@
     return allowed_types_;
   }
 
-  // Whether the specific |host_name| is blacklisted based only on the host
+  // Whether the specific |host_name| is blocklisted based only on the host
   // rule.
-  bool IsHostBlacklisted(const std::string& host_name, base::Time time) const;
+  bool IsHostBlocklisted(const std::string& host_name, base::Time time) const;
 
-  // Whether the user is opted out based solely on the persistent blacklist
+  // Whether the user is opted out based solely on the persistent blocklist
   // rule.
   bool IsUserOptedOutInGeneral(base::Time time) const;
 
   // Exposed for logging purposes only.
-  const std::map<std::string, OptOutBlacklistItem>& black_list_item_host_map()
+  const std::map<std::string, OptOutBlocklistItem>& block_list_item_host_map()
       const {
-    return black_list_item_host_map_;
+    return block_list_item_host_map_;
   }
 
  private:
-  // Removes the oldest (or safest) host item from |black_list_item_host_map_|.
+  // Removes the oldest (or safest) host item from |block_list_item_host_map_|.
   // Oldest is defined by most recent opt out time, and safest is defined as an
   // item with no opt outs.
   void EvictOldestHost();
@@ -144,33 +144,33 @@
   // The session rule policy. If non-null the session rule is enforced.
   std::unique_ptr<Policy> session_policy_;
   // The session rule history.
-  std::unique_ptr<OptOutBlacklistItem> session_black_list_item_;
+  std::unique_ptr<OptOutBlocklistItem> session_block_list_item_;
 
   // The persistent rule policy. If non-null the persistent rule is enforced.
   std::unique_ptr<Policy> persistent_policy_;
   // The persistent rule history.
-  std::unique_ptr<OptOutBlacklistItem> persistent_black_list_item_;
+  std::unique_ptr<OptOutBlocklistItem> persistent_block_list_item_;
 
   // The host rule policy. If non-null the host rule is enforced.
   std::unique_ptr<Policy> host_policy_;
-  // The maximum number of hosts allowed in the host blacklist.
+  // The maximum number of hosts allowed in the host blocklist.
   size_t max_hosts_;
-  // The host rule history. Each host is stored as a separate blacklist history.
-  std::map<std::string, OptOutBlacklistItem> black_list_item_host_map_;
+  // The host rule history. Each host is stored as a separate blocklist history.
+  std::map<std::string, OptOutBlocklistItem> block_list_item_host_map_;
 
   // The type rule policy. If non-null the type rule is enforced.
   std::unique_ptr<Policy> type_policy_;
-  // The type rule history. Each type is stored as a separate blacklist history.
-  std::map<int, OptOutBlacklistItem> black_list_item_type_map_;
+  // The type rule history. Each type is stored as a separate blocklist history.
+  std::map<int, OptOutBlocklistItem> block_list_item_type_map_;
 
   // The allowed types and what version they are. If it is non-empty, it is used
   // to remove stale entries from the database and to DCHECK that other methods
   // are not using disallowed types.
   AllowedTypesAndVersions allowed_types_;
 
-  DISALLOW_COPY_AND_ASSIGN(BlacklistData);
+  DISALLOW_COPY_AND_ASSIGN(BlocklistData);
 };
 
-}  // namespace blacklist
+}  // namespace blocklist
 
 #endif  // COMPONENTS_BLACKLIST_OPT_OUT_BLACKLIST_OPT_OUT_BLACKLIST_DATA_H_
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h b/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h
index d1e6b6c1..1047a40 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist_delegate.h
@@ -10,29 +10,29 @@
 #include "base/macros.h"
 #include "base/time/time.h"
 
-namespace blacklist {
+namespace blocklist {
 
-// An interface for a delegate to the opt out blacklist. This interface is for
-// responding to events occurring in the opt out blacklist (e.g. New blacklisted
-// host and user is blacklisted).
-class OptOutBlacklistDelegate {
+// An interface for a delegate to the opt out blocklist. This interface is for
+// responding to events occurring in the opt out blocklist (e.g. New blocklisted
+// host and user is blocklisted).
+class OptOutBlocklistDelegate {
  public:
-  OptOutBlacklistDelegate() {}
-  virtual ~OptOutBlacklistDelegate() {}
+  OptOutBlocklistDelegate() = default;
+  virtual ~OptOutBlocklistDelegate() = default;
 
-  // Notifies |this| that |host| has been blacklisted at |time|. This method is
-  // guaranteed to be called when a previously whitelisted host is now
-  // blacklisted.
-  virtual void OnNewBlacklistedHost(const std::string& host, base::Time time) {}
+  // Notifies |this| that |host| has been blocklisted at |time|. This method is
+  // guaranteed to be called when a previously allowlisted host is now
+  // blocklisted.
+  virtual void OnNewBlocklistedHost(const std::string& host, base::Time time) {}
 
-  // Notifies |this| that the user blacklisted has changed, and it is
-  // guaranteed to be called when the user blacklisted status is changed.
-  virtual void OnUserBlacklistedStatusChange(bool blacklisted) {}
+  // Notifies |this| that the user blocklisted has changed, and it is
+  // guaranteed to be called when the user blocklisted status is changed.
+  virtual void OnUserBlocklistedStatusChange(bool blocklisted) {}
 
-  // Notifies |this| that the blacklist is cleared at |time|.
-  virtual void OnBlacklistCleared(base::Time time) {}
+  // Notifies |this| that the blocklist is cleared at |time|.
+  virtual void OnBlocklistCleared(base::Time time) {}
 };
 
-}  // namespace blacklist
+}  // namespace blocklist
 
 #endif  // COMPONENTS_BLACKLIST_OPT_OUT_BLACKLIST_OPT_OUT_BLACKLIST_DELEGATE_H_
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.cc b/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.cc
index c59d4a8..57c6051 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.cc
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.cc
@@ -9,37 +9,37 @@
 
 #include "components/blacklist/opt_out_blacklist/opt_out_store.h"
 
-namespace blacklist {
+namespace blocklist {
 
-OptOutBlacklistItem::OptOutRecord::OptOutRecord(base::Time entry_time,
+OptOutBlocklistItem::OptOutRecord::OptOutRecord(base::Time entry_time,
                                                 bool opt_out)
     : entry_time_(entry_time), opt_out_(opt_out) {}
 
-OptOutBlacklistItem::OptOutRecord::~OptOutRecord() {}
+OptOutBlocklistItem::OptOutRecord::~OptOutRecord() = default;
 
-OptOutBlacklistItem::OptOutRecord::OptOutRecord(OptOutRecord&&) noexcept =
+OptOutBlocklistItem::OptOutRecord::OptOutRecord(OptOutRecord&&) noexcept =
     default;
-OptOutBlacklistItem::OptOutRecord& OptOutBlacklistItem::OptOutRecord::operator=(
+OptOutBlocklistItem::OptOutRecord& OptOutBlocklistItem::OptOutRecord::operator=(
     OptOutRecord&&) noexcept = default;
 
-bool OptOutBlacklistItem::OptOutRecord::operator<(
+bool OptOutBlocklistItem::OptOutRecord::operator<(
     const OptOutRecord& other) const {
   // Fresher entries are lower priority to evict, as are non-opt-outs.
   return std::tie(entry_time_, opt_out_) >
          std::tie(other.entry_time_, other.opt_out_);
 }
 
-OptOutBlacklistItem::OptOutBlacklistItem(size_t stored_history_length,
-                                         int opt_out_black_list_threshold,
-                                         base::TimeDelta black_list_duration)
+OptOutBlocklistItem::OptOutBlocklistItem(size_t stored_history_length,
+                                         int opt_out_block_list_threshold,
+                                         base::TimeDelta block_list_duration)
     : max_stored_history_length_(stored_history_length),
-      opt_out_black_list_threshold_(opt_out_black_list_threshold),
-      max_black_list_duration_(black_list_duration),
+      opt_out_block_list_threshold_(opt_out_block_list_threshold),
+      max_block_list_duration_(block_list_duration),
       total_opt_out_(0) {}
 
-OptOutBlacklistItem::~OptOutBlacklistItem() {}
+OptOutBlocklistItem::~OptOutBlocklistItem() = default;
 
-void OptOutBlacklistItem::AddEntry(bool opt_out, base::Time entry_time) {
+void OptOutBlocklistItem::AddEntry(bool opt_out, base::Time entry_time) {
   DCHECK_LE(opt_out_records_.size(), max_stored_history_length_);
 
   opt_out_records_.emplace(entry_time, opt_out);
@@ -60,15 +60,15 @@
   DCHECK_LE(opt_out_records_.size(), max_stored_history_length_);
 }
 
-bool OptOutBlacklistItem::IsBlackListed(base::Time now) const {
+bool OptOutBlocklistItem::IsBlockListed(base::Time now) const {
   DCHECK_LE(opt_out_records_.size(), max_stored_history_length_);
   return most_recent_opt_out_time_ &&
-         now - most_recent_opt_out_time_.value() < max_black_list_duration_ &&
-         total_opt_out_ >= opt_out_black_list_threshold_;
+         now - most_recent_opt_out_time_.value() < max_block_list_duration_ &&
+         total_opt_out_ >= opt_out_block_list_threshold_;
 }
 
-size_t OptOutBlacklistItem::OptOutRecordsSizeForTesting() const {
+size_t OptOutBlocklistItem::OptOutRecordsSizeForTesting() const {
   return opt_out_records_.size();
 }
 
-}  // namespace blacklist
+}  // namespace blocklist
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.h b/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.h
index beaf434a..b0f26f0 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.h
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist_item.h
@@ -17,27 +17,27 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 
-namespace blacklist {
+namespace blocklist {
 
-// Stores the recent black list history for a single host. Stores
+// Stores the recent block list history for a single host. Stores
 // |stored_history_length| of the most recent actions. To determine action
-// eligibility fewer than |opt_out_black_list_threshold| out of the past
-// |stored_history_length| navigations must be opt outs. |black_list_duration|
-// is the amount of time that elapses until the host is no longer on the black
+// eligibility fewer than |opt_out_block_list_threshold| out of the past
+// |stored_history_length| navigations must be opt outs. |block_list_duration|
+// is the amount of time that elapses until the host is no longer on the block
 // list.
-class OptOutBlacklistItem {
+class OptOutBlocklistItem {
  public:
-  OptOutBlacklistItem(size_t stored_history_length,
-                      int opt_out_black_list_threshold,
-                      base::TimeDelta black_list_duration);
+  OptOutBlocklistItem(size_t stored_history_length,
+                      int opt_out_block_list_threshold,
+                      base::TimeDelta block_list_duration);
 
-  ~OptOutBlacklistItem();
+  ~OptOutBlocklistItem();
 
   // Adds a new navigation at the specified |entry_time|.
   void AddEntry(bool opt_out, base::Time entry_time);
 
   // Whether the action corresponding to |this| should be disallowed.
-  bool IsBlackListed(base::Time now) const;
+  bool IsBlockListed(base::Time now) const;
 
   base::Optional<base::Time> most_recent_opt_out_time() const {
     return most_recent_opt_out_time_;
@@ -75,10 +75,10 @@
 
   // The number of entries to store to determine action eligibility.
   const size_t max_stored_history_length_;
-  // The number opt outs in recent history that will trigger blacklisting.
-  const int opt_out_black_list_threshold_;
-  // The amount of time to black list a domain after the most recent opt out.
-  const base::TimeDelta max_black_list_duration_;
+  // The number opt outs in recent history that will trigger blocklisting.
+  const int opt_out_block_list_threshold_;
+  // The amount of time to block list a domain after the most recent opt out.
+  const base::TimeDelta max_block_list_duration_;
 
   // The |max_stored_history_length_| most recent action. Is maintained as a
   // priority queue that has high priority for items that should be evicted
@@ -91,9 +91,9 @@
   // The total number of opt outs currently in |opt_out_records_|.
   int total_opt_out_;
 
-  DISALLOW_COPY_AND_ASSIGN(OptOutBlacklistItem);
+  DISALLOW_COPY_AND_ASSIGN(OptOutBlocklistItem);
 };
 
-}  // namespace blacklist
+}  // namespace blocklist
 
 #endif  // COMPONENTS_BLACKLIST_OPT_OUT_BLACKLIST_OPT_OUT_BLACKLIST_ITEM_H_
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist_item_unittest.cc b/components/blacklist/opt_out_blacklist/opt_out_blacklist_item_unittest.cc
index eec8091..4f09c1ad43 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist_item_unittest.cc
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist_item_unittest.cc
@@ -12,69 +12,69 @@
 
 namespace {
 
-using OptOutBlacklistItemTest = testing::Test;
+using OptOutBlocklistItemTest = testing::Test;
 
 }  // namespace
 
-namespace blacklist {
+namespace blocklist {
 
-TEST_F(OptOutBlacklistItemTest, BlackListState) {
+TEST_F(OptOutBlocklistItemTest, BlockListState) {
   const int history = 4;
   const int threshold = 2;
-  const base::TimeDelta max_blacklist_duration =
+  const base::TimeDelta max_blocklist_duration =
       base::TimeDelta::FromSeconds(30);
   const base::Time now = base::Time::UnixEpoch();
   const base::TimeDelta delay_between_entries = base::TimeDelta::FromSeconds(1);
   const base::Time later =
-      now + max_blacklist_duration + (delay_between_entries * 3);
+      now + max_blocklist_duration + (delay_between_entries * 3);
 
-  OptOutBlacklistItem black_list_item(history, threshold,
-                                      max_blacklist_duration);
+  OptOutBlocklistItem block_list_item(history, threshold,
+                                      max_blocklist_duration);
 
-  // Empty black list item should report that the host is allowed.
-  EXPECT_FALSE(black_list_item.IsBlackListed(now));
-  EXPECT_FALSE(black_list_item.IsBlackListed(later));
+  // Empty block list item should report that the host is allowed.
+  EXPECT_FALSE(block_list_item.IsBlockListed(now));
+  EXPECT_FALSE(block_list_item.IsBlockListed(later));
 
-  EXPECT_FALSE(black_list_item.most_recent_opt_out_time());
-  black_list_item.AddEntry(false, now);
-  EXPECT_FALSE(black_list_item.most_recent_opt_out_time());
+  EXPECT_FALSE(block_list_item.most_recent_opt_out_time());
+  block_list_item.AddEntry(false, now);
+  EXPECT_FALSE(block_list_item.most_recent_opt_out_time());
 
-  black_list_item.AddEntry(true, now);
-  EXPECT_TRUE(black_list_item.most_recent_opt_out_time());
-  EXPECT_EQ(now, black_list_item.most_recent_opt_out_time().value());
-  // Black list item of size less that |threshold| should report that the host
+  block_list_item.AddEntry(true, now);
+  EXPECT_TRUE(block_list_item.most_recent_opt_out_time());
+  EXPECT_EQ(now, block_list_item.most_recent_opt_out_time().value());
+  // Block list item of size less that |threshold| should report that the host
   // is allowed.
-  EXPECT_FALSE(black_list_item.IsBlackListed(now));
-  EXPECT_FALSE(black_list_item.IsBlackListed(later));
+  EXPECT_FALSE(block_list_item.IsBlockListed(now));
+  EXPECT_FALSE(block_list_item.IsBlockListed(later));
 
-  black_list_item.AddEntry(true, now + delay_between_entries);
-  // Black list item with |threshold| fresh entries should report the host as
+  block_list_item.AddEntry(true, now + delay_between_entries);
+  // Block list item with |threshold| fresh entries should report the host as
   // disallowed.
-  EXPECT_TRUE(black_list_item.IsBlackListed(now));
-  // Black list item with only entries from longer than |duration| ago should
+  EXPECT_TRUE(block_list_item.IsBlockListed(now));
+  // Block list item with only entries from longer than |duration| ago should
   // report the host is allowed.
-  EXPECT_FALSE(black_list_item.IsBlackListed(later));
-  black_list_item.AddEntry(true, later - (delay_between_entries * 2));
-  // Black list item with a fresh opt out and total number of opt outs larger
+  EXPECT_FALSE(block_list_item.IsBlockListed(later));
+  block_list_item.AddEntry(true, later - (delay_between_entries * 2));
+  // Block list item with a fresh opt out and total number of opt outs larger
   // than |threshold| should report the host is disallowed.
-  EXPECT_TRUE(black_list_item.IsBlackListed(later));
+  EXPECT_TRUE(block_list_item.IsBlockListed(later));
 
-  // The black list item should maintain entries based on time, so adding
+  // The block list item should maintain entries based on time, so adding
   // |history| entries should not push out newer entries.
-  black_list_item.AddEntry(true, later - delay_between_entries * 2);
-  black_list_item.AddEntry(false, later - delay_between_entries * 3);
-  black_list_item.AddEntry(false, later - delay_between_entries * 3);
-  black_list_item.AddEntry(false, later - delay_between_entries * 3);
-  black_list_item.AddEntry(false, later - delay_between_entries * 3);
-  EXPECT_TRUE(black_list_item.IsBlackListed(later));
+  block_list_item.AddEntry(true, later - delay_between_entries * 2);
+  block_list_item.AddEntry(false, later - delay_between_entries * 3);
+  block_list_item.AddEntry(false, later - delay_between_entries * 3);
+  block_list_item.AddEntry(false, later - delay_between_entries * 3);
+  block_list_item.AddEntry(false, later - delay_between_entries * 3);
+  EXPECT_TRUE(block_list_item.IsBlockListed(later));
 
-  // The black list item should maintain entries based on time, so adding
+  // The block list item should maintain entries based on time, so adding
   // |history| newer entries should push out older entries.
-  black_list_item.AddEntry(false, later - delay_between_entries * 1);
-  black_list_item.AddEntry(false, later - delay_between_entries * 1);
-  black_list_item.AddEntry(false, later - delay_between_entries * 1);
-  black_list_item.AddEntry(false, later - delay_between_entries * 1);
-  EXPECT_FALSE(black_list_item.IsBlackListed(later));
+  block_list_item.AddEntry(false, later - delay_between_entries * 1);
+  block_list_item.AddEntry(false, later - delay_between_entries * 1);
+  block_list_item.AddEntry(false, later - delay_between_entries * 1);
+  block_list_item.AddEntry(false, later - delay_between_entries * 1);
+  EXPECT_FALSE(block_list_item.IsBlockListed(later));
 }
 
-}  // namespace blacklist
+}  // namespace blocklist
diff --git a/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc b/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc
index 82c34530..542f5fd 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc
+++ b/components/blacklist/opt_out_blacklist/opt_out_blacklist_unittest.cc
@@ -29,70 +29,67 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace blacklist {
+namespace blocklist {
 
 namespace {
 
 const char kTestHost1[] = "testhost1.com";
 const char kTestHost2[] = "testhost2.com";
 
-// Mock class to test that OptOutBlacklist notifies the delegate with correct
-// events (e.g. New host blacklisted, user blacklisted, and blacklist cleared).
-class TestOptOutBlacklistDelegate : public OptOutBlacklistDelegate {
+// Mock class to test that OptOutBlocklist notifies the delegate with correct
+// events (e.g. New host blocklisted, user blocklisted, and blocklist cleared).
+class TestOptOutBlocklistDelegate : public OptOutBlocklistDelegate {
  public:
-  TestOptOutBlacklistDelegate()
-      : user_blacklisted_(false),
-        blacklist_cleared_(false),
-        blacklist_cleared_time_(base::Time::Now()) {}
+  TestOptOutBlocklistDelegate() : blocklist_cleared_time_(base::Time::Now()) {}
 
-  // OptOutBlacklistDelegate:
-  void OnNewBlacklistedHost(const std::string& host, base::Time time) override {
-    blacklisted_hosts_[host] = time;
+  // OptOutBlocklistDelegate:
+  void OnNewBlocklistedHost(const std::string& host, base::Time time) override {
+    blocklisted_hosts_[host] = time;
   }
-  void OnUserBlacklistedStatusChange(bool blacklisted) override {
-    user_blacklisted_ = blacklisted;
+  void OnUserBlocklistedStatusChange(bool blocklisted) override {
+    user_blocklisted_ = blocklisted;
   }
-  void OnBlacklistCleared(base::Time time) override {
-    blacklist_cleared_ = true;
-    blacklist_cleared_time_ = time;
+  void OnBlocklistCleared(base::Time time) override {
+    blocklist_cleared_ = true;
+    blocklist_cleared_time_ = time;
   }
 
-  // Gets the set of blacklisted hosts recorded.
-  const std::unordered_map<std::string, base::Time>& blacklisted_hosts() const {
-    return blacklisted_hosts_;
+  // Gets the set of blocklisted hosts recorded.
+  const std::unordered_map<std::string, base::Time>& blocklisted_hosts() const {
+    return blocklisted_hosts_;
   }
 
-  // Gets the state of user blacklisted status.
-  bool user_blacklisted() const { return user_blacklisted_; }
+  // Gets the state of user blocklisted status.
+  bool user_blocklisted() const { return user_blocklisted_; }
 
-  // Gets the state of blacklisted cleared status of |this| for testing.
-  bool blacklist_cleared() const { return blacklist_cleared_; }
+  // Gets the state of blocklisted cleared status of |this| for testing.
+  bool blocklist_cleared() const { return blocklist_cleared_; }
 
-  // Gets the event time of blacklist is as cleared.
-  base::Time blacklist_cleared_time() const { return blacklist_cleared_time_; }
+  // Gets the event time of blocklist is as cleared.
+  base::Time blocklist_cleared_time() const { return blocklist_cleared_time_; }
 
  private:
-  // The user blacklisted status of |this| blacklist_delegate.
-  bool user_blacklisted_;
+  // The user blocklisted status of |this| blocklist_delegate.
+  bool user_blocklisted_ = false;
 
-  // Check if the blacklist is notified as cleared on |this| blacklist_delegate.
-  bool blacklist_cleared_;
+  // Check if the blocklist is notified as cleared on |this| blocklist_delegate.
+  bool blocklist_cleared_ = false;
 
-  // The time when blacklist is cleared.
-  base::Time blacklist_cleared_time_;
+  // The time when blocklist is cleared.
+  base::Time blocklist_cleared_time_;
 
-  // |this| blacklist_delegate's collection of blacklisted hosts.
-  std::unordered_map<std::string, base::Time> blacklisted_hosts_;
+  // |this| blocklist_delegate's collection of blocklisted hosts.
+  std::unordered_map<std::string, base::Time> blocklisted_hosts_;
 };
 
 class TestOptOutStore : public OptOutStore {
  public:
-  TestOptOutStore() : clear_blacklist_count_(0) {}
-  ~TestOptOutStore() override {}
+  TestOptOutStore() = default;
+  ~TestOptOutStore() override = default;
 
-  int clear_blacklist_count() { return clear_blacklist_count_; }
+  int clear_blocklist_count() { return clear_blocklist_count_; }
 
-  void SetBlacklistData(std::unique_ptr<BlacklistData> data) {
+  void SetBlocklistData(std::unique_ptr<BlocklistData> data) {
     data_ = std::move(data);
   }
 
@@ -103,50 +100,50 @@
                 int type,
                 base::Time now) override {}
 
-  void LoadBlackList(std::unique_ptr<BlacklistData> blacklist_data,
-                     LoadBlackListCallback callback) override {
+  void LoadBlockList(std::unique_ptr<BlocklistData> blocklist_data,
+                     LoadBlockListCallback callback) override {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::BindOnce(std::move(callback),
-                       data_ ? std::move(data_) : std::move(blacklist_data)));
+                       data_ ? std::move(data_) : std::move(blocklist_data)));
   }
 
-  void ClearBlackList(base::Time begin_time, base::Time end_time) override {
-    ++clear_blacklist_count_;
+  void ClearBlockList(base::Time begin_time, base::Time end_time) override {
+    ++clear_blocklist_count_;
   }
 
-  int clear_blacklist_count_;
+  int clear_blocklist_count_ = 0;
 
-  std::unique_ptr<BlacklistData> data_;
+  std::unique_ptr<BlocklistData> data_;
 };
 
-class TestOptOutBlacklist : public OptOutBlacklist {
+class TestOptOutBlocklist : public OptOutBlocklist {
  public:
-  TestOptOutBlacklist(std::unique_ptr<OptOutStore> opt_out_store,
+  TestOptOutBlocklist(std::unique_ptr<OptOutStore> opt_out_store,
                       base::Clock* clock,
-                      OptOutBlacklistDelegate* blacklist_delegate)
-      : OptOutBlacklist(std::move(opt_out_store), clock, blacklist_delegate) {}
-  ~TestOptOutBlacklist() override {}
+                      OptOutBlocklistDelegate* blocklist_delegate)
+      : OptOutBlocklist(std::move(opt_out_store), clock, blocklist_delegate) {}
+  ~TestOptOutBlocklist() override = default;
 
-  void SetSessionRule(std::unique_ptr<BlacklistData::Policy> policy) {
+  void SetSessionRule(std::unique_ptr<BlocklistData::Policy> policy) {
     session_policy_ = std::move(policy);
   }
 
-  void SetPersistentRule(std::unique_ptr<BlacklistData::Policy> policy) {
+  void SetPersistentRule(std::unique_ptr<BlocklistData::Policy> policy) {
     persistent_policy_ = std::move(policy);
   }
 
-  void SetHostRule(std::unique_ptr<BlacklistData::Policy> policy,
+  void SetHostRule(std::unique_ptr<BlocklistData::Policy> policy,
                    size_t max_hosts) {
     host_policy_ = std::move(policy);
     max_hosts_ = max_hosts;
   }
 
-  void SetTypeRule(std::unique_ptr<BlacklistData::Policy> policy) {
+  void SetTypeRule(std::unique_ptr<BlocklistData::Policy> policy) {
     type_policy_ = std::move(policy);
   }
 
-  void SetAllowedTypes(BlacklistData::AllowedTypesAndVersions allowed_types) {
+  void SetAllowedTypes(BlocklistData::AllowedTypesAndVersions allowed_types) {
     allowed_types_ = std::move(allowed_types);
   }
 
@@ -201,107 +198,107 @@
     return true;
   }
 
-  BlacklistData::AllowedTypesAndVersions GetAllowedTypes() const override {
+  BlocklistData::AllowedTypesAndVersions GetAllowedTypes() const override {
     return allowed_types_;
   }
 
-  std::unique_ptr<BlacklistData::Policy> session_policy_;
-  std::unique_ptr<BlacklistData::Policy> persistent_policy_;
-  std::unique_ptr<BlacklistData::Policy> host_policy_;
-  std::unique_ptr<BlacklistData::Policy> type_policy_;
+  std::unique_ptr<BlocklistData::Policy> session_policy_;
+  std::unique_ptr<BlocklistData::Policy> persistent_policy_;
+  std::unique_ptr<BlocklistData::Policy> host_policy_;
+  std::unique_ptr<BlocklistData::Policy> type_policy_;
 
   size_t max_hosts_ = 0;
 
-  BlacklistData::AllowedTypesAndVersions allowed_types_;
+  BlocklistData::AllowedTypesAndVersions allowed_types_;
 };
 
-class OptOutBlacklistTest : public testing::Test {
+class OptOutBlocklistTest : public testing::Test {
  public:
-  OptOutBlacklistTest() {}
-  ~OptOutBlacklistTest() override {}
+  OptOutBlocklistTest() = default;
+  ~OptOutBlocklistTest() override = default;
 
   void StartTest(bool null_opt_out_store) {
     std::unique_ptr<TestOptOutStore> opt_out_store =
         null_opt_out_store ? nullptr : std::make_unique<TestOptOutStore>();
     opt_out_store_ = opt_out_store.get();
 
-    black_list_ = std::make_unique<TestOptOutBlacklist>(
-        std::move(opt_out_store), &test_clock_, &blacklist_delegate_);
+    block_list_ = std::make_unique<TestOptOutBlocklist>(
+        std::move(opt_out_store), &test_clock_, &blocklist_delegate_);
     if (session_policy_) {
-      black_list_->SetSessionRule(std::move(session_policy_));
+      block_list_->SetSessionRule(std::move(session_policy_));
     }
     if (persistent_policy_) {
-      black_list_->SetPersistentRule(std::move(persistent_policy_));
+      block_list_->SetPersistentRule(std::move(persistent_policy_));
     }
     if (host_policy_) {
-      black_list_->SetHostRule(std::move(host_policy_), max_hosts_);
+      block_list_->SetHostRule(std::move(host_policy_), max_hosts_);
     }
     if (type_policy_) {
-      black_list_->SetTypeRule(std::move(type_policy_));
+      block_list_->SetTypeRule(std::move(type_policy_));
     }
 
-    black_list_->SetAllowedTypes(std::move(allowed_types_));
-    black_list_->Init();
+    block_list_->SetAllowedTypes(std::move(allowed_types_));
+    block_list_->Init();
 
     start_ = test_clock_.Now();
 
     passed_reasons_ = {};
   }
 
-  void SetSessionRule(std::unique_ptr<BlacklistData::Policy> policy) {
+  void SetSessionRule(std::unique_ptr<BlocklistData::Policy> policy) {
     session_policy_ = std::move(policy);
   }
 
-  void SetPersistentRule(std::unique_ptr<BlacklistData::Policy> policy) {
+  void SetPersistentRule(std::unique_ptr<BlocklistData::Policy> policy) {
     persistent_policy_ = std::move(policy);
   }
 
-  void SetHostRule(std::unique_ptr<BlacklistData::Policy> policy,
+  void SetHostRule(std::unique_ptr<BlocklistData::Policy> policy,
                    size_t max_hosts) {
     host_policy_ = std::move(policy);
     max_hosts_ = max_hosts;
   }
 
-  void SetTypeRule(std::unique_ptr<BlacklistData::Policy> policy) {
+  void SetTypeRule(std::unique_ptr<BlocklistData::Policy> policy) {
     type_policy_ = std::move(policy);
   }
 
-  void SetAllowedTypes(BlacklistData::AllowedTypesAndVersions allowed_types) {
+  void SetAllowedTypes(BlocklistData::AllowedTypesAndVersions allowed_types) {
     allowed_types_ = std::move(allowed_types);
   }
 
  protected:
   base::test::SingleThreadTaskEnvironment task_environment_;
 
-  // Observer to |black_list_|.
-  TestOptOutBlacklistDelegate blacklist_delegate_;
+  // Observer to |block_list_|.
+  TestOptOutBlocklistDelegate blocklist_delegate_;
 
   base::SimpleTestClock test_clock_;
   TestOptOutStore* opt_out_store_;
   base::Time start_;
 
-  std::unique_ptr<TestOptOutBlacklist> black_list_;
-  std::vector<BlacklistReason> passed_reasons_;
+  std::unique_ptr<TestOptOutBlocklist> block_list_;
+  std::vector<BlocklistReason> passed_reasons_;
 
  private:
-  std::unique_ptr<BlacklistData::Policy> session_policy_;
-  std::unique_ptr<BlacklistData::Policy> persistent_policy_;
-  std::unique_ptr<BlacklistData::Policy> host_policy_;
-  std::unique_ptr<BlacklistData::Policy> type_policy_;
+  std::unique_ptr<BlocklistData::Policy> session_policy_;
+  std::unique_ptr<BlocklistData::Policy> persistent_policy_;
+  std::unique_ptr<BlocklistData::Policy> host_policy_;
+  std::unique_ptr<BlocklistData::Policy> type_policy_;
 
   size_t max_hosts_ = 0;
 
-  BlacklistData::AllowedTypesAndVersions allowed_types_;
+  BlocklistData::AllowedTypesAndVersions allowed_types_;
 
-  DISALLOW_COPY_AND_ASSIGN(OptOutBlacklistTest);
+  DISALLOW_COPY_AND_ASSIGN(OptOutBlocklistTest);
 };
 
-TEST_F(OptOutBlacklistTest, HostBlackListNoStore) {
-  // Tests the black list behavior when a null OptOutStore is passed in.
-  auto host_policy = std::make_unique<BlacklistData::Policy>(
+TEST_F(OptOutBlocklistTest, HostBlockListNoStore) {
+  // Tests the block list behavior when a null OptOutStore is passed in.
+  auto host_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, 2);
   SetHostRule(std::move(host_policy), 5);
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
@@ -310,76 +307,76 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost2, true, 1);
+  block_list_->AddEntry(kTestHost2, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost2, true, 1);
+  block_list_->AddEntry(kTestHost2, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost2, false, 1);
+  block_list_->AddEntry(kTestHost2, false, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost2, false, 1);
+  block_list_->AddEntry(kTestHost2, false, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost2, false, 1);
+  block_list_->AddEntry(kTestHost2, false, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
 
-  black_list_->ClearBlackList(start_, test_clock_.Now());
+  block_list_->ClearBlockList(start_, test_clock_.Now());
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
 }
 
-TEST_F(OptOutBlacklistTest, TypeBlackListWithStore) {
-  // Tests the black list behavior when a non-null OptOutStore is passed in.
+TEST_F(OptOutBlocklistTest, TypeBlockListWithStore) {
+  // Tests the block list behavior when a non-null OptOutStore is passed in.
 
-  auto type_policy = std::make_unique<BlacklistData::Policy>(
+  auto type_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, 2);
   SetTypeRule(std::move(type_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   allowed_types.insert({2, 0});
   SetAllowedTypes(std::move(allowed_types));
@@ -389,111 +386,111 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kBlacklistNotLoaded,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kBlocklistNotLoaded,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kBlacklistNotLoaded,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kBlocklistNotLoaded,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kBlacklistNotLoaded,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kBlocklistNotLoaded,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, true, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost1, true, 2);
+  block_list_->AddEntry(kTestHost1, true, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 2);
+  block_list_->AddEntry(kTestHost1, true, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost1, false, 2);
+  block_list_->AddEntry(kTestHost1, false, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, false, 2);
+  block_list_->AddEntry(kTestHost1, false, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, false, 2);
+  block_list_->AddEntry(kTestHost1, false, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  EXPECT_EQ(0, opt_out_store_->clear_blacklist_count());
-  black_list_->ClearBlackList(start_, base::Time::Now());
-  EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
+  EXPECT_EQ(0, opt_out_store_->clear_blocklist_count());
+  block_list_->ClearBlockList(start_, base::Time::Now());
+  EXPECT_EQ(1, opt_out_store_->clear_blocklist_count());
 
   EXPECT_EQ(
-      BlacklistReason::kBlacklistNotLoaded,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kBlocklistNotLoaded,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kBlacklistNotLoaded,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kBlocklistNotLoaded,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kBlacklistNotLoaded,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kBlocklistNotLoaded,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
+  EXPECT_EQ(1, opt_out_store_->clear_blocklist_count());
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 }
 
-TEST_F(OptOutBlacklistTest, TypeBlackListNoStore) {
-  // Tests the black list behavior when a null OptOutStore is passed in.
-  auto type_policy = std::make_unique<BlacklistData::Policy>(
+TEST_F(OptOutBlocklistTest, TypeBlockListNoStore) {
+  // Tests the block list behavior when a null OptOutStore is passed in.
+  auto type_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, 2);
   SetTypeRule(std::move(type_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   allowed_types.insert({2, 0});
   SetAllowedTypes(std::move(allowed_types));
@@ -503,81 +500,84 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost1, true, 2);
+  block_list_->AddEntry(kTestHost1, true, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 2);
+  block_list_->AddEntry(kTestHost1, true, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  black_list_->AddEntry(kTestHost1, false, 2);
+  block_list_->AddEntry(kTestHost1, false, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, false, 2);
+  block_list_->AddEntry(kTestHost1, false, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, false, 2);
+  block_list_->AddEntry(kTestHost1, false, 2);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfType,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfType,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, true, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 
-  black_list_->ClearBlackList(start_, test_clock_.Now());
+  block_list_->ClearBlockList(start_, test_clock_.Now());
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 2, false, &passed_reasons_));
 }
 
-TEST_F(OptOutBlacklistTest, HostIndifferentBlacklist) {
-  // Tests the black list behavior when a null OptOutStore is passed in.
+TEST_F(OptOutBlocklistTest, HostIndifferentBlocklist) {
+  // Tests the block list behavior when a null OptOutStore is passed in.
   const std::string hosts[] = {
-      "url_0.com", "url_1.com", "url_2.com", "url_3.com",
+      "url_0.com",
+      "url_1.com",
+      "url_2.com",
+      "url_3.com",
   };
 
   int host_indifferent_threshold = 4;
 
-  auto persistent_policy = std::make_unique<BlacklistData::Policy>(
+  auto persistent_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, host_indifferent_threshold);
   SetPersistentRule(std::move(persistent_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
@@ -585,345 +585,348 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
 
   for (int i = 0; i < host_indifferent_threshold; i++) {
-    black_list_->AddEntry(hosts[i], true, 1);
+    block_list_->AddEntry(hosts[i], true, 1);
     EXPECT_EQ(
-        i != 3 ? BlacklistReason::kAllowed
-               : BlacklistReason::kUserOptedOutInGeneral,
-        black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
+        i != 3 ? BlocklistReason::kAllowed
+               : BlocklistReason::kUserOptedOutInGeneral,
+        block_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
   }
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInGeneral,
-      black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInGeneral,
+      block_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInGeneral,
-      black_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInGeneral,
+      block_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInGeneral,
-      black_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInGeneral,
+      block_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInGeneral,
-      black_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInGeneral,
+      block_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[3], 1, true, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[3], 1, true, &passed_reasons_));
 
-  black_list_->AddEntry(hosts[3], false, 1);
+  block_list_->AddEntry(hosts[3], false, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   // New non-opt-out entry will cause these to be allowed now.
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[1], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[2], 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(hosts[3], 1, false, &passed_reasons_));
 }
 
-TEST_F(OptOutBlacklistTest, QueueBehavior) {
-  // Tests the black list asynchronous queue behavior. Methods called while
+TEST_F(OptOutBlocklistTest, QueueBehavior) {
+  // Tests the block list asynchronous queue behavior. Methods called while
   // loading the opt-out store are queued and should run in the order they were
   // queued.
 
   std::vector<bool> test_opt_out{true, false};
 
   for (auto opt_out : test_opt_out) {
-    auto host_policy = std::make_unique<BlacklistData::Policy>(
+    auto host_policy = std::make_unique<BlocklistData::Policy>(
         base::TimeDelta::FromDays(365), 4u, 2);
     SetHostRule(std::move(host_policy), 5);
-    BlacklistData::AllowedTypesAndVersions allowed_types;
+    BlocklistData::AllowedTypesAndVersions allowed_types;
     allowed_types.insert({1, 0});
     SetAllowedTypes(std::move(allowed_types));
 
     StartTest(false /* null_opt_out */);
 
-    EXPECT_EQ(BlacklistReason::kBlacklistNotLoaded,
-              black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
+    EXPECT_EQ(BlocklistReason::kBlocklistNotLoaded,
+              block_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
                                               &passed_reasons_));
-    black_list_->AddEntry(kTestHost1, opt_out, 1);
+    block_list_->AddEntry(kTestHost1, opt_out, 1);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-    black_list_->AddEntry(kTestHost1, opt_out, 1);
+    block_list_->AddEntry(kTestHost1, opt_out, 1);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-    EXPECT_EQ(BlacklistReason::kBlacklistNotLoaded,
-              black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
+    EXPECT_EQ(BlocklistReason::kBlocklistNotLoaded,
+              block_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
                                               &passed_reasons_));
     base::RunLoop().RunUntilIdle();
-    EXPECT_EQ(opt_out ? BlacklistReason::kUserOptedOutOfHost
-                      : BlacklistReason::kAllowed,
-              black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
+    EXPECT_EQ(opt_out ? BlocklistReason::kUserOptedOutOfHost
+                      : BlocklistReason::kAllowed,
+              block_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
                                               &passed_reasons_));
-    black_list_->AddEntry(kTestHost1, opt_out, 1);
+    block_list_->AddEntry(kTestHost1, opt_out, 1);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-    black_list_->AddEntry(kTestHost1, opt_out, 1);
+    block_list_->AddEntry(kTestHost1, opt_out, 1);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-    EXPECT_EQ(0, opt_out_store_->clear_blacklist_count());
-    black_list_->ClearBlackList(
+    EXPECT_EQ(0, opt_out_store_->clear_blocklist_count());
+    block_list_->ClearBlockList(
         start_, test_clock_.Now() + base::TimeDelta::FromSeconds(1));
-    EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
-    black_list_->AddEntry(kTestHost2, opt_out, 1);
+    EXPECT_EQ(1, opt_out_store_->clear_blocklist_count());
+    block_list_->AddEntry(kTestHost2, opt_out, 1);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-    black_list_->AddEntry(kTestHost2, opt_out, 1);
+    block_list_->AddEntry(kTestHost2, opt_out, 1);
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
     base::RunLoop().RunUntilIdle();
-    EXPECT_EQ(1, opt_out_store_->clear_blacklist_count());
+    EXPECT_EQ(1, opt_out_store_->clear_blocklist_count());
 
-    EXPECT_EQ(BlacklistReason::kAllowed,
-              black_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
+    EXPECT_EQ(BlocklistReason::kAllowed,
+              block_list_->IsLoadedAndAllowed(kTestHost1, 1, false,
                                               &passed_reasons_));
-    EXPECT_EQ(opt_out ? BlacklistReason::kUserOptedOutOfHost
-                      : BlacklistReason::kAllowed,
-              black_list_->IsLoadedAndAllowed(kTestHost2, 1, false,
+    EXPECT_EQ(opt_out ? BlocklistReason::kUserOptedOutOfHost
+                      : BlocklistReason::kAllowed,
+              block_list_->IsLoadedAndAllowed(kTestHost2, 1, false,
                                               &passed_reasons_));
   }
 }
 
-TEST_F(OptOutBlacklistTest, MaxHosts) {
-  // Test that the black list only stores n hosts, and it stores the correct n
+TEST_F(OptOutBlocklistTest, MaxHosts) {
+  // Test that the block list only stores n hosts, and it stores the correct n
   // hosts.
   const std::string test_host_3("host3.com");
   const std::string test_host_4("host4.com");
   const std::string test_host_5("host5.com");
 
-  auto host_policy = std::make_unique<BlacklistData::Policy>(
+  auto host_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 1u, 1);
   SetHostRule(std::move(host_policy), 2);
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(true /* null_opt_out */);
 
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost2, false, 1);
+  block_list_->AddEntry(kTestHost2, false, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(test_host_3, false, 1);
+  block_list_->AddEntry(test_host_3, false, 1);
   // kTestHost1 should stay in the map, since it has an opt out time.
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
 
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(test_host_4, true, 1);
+  block_list_->AddEntry(test_host_4, true, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(test_host_5, true, 1);
+  block_list_->AddEntry(test_host_5, true, 1);
   // test_host_4 and test_host_5 should remain in the map, but host should be
   // evicted.
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(test_host_4, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(test_host_4, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(test_host_5, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(test_host_5, 1, false, &passed_reasons_));
 }
 
-TEST_F(OptOutBlacklistTest, SingleOptOut) {
+TEST_F(OptOutBlocklistTest, SingleOptOut) {
   // Test that when a user opts out of an action, actions won't be allowed until
   // |single_opt_out_duration| has elapsed.
   int single_opt_out_duration = 5;
   const std::string test_host_3("host3.com");
 
-  auto session_policy = std::make_unique<BlacklistData::Policy>(
+  auto session_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromSeconds(single_opt_out_duration), 1u, 1);
   SetSessionRule(std::move(session_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(true /* null_opt_out */);
 
-  black_list_->AddEntry(kTestHost1, false, 1);
+  block_list_->AddEntry(kTestHost1, false, 1);
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
 
   test_clock_.Advance(
       base::TimeDelta::FromSeconds(single_opt_out_duration + 1));
 
-  black_list_->AddEntry(kTestHost2, true, 1);
+  block_list_->AddEntry(kTestHost2, true, 1);
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInSession,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInSession,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInSession,
-      black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInSession,
+      block_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
 
   test_clock_.Advance(
       base::TimeDelta::FromSeconds(single_opt_out_duration - 1));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInSession,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInSession,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInSession,
-      black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInSession,
+      block_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
 
   test_clock_.Advance(
       base::TimeDelta::FromSeconds(single_opt_out_duration + 1));
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost2, 1, false, &passed_reasons_));
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(test_host_3, 1, false, &passed_reasons_));
 }
 
-TEST_F(OptOutBlacklistTest, ClearingBlackListClearsRecentNavigation) {
-  // Tests that clearing the black list for a long amount of time (relative to
-  // "single_opt_out_duration_in_seconds") resets the blacklist's recent opt out
+TEST_F(OptOutBlocklistTest, ClearingBlockListClearsRecentNavigation) {
+  // Tests that clearing the block list for a long amount of time (relative to
+  // "single_opt_out_duration_in_seconds") resets the blocklist's recent opt out
   // rule.
 
-  auto session_policy = std::make_unique<BlacklistData::Policy>(
+  auto session_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromSeconds(5), 1u, 1);
   SetSessionRule(std::move(session_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(false /* null_opt_out */);
 
-  black_list_->AddEntry(kTestHost1, true /* opt_out */, 1);
+  block_list_->AddEntry(kTestHost1, true /* opt_out */, 1);
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->ClearBlackList(start_, test_clock_.Now());
+  block_list_->ClearBlockList(start_, test_clock_.Now());
   base::RunLoop().RunUntilIdle();
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
 }
 
-TEST_F(OptOutBlacklistTest, ObserverIsNotifiedOnHostBlacklisted) {
-  // Tests the black list behavior when a null OptOutStore is passed in.
+TEST_F(OptOutBlocklistTest, ObserverIsNotifiedOnHostBlocklisted) {
+  // Tests the block list behavior when a null OptOutStore is passed in.
 
-  auto host_policy = std::make_unique<BlacklistData::Policy>(
+  auto host_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, 2);
   SetHostRule(std::move(host_policy), 5);
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(true /* null_opt_out */);
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
 
-  // Observer is not notified as blacklisted when the threshold does not met.
+  // Observer is not notified as blocklisted when the threshold does not met.
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   base::RunLoop().RunUntilIdle();
-  EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(0));
+  EXPECT_THAT(blocklist_delegate_.blocklisted_hosts(), ::testing::SizeIs(0));
 
-  // Observer is notified as blacklisted when the threshold is met.
+  // Observer is notified as blocklisted when the threshold is met.
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   base::RunLoop().RunUntilIdle();
-  const base::Time blacklisted_time = test_clock_.Now();
-  EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(1));
-  EXPECT_EQ(blacklisted_time,
-            blacklist_delegate_.blacklisted_hosts().find(kTestHost1)->second);
+  const base::Time blocklisted_time = test_clock_.Now();
+  EXPECT_THAT(blocklist_delegate_.blocklisted_hosts(), ::testing::SizeIs(1));
+  EXPECT_EQ(blocklisted_time,
+            blocklist_delegate_.blocklisted_hosts().find(kTestHost1)->second);
 
-  // Observer is not notified when the host is already blacklisted.
+  // Observer is not notified when the host is already blocklisted.
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   base::RunLoop().RunUntilIdle();
-  EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(1));
-  EXPECT_EQ(blacklisted_time,
-            blacklist_delegate_.blacklisted_hosts().find(kTestHost1)->second);
+  EXPECT_THAT(blocklist_delegate_.blocklisted_hosts(), ::testing::SizeIs(1));
+  EXPECT_EQ(blocklisted_time,
+            blocklist_delegate_.blocklisted_hosts().find(kTestHost1)->second);
 
-  // Observer is notified when blacklist is cleared.
-  EXPECT_FALSE(blacklist_delegate_.blacklist_cleared());
+  // Observer is notified when blocklist is cleared.
+  EXPECT_FALSE(blocklist_delegate_.blocklist_cleared());
 
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->ClearBlackList(start_, test_clock_.Now());
+  block_list_->ClearBlockList(start_, test_clock_.Now());
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(blacklist_delegate_.blacklist_cleared());
-  EXPECT_EQ(test_clock_.Now(), blacklist_delegate_.blacklist_cleared_time());
+  EXPECT_TRUE(blocklist_delegate_.blocklist_cleared());
+  EXPECT_EQ(test_clock_.Now(), blocklist_delegate_.blocklist_cleared_time());
 }
 
-TEST_F(OptOutBlacklistTest, ObserverIsNotifiedOnUserBlacklisted) {
-  // Tests the black list behavior when a null OptOutStore is passed in.
+TEST_F(OptOutBlocklistTest, ObserverIsNotifiedOnUserBlocklisted) {
+  // Tests the block list behavior when a null OptOutStore is passed in.
   const std::string hosts[] = {
-      "url_0.com", "url_1.com", "url_2.com", "url_3.com",
+      "url_0.com",
+      "url_1.com",
+      "url_2.com",
+      "url_3.com",
   };
 
   int host_indifferent_threshold = 4;
 
-  auto persistent_policy = std::make_unique<BlacklistData::Policy>(
+  auto persistent_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(30), 4u, host_indifferent_threshold);
   SetPersistentRule(std::move(persistent_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(true /* null_opt_out */);
 
-  // Initially no host is blacklisted, and user is not blacklisted.
-  EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(0));
-  EXPECT_FALSE(blacklist_delegate_.user_blacklisted());
+  // Initially no host is blocklisted, and user is not blocklisted.
+  EXPECT_THAT(blocklist_delegate_.blocklisted_hosts(), ::testing::SizeIs(0));
+  EXPECT_FALSE(blocklist_delegate_.user_blocklisted());
 
   for (int i = 0; i < host_indifferent_threshold; ++i) {
     test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-    black_list_->AddEntry(hosts[i], true, 1);
+    block_list_->AddEntry(hosts[i], true, 1);
     base::RunLoop().RunUntilIdle();
 
-    EXPECT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(0));
+    EXPECT_THAT(blocklist_delegate_.blocklisted_hosts(), ::testing::SizeIs(0));
     // Observer is notified when number of recently opt out meets
     // |host_indifferent_threshold|.
     EXPECT_EQ(i >= host_indifferent_threshold - 1,
-              blacklist_delegate_.user_blacklisted());
+              blocklist_delegate_.user_blocklisted());
   }
 
-  // Observer is notified when the user is no longer blacklisted.
+  // Observer is notified when the user is no longer blocklisted.
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
-  black_list_->AddEntry(hosts[3], false, 1);
+  block_list_->AddEntry(hosts[3], false, 1);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_FALSE(blacklist_delegate_.user_blacklisted());
+  EXPECT_FALSE(blocklist_delegate_.user_blocklisted());
 }
 
-TEST_F(OptOutBlacklistTest, ObserverIsNotifiedWhenLoadBlacklistDone) {
+TEST_F(OptOutBlocklistTest, ObserverIsNotifiedWhenLoadBlocklistDone) {
   int host_indifferent_threshold = 4;
   size_t host_indifferent_history = 4u;
-  auto persistent_policy = std::make_unique<BlacklistData::Policy>(
+  auto persistent_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(30), host_indifferent_history,
       host_indifferent_threshold);
   SetPersistentRule(std::move(persistent_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
@@ -931,9 +934,9 @@
 
   allowed_types.clear();
   allowed_types[0] = 0;
-  std::unique_ptr<BlacklistData> data = std::make_unique<BlacklistData>(
+  std::unique_ptr<BlocklistData> data = std::make_unique<BlocklistData>(
       nullptr,
-      std::make_unique<BlacklistData::Policy>(base::TimeDelta::FromSeconds(365),
+      std::make_unique<BlocklistData::Policy>(base::TimeDelta::FromSeconds(365),
                                               host_indifferent_history,
                                               host_indifferent_threshold),
       nullptr, nullptr, 0, std::move(allowed_types));
@@ -946,34 +949,34 @@
 
   std::unique_ptr<TestOptOutStore> opt_out_store =
       std::make_unique<TestOptOutStore>();
-  opt_out_store->SetBlacklistData(std::move(data));
+  opt_out_store->SetBlocklistData(std::move(data));
 
-  EXPECT_FALSE(blacklist_delegate_.user_blacklisted());
+  EXPECT_FALSE(blocklist_delegate_.user_blocklisted());
   allowed_types.clear();
   allowed_types[1] = 0;
-  auto black_list = std::make_unique<TestOptOutBlacklist>(
-      std::move(opt_out_store), &test_clock, &blacklist_delegate_);
-  black_list->SetAllowedTypes(std::move(allowed_types));
+  auto block_list = std::make_unique<TestOptOutBlocklist>(
+      std::move(opt_out_store), &test_clock, &blocklist_delegate_);
+  block_list->SetAllowedTypes(std::move(allowed_types));
 
-  persistent_policy = std::make_unique<BlacklistData::Policy>(
+  persistent_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(30), host_indifferent_history,
       host_indifferent_threshold);
-  black_list->SetPersistentRule(std::move(persistent_policy));
+  block_list->SetPersistentRule(std::move(persistent_policy));
 
-  black_list->Init();
+  block_list->Init();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(blacklist_delegate_.user_blacklisted());
+  EXPECT_TRUE(blocklist_delegate_.user_blocklisted());
 }
 
-TEST_F(OptOutBlacklistTest, ObserverIsNotifiedOfHistoricalBlacklistedHosts) {
-  // Tests the black list behavior when a non-null OptOutStore is passed in.
+TEST_F(OptOutBlocklistTest, ObserverIsNotifiedOfHistoricalBlocklistedHosts) {
+  // Tests the block list behavior when a non-null OptOutStore is passed in.
   int host_indifferent_threshold = 2;
   size_t host_indifferent_history = 4u;
-  auto host_policy = std::make_unique<BlacklistData::Policy>(
+  auto host_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), host_indifferent_history,
       host_indifferent_threshold);
   SetHostRule(std::move(host_policy), 5);
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
@@ -983,9 +986,9 @@
 
   allowed_types.clear();
   allowed_types[static_cast<int>(1)] = 0;
-  std::unique_ptr<BlacklistData> data = std::make_unique<BlacklistData>(
+  std::unique_ptr<BlocklistData> data = std::make_unique<BlocklistData>(
       nullptr, nullptr,
-      std::make_unique<BlacklistData::Policy>(base::TimeDelta::FromDays(365),
+      std::make_unique<BlocklistData::Policy>(base::TimeDelta::FromDays(365),
                                               host_indifferent_history,
                                               host_indifferent_threshold),
       nullptr, 2, std::move(allowed_types));
@@ -994,94 +997,96 @@
   data->AddEntry(kTestHost1, true, static_cast<int>(1), test_clock.Now(), true);
   test_clock.Advance(base::TimeDelta::FromSeconds(1));
   data->AddEntry(kTestHost1, true, static_cast<int>(1), test_clock.Now(), true);
-  base::Time blacklisted_time = test_clock.Now();
+  base::Time blocklisted_time = test_clock.Now();
 
   base::RunLoop().RunUntilIdle();
-  std::vector<BlacklistReason> reasons;
-  EXPECT_NE(BlacklistReason::kAllowed,
+  std::vector<BlocklistReason> reasons;
+  EXPECT_NE(BlocklistReason::kAllowed,
             data->IsAllowed(kTestHost1, static_cast<int>(1), false,
                             test_clock.Now(), &reasons));
 
-  // Host |url_b| is not blacklisted.
+  // Host |url_b| is not blocklisted.
   test_clock.Advance(base::TimeDelta::FromSeconds(1));
   data->AddEntry(kTestHost2, true, static_cast<int>(1), test_clock.Now(), true);
 
   std::unique_ptr<TestOptOutStore> opt_out_store =
       std::make_unique<TestOptOutStore>();
-  opt_out_store->SetBlacklistData(std::move(data));
+  opt_out_store->SetBlocklistData(std::move(data));
 
   allowed_types.clear();
   allowed_types[static_cast<int>(1)] = 0;
-  auto black_list = std::make_unique<TestOptOutBlacklist>(
-      std::move(opt_out_store), &test_clock, &blacklist_delegate_);
-  black_list->SetAllowedTypes(std::move(allowed_types));
+  auto block_list = std::make_unique<TestOptOutBlocklist>(
+      std::move(opt_out_store), &test_clock, &blocklist_delegate_);
+  block_list->SetAllowedTypes(std::move(allowed_types));
 
-  host_policy = std::make_unique<BlacklistData::Policy>(
+  host_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(30), host_indifferent_history,
       host_indifferent_threshold);
-  black_list->SetPersistentRule(std::move(host_policy));
+  block_list->SetPersistentRule(std::move(host_policy));
 
-  black_list->Init();
+  block_list->Init();
 
   base::RunLoop().RunUntilIdle();
 
-  ASSERT_THAT(blacklist_delegate_.blacklisted_hosts(), ::testing::SizeIs(1));
-  EXPECT_EQ(blacklisted_time,
-            blacklist_delegate_.blacklisted_hosts().find(kTestHost1)->second);
+  ASSERT_THAT(blocklist_delegate_.blocklisted_hosts(), ::testing::SizeIs(1));
+  EXPECT_EQ(blocklisted_time,
+            blocklist_delegate_.blocklisted_hosts().find(kTestHost1)->second);
 }
 
-TEST_F(OptOutBlacklistTest, PassedReasonsWhenBlacklistDataNotLoaded) {
-  // Test that IsLoadedAndAllow, push checked BlacklistReasons to the
+TEST_F(OptOutBlocklistTest, PassedReasonsWhenBlocklistDataNotLoaded) {
+  // Test that IsLoadedAndAllow, push checked BlocklistReasons to the
   // |passed_reasons| vector.
 
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
   StartTest(false /* null_opt_out */);
 
   EXPECT_EQ(
-      BlacklistReason::kBlacklistNotLoaded,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kBlocklistNotLoaded,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
 
   EXPECT_EQ(0UL, passed_reasons_.size());
 }
 
-TEST_F(OptOutBlacklistTest, PassedReasonsWhenUserRecentlyOptedOut) {
-  // Test that IsLoadedAndAllow, push checked BlacklistReasons to the
+TEST_F(OptOutBlocklistTest, PassedReasonsWhenUserRecentlyOptedOut) {
+  // Test that IsLoadedAndAllow, push checked BlocklistReasons to the
   // |passed_reasons| vector.
 
-  auto session_policy = std::make_unique<BlacklistData::Policy>(
+  auto session_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromSeconds(5), 1u, 1);
   SetSessionRule(std::move(session_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(true /* null_opt_out */);
 
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInSession,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInSession,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
   EXPECT_EQ(1UL, passed_reasons_.size());
-  EXPECT_EQ(BlacklistReason::kBlacklistNotLoaded, passed_reasons_[0]);
+  EXPECT_EQ(BlocklistReason::kBlocklistNotLoaded, passed_reasons_[0]);
 }
 
-TEST_F(OptOutBlacklistTest, PassedReasonsWhenUserBlacklisted) {
-  // Test that IsLoadedAndAllow, push checked BlacklistReasons to the
+TEST_F(OptOutBlocklistTest, PassedReasonsWhenUserBlocklisted) {
+  // Test that IsLoadedAndAllow, push checked BlocklistReasons to the
   // |passed_reasons| vector.
   const std::string hosts[] = {
-      "http://www.url_0.com", "http://www.url_1.com", "http://www.url_2.com",
+      "http://www.url_0.com",
+      "http://www.url_1.com",
+      "http://www.url_2.com",
       "http://www.url_3.com",
   };
 
-  auto session_policy = std::make_unique<BlacklistData::Policy>(
+  auto session_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromSeconds(1), 1u, 1);
   SetSessionRule(std::move(session_policy));
-  auto persistent_policy = std::make_unique<BlacklistData::Policy>(
+  auto persistent_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, 4);
   SetPersistentRule(std::move(persistent_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
@@ -1089,18 +1094,18 @@
   test_clock_.Advance(base::TimeDelta::FromSeconds(1));
 
   for (auto host : hosts) {
-    black_list_->AddEntry(host, true, 1);
+    block_list_->AddEntry(host, true, 1);
   }
 
   test_clock_.Advance(base::TimeDelta::FromSeconds(2));
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutInGeneral,
-      black_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutInGeneral,
+      block_list_->IsLoadedAndAllowed(hosts[0], 1, false, &passed_reasons_));
 
-  BlacklistReason expected_reasons[] = {
-      BlacklistReason::kBlacklistNotLoaded,
-      BlacklistReason::kUserOptedOutInSession,
+  BlocklistReason expected_reasons[] = {
+      BlocklistReason::kBlocklistNotLoaded,
+      BlocklistReason::kUserOptedOutInSession,
   };
   EXPECT_EQ(base::size(expected_reasons), passed_reasons_.size());
   for (size_t i = 0; i < passed_reasons_.size(); i++) {
@@ -1108,36 +1113,36 @@
   }
 }
 
-TEST_F(OptOutBlacklistTest, PassedReasonsWhenHostBlacklisted) {
-  // Test that IsLoadedAndAllow, push checked BlacklistReasons to the
+TEST_F(OptOutBlocklistTest, PassedReasonsWhenHostBlocklisted) {
+  // Test that IsLoadedAndAllow, push checked BlocklistReasons to the
   // |passed_reasons| vector.
 
-  auto session_policy = std::make_unique<BlacklistData::Policy>(
+  auto session_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(5), 3u, 3);
   SetSessionRule(std::move(session_policy));
-  auto persistent_policy = std::make_unique<BlacklistData::Policy>(
+  auto persistent_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, 4);
   SetPersistentRule(std::move(persistent_policy));
-  auto host_policy = std::make_unique<BlacklistData::Policy>(
+  auto host_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(30), 4u, 2);
   SetHostRule(std::move(host_policy), 2);
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(true /* null_opt_out */);
 
-  black_list_->AddEntry(kTestHost1, true, 1);
-  black_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
+  block_list_->AddEntry(kTestHost1, true, 1);
 
   EXPECT_EQ(
-      BlacklistReason::kUserOptedOutOfHost,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kUserOptedOutOfHost,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
 
-  BlacklistReason expected_reasons[] = {
-      BlacklistReason::kBlacklistNotLoaded,
-      BlacklistReason::kUserOptedOutInSession,
-      BlacklistReason::kUserOptedOutInGeneral,
+  BlocklistReason expected_reasons[] = {
+      BlocklistReason::kBlocklistNotLoaded,
+      BlocklistReason::kUserOptedOutInSession,
+      BlocklistReason::kUserOptedOutInGeneral,
   };
   EXPECT_EQ(base::size(expected_reasons), passed_reasons_.size());
   for (size_t i = 0; i < passed_reasons_.size(); i++) {
@@ -1145,38 +1150,38 @@
   }
 }
 
-TEST_F(OptOutBlacklistTest, PassedReasonsWhenAllowed) {
-  // Test that IsLoadedAndAllow, push checked BlacklistReasons to the
+TEST_F(OptOutBlocklistTest, PassedReasonsWhenAllowed) {
+  // Test that IsLoadedAndAllow, push checked BlocklistReasons to the
   // |passed_reasons| vector.
 
-  auto session_policy = std::make_unique<BlacklistData::Policy>(
+  auto session_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromSeconds(1), 1u, 1);
   SetSessionRule(std::move(session_policy));
-  auto persistent_policy = std::make_unique<BlacklistData::Policy>(
+  auto persistent_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(365), 4u, 4);
   SetPersistentRule(std::move(persistent_policy));
-  auto host_policy = std::make_unique<BlacklistData::Policy>(
+  auto host_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(30), 4u, 4);
   SetHostRule(std::move(host_policy), 1);
-  auto type_policy = std::make_unique<BlacklistData::Policy>(
+  auto type_policy = std::make_unique<BlocklistData::Policy>(
       base::TimeDelta::FromDays(30), 4u, 4);
   SetTypeRule(std::move(type_policy));
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetAllowedTypes(std::move(allowed_types));
 
   StartTest(true /* null_opt_out */);
 
   EXPECT_EQ(
-      BlacklistReason::kAllowed,
-      black_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
+      BlocklistReason::kAllowed,
+      block_list_->IsLoadedAndAllowed(kTestHost1, 1, false, &passed_reasons_));
 
-  BlacklistReason expected_reasons[] = {
-      BlacklistReason::kBlacklistNotLoaded,
-      BlacklistReason::kUserOptedOutInSession,
-      BlacklistReason::kUserOptedOutInGeneral,
-      BlacklistReason::kUserOptedOutOfHost,
-      BlacklistReason::kUserOptedOutOfType,
+  BlocklistReason expected_reasons[] = {
+      BlocklistReason::kBlocklistNotLoaded,
+      BlocklistReason::kUserOptedOutInSession,
+      BlocklistReason::kUserOptedOutInGeneral,
+      BlocklistReason::kUserOptedOutOfHost,
+      BlocklistReason::kUserOptedOutOfType,
   };
   EXPECT_EQ(base::size(expected_reasons), passed_reasons_.size());
   for (size_t i = 0; i < passed_reasons_.size(); i++) {
@@ -1186,4 +1191,4 @@
 
 }  // namespace
 
-}  // namespace blacklist
+}  // namespace blocklist
diff --git a/components/blacklist/opt_out_blacklist/opt_out_store.h b/components/blacklist/opt_out_blacklist/opt_out_store.h
index d5a49326..7c03c3d 100644
--- a/components/blacklist/opt_out_blacklist/opt_out_store.h
+++ b/components/blacklist/opt_out_blacklist/opt_out_store.h
@@ -14,12 +14,12 @@
 #include "base/time/time.h"
 #include "components/blacklist/opt_out_blacklist/opt_out_blacklist_data.h"
 
-namespace blacklist {
+namespace blocklist {
 
-typedef base::OnceCallback<void(std::unique_ptr<BlacklistData>)>
-    LoadBlackListCallback;
+typedef base::OnceCallback<void(std::unique_ptr<BlocklistData>)>
+    LoadBlockListCallback;
 
-// OptOutStore keeps opt out information for the blacklist.
+// OptOutStore keeps opt out information for the blocklist.
 // Ability to create multiple instances of the store as well as behavior of
 // asynchronous operations when the object is being destroyed, before such
 // operation finishes will depend on implementation. It is possible to issue
@@ -35,15 +35,15 @@
                         int type,
                         base::Time now) = 0;
 
-  // Asynchronously loads a map of host names to OptOutBlacklistItem for that
+  // Asynchronously loads a map of host names to OptOutBlocklistItem for that
   // host from the store. And runs |callback| once loading is finished.
-  virtual void LoadBlackList(std::unique_ptr<BlacklistData> blacklist_data,
-                             LoadBlackListCallback callback) = 0;
+  virtual void LoadBlockList(std::unique_ptr<BlocklistData> blocklist_data,
+                             LoadBlockListCallback callback) = 0;
 
   // Deletes all history in the store between |begin_time| and |end_time|.
-  virtual void ClearBlackList(base::Time begin_time, base::Time end_time) = 0;
+  virtual void ClearBlockList(base::Time begin_time, base::Time end_time) = 0;
 };
 
-}  // namespace blacklist
+}  // namespace blocklist
 
 #endif  // COMPONENTS_BLACKLIST_OPT_OUT_BLACKLIST_OPT_OUT_STORE_H_
diff --git a/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.cc b/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.cc
index f4cf3dcc..6f693c6b 100644
--- a/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.cc
+++ b/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.cc
@@ -26,7 +26,7 @@
 #include "sql/statement.h"
 #include "sql/transaction.h"
 
-namespace blacklist {
+namespace blocklist {
 
 namespace {
 
@@ -46,7 +46,7 @@
   return base::StringToInt(max_rows, &value) ? value : 32;
 }
 
-// Returns the maximum number of table rows allowed for the blacklist opt out
+// Returns the maximum number of table rows allowed for the blocklist opt out
 // store. This is enforced during load time; thus the database can grow
 // larger than this temporarily.
 int MaxRowsInOptOutDB() {
@@ -126,6 +126,8 @@
   // The total size of the database will be capped at 3200 entries.
   db->set_page_size(4096);
   db->set_cache_size(250);
+  // TODO(crbug.com/1092101): Migrate to OptOutBlocklist and update any backend
+  // code that may depend on this tag.
   db->set_histogram_tag("OptOutBlacklist");
   db->set_exclusive_locking();
 
@@ -186,7 +188,7 @@
 }
 
 // Deletes every entry for |type|.
-void ClearBlacklistForTypeInDataBase(sql::Database* db, int type) {
+void ClearBlocklistForTypeInDataBase(sql::Database* db, int type) {
   static const char kSql[] =
       "DELETE FROM " OPT_OUT_TABLE_NAME " WHERE type == ?";
   sql::Statement statement(db->GetUniqueStatement(kSql));
@@ -196,14 +198,14 @@
 
 // Retrieves the list of previously enabled types with their version from the
 // Enabled table.
-BlacklistData::AllowedTypesAndVersions GetStoredEntries(sql::Database* db) {
+BlocklistData::AllowedTypesAndVersions GetStoredEntries(sql::Database* db) {
   static const char kSqlLoadEnabledTypesVersions[] =
       "SELECT type, version FROM " ENABLED_TYPES_TABLE_NAME;
 
   sql::Statement statement(
       db->GetUniqueStatement(kSqlLoadEnabledTypesVersions));
 
-  BlacklistData::AllowedTypesAndVersions stored_entries;
+  BlocklistData::AllowedTypesAndVersions stored_entries;
   while (statement.Step()) {
     int type = statement.ColumnInt(0);
     int version = statement.ColumnInt(1);
@@ -240,11 +242,11 @@
 
 // Checks the current set of enabled types (with their current version)
 // and where a type is now disabled or has a different version, cleans up
-// any associated blacklist entries.
+// any associated blocklist entries.
 void CheckAndReconcileEnabledTypesWithDataBase(
     sql::Database* db,
-    const BlacklistData::AllowedTypesAndVersions& allowed_types) {
-  BlacklistData::AllowedTypesAndVersions stored_entries = GetStoredEntries(db);
+    const BlocklistData::AllowedTypesAndVersions& allowed_types) {
+  BlocklistData::AllowedTypesAndVersions stored_entries = GetStoredEntries(db);
 
   for (auto enabled_it : allowed_types) {
     int type = enabled_it.first;
@@ -255,7 +257,7 @@
     } else {
       if (stored_it->second != current_version) {
         DCHECK_GE(current_version, stored_it->second);
-        ClearBlacklistForTypeInDataBase(db, type);
+        ClearBlocklistForTypeInDataBase(db, type);
         UpdateEnabledTypesInDataBase(db, type, current_version);
       }
     }
@@ -266,14 +268,14 @@
   // it'll still be around for the next time it is used.
 }
 
-void LoadBlackListFromDataBase(
+void LoadBlockListFromDataBase(
     sql::Database* db,
-    std::unique_ptr<BlacklistData> blacklist_data,
+    std::unique_ptr<BlocklistData> blocklist_data,
     scoped_refptr<base::SingleThreadTaskRunner> runner,
-    LoadBlackListCallback callback) {
+    LoadBlockListCallback callback) {
   // First handle any update needed wrt enabled types and their versions.
   CheckAndReconcileEnabledTypesWithDataBase(db,
-                                            blacklist_data->allowed_types());
+                                            blocklist_data->allowed_types());
 
   // Gets the table sorted by host and time. Limits the number of hosts using
   // most recent opt_out time as the limiting function. Sorting is free due to
@@ -287,7 +289,7 @@
   int count = 0;
   while (statement.Step()) {
     ++count;
-    blacklist_data->AddEntry(statement.ColumnString(0), statement.ColumnBool(2),
+    blocklist_data->AddEntry(statement.ColumnString(0), statement.ColumnBool(2),
                              statement.ColumnInt64(3),
                              base::Time() + base::TimeDelta::FromMicroseconds(
                                                 statement.ColumnInt64(1)),
@@ -311,26 +313,26 @@
   }
 
   runner->PostTask(FROM_HERE, base::BindOnce(std::move(callback),
-                                             std::move(blacklist_data)));
+                                             std::move(blocklist_data)));
 }
 
 // Synchronous implementations, these are run on the background thread
 // and actually do the work to access the SQL data base.
-void LoadBlackListSync(sql::Database* db,
+void LoadBlockListSync(sql::Database* db,
                        const base::FilePath& path,
-                       std::unique_ptr<BlacklistData> blacklist_data,
+                       std::unique_ptr<BlocklistData> blocklist_data,
                        scoped_refptr<base::SingleThreadTaskRunner> runner,
-                       LoadBlackListCallback callback) {
+                       LoadBlockListCallback callback) {
   if (!db->is_open())
     InitDatabase(db, path);
 
-  LoadBlackListFromDataBase(db, std::move(blacklist_data), runner,
+  LoadBlockListFromDataBase(db, std::move(blocklist_data), runner,
                             std::move(callback));
 }
 
 // Deletes every row in the table that has entry time between |begin_time| and
 // |end_time|.
-void ClearBlackListSync(sql::Database* db,
+void ClearBlockListSync(sql::Database* db,
                         base::Time begin_time,
                         base::Time end_time) {
   static const char kSql[] =
@@ -383,26 +385,26 @@
       base::BindOnce(&AddEntrySync, opt_out, host_name, type, now, db_.get()));
 }
 
-void OptOutStoreSQL::ClearBlackList(base::Time begin_time,
+void OptOutStoreSQL::ClearBlockList(base::Time begin_time,
                                     base::Time end_time) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   DCHECK(db_);
   background_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&ClearBlackListSync, db_.get(), begin_time, end_time));
+      base::BindOnce(&ClearBlockListSync, db_.get(), begin_time, end_time));
 }
 
-void OptOutStoreSQL::LoadBlackList(
-    std::unique_ptr<BlacklistData> blacklist_data,
-    LoadBlackListCallback callback) {
+void OptOutStoreSQL::LoadBlockList(
+    std::unique_ptr<BlocklistData> blocklist_data,
+    LoadBlockListCallback callback) {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
   if (!db_)
     db_ = std::make_unique<sql::Database>();
   background_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(&LoadBlackListSync, db_.get(), db_file_path_,
-                     std::move(blacklist_data),
+      base::BindOnce(&LoadBlockListSync, db_.get(), db_file_path_,
+                     std::move(blocklist_data),
                      base::ThreadTaskRunnerHandle::Get(), std::move(callback)));
 }
 
-}  // namespace blacklist
+}  // namespace blocklist
diff --git a/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.h b/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.h
index 9ec0f270..c1043ef 100644
--- a/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.h
+++ b/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql.h
@@ -26,7 +26,7 @@
 class Database;
 }  // namespace sql
 
-namespace blacklist {
+namespace blocklist {
 
 // OptOutStoreSQL is an instance of OptOutStore
 // which is implemented using a SQLite database.
@@ -43,9 +43,9 @@
                 const std::string& host_name,
                 int type,
                 base::Time now) override;
-  void ClearBlackList(base::Time begin_time, base::Time end_time) override;
-  void LoadBlackList(std::unique_ptr<BlacklistData> blacklist_data,
-                     LoadBlackListCallback callback) override;
+  void ClearBlockList(base::Time begin_time, base::Time end_time) override;
+  void LoadBlockList(std::unique_ptr<BlocklistData> blocklist_data,
+                     LoadBlockListCallback callback) override;
 
  private:
   // Thread this object is accessed on.
@@ -63,6 +63,6 @@
   DISALLOW_COPY_AND_ASSIGN(OptOutStoreSQL);
 };
 
-}  // namespace blacklist
+}  // namespace blocklist
 
 #endif  // COMPONENTS_BLACKLIST_OPT_OUT_BLACKLIST_SQL_OPT_OUT_STORE_SQL_H_
diff --git a/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc b/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc
index 053b516c..d8ce2fc 100644
--- a/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc
+++ b/components/blacklist/opt_out_blacklist/sql/opt_out_store_sql_unittest.cc
@@ -26,7 +26,7 @@
 #include "sql/test/test_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
-namespace blacklist {
+namespace blocklist {
 
 namespace {
 
@@ -40,23 +40,23 @@
   ~OptOutStoreSQLTest() override {}
 
   // Called when |store_| is done loading.
-  void OnLoaded(std::unique_ptr<BlacklistData> blacklist_data) {
-    blacklist_data_ = std::move(blacklist_data);
+  void OnLoaded(std::unique_ptr<BlocklistData> blocklist_data) {
+    blocklist_data_ = std::move(blocklist_data);
   }
 
   // Initializes the store and get the data from it.
   void Load() {
     // Choose reasonable constants.
-    std::unique_ptr<BlacklistData> data = std::make_unique<BlacklistData>(
-        std::make_unique<BlacklistData::Policy>(base::TimeDelta::FromMinutes(5),
+    std::unique_ptr<BlocklistData> data = std::make_unique<BlocklistData>(
+        std::make_unique<BlocklistData::Policy>(base::TimeDelta::FromMinutes(5),
                                                 1, 1),
-        std::make_unique<BlacklistData::Policy>(base::TimeDelta::FromDays(30),
+        std::make_unique<BlocklistData::Policy>(base::TimeDelta::FromDays(30),
                                                 10, 6u),
-        std::make_unique<BlacklistData::Policy>(base::TimeDelta::FromDays(30),
+        std::make_unique<BlocklistData::Policy>(base::TimeDelta::FromDays(30),
                                                 4, 2u),
         nullptr, 10, allowed_types_);
 
-    store_->LoadBlackList(
+    store_->LoadBlockList(
         std::move(data),
         base::BindOnce(&OptOutStoreSQLTest::OnLoaded, base::Unretained(this)));
     base::RunLoop().RunUntilIdle();
@@ -82,7 +82,7 @@
     Load();
   }
 
-  void SetEnabledTypes(BlacklistData::AllowedTypesAndVersions allowed_types) {
+  void SetEnabledTypes(BlocklistData::AllowedTypesAndVersions allowed_types) {
     allowed_types_ = std::move(allowed_types);
   }
 
@@ -99,19 +99,19 @@
   std::unique_ptr<OptOutStoreSQL> store_;
 
   // The map returned from |store_|.
-  std::unique_ptr<BlacklistData> blacklist_data_;
+  std::unique_ptr<BlocklistData> blocklist_data_;
 
   // The directory for the database.
   base::ScopedTempDir temp_dir_;
 
  private:
-  BlacklistData::AllowedTypesAndVersions allowed_types_;
+  BlocklistData::AllowedTypesAndVersions allowed_types_;
 };
 
 TEST_F(OptOutStoreSQLTest, TestErrorRecovery) {
   // Creates the database and corrupt to test the recovery method.
   std::string test_host = "host.com";
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
@@ -129,18 +129,18 @@
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
   // The data should be recovered.
-  EXPECT_EQ(1U, blacklist_data_->black_list_item_host_map().size());
+  EXPECT_EQ(1U, blocklist_data_->block_list_item_host_map().size());
   const auto& iter =
-      blacklist_data_->black_list_item_host_map().find(test_host);
+      blocklist_data_->block_list_item_host_map().find(test_host);
 
-  EXPECT_NE(blacklist_data_->black_list_item_host_map().end(), iter);
+  EXPECT_NE(blocklist_data_->block_list_item_host_map().end(), iter);
   EXPECT_EQ(1U, iter->second.OptOutRecordsSizeForTesting());
 }
 
 TEST_F(OptOutStoreSQLTest, TestPersistance) {
   // Tests if data is stored as expected in the SQLite database.
   std::string test_host = "host.com";
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
@@ -157,11 +157,11 @@
   allowed_types.insert({1, 0});
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
-  EXPECT_EQ(1U, blacklist_data_->black_list_item_host_map().size());
+  EXPECT_EQ(1U, blocklist_data_->block_list_item_host_map().size());
   const auto& iter =
-      blacklist_data_->black_list_item_host_map().find(test_host);
+      blocklist_data_->block_list_item_host_map().find(test_host);
 
-  EXPECT_NE(blacklist_data_->black_list_item_host_map().end(), iter);
+  EXPECT_NE(blocklist_data_->block_list_item_host_map().end(), iter);
   EXPECT_EQ(1U, iter->second.OptOutRecordsSizeForTesting());
   EXPECT_EQ(now, iter->second.most_recent_opt_out_time().value());
 }
@@ -176,7 +176,7 @@
   size_t row_limit = 2;
   std::string row_limit_string = base::NumberToString(row_limit);
   command_line->AppendSwitchASCII("max-opt-out-rows", row_limit_string);
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
@@ -203,7 +203,7 @@
   CreateAndLoad();
   // The delete happens after the load, so it is possible to load more than
   // |row_limit| into the in memory map.
-  EXPECT_EQ(row_limit + 1, blacklist_data_->black_list_item_host_map().size());
+  EXPECT_EQ(row_limit + 1, blocklist_data_->block_list_item_host_map().size());
 
   DestroyStore();
   allowed_types.clear();
@@ -211,16 +211,16 @@
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
 
-  EXPECT_EQ(row_limit, blacklist_data_->black_list_item_host_map().size());
+  EXPECT_EQ(row_limit, blocklist_data_->block_list_item_host_map().size());
   const auto& iter_host_b =
-      blacklist_data_->black_list_item_host_map().find(test_host_b);
+      blocklist_data_->block_list_item_host_map().find(test_host_b);
   const auto& iter_host_c =
-      blacklist_data_->black_list_item_host_map().find(test_host_c);
+      blocklist_data_->block_list_item_host_map().find(test_host_c);
 
-  EXPECT_EQ(blacklist_data_->black_list_item_host_map().end(),
-            blacklist_data_->black_list_item_host_map().find(test_host_a));
-  EXPECT_NE(blacklist_data_->black_list_item_host_map().end(), iter_host_b);
-  EXPECT_NE(blacklist_data_->black_list_item_host_map().end(), iter_host_c);
+  EXPECT_EQ(blocklist_data_->block_list_item_host_map().end(),
+            blocklist_data_->block_list_item_host_map().find(test_host_a));
+  EXPECT_NE(blocklist_data_->block_list_item_host_map().end(), iter_host_b);
+  EXPECT_NE(blocklist_data_->block_list_item_host_map().end(), iter_host_c);
   EXPECT_EQ(host_b_time,
             iter_host_b->second.most_recent_opt_out_time().value());
   EXPECT_EQ(1U, iter_host_b->second.OptOutRecordsSizeForTesting());
@@ -234,7 +234,7 @@
   std::string row_limit_string = base::NumberToString(row_limit);
   command_line->AppendSwitchASCII("max-opt-out-rows-per-host",
                                   row_limit_string);
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 0});
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
@@ -261,23 +261,23 @@
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
 
-  EXPECT_EQ(1U, blacklist_data_->black_list_item_host_map().size());
+  EXPECT_EQ(1U, blocklist_data_->block_list_item_host_map().size());
   const auto& iter =
-      blacklist_data_->black_list_item_host_map().find(test_host);
+      blocklist_data_->block_list_item_host_map().find(test_host);
 
-  EXPECT_NE(blacklist_data_->black_list_item_host_map().end(), iter);
+  EXPECT_NE(blocklist_data_->block_list_item_host_map().end(), iter);
   EXPECT_EQ(last_opt_out_time, iter->second.most_recent_opt_out_time().value());
   EXPECT_EQ(row_limit, iter->second.OptOutRecordsSizeForTesting());
   clock.Advance(base::TimeDelta::FromSeconds(1));
   // If both entries' opt out states are stored correctly, then this should not
-  // be black listed.
-  EXPECT_FALSE(iter->second.IsBlackListed(clock.Now()));
+  // be block listed.
+  EXPECT_FALSE(iter->second.IsBlockListed(clock.Now()));
 }
 
-TEST_F(OptOutStoreSQLTest, TestTypesVersionUpdateClearsBlacklistEntry) {
+TEST_F(OptOutStoreSQLTest, TestTypesVersionUpdateClearsBlocklistEntry) {
   // Tests if data is cleared for new version of type.
   std::string test_host = "host.com";
-  BlacklistData::AllowedTypesAndVersions allowed_types;
+  BlocklistData::AllowedTypesAndVersions allowed_types;
   allowed_types.insert({1, 1});
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
@@ -285,7 +285,7 @@
   store_->AddEntry(true, test_host, 1, now);
   base::RunLoop().RunUntilIdle();
 
-  // Force data write to database then reload it and verify black list entry
+  // Force data write to database then reload it and verify block list entry
   // is present.
   DestroyStore();
   allowed_types.clear();
@@ -293,8 +293,8 @@
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
   const auto& iter =
-      blacklist_data_->black_list_item_host_map().find(test_host);
-  EXPECT_NE(blacklist_data_->black_list_item_host_map().end(), iter);
+      blocklist_data_->block_list_item_host_map().find(test_host);
+  EXPECT_NE(blocklist_data_->block_list_item_host_map().end(), iter);
   EXPECT_EQ(1U, iter->second.OptOutRecordsSizeForTesting());
 
   DestroyStore();
@@ -303,8 +303,8 @@
   SetEnabledTypes(std::move(allowed_types));
   CreateAndLoad();
   const auto& iter2 =
-      blacklist_data_->black_list_item_host_map().find(test_host);
-  EXPECT_EQ(blacklist_data_->black_list_item_host_map().end(), iter2);
+      blocklist_data_->block_list_item_host_map().find(test_host);
+  EXPECT_EQ(blocklist_data_->block_list_item_host_map().end(), iter2);
 }
 
-}  // namespace blacklist
+}  // namespace blocklist
diff --git a/components/browser_ui/share/DEPS b/components/browser_ui/share/DEPS
index b7c84e1..876f134 100644
--- a/components/browser_ui/share/DEPS
+++ b/components/browser_ui/share/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+chrome/android/java/src/org/chromium/chrome/browser/FileProviderHelper.java",
   "+components/dom_distiller/core/android",
   "+content/public/android",
   "+content/public/test/android/javatests",
diff --git a/components/browser_ui/share/android/BUILD.gn b/components/browser_ui/share/android/BUILD.gn
index 929f90830..06343f4 100644
--- a/components/browser_ui/share/android/BUILD.gn
+++ b/components/browser_ui/share/android/BUILD.gn
@@ -41,6 +41,7 @@
     ":java",
     "//base:base_java",
     "//base:base_java_test_support",
+    "//chrome/android:chrome_java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_deps:androidx_appcompat_appcompat_java",
     "//third_party/android_deps:androidx_core_core_java",
diff --git a/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareImageFileUtilsTest.java b/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareImageFileUtilsTest.java
index 9385dcb3..e9da72c 100644
--- a/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareImageFileUtilsTest.java
+++ b/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareImageFileUtilsTest.java
@@ -19,7 +19,6 @@
 import android.provider.MediaStore;
 import android.support.test.filters.SmallTest;
 
-import androidx.core.content.FileProvider;
 import androidx.core.util.ObjectsCompat;
 
 import org.junit.Assert;
@@ -35,6 +34,7 @@
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
+import org.chromium.chrome.browser.FileProviderHelper;
 import org.chromium.content_public.browser.test.util.Criteria;
 import org.chromium.content_public.browser.test.util.CriteriaHelper;
 import org.chromium.ui.base.Clipboard;
@@ -57,17 +57,6 @@
     private static final String TEST_JPG_IMAGE_FILE_EXTENSION = ".jpg";
     private static final String TEST_PNG_IMAGE_FILE_EXTENSION = ".png";
 
-    private class FileProviderHelper implements ContentUriUtils.FileProviderUtil {
-        private static final String API_AUTHORITY_SUFFIX = ".FileProvider";
-
-        @Override
-        public Uri getContentUriFromFile(File file) {
-            Context appContext = ContextUtils.getApplicationContext();
-            return FileProvider.getUriForFile(
-                    appContext, appContext.getPackageName() + API_AUTHORITY_SUFFIX, file);
-        }
-    }
-
     private class GenerateUriCallback extends CallbackHelper implements Callback<Uri> {
         private Uri mImageUri;
 
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
index b57a117ed..ae7feef 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -611,7 +611,8 @@
                     new ChromeImageViewPreference(getStyledContext());
 
             preference.setKey(CHOOSER_PERMISSION_PREFERENCE_KEY);
-            preference.setIcon(ContentSettingsResources.getIcon(info.getContentSettingsType()));
+            preference.setIcon(SettingsUtils.getTintedIcon(getActivity(),
+                    ContentSettingsResources.getIcon(info.getContentSettingsType())));
             preference.setOrder(maxPermissionOrder);
             preference.setTitle(info.getName());
             preference.setImageView(R.drawable.ic_delete_white_24dp,
diff --git a/components/cdm/browser/BUILD.gn b/components/cdm/browser/BUILD.gn
index af49e12..f85eaad 100644
--- a/components/cdm/browser/BUILD.gn
+++ b/components/cdm/browser/BUILD.gn
@@ -12,6 +12,7 @@
 
   public_deps = [
     "//base",
+    "//base/util/values:values_util",
     "//content/public/browser",
     "//media/mojo/mojom",
     "//url",
diff --git a/components/cdm/browser/media_drm_storage_impl.cc b/components/cdm/browser/media_drm_storage_impl.cc
index 22f0587..cb8b09a 100644
--- a/components/cdm/browser/media_drm_storage_impl.cc
+++ b/components/cdm/browser/media_drm_storage_impl.cc
@@ -14,7 +14,7 @@
 #include "base/no_destructor.h"
 #include "base/optional.h"
 #include "base/strings/string_util.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "build/build_config.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/pref_service.h"
@@ -147,7 +147,7 @@
   base::Value ToDictValue() const {
     base::Value dict(base::Value::Type::DICTIONARY);
 
-    dict.SetKey(kOriginId, base::CreateUnguessableTokenValue(origin_id_));
+    dict.SetKey(kOriginId, util::UnguessableTokenToValue(origin_id_));
     dict.SetKey(kCreationTime, base::Value(provision_time_.ToDoubleT()));
 
     return dict;
@@ -165,15 +165,16 @@
     if (!origin_id_value)
       return nullptr;
 
-    base::UnguessableToken origin_id;
-    if (!base::GetValueAsUnguessableToken(*origin_id_value, &origin_id))
+    base::Optional<base::UnguessableToken> origin_id =
+        util::ValueToUnguessableToken(*origin_id_value);
+    if (!origin_id)
       return nullptr;
 
     base::Time time;
     if (!GetCreationTimeFromDict(origin_dict, &time))
       return nullptr;
 
-    return base::WrapUnique(new OriginData(origin_id, time));
+    return base::WrapUnique(new OriginData(*origin_id, time));
   }
 
  private:
diff --git a/components/chromeos_camera/BUILD.gn b/components/chromeos_camera/BUILD.gn
index 562adf8..045fab8 100644
--- a/components/chromeos_camera/BUILD.gn
+++ b/components/chromeos_camera/BUILD.gn
@@ -189,6 +189,19 @@
   }
 }
 
+source_set("camera_app_helper") {
+  sources = [
+    "camera_app_helper_impl.cc",
+    "camera_app_helper_impl.h",
+  ]
+
+  deps = [
+    "common:camera_app_helper",
+    "//ash/public/cpp",
+    "//ui/aura",
+  ]
+}
+
 test("jpeg_decode_accelerator_unittest") {
   deps = [
     ":mjpeg_decode_accelerator",
diff --git a/components/chromeos_camera/DEPS b/components/chromeos_camera/DEPS
index 995c9eb..ad030f9 100644
--- a/components/chromeos_camera/DEPS
+++ b/components/chromeos_camera/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
+  "+ash/public/cpp",
   "+media",
   "+mojo",
   "+third_party/libyuv",
diff --git a/chromeos/components/camera_app_ui/camera_app_helper_impl.cc b/components/chromeos_camera/camera_app_helper_impl.cc
similarity index 96%
rename from chromeos/components/camera_app_ui/camera_app_helper_impl.cc
rename to components/chromeos_camera/camera_app_helper_impl.cc
index 80d3814..cb4a5c8 100644
--- a/chromeos/components/camera_app_ui/camera_app_helper_impl.cc
+++ b/components/chromeos_camera/camera_app_helper_impl.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 "chromeos/components/camera_app_ui/camera_app_helper_impl.h"
+#include "components/chromeos_camera/camera_app_helper_impl.h"
 
 #include <utility>
 
diff --git a/chromeos/components/camera_app_ui/camera_app_helper_impl.h b/components/chromeos_camera/camera_app_helper_impl.h
similarity index 87%
rename from chromeos/components/camera_app_ui/camera_app_helper_impl.h
rename to components/chromeos_camera/camera_app_helper_impl.h
index b5d6eab..b1b8f2c 100644
--- a/chromeos/components/camera_app_ui/camera_app_helper_impl.h
+++ b/components/chromeos_camera/camera_app_helper_impl.h
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_HELPER_IMPL_H_
-#define CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_HELPER_IMPL_H_
+#ifndef COMPONENTS_CHROMEOS_CAMERA_CAMERA_APP_HELPER_IMPL_H_
+#define COMPONENTS_CHROMEOS_CAMERA_CAMERA_APP_HELPER_IMPL_H_
 
 #include <vector>
 
 #include "ash/public/cpp/tablet_mode_observer.h"
 #include "base/macros.h"
-#include "chromeos/components/camera_app_ui/camera_app_helper.mojom.h"
+#include "components/chromeos_camera/common/camera_app_helper.mojom.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 namespace aura {
@@ -57,4 +57,4 @@
 
 }  // namespace chromeos_camera
 
-#endif  // CHROMEOS_COMPONENTS_CAMERA_APP_UI_CAMERA_APP_HELPER_IMPL_H_
+#endif  // COMPONENTS_CHROMEOS_CAMERA_CAMERA_APP_HELPER_IMPL_H_
diff --git a/components/chromeos_camera/common/BUILD.gn b/components/chromeos_camera/common/BUILD.gn
index d49f9e7..0385972 100644
--- a/components/chromeos_camera/common/BUILD.gn
+++ b/components/chromeos_camera/common/BUILD.gn
@@ -17,3 +17,8 @@
     "//ui/gfx/geometry/mojom",
   ]
 }
+
+mojom("camera_app_helper") {
+  sources = [ "camera_app_helper.mojom" ]
+  deps = [ "//components/arc/mojom:camera_intent" ]
+}
diff --git a/chromeos/components/camera_app_ui/camera_app_helper.mojom b/components/chromeos_camera/common/camera_app_helper.mojom
similarity index 100%
rename from chromeos/components/camera_app_ui/camera_app_helper.mojom
rename to components/chromeos_camera/common/camera_app_helper.mojom
diff --git a/components/cronet/host_cache_persistence_manager.cc b/components/cronet/host_cache_persistence_manager.cc
index e76a222..fc400fdd 100644
--- a/components/cronet/host_cache_persistence_manager.cc
+++ b/components/cronet/host_cache_persistence_manager.cc
@@ -7,7 +7,6 @@
 #include <memory>
 
 #include "base/bind.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/values.h"
 #include "components/prefs/pref_service.h"
 #include "net/log/net_log.h"
@@ -62,9 +61,6 @@
   net_log_.AddEntryWithBoolParams(net::NetLogEventType::HOST_CACHE_PREF_READ,
                                   net::NetLogEventPhase::END, "success",
                                   success);
-
-  UMA_HISTOGRAM_BOOLEAN("DNS.HostCache.RestoreSuccess", success);
-  UMA_HISTOGRAM_COUNTS_1000("DNS.HostCache.RestoreSize", pref_value->GetSize());
 }
 
 void HostCachePersistenceManager::ScheduleWrite() {
diff --git a/components/cronet/ios/test/cronet_metrics_test.mm b/components/cronet/ios/test/cronet_metrics_test.mm
index b7647b0..ac0f39b0b 100644
--- a/components/cronet/ios/test/cronet_metrics_test.mm
+++ b/components/cronet/ios/test/cronet_metrics_test.mm
@@ -65,7 +65,8 @@
 };
 
 // Tests that metrics data is sane for a QUIC request.
-TEST_F(CronetEnabledMetricsTest, ProtocolIsQuic) {
+// TODO(crbug.com/971378): This test is consistently failing.
+TEST_F(CronetEnabledMetricsTest, DISABLED_ProtocolIsQuic) {
   if (@available(iOS 10.2, *)) {
     NSURL* url = net::NSURLWithGURL(net::QuicSimpleTestServer::GetSimpleURL());
 
diff --git a/components/cronet/ios/test/cronet_quic_test.mm b/components/cronet/ios/test/cronet_quic_test.mm
index 5997946..b1436dd 100644
--- a/components/cronet/ios/test/cronet_quic_test.mm
+++ b/components/cronet/ios/test/cronet_quic_test.mm
@@ -86,7 +86,8 @@
 
 // Tests a request with enabled "enable_socket_recv_optimization" QUIC
 // experimental option.
-TEST_F(QuicTest, RequestWithSocketOptimizationEnabled) {
+// TODO(crbug.com/971378): This test is consistently failing.
+TEST_F(QuicTest, DISABLED_RequestWithSocketOptimizationEnabled) {
   // Apply test specific Cronet configuration and start it.
   [Cronet setExperimentalOptions:
               @"{\"QUIC\" : {\"enable_socket_recv_optimization\" : true} }"];
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
index a2d7bcb..4f086c18 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc
@@ -532,8 +532,8 @@
   service_->UpdatePrefetchProxyHosts(
       GetPrefetchProxyHosts(config.prefetch_proxy_config()));
 
-  service_->SetIgnoreLongTermBlackListRules(
-      config.ignore_long_term_black_list_rules());
+  service_->SetIgnoreLongTermBlockListRules(
+      config.ignore_long_term_block_list_rules());
 
   request_options_->SetSecureSession(config.session_key());
   remote_config_applied_ = true;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
index 0cf5af6..cb20b9d 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc
@@ -137,9 +137,9 @@
         kPersistedSessionKey, kConfigRefreshDurationSeconds, 0);
     loaded_config_ = EncodeConfig(persisted);
 
-    ClientConfig ignore_black_list_config = CreateClientConfig(
+    ClientConfig ignore_block_list_config = CreateClientConfig(
         kSuccessSessionKey, kConfigRefreshDurationSeconds, 0);
-    ignore_black_list_encoded_config_ = EncodeConfig(ignore_black_list_config);
+    ignore_block_list_encoded_config_ = EncodeConfig(ignore_block_list_config);
 
     ClientConfig no_proxies_config;
     no_proxies_config.set_session_key(kSuccessSessionKey);
@@ -179,11 +179,6 @@
     return test_context_->mock_request_options();
   }
 
-  bool ignore_blacklist() const {
-    return test_context_->test_data_reduction_proxy_service()
-        ->ignore_blacklist();
-  }
-
   void RunUntilIdle() { test_context_->RunUntilIdle(); }
 
   void AddMockSuccess() {
@@ -217,8 +212,8 @@
   const std::string& previous_success_response() const {
     return previous_config_;
   }
-  const std::string& ignore_black_list_encoded_config() const {
-    return ignore_black_list_encoded_config_;
+  const std::string& ignore_block_list_encoded_config() const {
+    return ignore_block_list_encoded_config_;
   }
   const std::string& no_proxies_config() const { return no_proxies_config_; }
 
@@ -249,8 +244,8 @@
   // An encoded config that represents a previously saved configuration.
   std::string loaded_config_;
 
-  // A configuration where the black list rules are ignored.
-  std::string ignore_black_list_encoded_config_;
+  // A configuration where the block list rules are ignored.
+  std::string ignore_block_list_encoded_config_;
 
   // A configuration where no proxies are configured.
   std::string no_proxies_config_;
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
index c2a6dfc5..edd615b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.cc
@@ -298,10 +298,10 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 }
 
-void DataReductionProxyService::SetIgnoreLongTermBlackListRules(
-    bool ignore_long_term_black_list_rules) {
+void DataReductionProxyService::SetIgnoreLongTermBlockListRules(
+    bool ignore_long_term_block_list_rules) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  settings_->SetIgnoreLongTermBlackListRules(ignore_long_term_black_list_rules);
+  settings_->SetIgnoreLongTermBlockListRules(ignore_long_term_block_list_rules);
 }
 
 void DataReductionProxyService::AddCustomProxyConfigClient(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
index 8a110be..669f508 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h
@@ -124,9 +124,9 @@
     settings_ = settings;
   }
 
-  // When triggering previews, prevent long term black list rules. Virtual for
+  // When triggering previews, prevent long term block list rules. Virtual for
   // testing.
-  virtual void SetIgnoreLongTermBlackListRules(
+  virtual void SetIgnoreLongTermBlockListRules(
       bool ignore_long_term_black_list_rules);
 
   // Returns the current network quality estimates.
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
index dc891a2..16ab568 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h
@@ -157,9 +157,9 @@
   // some of them should have.
   bool IsDataReductionProxyUnreachable();
 
-  // When triggering previews, prevent long term black list rules.
-  virtual void SetIgnoreLongTermBlackListRules(
-      bool ignore_long_term_black_list_rules) {}
+  // When triggering previews, prevent long term block list rules.
+  virtual void SetIgnoreLongTermBlockListRules(
+      bool ignore_long_term_block_list_rules) {}
 
   ContentLengthList GetDailyContentLengths(const char* pref_name);
 
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
index 160e6a3..482c87b 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc
@@ -236,9 +236,9 @@
 
 TestDataReductionProxyService::~TestDataReductionProxyService() {}
 
-void TestDataReductionProxyService::SetIgnoreLongTermBlackListRules(
-    bool ignore_long_term_black_list_rules) {
-  ignore_blacklist_ = ignore_long_term_black_list_rules;
+void TestDataReductionProxyService::SetIgnoreLongTermBlockListRules(
+    bool ignore_long_term_block_list_rules) {
+  ignore_blocklist_ = ignore_long_term_block_list_rules;
 }
 
 TestDataStore::TestDataStore() {}
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
index b7f6ced..42e465a 100644
--- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
+++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h
@@ -200,15 +200,15 @@
       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner);
   ~TestDataReductionProxyService() override;
 
-  // Records |ignore_long_term_black_list_rules| as |ignore_blacklist_|.
-  void SetIgnoreLongTermBlackListRules(
-      bool ignore_long_term_black_list_rules) override;
+  // Records |ignore_long_term_block_list_rules| as |ignore_blocklist_|.
+  void SetIgnoreLongTermBlockListRules(
+      bool ignore_long_term_block_list_rules) override;
 
-  bool ignore_blacklist() const { return ignore_blacklist_; }
+  bool ignore_blocklist() const { return ignore_blocklist_; }
 
  private:
-  // Whether the long term blacklist rules should be ignored.
-  bool ignore_blacklist_ = false;
+  // Whether the long term blocklist rules should be ignored.
+  bool ignore_blocklist_ = false;
 };
 
 // Test version of |DataStore|. Uses an in memory hash map to store data.
diff --git a/components/data_reduction_proxy/proto/client_config.proto b/components/data_reduction_proxy/proto/client_config.proto
index d0dc39b..58b9b0e 100644
--- a/components/data_reduction_proxy/proto/client_config.proto
+++ b/components/data_reduction_proxy/proto/client_config.proto
@@ -28,9 +28,9 @@
   // Configuration information for reporting pageload metrics.
   optional DeprecatedPageloadMetricsConfig pageload_metrics_config = 5
       [deprecated = true];
-  // Prevents the host base and user base blacklisting behaviors for lite pages
+  // Prevents the host base and user base blocklisting behaviors for lite pages
   // and server LoFi.
-  optional bool ignore_long_term_black_list_rules = 7 [deprecated = true];
+  optional bool ignore_long_term_block_list_rules = 7 [deprecated = true];
   // The configuration that the client should use to connect to the prefetch
   // proxy.
   optional PrefetchProxyConfig prefetch_proxy_config = 8;
diff --git a/components/download/public/common/download_schedule.cc b/components/download/public/common/download_schedule.cc
index 7a3672c..271d350 100644
--- a/components/download/public/common/download_schedule.cc
+++ b/components/download/public/common/download_schedule.cc
@@ -18,4 +18,9 @@
 
 DownloadSchedule::~DownloadSchedule() = default;
 
+bool DownloadSchedule::operator==(const DownloadSchedule& other) const {
+  return only_on_wifi_ == other.only_on_wifi() &&
+         start_time_ == other.start_time();
+}
+
 }  // namespace download
diff --git a/components/download/public/common/download_schedule.h b/components/download/public/common/download_schedule.h
index 4e57001..8b7107c8 100644
--- a/components/download/public/common/download_schedule.h
+++ b/components/download/public/common/download_schedule.h
@@ -20,6 +20,8 @@
   DownloadSchedule(const DownloadSchedule&);
   ~DownloadSchedule();
 
+  bool operator==(const DownloadSchedule&) const;
+
   bool only_on_wifi() const { return only_on_wifi_; }
 
   const base::Optional<base::Time>& start_time() const { return start_time_; }
diff --git a/components/feed/core/v2/BUILD.gn b/components/feed/core/v2/BUILD.gn
index 929a554b..e27fb66 100644
--- a/components/feed/core/v2/BUILD.gn
+++ b/components/feed/core/v2/BUILD.gn
@@ -82,6 +82,7 @@
 
   public_deps = [
     "//base",
+    "//base/util/values:values_util",
     "//components/feed/core/common:feed_core_common",
     "//components/feed/core/proto:proto_v2",
   ]
diff --git a/components/feed/core/v2/prefs.cc b/components/feed/core/v2/prefs.cc
index 535de50..41dc55c 100644
--- a/components/feed/core/v2/prefs.cc
+++ b/components/feed/core/v2/prefs.cc
@@ -6,7 +6,6 @@
 
 #include <utility>
 
-#include "base/value_conversions.h"
 #include "base/values.h"
 #include "components/feed/core/common/pref_names.h"
 #include "components/feed/core/v2/scheduling.h"
diff --git a/components/feed/core/v2/scheduling.cc b/components/feed/core/v2/scheduling.cc
index d65560e15..a198062 100644
--- a/components/feed/core/v2/scheduling.cc
+++ b/components/feed/core/v2/scheduling.cc
@@ -5,7 +5,7 @@
 #include "components/feed/core/v2/scheduling.h"
 
 #include "base/time/time.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "base/values.h"
 #include "components/feed/core/v2/config.h"
 
@@ -15,7 +15,7 @@
 base::Value VectorToValue(const std::vector<base::TimeDelta>& values) {
   base::Value result(base::Value::Type::LIST);
   for (base::TimeDelta delta : values) {
-    result.Append(CreateTimeDeltaValue(delta));
+    result.Append(util::TimeDeltaToValue(delta));
   }
   return result;
 }
@@ -25,10 +25,10 @@
   if (!value.is_list())
     return false;
   for (const base::Value& entry : value.GetList()) {
-    base::TimeDelta delta;
-    if (!GetValueAsTimeDelta(entry, &delta))
+    base::Optional<base::TimeDelta> delta = util::ValueToTimeDelta(entry);
+    if (!delta)
       return false;
-    result->push_back(delta);
+    result->push_back(*delta);
   }
   return true;
 }
@@ -41,7 +41,7 @@
 
 base::Value RequestScheduleToValue(const RequestSchedule& schedule) {
   base::Value result(base::Value::Type::DICTIONARY);
-  result.SetKey("anchor", CreateTimeValue(schedule.anchor_time));
+  result.SetKey("anchor", util::TimeToValue(schedule.anchor_time));
   result.SetKey("offsets", VectorToValue(schedule.refresh_offsets));
   return result;
 }
@@ -50,14 +50,13 @@
   if (!value.is_dict())
     return {};
   RequestSchedule result;
-  const base::Value* anchor = value.FindKey("anchor");
+  base::Optional<base::Time> anchor =
+      util::ValueToTime(value.FindKey("anchor"));
   const base::Value* offsets =
       value.FindKeyOfType("offsets", base::Value::Type::LIST);
-  if (!anchor || !offsets)
+  if (!anchor || !offsets || !ValueToVector(*offsets, &result.refresh_offsets))
     return {};
-  if (!GetValueAsTime(*anchor, &result.anchor_time) ||
-      !ValueToVector(*offsets, &result.refresh_offsets))
-    return {};
+  result.anchor_time = *anchor;
   return result;
 }
 
diff --git a/components/feed/core/v2/types.cc b/components/feed/core/v2/types.cc
index 4b09b65..240a789 100644
--- a/components/feed/core/v2/types.cc
+++ b/components/feed/core/v2/types.cc
@@ -9,7 +9,7 @@
 #include "base/base64.h"
 #include "base/pickle.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "base/values.h"
 #include "components/feed/core/v2/public/types.h"
 
@@ -109,9 +109,9 @@
 
 base::Value PersistentMetricsDataToValue(const PersistentMetricsData& data) {
   base::Value dict(base::Value::Type::DICTIONARY);
-  dict.SetKey("day_start", base::CreateTimeValue(data.current_day_start));
+  dict.SetKey("day_start", util::TimeToValue(data.current_day_start));
   dict.SetKey("time_spent_in_feed",
-              base::CreateTimeDeltaValue(data.accumulated_time_spent_in_feed));
+              util::TimeDeltaToValue(data.accumulated_time_spent_in_feed));
   return dict;
 }
 
@@ -119,15 +119,15 @@
   PersistentMetricsData result;
   if (!value.is_dict())
     return result;
-  const base::Value* day_start = value.FindKey("day_start");
-  if (!day_start ||
-      !base::GetValueAsTime(*day_start, &result.current_day_start))
+  base::Optional<base::Time> day_start =
+      util::ValueToTime(value.FindKey("day_start"));
+  if (!day_start)
     return result;
-  const base::Value* time_spent_in_feed = value.FindKey("time_spent_in_feed");
+  result.current_day_start = *day_start;
+  base::Optional<base::TimeDelta> time_spent_in_feed =
+      util::ValueToTimeDelta(value.FindKey("time_spent_in_feed"));
   if (time_spent_in_feed) {
-    // Ignore return value, OK to keep going on failure.
-    (void)base::GetValueAsTimeDelta(*time_spent_in_feed,
-                                    &result.accumulated_time_spent_in_feed);
+    result.accumulated_time_spent_in_feed = *time_spent_in_feed;
   }
 
   return result;
diff --git a/components/nacl/browser/nacl_file_host_unittest.cc b/components/nacl/browser/nacl_file_host_unittest.cc
index ef729113..1003457 100644
--- a/components/nacl/browser/nacl_file_host_unittest.cc
+++ b/components/nacl/browser/nacl_file_host_unittest.cc
@@ -58,7 +58,7 @@
   DISALLOW_COPY_AND_ASSIGN(NaClFileHostTest);
 };
 
-NaClFileHostTest::NaClFileHostTest() : nacl_browser_delegate_(NULL) {}
+NaClFileHostTest::NaClFileHostTest() : nacl_browser_delegate_(nullptr) {}
 
 NaClFileHostTest::~NaClFileHostTest() {
 }
diff --git a/components/nacl/browser/nacl_process_host.cc b/components/nacl/browser/nacl_process_host.cc
index 3b3b4c5..4f03c6b 100644
--- a/components/nacl/browser/nacl_process_host.cc
+++ b/components/nacl/browser/nacl_process_host.cc
@@ -222,7 +222,7 @@
 #if defined(OS_WIN)
       process_launched_by_broker_(false),
 #endif
-      reply_msg_(NULL),
+      reply_msg_(nullptr),
 #if defined(OS_WIN)
       debug_exception_handler_requested_(false),
 #endif
diff --git a/components/nacl/browser/pnacl_host.cc b/components/nacl/browser/pnacl_host.cc
index a5a8070..150081d9 100644
--- a/components/nacl/browser/pnacl_host.cc
+++ b/components/nacl/browser/pnacl_host.cc
@@ -81,14 +81,13 @@
 PnaclHost::PendingTranslation::PendingTranslation()
     : process_handle(base::kNullProcessHandle),
       render_view_id(0),
-      nexe_fd(NULL),
+      nexe_fd(nullptr),
       got_nexe_fd(false),
       got_cache_reply(false),
       got_cache_hit(false),
       is_incognito(false),
       callback(NexeFdCallback()),
-      cache_info(nacl::PnaclCacheInfo()) {
-}
+      cache_info(nacl::PnaclCacheInfo()) {}
 
 PnaclHost::PendingTranslation::PendingTranslation(
     const PendingTranslation& other) = default;
diff --git a/components/nacl/browser/pnacl_host_unittest.cc b/components/nacl/browser/pnacl_host_unittest.cc
index e3d19112..57d0645 100644
--- a/components/nacl/browser/pnacl_host_unittest.cc
+++ b/components/nacl/browser/pnacl_host_unittest.cc
@@ -36,7 +36,7 @@
 class PnaclHostTest : public testing::Test {
  protected:
   PnaclHostTest()
-      : host_(NULL),
+      : host_(nullptr),
         temp_callback_count_(0),
         write_callback_count_(0),
         task_environment_(content::BrowserTaskEnvironment::IO_MAINLOOP) {}
diff --git a/components/nacl/browser/pnacl_translation_cache.cc b/components/nacl/browser/pnacl_translation_cache.cc
index 9d777af0..d3a2535 100644
--- a/components/nacl/browser/pnacl_translation_cache.cc
+++ b/components/nacl/browser/pnacl_translation_cache.cc
@@ -145,7 +145,7 @@
     bool is_read)
     : cache_(cache),
       key_(key),
-      entry_(NULL),
+      entry_(nullptr),
       step_(UNINITIALIZED),
       is_read_(is_read) {}
 
diff --git a/components/nacl/renderer/plugin/pnacl_translate_thread.cc b/components/nacl/renderer/plugin/pnacl_translate_thread.cc
index 56fd14e..36eb424 100644
--- a/components/nacl/renderer/plugin/pnacl_translate_thread.cc
+++ b/components/nacl/renderer/plugin/pnacl_translate_thread.cc
@@ -59,18 +59,18 @@
 }  // namespace
 
 PnaclTranslateThread::PnaclTranslateThread()
-    : compiler_subprocess_(NULL),
-      ld_subprocess_(NULL),
+    : compiler_subprocess_(nullptr),
+      ld_subprocess_(nullptr),
       compiler_subprocess_active_(false),
       ld_subprocess_active_(false),
       buffer_cond_(&cond_mu_),
       done_(false),
       compile_time_(0),
-      obj_files_(NULL),
+      obj_files_(nullptr),
       num_threads_(0),
-      nexe_file_(NULL),
-      coordinator_error_info_(NULL),
-      coordinator_(NULL) {}
+      nexe_file_(nullptr),
+      coordinator_error_info_(nullptr),
+      coordinator_(nullptr) {}
 
 void PnaclTranslateThread::SetupState(
     const pp::CompletionCallback& finish_callback,
diff --git a/components/nacl/renderer/pnacl_translation_resource_host.cc b/components/nacl/renderer/pnacl_translation_resource_host.cc
index 7bd105ce..e133581d 100644
--- a/components/nacl/renderer/pnacl_translation_resource_host.cc
+++ b/components/nacl/renderer/pnacl_translation_resource_host.cc
@@ -14,8 +14,7 @@
 
 PnaclTranslationResourceHost::PnaclTranslationResourceHost(
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
-    : io_task_runner_(io_task_runner), sender_(NULL) {
-}
+    : io_task_runner_(io_task_runner), sender_(nullptr) {}
 
 PnaclTranslationResourceHost::~PnaclTranslationResourceHost() {
   DCHECK(io_task_runner_->BelongsToCurrentThread());
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc
index 13b26c6..e6975d6 100644
--- a/components/omnibox/browser/omnibox_field_trial.cc
+++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -813,6 +813,23 @@
       kOnDeviceHeadSuggestDemoteMode);
 }
 
+bool OmniboxFieldTrial::IsHidePathQueryRefEnabled() {
+  return base::FeatureList::IsEnabled(
+      omnibox::kHideSteadyStateUrlPathQueryAndRef);
+}
+
+bool OmniboxFieldTrial::ShouldRevealPathQueryRefOnHover() {
+  return IsHidePathQueryRefEnabled() &&
+         base::FeatureList::IsEnabled(
+             omnibox::kRevealSteadyStateUrlPathQueryAndRefOnHover);
+}
+
+bool OmniboxFieldTrial::ShouldHidePathQueryRefOnInteraction() {
+  return IsHidePathQueryRefEnabled() &&
+         base::FeatureList::IsEnabled(
+             omnibox::kHideSteadyStateUrlPathQueryAndRefOnInteraction);
+}
+
 const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] =
     "OmniboxBundledExperimentV1";
 const char OmniboxFieldTrial::kDisableProvidersRule[] = "DisableProviders";
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index a1b2fd1..b829181 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -435,6 +435,11 @@
 // Function only works in non-incognito when server suggestions are available.
 std::string OnDeviceHeadSuggestDemoteMode();
 
+// Experiment to hide the path, query, and ref in the steady state.
+bool IsHidePathQueryRefEnabled();
+bool ShouldRevealPathQueryRefOnHover();
+bool ShouldHidePathQueryRefOnInteraction();
+
 // ---------------------------------------------------------
 // Clipboard URL suggestions:
 
diff --git a/components/omnibox/browser/omnibox_popup_model.cc b/components/omnibox/browser/omnibox_popup_model.cc
index 2911b08..bb86d98 100644
--- a/components/omnibox/browser/omnibox_popup_model.cc
+++ b/components/omnibox/browser/omnibox_popup_model.cc
@@ -135,41 +135,46 @@
   return view_->IsOpen();
 }
 
-void OmniboxPopupModel::SetSelectedLine(size_t line,
-                                        bool reset_to_default,
-                                        bool force) {
-  const AutocompleteResult& result = this->result();
-  if (result.empty())
+void OmniboxPopupModel::SetSelection(Selection new_selection,
+                                     bool reset_to_default,
+                                     bool force_update_ui) {
+  if (result().empty())
     return;
 
   // Cancel the query so the matches don't change on the user.
   autocomplete_controller()->Stop(false);
 
-  if (line != kNoMatch)
-    line = std::min(line, result.size() - 1);
-
-  if (line == selected_line() && !force)
+  if (new_selection == selection_ && !force_update_ui)
     return;  // Nothing else to do.
 
-  // We need to update selection before calling InvalidateLine(), since it will
-  // use selection to determine how to draw.  We also need to update
-  // |selection_.line| before calling OnPopupDataChanged(), so that when the
-  // edit notifies its controller that something has changed, the controller
-  // can get the correct updated data.
+  // We need to update selection before notifying any views, as they will query
+  // selection_ to update themselves.
   const Selection old_selection = selection_;
-  selection_ = Selection(line, NORMAL);
+  selection_ = new_selection;
   view_->OnSelectionChanged(old_selection, selection_);
 
-  if (line == kNoMatch)
+  if (selection_.line == kNoMatch)
     return;
 
-  // Update the edit with the new data for this match.
-  // TODO(pkasting): If |selection_.line| moves to the controller, this can be
-  // eliminated and just become a call to the observer on the edit.
+  const AutocompleteMatch& match = result().match_at(selection_.line);
+  DCHECK((selection_.state != KEYWORD) || match.associated_keyword.get());
+  if (selection_.IsButtonFocused()) {
+    old_focused_url_ = match.destination_url;
+    edit_model_->SetAccessibilityLabel(match);
+    view_->ProvideButtonFocusHint(selected_line());
+  }
+
+  // When the selected line changes, we should also update the edit model with
+  // new data for this match. We don't do this when the state merely changes,
+  // as that breaks keyword mode.
+  //
+  // TODO(tommycli): Make this more nuanced to make section headers behave nice.
+  if (selection_.line == old_selection.line)
+    return;
+
   base::string16 keyword;
   bool is_keyword_hint;
   TemplateURLService* service = edit_model_->client()->GetTemplateURLService();
-  const AutocompleteMatch& match = result.match_at(line);
   match.GetKeywordUIState(service, &keyword, &is_keyword_hint);
 
   if (reset_to_default) {
@@ -185,30 +190,10 @@
 
 void OmniboxPopupModel::ResetToInitialState() {
   size_t new_line = result().default_match() ? 0 : kNoMatch;
-  SetSelectedLine(new_line, true, false);
+  SetSelection(Selection(new_line, NORMAL), /*reset_to_default=*/true);
   view_->OnDragCanceled();
 }
 
-void OmniboxPopupModel::SetSelectedLineState(LineState state) {
-  DCHECK(!result().empty());
-  DCHECK_NE(kNoMatch, selected_line());
-
-  const AutocompleteMatch& match = result().match_at(selected_line());
-  GURL current_destination(match.destination_url);
-  DCHECK((state != KEYWORD) || match.associated_keyword.get());
-
-  if (state == BUTTON_FOCUSED)
-    old_focused_url_ = current_destination;
-
-  selection_ = Selection(selected_line(), state);
-  view_->InvalidateLine(selected_line());
-
-  if (selection_.IsButtonFocused()) {
-    edit_model_->SetAccessibilityLabel(match);
-    view_->ProvideButtonFocusHint(selected_line());
-  }
-}
-
 void OmniboxPopupModel::TryDeletingLine(size_t line) {
   // When called with line == selected_line(), we could use
   // GetInfoForCurrentText() here, but it seems better to try and delete the
@@ -222,19 +207,24 @@
   const AutocompleteMatch& match = result().match_at(line);
   if (match.SupportsDeletion()) {
     // Try to preserve the selection even after match deletion.
-    const size_t old_selected_line = selected_line();
+    size_t old_selected_line = selected_line();
 
     // This will synchronously notify both the edit and us that the results
     // have changed, causing both to revert to the default match.
     autocomplete_controller()->DeleteMatch(match);
 
+    // Clamp the old selection to the new size of result(), since there may be
+    // fewer results now.
+    if (old_selected_line != kNoMatch)
+      old_selected_line = std::min(line, result().size() - 1);
+
     // Move the selection to the next choice after the deleted one.
     // SetSelectedLine() will clamp to take care of the case where we deleted
     // the last item.
     // TODO(pkasting): Eventually the controller should take care of this
     // before notifying us, reducing flicker.  At that point the check for
     // deletability can move there too.
-    SetSelectedLine(old_selected_line, false, true);
+    SetSelection(Selection(old_selected_line, NORMAL), false, true);
   }
 }
 
@@ -264,6 +254,7 @@
     const bool has_changed =
         selection.line != old_selected_line ||
         result.match_at(selection.line).destination_url != old_focused_url_;
+
     if (!has_focused_match || has_changed) {
       selection.state = NORMAL;
     }
@@ -484,16 +475,6 @@
   return selection_;
 }
 
-OmniboxPopupModel::Selection OmniboxPopupModel::ClearSelectionState() {
-  // This is subtle. DCHECK in SetSelectedLineState will fail if there are no
-  // results, which can happen when the popup gets closed. In that case, though,
-  // the state is left as NORMAL.
-  if (selection_.state != NORMAL) {
-    SetSelectedLineState(NORMAL);
-  }
-  return selection_;
-}
-
 bool OmniboxPopupModel::IsControlPresentOnMatch(Selection selection) const {
   if (selection.line >= result().size()) {
     return false;
@@ -554,15 +535,6 @@
   return false;
 }
 
-void OmniboxPopupModel::SetSelection(Selection selection) {
-  if (selection.line != selection_.line) {
-    SetSelectedLine(selection.line, false, false);
-  }
-  if (selection.state != selection_.state) {
-    SetSelectedLineState(selection.state);
-  }
-}
-
 bool OmniboxPopupModel::TriggerSelectionAction(Selection selection) {
   // Early exit for the kNoMatch case. Also exits if the calling UI passes in
   // an invalid |selection|.
diff --git a/components/omnibox/browser/omnibox_popup_model.h b/components/omnibox/browser/omnibox_popup_model.h
index e5ce750..ca73755f 100644
--- a/components/omnibox/browser/omnibox_popup_model.h
+++ b/components/omnibox/browser/omnibox_popup_model.h
@@ -97,7 +97,8 @@
     // match (if BUTTON_FOCUSED) is selected.
     LineState state;
 
-    Selection(size_t line, LineState state) : line(line), state(state) {}
+    explicit Selection(size_t line, LineState state = NORMAL)
+        : line(line), state(state) {}
 
     bool operator==(const Selection&) const;
     bool operator!=(const Selection&) const;
@@ -159,33 +160,28 @@
   size_t selected_line() const { return selection_.line; }
   LineState selected_line_state() const { return selection_.state; }
 
-  // Call to change the selected line.  This will update all state and repaint
-  // the necessary parts of the window, as well as updating the edit with the
-  // new temporary text.  |line| will be clamped to the range of valid lines.
-  // |reset_to_default| is true when the selection is being reset back to the
-  // initial state, and thus there is no temporary text (and not
-  // |has_selected_match_|). If |force| is true then the selected line will
-  // be updated forcibly even if the |line| is same as the current selected
-  // line.
-  // NOTE: This assumes the popup is open, although both the old and new values
-  // for the selected line can be kNoMatch.
-  void SetSelectedLine(size_t line, bool reset_to_default, bool force);
+  // Sets the current selection to |new_selection|. Caller is responsible for
+  // making sure |new_selection| is valid. This assumes the popup is open.
+  //
+  // This will update all state and repaint the necessary parts of the window,
+  // as well as updating the textfield with the new temporary text.
+  //
+  // |reset_to_default| restores the original inline autocompletion.
+  // |force_update_ui| updates the UI even if the selection has not changed.
+  void SetSelection(Selection new_selection,
+                    bool reset_to_default = false,
+                    bool force_update_ui = false);
+
+  // We still need to run through the whole SetSelection method, because
+  // changing the line state sometimes requires updating inline autocomplete.
+  void SetSelectedLineState(LineState new_state) {
+    SetSelection(Selection(selected_line(), new_state));
+  }
 
   // Called when the user hits escape after arrowing around the popup.  This
   // will reset the popup to the initial state.
   void ResetToInitialState();
 
-  // If the selected line has both a normal match and a keyword match, this can
-  // be used to choose which to select.  This allows the user to toggle between
-  // normal and keyword mode with tab/shift-tab without rerunning autocomplete
-  // or disturbing other popup state, which in turn is an important part of
-  // supporting the use of tab to do both tab-to-search and
-  // tab-to-traverse-dropdown.
-  //
-  // It is an error to call this when the selected line does not have both
-  // matches (or there is no selection).
-  void SetSelectedLineState(LineState state);
-
   // Tries to erase the suggestion at |line|.  This should determine if the item
   // at |line| can be removed from history, and if so, remove it and update the
   // popup.
@@ -238,14 +234,6 @@
   // keyword mode state maintained in the edit model.
   Selection StepSelection(Direction direction, Step step);
 
-  // Applies a given selection. Use GetNextSelection instead of constructing
-  // a selection from scratch.
-  void SetSelection(Selection selection);
-
-  // Preserves current selection line but resets it to default state.
-  // Returns new selection.
-  Selection ClearSelectionState();
-
   // Returns true if the control represented by |selection.state| is present on
   // the match in |selection.line|. This is the source-of-truth the UI code
   // should query to decide whether or not to draw the control.
diff --git a/components/omnibox/browser/omnibox_popup_model_unittest.cc b/components/omnibox/browser/omnibox_popup_model_unittest.cc
index f7eccf92c..c426b14 100644
--- a/components/omnibox/browser/omnibox_popup_model_unittest.cc
+++ b/components/omnibox/browser/omnibox_popup_model_unittest.cc
@@ -98,9 +98,9 @@
   result->SortAndCull(input, nullptr);
   popup_model()->OnResultChanged();
   EXPECT_TRUE(popup_model()->SelectionOnInitialLine());
-  popup_model()->SetSelectedLine(0, true, false);
+  popup_model()->SetSelection(OmniboxPopupModel::Selection(0), true, false);
   EXPECT_TRUE(popup_model()->SelectionOnInitialLine());
-  popup_model()->SetSelectedLine(0, false, false);
+  popup_model()->SetSelection(OmniboxPopupModel::Selection(0), false, false);
   EXPECT_TRUE(popup_model()->SelectionOnInitialLine());
 }
 
@@ -124,11 +124,11 @@
   EXPECT_EQ(OmniboxPopupModel::kNoMatch, popup_model()->selected_line());
   EXPECT_TRUE(popup_model()->SelectionOnInitialLine());
 
-  popup_model()->SetSelectedLine(0, false, false);
+  popup_model()->SetSelection(OmniboxPopupModel::Selection(0), false, false);
   EXPECT_EQ(0U, popup_model()->selected_line());
   EXPECT_FALSE(popup_model()->SelectionOnInitialLine());
 
-  popup_model()->SetSelectedLine(1, false, false);
+  popup_model()->SetSelection(OmniboxPopupModel::Selection(1), false, false);
   EXPECT_EQ(1U, popup_model()->selected_line());
   EXPECT_FALSE(popup_model()->SelectionOnInitialLine());
 
@@ -512,12 +512,12 @@
   result->AppendMatches(input, matches);
   result->SortAndCull(input, nullptr);
   popup_model()->OnResultChanged();
-  popup_model()->SetSelectedLine(0, true, false);
+  popup_model()->SetSelection(OmniboxPopupModel::Selection(0), true, false);
   // The default state should be unfocused.
   EXPECT_EQ(OmniboxPopupModel::NORMAL, popup_model()->selected_line_state());
 
   // Focus the selection.
-  popup_model()->SetSelectedLine(0, false, false);
+  popup_model()->SetSelection(OmniboxPopupModel::Selection(0));
   popup_model()->SetSelectedLineState(OmniboxPopupModel::BUTTON_FOCUSED);
   EXPECT_EQ(OmniboxPopupModel::BUTTON_FOCUSED,
             popup_model()->selected_line_state());
@@ -535,17 +535,7 @@
             popup_model()->selected_line_state());
 
   // Changing selection should change focused state.
-  popup_model()->SetSelectedLine(1, false, false);
-  EXPECT_EQ(OmniboxPopupModel::NORMAL, popup_model()->selected_line_state());
-
-  // Changing selection to same selection might change state.
-  popup_model()->SetSelectedLineState(OmniboxPopupModel::BUTTON_FOCUSED);
-  // Letting routine filter selecting same line should not change it.
-  popup_model()->SetSelectedLine(1, false, false);
-  EXPECT_EQ(OmniboxPopupModel::BUTTON_FOCUSED,
-            popup_model()->selected_line_state());
-  // Forcing routine to handle selecting same line should change it.
-  popup_model()->SetSelectedLine(1, false, true);
+  popup_model()->SetSelection(OmniboxPopupModel::Selection(1));
   EXPECT_EQ(OmniboxPopupModel::NORMAL, popup_model()->selected_line_state());
 
   // Adding a match at end will reset selection to first, so should change
@@ -574,7 +564,8 @@
 
   // Selecting |kNoMatch| should clear focus.
   popup_model()->SetSelectedLineState(OmniboxPopupModel::BUTTON_FOCUSED);
-  popup_model()->SetSelectedLine(OmniboxPopupModel::kNoMatch, false, false);
+  popup_model()->SetSelection(
+      OmniboxPopupModel::Selection(OmniboxPopupModel::kNoMatch));
   popup_model()->OnResultChanged();
   EXPECT_EQ(OmniboxPopupModel::NORMAL, popup_model()->selected_line_state());
 }
diff --git a/components/omnibox/browser/omnibox_view.cc b/components/omnibox/browser/omnibox_view.cc
index baed91d..2842e7a7 100644
--- a/components/omnibox/browser/omnibox_view.cc
+++ b/components/omnibox/browser/omnibox_view.cc
@@ -329,13 +329,13 @@
     model_->OnChanged();
 }
 
-bool OmniboxView::UpdateTextStyle(
+void OmniboxView::UpdateTextStyle(
     const base::string16& display_text,
     const bool text_is_url,
     const AutocompleteSchemeClassifier& classifier) {
   if (!text_is_url) {
     SetEmphasis(true, gfx::Range::InvalidRange());
-    return false;  // Path not eligible for fading if it's not even a URL.
+    return;
   }
 
   enum DemphasizeComponents {
@@ -387,7 +387,4 @@
   // Emphasize the scheme for security UI display purposes (if necessary).
   if (!model()->user_input_in_progress() && scheme_range.IsValid())
     UpdateSchemeStyle(scheme_range);
-
-  // Path is eligible for fading only when the host is the only emphasized part.
-  return deemphasize == ALL_BUT_HOST;
 }
diff --git a/components/omnibox/browser/omnibox_view.h b/components/omnibox/browser/omnibox_view.h
index bc1398c5..183f73093 100644
--- a/components/omnibox/browser/omnibox_view.h
+++ b/components/omnibox/browser/omnibox_view.h
@@ -310,8 +310,8 @@
   // everything is emphasized equally, whereas for URLs the scheme may be styled
   // based on the current security state, with parts of the URL de-emphasized to
   // draw attention to whatever best represents the "identity" of the current
-  // URL. Returns true if the path component is eligible for fadeout.
-  bool UpdateTextStyle(const base::string16& display_text,
+  // URL.
+  void UpdateTextStyle(const base::string16& display_text,
                        const bool text_is_url,
                        const AutocompleteSchemeClassifier& classifier);
 
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index 338e86c4..c613b64 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -53,6 +53,20 @@
 #endif
 };
 
+// Feature used to reveal the path, query and ref from steady state URLs
+// on hover. Only has any effect when
+// OmniboxUIExperimentHideSteadyStateUrlPathQueryAndRef is enabled.
+const base::Feature kRevealSteadyStateUrlPathQueryAndRefOnHover{
+    "OmniboxUIExperimentRevealSteadyStateUrlPathQueryAndRefOnHover",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Feature used to hide the path, query and ref from steady state URLs
+// on interaction with the page. Only has any effect when
+// OmniboxUIExperimentHideSteadyStateUrlPathQueryAndRef is enabled.
+const base::Feature kHideSteadyStateUrlPathQueryAndRefOnInteraction{
+    "OmniboxUIExperimentHideSteadyStateUrlPathQueryAndRefOnInteraction",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Feature used to enable local entity suggestions. Similar to rich entities but
 // but location specific. E.g., typing 'starbucks near' could display the local
 // entity suggestion 'starbucks near disneyland \n starbucks * Anaheim, CA'.
diff --git a/components/omnibox/common/omnibox_features.h b/components/omnibox/common/omnibox_features.h
index bf7f600..ef461b8 100644
--- a/components/omnibox/common/omnibox_features.h
+++ b/components/omnibox/common/omnibox_features.h
@@ -16,6 +16,8 @@
 extern const base::Feature kHideSteadyStateUrlScheme;
 extern const base::Feature kHideSteadyStateUrlTrivialSubdomains;
 extern const base::Feature kHideSteadyStateUrlPathQueryAndRef;
+extern const base::Feature kRevealSteadyStateUrlPathQueryAndRefOnHover;
+extern const base::Feature kHideSteadyStateUrlPathQueryAndRefOnInteraction;
 extern const base::Feature kOmniboxLocalEntitySuggestions;
 extern const base::Feature kOmniboxReverseAnswers;
 extern const base::Feature kOmniboxShortBookmarkSuggestions;
diff --git a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java
index 6783c5a..6656923 100644
--- a/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java
+++ b/components/page_info/android/java/src/org/chromium/components/page_info/PageInfoView.java
@@ -462,19 +462,19 @@
         animatableViews.add(mConnectionMessage);
         animatableViews.add(mPerformanceSummary);
         animatableViews.add(mPerformanceMessage);
+        animatableViews.add(mPreviewSeparator);
         animatableViews.add(mPreviewMessage);
         animatableViews.add(mPreviewStaleTimestamp);
         animatableViews.add(mPreviewLoadOriginal);
-        animatableViews.add(mPreviewSeparator);
         animatableViews.add(mInstantAppButton);
-        animatableViews.add(mPermissionsTitle);
+        animatableViews.add(mCookieControlsSeparator);
+        animatableViews.add(mCookieControlsView);
         animatableViews.add(mPermissionsSeparator);
+        animatableViews.add(mPermissionsTitle);
         for (int i = 0; i < mPermissionsList.getChildCount(); i++) {
             animatableViews.add(mPermissionsList.getChildAt(i));
         }
         animatableViews.add(mSiteSettingsButton);
-        animatableViews.add(mCookieControlsSeparator);
-        animatableViews.add(mCookieControlsView);
 
         return animatableViews;
     }
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.cc b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
index f686b19..fcd8bc20 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer.cc
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer.cc
@@ -76,23 +76,6 @@
     observer->OnBrowserFeatureUsage(render_frame_host, new_features);
 }
 
-MetricsWebContentsObserver::MetricsWebContentsObserver(
-    content::WebContents* web_contents,
-    std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface)
-    : content::WebContentsObserver(web_contents),
-      in_foreground_(web_contents->GetVisibility() !=
-                     content::Visibility::HIDDEN),
-      embedder_interface_(std::move(embedder_interface)),
-      has_navigated_(false),
-      page_load_metrics_receiver_(web_contents, this) {
-  // Prerenders erroneously report that they are initially visible, so we
-  // manually override visibility state for prerender.
-  if (embedder_interface_->IsPrerender(web_contents))
-    in_foreground_ = false;
-
-  RegisterInputEventObserver(web_contents->GetRenderViewHost());
-}
-
 // static
 MetricsWebContentsObserver* MetricsWebContentsObserver::CreateForWebContents(
     content::WebContents* web_contents,
@@ -188,6 +171,23 @@
   has_navigated_ = true;
 }
 
+MetricsWebContentsObserver::MetricsWebContentsObserver(
+    content::WebContents* web_contents,
+    std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface)
+    : content::WebContentsObserver(web_contents),
+      in_foreground_(web_contents->GetVisibility() !=
+                     content::Visibility::HIDDEN),
+      embedder_interface_(std::move(embedder_interface)),
+      has_navigated_(false),
+      page_load_metrics_receiver_(web_contents, this) {
+  // Prerenders erroneously report that they are initially visible, so we
+  // manually override visibility state for prerender.
+  if (embedder_interface_->IsPrerender(web_contents))
+    in_foreground_ = false;
+
+  RegisterInputEventObserver(web_contents->GetRenderViewHost());
+}
+
 void MetricsWebContentsObserver::WillStartNavigationRequestImpl(
     content::NavigationHandle* navigation_handle) {
   UserInitiatedInfo user_initiated_info(
diff --git a/components/page_load_metrics/browser/metrics_web_contents_observer.h b/components/page_load_metrics/browser/metrics_web_contents_observer.h
index f893151..3fedb70 100644
--- a/components/page_load_metrics/browser/metrics_web_contents_observer.h
+++ b/components/page_load_metrics/browser/metrics_web_contents_observer.h
@@ -87,9 +87,6 @@
   static MetricsWebContentsObserver* CreateForWebContents(
       content::WebContents* web_contents,
       std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface);
-  MetricsWebContentsObserver(
-      content::WebContents* web_contents,
-      std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface);
   ~MetricsWebContentsObserver() override;
 
   // Any visibility changes that occur after this method should be ignored since
@@ -175,6 +172,10 @@
  private:
   friend class content::WebContentsUserData<MetricsWebContentsObserver>;
 
+  MetricsWebContentsObserver(
+      content::WebContents* web_contents,
+      std::unique_ptr<PageLoadMetricsEmbedderInterface> embedder_interface);
+
   void WillStartNavigationRequestImpl(
       content::NavigationHandle* navigation_handle);
 
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java
index 5f89219..561963e 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameCoordinator.java
@@ -7,7 +7,8 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.view.View;
-import android.widget.Scroller;
+import android.view.ViewConfiguration;
+import android.widget.OverScroller;
 
 import org.chromium.base.UnguessableToken;
 import org.chromium.components.paintpreview.player.OverscrollHandler;
@@ -32,8 +33,10 @@
             UnguessableToken frameGuid, int contentWidth, int contentHeight, boolean canDetectZoom,
             @Nullable OverscrollHandler overscrollHandler) {
         PropertyModel model = new PropertyModel.Builder(PlayerFrameProperties.ALL_KEYS).build();
-        mMediator = new PlayerFrameMediator(model, compositorDelegate, new Scroller(context),
-                frameGuid, contentWidth, contentHeight);
+        OverScroller scroller = new OverScroller(context);
+        scroller.setFriction(ViewConfiguration.getScrollFriction() / 2);
+        mMediator = new PlayerFrameMediator(
+                model, compositorDelegate, scroller, frameGuid, contentWidth, contentHeight);
         mView = new PlayerFrameView(context, canDetectZoom, mMediator);
         if (overscrollHandler != null) {
             mMediator.setOverscrollHandler(overscrollHandler);
diff --git a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java
index c2f874d..8e0bf3f1 100644
--- a/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java
+++ b/components/paint_preview/player/android/java/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediator.java
@@ -8,7 +8,7 @@
 import android.graphics.Rect;
 import android.os.Handler;
 import android.view.View;
-import android.widget.Scroller;
+import android.widget.OverScroller;
 
 import androidx.annotation.VisibleForTesting;
 
@@ -66,7 +66,7 @@
     private final List<Rect> mVisibleSubFrameScaledRects = new ArrayList<>();
     private final PropertyModel mModel;
     private final PlayerCompositorDelegate mCompositorDelegate;
-    private final Scroller mScroller;
+    private final OverScroller mScroller;
     private final Handler mScrollerHandler;
     /** The user-visible area for this frame. */
     private final Rect mViewportRect = new Rect();
@@ -96,7 +96,8 @@
     private float mOverscrollAmount = 0.0f;
 
     PlayerFrameMediator(PropertyModel model, PlayerCompositorDelegate compositorDelegate,
-            Scroller scroller, UnguessableToken frameGuid, int contentWidth, int contentHeight) {
+            OverScroller scroller, UnguessableToken frameGuid, int contentWidth,
+            int contentHeight) {
         mModel = model;
         mModel.set(PlayerFrameProperties.SUBFRAME_VIEWS, mVisibleSubFrameViews);
         mModel.set(PlayerFrameProperties.SUBFRAME_RECTS, mVisibleSubFrameScaledRects);
diff --git a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PaintPreviewCustomFlingingShadowScroller.java b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PaintPreviewCustomFlingingShadowScroller.java
index 26a2eec..2a2525d2 100644
--- a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PaintPreviewCustomFlingingShadowScroller.java
+++ b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PaintPreviewCustomFlingingShadowScroller.java
@@ -5,7 +5,7 @@
 package org.chromium.components.paintpreview.player.frame;
 
 import android.content.Context;
-import android.widget.Scroller;
+import android.widget.OverScroller;
 
 import org.robolectric.annotation.Implementation;
 import org.robolectric.annotation.Implements;
@@ -13,7 +13,7 @@
 /**
  * A custom shadow of {@link Scroller} that supports fake flinging.
  */
-@Implements(Scroller.class)
+@Implements(OverScroller.class)
 public class PaintPreviewCustomFlingingShadowScroller {
     private int mFinalX;
     private int mFinalY;
diff --git a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
index f9badc9..15f5427 100644
--- a/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
+++ b/components/paint_preview/player/android/junit/src/org/chromium/components/paintpreview/player/frame/PlayerFrameMediatorTest.java
@@ -9,7 +9,7 @@
 import android.os.Parcel;
 import android.util.Pair;
 import android.view.View;
-import android.widget.Scroller;
+import android.widget.OverScroller;
 
 import androidx.annotation.NonNull;
 
@@ -44,7 +44,7 @@
     private UnguessableToken mFrameGuid;
     private PropertyModel mModel;
     private TestPlayerCompositorDelegate mCompositorDelegate;
-    private Scroller mScroller;
+    private OverScroller mScroller;
     private PlayerFrameMediator mMediator;
 
     /**
@@ -165,7 +165,7 @@
         mFrameGuid = frameGuid();
         mModel = new PropertyModel.Builder(PlayerFrameProperties.ALL_KEYS).build();
         mCompositorDelegate = new TestPlayerCompositorDelegate();
-        mScroller = new Scroller(ContextUtils.getApplicationContext());
+        mScroller = new OverScroller(ContextUtils.getApplicationContext());
         mMediator = new PlayerFrameMediator(
                 mModel, mCompositorDelegate, mScroller, mFrameGuid, CONTENT_WIDTH, CONTENT_HEIGHT);
     }
diff --git a/components/password_manager/core/browser/password_manager_features_util.cc b/components/password_manager/core/browser/password_manager_features_util.cc
index 7bd4931..fc534b9 100644
--- a/components/password_manager/core/browser/password_manager_features_util.cc
+++ b/components/password_manager/core/browser/password_manager_features_util.cc
@@ -4,6 +4,7 @@
 
 #include "components/password_manager/core/browser/password_manager_features_util.h"
 
+#include "base/containers/flat_set.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/values.h"
 #include "components/autofill/core/common/gaia_id_hash.h"
@@ -296,6 +297,31 @@
       .SetDefaultStore(default_store);
 }
 
+void KeepAccountStorageSettingsOnlyForUsers(
+    PrefService* pref_service,
+    const std::vector<std::string>& gaia_ids) {
+  DCHECK(pref_service);
+
+  // Build a set of hashes of all the Gaia IDs.
+  std::vector<std::string> hashes_to_keep_list;
+  for (const std::string& gaia_id : gaia_ids)
+    hashes_to_keep_list.push_back(GaiaIdHash::FromGaiaId(gaia_id).ToBase64());
+  base::flat_set<std::string> hashes_to_keep(std::move(hashes_to_keep_list));
+
+  // Now remove any settings for account that are *not* in the set of hashes.
+  // DictionaryValue doesn't allow removing elements while iterating, so first
+  // collect all the keys to remove, then actually remove them in a second pass.
+  DictionaryPrefUpdate update(pref_service,
+                              prefs::kAccountStoragePerAccountSettings);
+  std::vector<std::string> keys_to_remove;
+  for (auto kv : update->DictItems()) {
+    if (!hashes_to_keep.contains(kv.first))
+      keys_to_remove.push_back(kv.first);
+  }
+  for (const std::string& key_to_remove : keys_to_remove)
+    update->RemoveKey(key_to_remove);
+}
+
 void ClearAccountStorageSettingsForAllUsers(PrefService* pref_service) {
   DCHECK(pref_service);
   pref_service->ClearPref(prefs::kAccountStoragePerAccountSettings);
diff --git a/components/password_manager/core/browser/password_manager_features_util.h b/components/password_manager/core/browser/password_manager_features_util.h
index a524b4c..bbd84fb 100644
--- a/components/password_manager/core/browser/password_manager_features_util.h
+++ b/components/password_manager/core/browser/password_manager_features_util.h
@@ -91,6 +91,14 @@
     const PrefService* pref_service,
     const syncer::SyncService* sync_service);
 
+// Clears all account-storage-related settings for all users *except* the ones
+// in the passed-in |gaia_ids|. Most notably, this includes the opt-in, but also
+// all other related settings like the default password store.
+// |pref_service| must not be null.
+void KeepAccountStorageSettingsOnlyForUsers(
+    PrefService* pref_service,
+    const std::vector<std::string>& gaia_ids);
+
 // Clears all account-storage-related settings for all users. Most notably, this
 // includes the opt-in, but also all other related settings like the default
 // password store. Meant to be called when account cookies were cleared.
diff --git a/components/password_manager/core/browser/password_manager_features_util_unittest.cc b/components/password_manager/core/browser/password_manager_features_util_unittest.cc
index f1a5f9c..a835570 100644
--- a/components/password_manager/core/browser/password_manager_features_util_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_features_util_unittest.cc
@@ -220,6 +220,55 @@
             autofill::PasswordForm::Store::kProfileStore);
 }
 
+TEST(PasswordFeatureManagerUtil, AccountStorageKeepSettingsOnlyForUsers) {
+  base::test::ScopedFeatureList features;
+  features.InitAndEnableFeature(features::kEnablePasswordsAccountStorage);
+
+  TestingPrefServiceSimple pref_service;
+  pref_service.registry()->RegisterDictionaryPref(
+      prefs::kAccountStoragePerAccountSettings);
+
+  CoreAccountInfo first_account;
+  first_account.email = "first@account.com";
+  first_account.gaia = "first";
+  first_account.account_id = CoreAccountId::FromGaiaId(first_account.gaia);
+
+  CoreAccountInfo second_account;
+  second_account.email = "second@account.com";
+  second_account.gaia = "second";
+  second_account.account_id = CoreAccountId::FromGaiaId(second_account.gaia);
+
+  syncer::TestSyncService sync_service;
+  sync_service.SetDisableReasons({});
+  sync_service.SetIsAuthenticatedAccountPrimary(false);
+  sync_service.SetTransportState(syncer::SyncService::TransportState::ACTIVE);
+
+  // Let SyncService run in transport mode with |first_account| and opt in.
+  sync_service.SetAuthenticatedAccountInfo(first_account);
+  OptInToAccountStorage(&pref_service, &sync_service);
+  ASSERT_TRUE(IsOptedInForAccountStorage(&pref_service, &sync_service));
+
+  // Switch to |second_account| and again opt in.
+  sync_service.SetAuthenticatedAccountInfo(second_account);
+  OptInToAccountStorage(&pref_service, &sync_service);
+  ASSERT_TRUE(IsOptedInForAccountStorage(&pref_service, &sync_service));
+
+  // Sign out. The opt-in still exists, but doesn't apply anymore.
+  sync_service.SetAuthenticatedAccountInfo(CoreAccountInfo());
+  ASSERT_FALSE(IsOptedInForAccountStorage(&pref_service, &sync_service));
+
+  // Keep the opt-in only for |first_account| (and some unknown other user).
+  KeepAccountStorageSettingsOnlyForUsers(&pref_service,
+                                         {first_account.gaia, "other_gaia_id"});
+
+  // The first account should still be opted in, but not the second.
+  sync_service.SetAuthenticatedAccountInfo(first_account);
+  EXPECT_TRUE(IsOptedInForAccountStorage(&pref_service, &sync_service));
+
+  sync_service.SetAuthenticatedAccountInfo(second_account);
+  EXPECT_FALSE(IsOptedInForAccountStorage(&pref_service, &sync_service));
+}
+
 TEST(PasswordFeatureManagerUtil, SyncSuppressesAccountStorageOptIn) {
   base::test::ScopedFeatureList features;
   features.InitAndEnableFeature(features::kEnablePasswordsAccountStorage);
diff --git a/components/password_manager/core/browser/sync/password_model_type_controller.cc b/components/password_manager/core/browser/sync/password_model_type_controller.cc
index feca14dc..aca14efb 100644
--- a/components/password_manager/core/browser/sync/password_model_type_controller.cc
+++ b/components/password_manager/core/browser/sync/password_model_type_controller.cc
@@ -8,6 +8,7 @@
 
 #include "components/password_manager/core/browser/password_manager_features_util.h"
 #include "components/prefs/pref_service.h"
+#include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
 #include "components/sync/base/model_type.h"
 #include "components/sync/driver/sync_client.h"
 #include "components/sync/driver/sync_service.h"
@@ -96,6 +97,29 @@
   state_changed_callback_.Run();
 }
 
+void PasswordModelTypeController::OnAccountsInCookieUpdated(
+    const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+    const GoogleServiceAuthError& error) {
+  // If the account information is stale, do nothing for now - wait until there
+  // is fresh information.
+  if (!accounts_in_cookie_jar_info.accounts_are_fresh) {
+    return;
+  }
+  // Collect all the known accounts (signed-in or signed-out).
+  std::vector<std::string> gaia_ids;
+  for (const gaia::ListedAccount& account :
+       accounts_in_cookie_jar_info.signed_in_accounts) {
+    gaia_ids.push_back(account.gaia_id);
+  }
+  for (const gaia::ListedAccount& account :
+       accounts_in_cookie_jar_info.signed_out_accounts) {
+    gaia_ids.push_back(account.gaia_id);
+  }
+  // Keep any account-storage settings only for known accounts.
+  features_util::KeepAccountStorageSettingsOnlyForUsers(pref_service_,
+                                                        gaia_ids);
+}
+
 void PasswordModelTypeController::OnAccountsCookieDeletedByUserAction() {
   features_util::ClearAccountStorageSettingsForAllUsers(pref_service_);
 }
diff --git a/components/password_manager/core/browser/sync/password_model_type_controller.h b/components/password_manager/core/browser/sync/password_model_type_controller.h
index a25be9f..8c850d69 100644
--- a/components/password_manager/core/browser/sync/password_model_type_controller.h
+++ b/components/password_manager/core/browser/sync/password_model_type_controller.h
@@ -50,6 +50,9 @@
   void OnStateChanged(syncer::SyncService* sync) override;
 
   // IdentityManager::Observer overrides.
+  void OnAccountsInCookieUpdated(
+      const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
+      const GoogleServiceAuthError& error) override;
   void OnAccountsCookieDeletedByUserAction() override;
 
  private:
diff --git a/components/performance_manager/graph/frame_node_impl_unittest.cc b/components/performance_manager/graph/frame_node_impl_unittest.cc
index de89772..b7dc421 100644
--- a/components/performance_manager/graph/frame_node_impl_unittest.cc
+++ b/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -467,7 +467,10 @@
   LenientMockPageObserver() = default;
   ~LenientMockPageObserver() override = default;
 
+  MOCK_METHOD1(OnBeforePageNodeRemoved, void(const PageNode* page_node));
+
   // Note that opener functionality is actually tested in the
+  // performance_manager_browsertest.
   MOCK_METHOD3(OnOpenerFrameNodeChanged,
                void(const PageNode*, const FrameNode*, OpenedType));
 };
@@ -623,6 +626,30 @@
   EXPECT_TRUE(frameA2->opened_page_nodes().empty());
   testing::Mock::VerifyAndClear(&obs);
 
+  // verify that the opener relationship is torn down before any node removal
+  // notification arrives.
+  EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), nullptr,
+                                            OpenedType::kInvalid));
+  pageB->SetOpenerFrameNodeAndOpenedType(frameA2.get(), OpenedType::kPopup);
+  EXPECT_EQ(frameA2.get(), pageB->opener_frame_node());
+  EXPECT_EQ(OpenedType::kPopup, pageB->opened_type());
+  EXPECT_TRUE(frameA1->opened_page_nodes().empty());
+  EXPECT_EQ(1u, frameA2->opened_page_nodes().size());
+  EXPECT_EQ(1u, frameA2->opened_page_nodes().count(pageB.get()));
+  testing::Mock::VerifyAndClear(&obs);
+
+  {
+    ::testing::InSequence seq;
+
+    // These must occur in sequence.
+    EXPECT_CALL(obs, OnOpenerFrameNodeChanged(pageB.get(), frameA2.get(),
+                                              OpenedType::kPopup));
+    EXPECT_CALL(obs, OnBeforePageNodeRemoved(pageB.get()));
+  }
+  frameB1.reset();
+  pageB.reset();
+  testing::Mock::VerifyAndClear(&obs);
+
   graph()->RemovePageNodeObserver(&obs);
 }
 
diff --git a/components/performance_manager/public/graph/page_node.h b/components/performance_manager/public/graph/page_node.h
index 938d8e2..422c043 100644
--- a/components/performance_manager/public/graph/page_node.h
+++ b/components/performance_manager/public/graph/page_node.h
@@ -175,8 +175,7 @@
   // Invoked when this page has been assigned an opener, had the opener change,
   // or had the opener removed. This can happen if a page is opened via
   // window.open, webviews, portals, etc, or when that relationship is
-  // subsequently severed or reparented. Note that this can be invoked *after*
-  // OnBeforePageNodeRemoved() if a page disappears while still attached.
+  // subsequently severed or reparented.
   virtual void OnOpenerFrameNodeChanged(const PageNode* page_node,
                                         const FrameNode* previous_opener,
                                         OpenedType previous_opened_type) = 0;
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc
index 637789d4..5ac3ac97 100644
--- a/components/plugins/renderer/webview_plugin.cc
+++ b/components/plugins/renderer/webview_plugin.cc
@@ -283,9 +283,9 @@
           .BindNewEndpointAndPassDedicatedRemoteForTesting(),
       blink_widget_.BindNewEndpointAndPassDedicatedReceiverForTesting());
 
-  // The WebFrame created here was already attached to the Page as its
-  // main frame, and the WebFrameWidget has been initialized, so we can call
-  // WebViewImpl's DidAttachLocalMainFrame().
+  // The WebFrame created here was already attached to the Page as its main
+  // frame, and the WebFrameWidget has been initialized, so we can call
+  // WebView's DidAttachLocalMainFrame().
   web_view_->DidAttachLocalMainFrame();
 }
 
diff --git a/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java b/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java
index 42965b2..cc08192 100644
--- a/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java
+++ b/components/policy/android/javatests/src/org/chromium/policy/test/annotations/Policies.java
@@ -10,8 +10,9 @@
 import androidx.annotation.VisibleForTesting;
 
 import org.junit.Assert;
+import org.junit.runners.model.FrameworkMethod;
 
-import org.chromium.base.test.BaseTestResult.PreTestHook;
+import org.chromium.base.test.BaseJUnit4ClassRunner.TestHook;
 import org.chromium.policy.AbstractAppRestrictionsProvider;
 import org.chromium.policy.test.PolicyData;
 
@@ -106,8 +107,8 @@
         return result;
     }
 
-    /** @see PreTestHook */
-    public static PreTestHook getRegistrationHook() {
+    /** see {@link TestHook} */
+    public static TestHook getRegistrationHook() {
         return new RegistrationHook();
     }
 
@@ -136,10 +137,10 @@
      * Registration hook for the {@link Policies} annotation family. Before a test, will parse
      * the declared policies and use them as cached policies.
      */
-    public static class RegistrationHook implements PreTestHook {
+    public static class RegistrationHook implements TestHook {
         @Override
-        public void run(Context targetContext, Method testMethod) {
-            Map<String, PolicyData> policyMap = getPolicies(testMethod);
+        public void run(Context targetContext, FrameworkMethod testMethod) {
+            Map<String, PolicyData> policyMap = getPolicies(testMethod.getMethod());
             if (policyMap.isEmpty()) {
                 AbstractAppRestrictionsProvider.setTestRestrictions(null);
             } else {
diff --git a/components/policy/core/browser/configuration_policy_handler_list.cc b/components/policy/core/browser/configuration_policy_handler_list.cc
index b643d62..3048bca 100644
--- a/components/policy/core/browser/configuration_policy_handler_list.cc
+++ b/components/policy/core/browser/configuration_policy_handler_list.cc
@@ -24,9 +24,11 @@
 
 ConfigurationPolicyHandlerList::ConfigurationPolicyHandlerList(
     const PopulatePolicyHandlerParametersCallback& parameters_callback,
-    const GetChromePolicyDetailsCallback& details_callback)
+    const GetChromePolicyDetailsCallback& details_callback,
+    bool allow_future_policies)
     : parameters_callback_(parameters_callback),
-      details_callback_(details_callback) {}
+      details_callback_(details_callback),
+      allow_future_policies_(allow_future_policies) {}
 
 ConfigurationPolicyHandlerList::~ConfigurationPolicyHandlerList() {
 }
@@ -47,11 +49,11 @@
   // TODO(aberent): split into two functions.
   // TODO(crbug.com/1076560): Returns filtered out future policies for better
   // user interface.
-  // TODO(crbug.com/1076560): Provides a way to all whitelist experimental
-  // policies in Canary/Dev and test.
   std::unique_ptr<PolicyMap> filtered_policies = policies.DeepCopy();
   base::flat_set<std::string> enabled_future_policies =
-      ValueToStringSet(policies.GetValue(key::kEnableExperimentalPolicies));
+      allow_future_policies_ ? base::flat_set<std::string>()
+                             : ValueToStringSet(policies.GetValue(
+                                   key::kEnableExperimentalPolicies));
   filtered_policies->EraseMatching(base::BindRepeating(
       &ConfigurationPolicyHandlerList::FilterOutUnsupportedPolicies,
       base::Unretained(this), enabled_future_policies));
@@ -123,7 +125,7 @@
     const base::flat_set<std::string>& enabled_future_policies,
     const PolicyDetails& policy_details,
     const PolicyMap::const_iterator iter) const {
-  return policy_details.is_future &&
+  return !allow_future_policies_ && policy_details.is_future &&
          !enabled_future_policies.contains(iter->first);
 }
 
diff --git a/components/policy/core/browser/configuration_policy_handler_list.h b/components/policy/core/browser/configuration_policy_handler_list.h
index 2df2783e..c8b929b6 100644
--- a/components/policy/core/browser/configuration_policy_handler_list.h
+++ b/components/policy/core/browser/configuration_policy_handler_list.h
@@ -37,7 +37,8 @@
 
   explicit ConfigurationPolicyHandlerList(
       const PopulatePolicyHandlerParametersCallback& parameters_callback,
-      const GetChromePolicyDetailsCallback& details_callback);
+      const GetChromePolicyDetailsCallback& details_callback,
+      bool allow_future_policies);
   ~ConfigurationPolicyHandlerList();
 
   // Adds a policy handler to the list.
@@ -73,6 +74,8 @@
   const PopulatePolicyHandlerParametersCallback parameters_callback_;
   const GetChromePolicyDetailsCallback details_callback_;
 
+  bool allow_future_policies_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyHandlerList);
 };
 
diff --git a/components/policy/core/browser/configuration_policy_handler_list_unittest.cc b/components/policy/core/browser/configuration_policy_handler_list_unittest.cc
index bfb0433..f006c484 100644
--- a/components/policy/core/browser/configuration_policy_handler_list_unittest.cc
+++ b/components/policy/core/browser/configuration_policy_handler_list_unittest.cc
@@ -52,6 +52,8 @@
 
 class ConfigurationPolicyHandlerListTest : public ::testing::Test {
  public:
+  void SetUp() override { CreateHandlerList(); }
+
   void AddSimplePolicy() {
     AddPolicy(kPolicyName, /* is_cloud */ true,
               std::make_unique<base::Value>(kPolicyValue));
@@ -66,14 +68,24 @@
                            : PolicySource::POLICY_SOURCE_PLATFORM,
                   std::move(value), nullptr);
     if (policy_name != key::kEnableExperimentalPolicies) {
-      handler_list_.AddHandler(
+      handler_list_->AddHandler(
           std::make_unique<StubPolicyHandler>(policy_name));
     }
   }
 
   void ApplySettings() {
-    handler_list_.ApplyPolicySettings(policies_, &prefs_, &errors_,
-                                      &deprecated_policies_);
+    handler_list_->ApplyPolicySettings(policies_, &prefs_, &errors_,
+                                       &deprecated_policies_);
+  }
+
+  void CreateHandlerList(bool allow_all_future_policies = false) {
+    handler_list_ = std::make_unique<ConfigurationPolicyHandlerList>(
+        ConfigurationPolicyHandlerList::
+            PopulatePolicyHandlerParametersCallback(),
+        base::BindRepeating(
+            &ConfigurationPolicyHandlerListTest::GetPolicyDetails,
+            base::Unretained(this)),
+        allow_all_future_policies);
   }
 
   PrefValueMap* prefs() { return &prefs_; }
@@ -108,10 +120,7 @@
   DeprecatedPoliciesSet deprecated_policies_;
   PolicyDetails details_{false, false, false, 0, 0, {}};
 
-  ConfigurationPolicyHandlerList handler_list_{
-      ConfigurationPolicyHandlerList::PopulatePolicyHandlerParametersCallback(),
-      base::BindRepeating(&ConfigurationPolicyHandlerListTest::GetPolicyDetails,
-                          base::Unretained(this))};
+  std::unique_ptr<ConfigurationPolicyHandlerList> handler_list_;
 };
 
 TEST_F(ConfigurationPolicyHandlerListTest, ApplySettingsWithNormalPolicy) {
@@ -150,6 +159,16 @@
   VerifyPolicyAndPref(kPolicyName, /* in_pref */ true);
 }
 
+TEST_F(ConfigurationPolicyHandlerListTest,
+       ApplySettingsWithoutFutureFilterPolicy) {
+  CreateHandlerList(true);
+  AddSimplePolicy();
+  details()->is_future = true;
+
+  ApplySettings();
+
+  VerifyPolicyAndPref(kPolicyName, /* in_pref */ true);
+}
 // Device platform policy will be fitered out.
 TEST_F(ConfigurationPolicyHandlerListTest,
        ApplySettingsWithPlatformDevicePolicy) {
diff --git a/components/policy/core/browser/configuration_policy_pref_store_test.cc b/components/policy/core/browser/configuration_policy_pref_store_test.cc
index 274f814..16303a8 100644
--- a/components/policy/core/browser/configuration_policy_pref_store_test.cc
+++ b/components/policy/core/browser/configuration_policy_pref_store_test.cc
@@ -25,7 +25,8 @@
     : handler_list_(base::BindRepeating(&ConfigurationPolicyPrefStoreTest::
                                             PopulatePolicyHandlerParameters,
                                         base::Unretained(this)),
-                    GetChromePolicyDetailsCallback()) {
+                    GetChromePolicyDetailsCallback(),
+                    /* allow_all_future_policies*/ true) {
   EXPECT_CALL(provider_, IsInitializationComplete(_))
       .WillRepeatedly(Return(false));
   provider_.Init();
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc
index 2ca93953..a6b8dea 100644
--- a/components/policy/core/common/policy_map.cc
+++ b/components/policy/core/common/policy_map.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/callback.h"
+#include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
@@ -224,6 +225,18 @@
   Set(policy, std::move(entry));
 }
 
+void PolicyMap::Set(
+    const std::string& policy,
+    PolicyLevel level,
+    PolicyScope scope,
+    PolicySource source,
+    base::Optional<base::Value> value,
+    std::unique_ptr<ExternalDataFetcher> external_data_fetcher) {
+  Entry entry(level, scope, source, std::move(value),
+              std::move(external_data_fetcher));
+  Set(policy, std::move(entry));
+}
+
 void PolicyMap::Set(const std::string& policy, Entry entry) {
   map_[policy] = std::move(entry);
 }
@@ -334,7 +347,7 @@
                          PolicySource source) {
   for (base::DictionaryValue::Iterator it(*policies); !it.IsAtEnd();
        it.Advance()) {
-    Set(it.key(), level, scope, source, it.value().CreateDeepCopy(), nullptr);
+    Set(it.key(), level, scope, source, it.value().Clone(), nullptr);
   }
 }
 
diff --git a/components/policy/core/common/policy_map.h b/components/policy/core/common/policy_map.h
index baccfbf..732d86a0 100644
--- a/components/policy/core/common/policy_map.h
+++ b/components/policy/core/common/policy_map.h
@@ -143,12 +143,22 @@
 
   // Overwrites any existing information stored in the map for the key |policy|.
   // Resets the error for that policy to the empty string.
+  // DEPRECATED: Use the other version that takes base::Optional<base::Value>
+  // below.
+  // TODO(crbug.com/1092469): Migrate the existing usages and delete this
+  // method.
   void Set(const std::string& policy,
            PolicyLevel level,
            PolicyScope scope,
            PolicySource source,
            std::unique_ptr<base::Value> value,
            std::unique_ptr<ExternalDataFetcher> external_data_fetcher);
+  void Set(const std::string& policy,
+           PolicyLevel level,
+           PolicyScope scope,
+           PolicySource source,
+           base::Optional<base::Value> value,
+           std::unique_ptr<ExternalDataFetcher> external_data_fetcher);
 
   void Set(const std::string& policy, Entry entry);
 
diff --git a/components/policy/proto/BUILD.gn b/components/policy/proto/BUILD.gn
index 0705695..ea16d7f 100644
--- a/components/policy/proto/BUILD.gn
+++ b/components/policy/proto/BUILD.gn
@@ -17,14 +17,24 @@
 proto_library("policy_record_constants") {
   visibility = [
     "//chrome/browser:browser",
-    "//chrome/browser:reporting_record_proto",
-    "//chrome/browser:reporting_record_proto_gen",
+    ":reporting_record_proto",
+    ":reporting_record_proto_gen",
   ]
   sources = [ "record_constants.proto" ]
 
   proto_out_dir = "components/policy/proto"
 }
 
+# Record definitions for reporting.
+proto_library("reporting_record_proto") {
+  visibility = [ "//chrome/browser:browser" ]
+  sources = [ "record.proto" ]
+
+  deps = [ ":policy_record_constants" ]
+
+  proto_out_dir = "components/policy/proto"
+}
+
 proto_library("policy_common_definitions_compile_proto") {
   visibility = [
     "//components/policy:cloud_policy_proto_generated_compile_proto",
diff --git a/chrome/browser/policy/messaging_layer/proto/record.proto b/components/policy/proto/record.proto
similarity index 97%
rename from chrome/browser/policy/messaging_layer/proto/record.proto
rename to components/policy/proto/record.proto
index efa1e84..0dae08ad 100644
--- a/chrome/browser/policy/messaging_layer/proto/record.proto
+++ b/components/policy/proto/record.proto
@@ -6,9 +6,9 @@
 
 option optimize_for = LITE_RUNTIME;
 
-package reporting_messaging_layer;
+package reporting;
 
-import "components/policy/proto/record_constants.proto";
+import "record_constants.proto";
 
 // Record represents the data sent from the Reporting Client.
 message Record {
diff --git a/components/policy/proto/record_constants.proto b/components/policy/proto/record_constants.proto
index d2504a3..17f7c79 100644
--- a/components/policy/proto/record_constants.proto
+++ b/components/policy/proto/record_constants.proto
@@ -6,7 +6,7 @@
 
 option optimize_for = LITE_RUNTIME;
 
-package reporting_messaging_layer;
+package reporting;
 
 // |Destination| indicates which handler a |Record| should be delivered to.
 enum Destination {
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index fb263a6..294be902 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -1243,11 +1243,9 @@
       'id': 4,
       'caption': '''Application locale''',
       'tags': [],
-      'desc': '''Configures the application locale in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> and prevents users from changing the locale.
+      'desc': '''Setting the policy specifies the locale <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> uses.
 
-      If you enable this setting, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> uses the specified locale. If the configured locale is not supported, 'en-US' is used instead.
-
-      If this setting is disabled or not set, <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph> uses either the user-specified preferred locale (if configured), the system locale or the fallback locale 'en-US'.''',
+      Turning it off or leaving it unset means users specify the locale (if configured), the system locale, or the fallback locale (en-US).''',
       'label': '''Application locale''',
     },
     {
@@ -9595,15 +9593,11 @@
       'id': 158,
       'caption': '''Timezone''',
       'tags': [],
-      'desc': '''Specifies the enforced timezone to be used for the device. When this policy is set, users on the device cannot override the specified timezone. If an invalid value is provided, the policy is still activated using "GMT" instead. If an empty string is provided, the policy is ignored.
+      'desc': '''Setting the policy specifies a device's time zone and turns off location-based automatic time zone adjustment while overriding the <ph name="SYSTEM_TIMEZONE_AUTOMATIC_DETECTION_POLICY_NAME">SystemTimezoneAutomaticDetection</ph> policy. Users can't change the time zone.
 
-      If this policy is not used, the currently active timezone will remain in use however users can change the timezone.
+      New devices start with the time zone set to US Pacific. Value format follows the names in the IANA Time Zone Database ( https://en.wikipedia.org/wiki/Tz_database ). Entering an invalid value activates the policy using GMT.
 
-      New devices start out with the timezone set to "US/Pacific".
-
-      The format of the value follows the names of timezones in the "IANA Time Zone Database" (see "https://en.wikipedia.org/wiki/Tz_database"). In particular, most timezones can be referred to by "continent/large_city" or "ocean/large_city".
-
-      Setting this policy completely disables automatic timezone resolve by device location. It also overrides SystemTimezoneAutomaticDetection policy.''',
+      If not set or if you enter an empty string, the device uses the currently active time zone, but users can change it.''',
     },
     {
       'name': 'SystemUse24HourClock',
@@ -9619,13 +9613,9 @@
       'id': 236,
       'caption': '''Use 24 hour clock by default''',
       'tags': [],
-      'desc': '''Specifies the clock format be used for the device.
+      'desc': '''Setting the policy to True or leaving it unset gives a device's sign-in screen a 24-hour clock format. User sessions also default to this format, but users can change an account's clock format.
 
-      This policy configures the clock format to use on the login screen and as a default for user sessions. Users can still override the clock format for their account.
-
-      If the policy is set to true, the device will use a 24 hour clock format. If the policy is set to false, the device will use 12 hour clock format.
-
-      If this policy is not set, the device will default to a 24 hour clock format.''',
+      Setting the policy to False gives a device the 12-hour clock format.''',
     },
     {
       'name': 'TouchVirtualKeyboardEnabled',
@@ -12538,15 +12528,13 @@
       'id': 262,
       'caption': '''Wallpaper image''',
       'tags': [],
-      'desc': '''This policy allows you to configure the wallpaper image that is shown on the desktop and on the login screen background for the user. The policy is set by specifying the URL from which <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> can download the wallpaper image and a cryptographic hash used to verify the integrity of the download. The image must be in JPEG format, its file size must not exceed 16MB. The URL must be accessible without any authentication.
+      'desc': '''If you set the policy, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph>
 
-      The wallpaper image is downloaded and cached. It will be re-downloaded whenever the URL or the hash changes.
+      downloads and uses the wallpaper image you set for the user's desktop and sign-in screen background, and users can't change it. Specify the URL (that's accessible without authentication) which <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph>
 
-      If this policy is set, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will download and use the wallpaper image.
+      can download the wallpaper image from, as well as a cryptographic hash (in JPEG format with a file size up to 16 MB) to verify its integrity.
 
-      If you set this policy, users cannot change or override it.
-
-      If the policy is left not set, the user can choose an image to be shown on the desktop and on the login screen background.''',
+      If not set, users choose the image for the desktop and sign-in screen background.''',
     },
     {
       'name': 'EnableDeprecatedWebPlatformFeatures',
@@ -12651,22 +12639,15 @@
       'id': 274,
       'caption': '''Set the recommended locales for a managed session''',
       'tags': [],
-      'desc': '''Sets one or more recommended locales for a managed session, allowing users to easily choose one of these locales.
+      'desc': '''Setting the policy (as recommended only) moves recommended locales for a managed session to the top of the list, in the order in which they appear in the policy. The first recommended locale is preselected.
 
-      The user can choose a locale and a keyboard layout before starting a managed session. By default, all locales supported by <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> are listed in alphabetic order. You can use this policy to move a set of recommended locales to the top of the list.
+      If not set, the current UI locale is preselected.
 
-      If this policy is not set, the current UI locale will be pre-selected.
+      For more than one recommended locale, the assumption is that users want to choose among these locales. Locale and keyboard layout selection is prominent when starting a managed session. Otherwise, the assumption is that most users want the preselected locale. Locale and keyboard layout selection is less prominent when starting a managed session.
 
-      If this policy is set, the recommended locales will be moved to the top of the list and will be visually separated from all other locales. The recommended locales will be listed in the order in which they appear in the policy. The first recommended locale will be pre-selected.
+      If you set the policy and turn automatic sign-in on (see the <ph name="DEVICE_LOCAL_ACCOUNT_AUTO_LOGIN_ID_POLICY_NAME">DeviceLocalAccountAutoLoginId</ph> and <ph name="DEVICE_LOCAL_ACCOUNT_AUTO_LOGIN_DELAY_POLICY_NAME">DeviceLocalAccountAutoLoginDelay</ph> policies), the managed session uses the first recommended locale and the most popular matching keyboard layout.
 
-      If there is more than one recommended locale, it is assumed that users will want to select among these locales. Locale and keyboard layout selection will be prominently offered when starting a managed session. Otherwise, it is assumed that most users will want to use the pre-selected locale. Locale and keyboard layout selection will be less prominently offered when starting a managed session.
-
-      When this policy is set and automatic login is enabled (see the |DeviceLocalAccountAutoLoginId| and |DeviceLocalAccountAutoLoginDelay| policies), the automatically started managed session will use the first recommended locale and the most popular keyboard layout matching this locale.
-
-      The pre-selected keyboard layout will always be the most popular layout matching the pre-selected locale.
-
-      This policy can only be set as recommended. You can use this policy to move a set of recommended locales to the top but users are always allowed to choose any locale supported by <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> for their session.
-      ''',
+      The preselected keyboard layout is always the most popular layout matching the preselected locale. Users can always choose any locale supported by <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> for their session.''',
     },
     {
       'name': 'BrowserGuestModeEnabled',
@@ -13076,13 +13057,9 @@
       'id': 281,
       'caption': '''Enable Touch to Search''',
       'tags': [],
-      'desc': '''Enables the availability of Touch to Search in <ph name="PRODUCT_NAME">$1<ex>Google Chrome</ex></ph>'s content view.
+      'desc': '''Setting the policy to True or leaving it unset makes Touch to Search available to the user, and they can turn the feature on or off.
 
-      If you enable this setting, Touch to Search will be available to the user and they can choose to turn the feature on or off.
-
-      If you disable this setting, Touch to Search will be disabled completely.
-
-      If this policy is left not set, it is equivalent to being enabled, see description above.''',
+      Setting the policy to False turns Touch to Search off completely.''',
     },
     {
       'name': 'DeviceRebootOnShutdown',
@@ -13283,13 +13260,9 @@
       'id': 307,
       'caption': '''Make Unified Desktop available and turn on by default''',
       'tags': [],
-      'desc': '''If this policy is set to true, Unified Desktop is allowed and
-      enabled by default, which allows applications to span multiple displays.
-      The user may disable Unified Desktop for individual displays by unchecking
-      it in the display settings.
+      'desc': '''Setting the policy to True turns on Unified Desktop, which allows applications to span multiple displays. Users can turn off Unified Desktop for individual displays.
 
-      If this policy is set to false or unset, Unified Desktop will be
-      disabled. In this case, the user cannot enable the feature.''',
+      Setting the policy to False or leaving it unset turns off Unified Desktop, and users can't turn it on.''',
     },
     {
       'name': 'DisplayRotationDefault',
@@ -13628,21 +13601,15 @@
       'id': 326,
       'caption': '''Configure the automatic timezone detection method''',
       'tags': ['google-sharing'],
-      'desc': '''When this policy is set, automatic timezone detection flow will be in one of the following ways depending on the value of the setting:
+      'desc': '''Unless the <ph name="SYSTEM_TIMEZONE_POLICY_NAME">SystemTimezone</ph> policy turns off automatic time zone detection, then setting the policy outlines the automatic time zone detection method, which users can't change.
 
-      If set to TimezoneAutomaticDetectionUsersDecide, users would be able to control automatic timezone detection using normal controls in chrome://settings.
+      Setting the policy to:
+       * <ph name="POLICY_ENUM_SYSTEMTIMEZONEAUTOMATICDETECTION_TIMEZONEAUTOMATICDETECTIONDISABLED">TimezoneAutomaticDetectionDisabled</ph> keeps automatic time zone detection off.
+       * <ph name="POLICY_ENUM_SYSTEMTIMEZONEAUTOMATICDETECTION_TTIMEZONEAUTOMATICDETECTIONIPONLY">TimezoneAutomaticDetectionIPOnly</ph> keeps automatic time zone detection on, using the IP-only method.
+       * <ph name="POLICY_ENUM_SYSTEMTIMEZONEAUTOMATICDETECTION_TIMEZONEAUTOMATICDETECTIONSENDWIFIACCESSPOINTS">TimezoneAutomaticDetectionSendWiFiAccessPoints</ph> keeps automatic time zone detection on, continually sending the list of visible Wi-Fi access-points to the Geolocation API server for finer-grained time zone detection.
+       * <ph name="POLICY_ENUM_SYSTEMTIMEZONEAUTOMATICDETECTION_TIMEZONEAUTOMATICDETECTIONSENDALLLOCATIONINFO">TimezoneAutomaticDetectionSendAllLocationInfo</ph> keeps automatic time zone detection on, continually sending location information (such as Wi-Fi access points, reachable cell towers, GPS) to a server for the most fine-grained time zone detection.
 
-      If set to TimezoneAutomaticDetectionDisabled, automatic timezone controls in chrome://settings will be disabled. Automatic timezone detection will be always off.
-
-      If set to TimezoneAutomaticDetectionIPOnly, timezone controls in chrome://settings will be disabled. Automatic timezone detection will be always on. Timezone detection will use IP-only method to resolve location.
-
-      If set to TimezoneAutomaticDetectionSendWiFiAccessPoints, timezone controls in chrome://settings will be disabled. Automatic timezone detection will be always on. The list of visible WiFi access-points will be always sent to Geolocation API server for fine-grained timezone detection.
-
-      If set to TimezoneAutomaticDetectionSendAllLocationInfo, timezone controls in chrome://settings will be disabled. Automatic timezone detection will be always on. Location information (such as WiFi access-points, reachable Cell Towers, GPS) will be sent to a server for fine-grained timezone detection.
-
-      If this policy is not set, it will behave as if TimezoneAutomaticDetectionUsersDecide is set.
-
-      If SystemTimezone policy is set, it overrides this policy. In this case automatic timezone detection is completely disabled.''',
+      If not set, set to Let users decide, or set to None, then users control automatic time zone detection using normal controls in chrome://settings.''',
     },
     {
       'name': 'TaskManagerEndProcessEnabled',
@@ -14075,9 +14042,9 @@
       'caption': '''Show content suggestions on the New Tab page''',
       'tags': [],
       'desc':
-      '''If this is set to true or not set, the New Tab page may show content suggestions based on the user's browsing history, interests, or location.
+      '''Setting the policy to True or leaving it unset displays autogenerated content suggestions on the New Tab page, based on the user's browsing history, interests, or location.
 
-      If this is set to false, automatically-generated content suggestions are not shown on the New Tab page.''',
+      Setting the policy to False prevents autogenerated content suggestions from appearing on the New Tab page.''',
     },
     {
       'name': 'NTPCustomBackgroundEnabled',
@@ -16533,9 +16500,11 @@
       'id': 444,
       'caption': '''Configure the allowed languages in a user session''',
       'tags': [],
-      'desc': '''Configures the languages that can be used as the preferred languages by <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph>.
+      'desc': '''Setting the policy lets users add only one of the languages listed in this policy to the list of preferred languages.
 
-      If this policy is set, the user can only add one of the languages listed in this policy to the list of preferred languages. If this policy is not set or set to an empty list, user can specify any languages as preferred. If this policy is set to a list with invalid values, all invalid values will be ignored. If a user previously added some languages that are not allowed by this policy to the list of preferred languages they will be removed. If the user had previously configured <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> to be displayed in one of the languages not allowed by this policy, the display language will be switched to an allowed UI language next time user signs in. Otherwise, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> will switch to the first valid value specified by this policy, or to a fallback locale (currently en-US), if this policy only contains invalid entries.'''
+      If not set or set to an empty list, users can specify languages as preferred.
+
+      If set to a list with invalid values, those values are ignored. If users added languages not allowed by this policy to the list of preferred languages, they're removed. If they had <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> displayed in a language not allowed by this policy, the next time they sign in, the display language switches to an allowed UI language. Otherwise, if this policy only has invalid entries, <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> switches to the first valid value specified by this policy or a fallback locale such as en-US.'''
     },
     {
       'name': 'AllowedInputMethods',
@@ -17281,9 +17250,13 @@
       'id': 468,
       'caption': '''Configure list of force-installed Web Apps''',
       'tags': [],
-      'desc': '''Specifies a list of websites that are installed silently, without user interaction, and which cannot be uninstalled nor disabled by the user.
+      'desc': '''Setting the policy specifies a list of websites that install silently, without user interaction, and which users can't uninstall or turn off.
 
-      Each list item of the policy is an object with a mandatory member: "url" and two optional members: "default_launch_container" and "create_desktop_shortcut". "url" should be the URL of the web app to install, "launch_container" should be either "window" or "tab" to indicate how the Web App will be opened once installed, and "create_desktop_shortcut" should be true if a desktop shortcut should be created on Linux and Windows. If "default_launch_container" is omitted, the app will open in a tab by default. Regardless of the value of "default_launch_container", users are able to change which container the app will open in. If "create_desktop_shortcuts" is omitted, no desktop shortcuts will be created. See <ph name="PINNED_LAUNCHER_APPS_POLICY_NAME">PinnedLauncherApps</ph> policy for pinning apps to the ChromeOS shelf.''',
+      Each list item of the policy is an object with a mandatory member: <ph name="URL_LABEL">url</ph> (the URL of the web app to install) and 2 optional members: <ph name="DEFAULT_LAUNCH_CONTAINER_LABEL">default_launch_container</ph> (for how the web app opens—a new tab is the default) and <ph name="CREATE_DESKTOP_SHORTCUT_LABEL">create_desktop_shortcut</ph> (True, if creating <ph name="LINUX_OS_NAME">Linux</ph> and Windows® desktop shortcuts).
+
+      Users can change which container the app opens in and skip desktop shortcuts.
+
+      See <ph name="PINNED_LAUNCHER_APPS_POLICY_NAME">PinnedLauncherApps</ph> for pinning apps to the <ph name="PRODUCT_OS_NAME">$2<ex>Google Chrome OS</ex></ph> shelf.''',
       'label': '''URLs for Web Apps to be silently installed.''',
     },
     {
@@ -21120,7 +21093,7 @@
               'enum': [ 'rsa' ]
             },
             'renewal_period_seconds': {
-              'description': 'Number of days before expiration of a certificate when renewal should be triggered',
+              'description': 'Number of seconds before expiration of a certificate when renewal should be triggered',
               'type': 'integer'
             },
             'policy_version': {
@@ -21159,7 +21132,7 @@
               'type': 'string'
             },
             'cert_profile_id': {
-              'description': 'An identifier for this client certificate.',
+              'description': 'The identifier for this client certificate.',
               'type': 'string'
             },
             'key_algorithm': {
@@ -21168,7 +21141,7 @@
               'enum': [ 'rsa' ]
             },
             'renewal_period_seconds': {
-              'description': 'Number of days before expiration of a certificate when renewal should be triggered',
+              'description': 'Number of seconds before expiration of a certificate when renewal should be triggered',
               'type': 'integer'
             },
             'policy_version': {
diff --git a/components/prefs/pref_member.cc b/components/prefs/pref_member.cc
index 4051e5c..a53394f 100644
--- a/components/prefs/pref_member.cc
+++ b/components/prefs/pref_member.cc
@@ -10,7 +10,7 @@
 #include "base/callback_helpers.h"
 #include "base/location.h"
 #include "base/threading/sequenced_task_runner_handle.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "components/prefs/pref_service.h"
 
 using base::SequencedTaskRunner;
@@ -200,7 +200,11 @@
 bool PrefMember<base::FilePath>::Internal::UpdateValueInternal(
     const base::Value& value)
     const {
-  return base::GetValueAsFilePath(value, &value_);
+  base::Optional<base::FilePath> path = util::ValueToFilePath(value);
+  if (!path)
+    return false;
+  value_ = *path;
+  return true;
 }
 
 template <>
diff --git a/components/prefs/pref_service.cc b/components/prefs/pref_service.cc
index ba16dd4..7a8bd7e 100644
--- a/components/prefs/pref_service.cc
+++ b/components/prefs/pref_service.cc
@@ -23,7 +23,6 @@
 #include "base/strings/string_util.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/util/values/values_util.h"
-#include "base/value_conversions.h"
 #include "build/build_config.h"
 #include "components/prefs/default_pref_store.h"
 #include "components/prefs/pref_notifier_impl.h"
@@ -206,14 +205,12 @@
 base::FilePath PrefService::GetFilePath(const std::string& path) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  base::FilePath result;
-
   const base::Value* value = GetPreferenceValueChecked(path);
   if (!value)
-    return base::FilePath(result);
-  bool rv = base::GetValueAsFilePath(*value, &result);
-  DCHECK(rv);
-  return result;
+    return base::FilePath();
+  base::Optional<base::FilePath> result = util::ValueToFilePath(*value);
+  DCHECK(result);
+  return *result;
 }
 
 bool PrefService::HasPrefPath(const std::string& path) const {
@@ -492,7 +489,7 @@
 
 void PrefService::SetFilePath(const std::string& path,
                               const base::FilePath& value) {
-  SetUserPrefValue(path, base::CreateFilePathValue(value));
+  SetUserPrefValue(path, util::FilePathToValue(value));
 }
 
 void PrefService::SetInt64(const std::string& path, int64_t value) {
diff --git a/components/prerender/BUILD.gn b/components/prerender/BUILD.gn
deleted file mode 100644
index c58cfbb0..0000000
--- a/components/prerender/BUILD.gn
+++ /dev/null
@@ -1,14 +0,0 @@
-# Copyright 2020 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-static_library("prerender") {
-  sources = [
-    "prerender_final_status.cc",
-    "prerender_final_status.h",
-    "prerender_origin.cc",
-    "prerender_origin.h",
-    "prerender_types.h",
-  ]
-  deps = [ "//base" ]
-}
diff --git a/components/prerender/common/BUILD.gn b/components/prerender/common/BUILD.gn
new file mode 100644
index 0000000..d3ec045
--- /dev/null
+++ b/components/prerender/common/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//mojo/public/tools/bindings/mojom.gni")
+
+static_library("common") {
+  sources = [
+    "prerender_final_status.cc",
+    "prerender_final_status.h",
+    "prerender_messages.h",
+    "prerender_origin.cc",
+    "prerender_origin.h",
+    "prerender_types.h",
+  ]
+  deps = [
+    "//ipc",
+    "//ipc:message_support",
+    "//ipc:param_traits",
+  ]
+}
+
+mojom("mojo_bindings") {
+  sources = [ "prerender_canceler.mojom" ]
+  deps = [ "//url/mojom:url_mojom_gurl" ]
+}
diff --git a/components/prerender/common/DEPS b/components/prerender/common/DEPS
new file mode 100644
index 0000000..1c40d98
--- /dev/null
+++ b/components/prerender/common/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+ipc",
+]
diff --git a/components/prerender/common/OWNERS b/components/prerender/common/OWNERS
new file mode 100644
index 0000000..d8469177
--- /dev/null
+++ b/components/prerender/common/OWNERS
@@ -0,0 +1,5 @@
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/common/prerender_canceler.mojom b/components/prerender/common/prerender_canceler.mojom
similarity index 92%
rename from chrome/common/prerender_canceler.mojom
rename to components/prerender/common/prerender_canceler.mojom
index 58d0ee0..a7e78bf 100644
--- a/chrome/common/prerender_canceler.mojom
+++ b/components/prerender/common/prerender_canceler.mojom
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-module chrome.mojom;
+module components.prerender.common.mojom;
 
 import "url/mojom/url.mojom";
 
diff --git a/components/prerender/prerender_final_status.cc b/components/prerender/common/prerender_final_status.cc
similarity index 96%
rename from components/prerender/prerender_final_status.cc
rename to components/prerender/common/prerender_final_status.cc
index 0c127d6..54ae6e1 100644
--- a/components/prerender/prerender_final_status.cc
+++ b/components/prerender/common/prerender_final_status.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/prerender/prerender_final_status.h"
+#include "components/prerender/common/prerender_final_status.h"
 
 #include "base/stl_util.h"
 
diff --git a/components/prerender/prerender_final_status.h b/components/prerender/common/prerender_final_status.h
similarity index 93%
rename from components/prerender/prerender_final_status.h
rename to components/prerender/common/prerender_final_status.h
index 1260fa36..ffcddd3 100644
--- a/components/prerender/prerender_final_status.h
+++ b/components/prerender/common/prerender_final_status.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_PRERENDER_PRERENDER_FINAL_STATUS_H_
-#define COMPONENTS_PRERENDER_PRERENDER_FINAL_STATUS_H_
+#ifndef COMPONENTS_PRERENDER_COMMON_PRERENDER_FINAL_STATUS_H_
+#define COMPONENTS_PRERENDER_COMMON_PRERENDER_FINAL_STATUS_H_
 
-#include "components/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_origin.h"
 
 namespace prerender {
 
@@ -88,4 +88,4 @@
 
 }  // namespace prerender
 
-#endif  // COMPONENTS_PRERENDER_PRERENDER_FINAL_STATUS_H_
+#endif  // COMPONENTS_PRERENDER_COMMON_PRERENDER_FINAL_STATUS_H_
\ No newline at end of file
diff --git a/chrome/common/prerender_messages.h b/components/prerender/common/prerender_messages.h
similarity index 82%
rename from chrome/common/prerender_messages.h
rename to components/prerender/common/prerender_messages.h
index 2d22e25..8419188 100644
--- a/chrome/common/prerender_messages.h
+++ b/components/prerender/common/prerender_messages.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_COMMON_PRERENDER_MESSAGES_H_
-#define CHROME_COMMON_PRERENDER_MESSAGES_H_
+#ifndef COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
+#define COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
 
-#include "components/prerender/prerender_types.h"
+#include "components/prerender/common/prerender_types.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
 #include "ipc/ipc_param_traits.h"
@@ -32,4 +32,4 @@
                     prerender::PrerenderMode,
                     std::string /* histogram_prefix */)
 
-#endif  // CHROME_COMMON_PRERENDER_MESSAGES_H_
+#endif  // COMPONENTS_PRERENDER_COMMON_PRERENDER_MESSAGES_H_
diff --git a/components/prerender/prerender_origin.cc b/components/prerender/common/prerender_origin.cc
similarity index 94%
rename from components/prerender/prerender_origin.cc
rename to components/prerender/common/prerender_origin.cc
index 636ea16..ccb6d43 100644
--- a/components/prerender/prerender_origin.cc
+++ b/components/prerender/common/prerender_origin.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/prerender/prerender_origin.h"
+#include "components/prerender/common/prerender_origin.h"
 
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
diff --git a/components/prerender/prerender_origin.h b/components/prerender/common/prerender_origin.h
similarity index 88%
rename from components/prerender/prerender_origin.h
rename to components/prerender/common/prerender_origin.h
index 6cc97e3..861d7bb1 100644
--- a/components/prerender/prerender_origin.h
+++ b/components/prerender/common/prerender_origin.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_PRERENDER_PRERENDER_ORIGIN_H_
-#define COMPONENTS_PRERENDER_PRERENDER_ORIGIN_H_
+#ifndef COMPONENTS_PRERENDER_COMMON_PRERENDER_ORIGIN_H_
+#define COMPONENTS_PRERENDER_COMMON_PRERENDER_ORIGIN_H_
 
 namespace prerender {
 
@@ -40,4 +40,4 @@
 
 }  // namespace prerender
 
-#endif  // COMPONENTS_PRERENDER_PRERENDER_ORIGIN_H_
+#endif  // COMPONENTS_PRERENDER_COMMON_PRERENDER_ORIGIN_H_
diff --git a/components/prerender/prerender_types.h b/components/prerender/common/prerender_types.h
similarity index 74%
rename from components/prerender/prerender_types.h
rename to components/prerender/common/prerender_types.h
index ac81495..3a8e7fc1 100644
--- a/components/prerender/prerender_types.h
+++ b/components/prerender/common/prerender_types.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_PRERENDER_PRERENDER_TYPES_H_
-#define COMPONENTS_PRERENDER_PRERENDER_TYPES_H_
+#ifndef COMPONENTS_PRERENDER_COMMON_PRERENDER_TYPES_H_
+#define COMPONENTS_PRERENDER_COMMON_PRERENDER_TYPES_H_
 
 namespace prerender {
 
@@ -22,4 +22,4 @@
 
 }  // namespace prerender
 
-#endif  // CHROME_COMMON_PRERCOMPONENTS_PRERENDER_PRERENDER_TYPES_H_ENDER_TYPES_H_
+#endif  // COMPONENTS_PRERENDER_COMMON_PRERENDER_TYPES_H_
diff --git a/components/previews/content/previews_decider_impl.cc b/components/previews/content/previews_decider_impl.cc
index dc22202..b250472 100644
--- a/components/previews/content/previews_decider_impl.cc
+++ b/components/previews/content/previews_decider_impl.cc
@@ -94,7 +94,7 @@
 }  // namespace
 
 PreviewsDeciderImpl::PreviewsDeciderImpl(base::Clock* clock)
-    : blacklist_ignored_(switches::ShouldIgnorePreviewsBlacklist()),
+    : blocklist_ignored_(switches::ShouldIgnorePreviewsBlocklist()),
       clock_(clock),
       page_id_(1u) {}
 
@@ -104,41 +104,41 @@
 
 void PreviewsDeciderImpl::Initialize(
     PreviewsUIService* previews_ui_service,
-    std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store,
+    std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store,
     std::unique_ptr<PreviewsOptimizationGuide> previews_opt_guide,
     const PreviewsIsEnabledCallback& is_enabled_callback,
-    blacklist::BlacklistData::AllowedTypesAndVersions allowed_previews) {
+    blocklist::BlocklistData::AllowedTypesAndVersions allowed_previews) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(!is_enabled_callback.is_null());
   is_enabled_callback_ = is_enabled_callback;
   previews_ui_service_ = previews_ui_service;
   previews_opt_guide_ = std::move(previews_opt_guide);
 
-  previews_black_list_ = std::make_unique<PreviewsBlackList>(
+  previews_block_list_ = std::make_unique<PreviewsBlockList>(
       std::move(previews_opt_out_store), clock_, this,
       std::move(allowed_previews));
 }
 
-void PreviewsDeciderImpl::OnNewBlacklistedHost(const std::string& host,
+void PreviewsDeciderImpl::OnNewBlocklistedHost(const std::string& host,
                                                base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  previews_ui_service_->OnNewBlacklistedHost(host, time);
+  previews_ui_service_->OnNewBlocklistedHost(host, time);
 }
 
-void PreviewsDeciderImpl::OnUserBlacklistedStatusChange(bool blacklisted) {
+void PreviewsDeciderImpl::OnUserBlocklistedStatusChange(bool blocklisted) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  previews_ui_service_->OnUserBlacklistedStatusChange(blacklisted);
+  previews_ui_service_->OnUserBlocklistedStatusChange(blocklisted);
 }
 
-void PreviewsDeciderImpl::OnBlacklistCleared(base::Time time) {
+void PreviewsDeciderImpl::OnBlocklistCleared(base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  previews_ui_service_->OnBlacklistCleared(time);
+  previews_ui_service_->OnBlocklistCleared(time);
 }
 
-void PreviewsDeciderImpl::SetPreviewsBlacklistForTesting(
-    std::unique_ptr<PreviewsBlackList> previews_back_list) {
+void PreviewsDeciderImpl::SetPreviewsBlocklistForTesting(
+    std::unique_ptr<PreviewsBlockList> previews_block_list) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  previews_black_list_ = std::move(previews_back_list);
+  previews_block_list_ = std::move(previews_block_list);
 }
 
 void PreviewsDeciderImpl::LogPreviewNavigation(const GURL& url,
@@ -170,22 +170,22 @@
                                                uint64_t page_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   base::Time time =
-      previews_black_list_->AddPreviewNavigation(url, opt_out, type);
+      previews_block_list_->AddPreviewNavigation(url, opt_out, type);
   LogPreviewNavigation(url, opt_out, type, time, page_id);
 }
 
-void PreviewsDeciderImpl::ClearBlackList(base::Time begin_time,
+void PreviewsDeciderImpl::ClearBlockList(base::Time begin_time,
                                          base::Time end_time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  previews_black_list_->ClearBlackList(begin_time, end_time);
+  previews_block_list_->ClearBlockList(begin_time, end_time);
 }
 
-void PreviewsDeciderImpl::SetIgnorePreviewsBlacklistDecision(bool ignored) {
+void PreviewsDeciderImpl::SetIgnorePreviewsBlocklistDecision(bool ignored) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  blacklist_ignored_ = ignored;
-  previews_ui_service_->OnIgnoreBlacklistDecisionStatusChanged(
-      blacklist_ignored_);
+  blocklist_ignored_ = ignored;
+  previews_ui_service_->OnIgnoreBlocklistDecisionStatusChanged(
+      blocklist_ignored_);
 }
 
 bool PreviewsDeciderImpl::ShouldAllowPreviewAtNavigationStart(
@@ -319,14 +319,14 @@
     }
   }
 
-  // Skip blacklist checks if the blacklist is ignored or defer check until
+  // Skip blocklist checks if the blocklist is ignored or defer check until
   // commit time if preview type is to be decided at commit time.
-  if (!blacklist_ignored_ && !IsCommitTimePreview(type)) {
+  if (!blocklist_ignored_ && !IsCommitTimePreview(type)) {
     PreviewsEligibilityReason status =
-        CheckLocalBlacklist(url, type, is_drp_server_preview, passed_reasons);
+        CheckLocalBlocklist(url, type, is_drp_server_preview, passed_reasons);
     if (status != PreviewsEligibilityReason::ALLOWED) {
       if (type == PreviewsType::LITE_PAGE) {
-        previews_data->set_black_listed_for_lite_page(true);
+        previews_data->set_block_listed_for_lite_page(true);
       }
       return status;
     }
@@ -335,14 +335,14 @@
   return PreviewsEligibilityReason::ALLOWED;
 }
 
-PreviewsEligibilityReason PreviewsDeciderImpl::CheckLocalBlacklist(
+PreviewsEligibilityReason PreviewsDeciderImpl::CheckLocalBlocklist(
     const GURL& url,
     PreviewsType type,
     bool is_drp_server_preview,
     std::vector<PreviewsEligibilityReason>* passed_reasons) const {
-  if (!previews_black_list_)
-    return PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE;
-  passed_reasons->push_back(PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE);
+  if (!previews_block_list_)
+    return PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE;
+  passed_reasons->push_back(PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE);
 
   // Trigger the USER_RECENTLY_OPTED_OUT rule when a reload on a preview has
   // occurred recently. No need to push_back the eligibility reason as it will
@@ -353,11 +353,11 @@
     return PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT;
   }
 
-  // The blacklist will disallow certain hosts for periods of time based on
+  // The blocklist will disallow certain hosts for periods of time based on
   // user's opting out of the preview.
-  return previews_black_list_->IsLoadedAndAllowed(
+  return previews_block_list_->IsLoadedAndAllowed(
       url, type,
-      is_drp_server_preview && ignore_long_term_blacklist_for_server_previews_,
+      is_drp_server_preview && ignore_long_term_blocklist_for_server_previews_,
       passed_reasons);
 }
 
@@ -394,11 +394,11 @@
     }
   }
 
-  // Check local blacklist for commit-time preview (if blacklist not ignored).
-  if (!blacklist_ignored_ && IsCommitTimePreview(type)) {
+  // Check local blocklist for commit-time preview (if blocklist not ignored).
+  if (!blocklist_ignored_ && IsCommitTimePreview(type)) {
     std::vector<PreviewsEligibilityReason> passed_reasons;
     PreviewsEligibilityReason status =
-        CheckLocalBlacklist(committed_url, type, false, &passed_reasons);
+        CheckLocalBlocklist(committed_url, type, false, &passed_reasons);
     if (status != PreviewsEligibilityReason::ALLOWED) {
       LogPreviewDecisionMade(status, committed_url, clock_->Now(), type,
                              std::move(passed_reasons), previews_data);
@@ -454,7 +454,7 @@
   passed_reasons->push_back(
       PreviewsEligibilityReason::PAGE_LOAD_PREDICTION_NOT_PAINFUL);
 
-  // Check if request URL is whitelisted by the optimization guide.
+  // Check if request URL is allowlisted by the optimization guide.
   if (!previews_opt_guide_->CanApplyPreview(previews_data, navigation_handle,
                                             type)) {
     return PreviewsEligibilityReason::NOT_ALLOWED_BY_OPTIMIZATION_GUIDE;
@@ -495,11 +495,11 @@
   return ++page_id_;
 }
 
-void PreviewsDeciderImpl::SetIgnoreLongTermBlackListForServerPreviews(
-    bool ignore_long_term_blacklist_for_server_previews) {
+void PreviewsDeciderImpl::SetIgnoreLongTermBlockListForServerPreviews(
+    bool ignore_long_term_blocklist_for_server_previews) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  ignore_long_term_blacklist_for_server_previews_ =
-      ignore_long_term_blacklist_for_server_previews;
+  ignore_long_term_blocklist_for_server_previews_ =
+      ignore_long_term_blocklist_for_server_previews;
 }
 
 void PreviewsDeciderImpl::SetEffectiveConnectionType(
diff --git a/components/previews/content/previews_decider_impl.h b/components/previews/content/previews_decider_impl.h
index b9b1a0b4..32a9f877 100644
--- a/components/previews/content/previews_decider_impl.h
+++ b/components/previews/content/previews_decider_impl.h
@@ -32,7 +32,7 @@
 class Clock;
 }
 
-namespace blacklist {
+namespace blocklist {
 class OptOutStore;
 }
 
@@ -49,24 +49,24 @@
 // previews/ objects. Created on the UI thread, but used only on the IO thread
 // after initialization.
 class PreviewsDeciderImpl : public PreviewsDecider,
-                            public blacklist::OptOutBlacklistDelegate {
+                            public blocklist::OptOutBlocklistDelegate {
  public:
   explicit PreviewsDeciderImpl(base::Clock* clock);
   ~PreviewsDeciderImpl() override;
 
-  // blacklist::OptOutBlacklistDelegate:
-  void OnNewBlacklistedHost(const std::string& host, base::Time time) override;
-  void OnUserBlacklistedStatusChange(bool blacklisted) override;
-  void OnBlacklistCleared(base::Time time) override;
+  // blocklist::OptOutBlocklistDelegate:
+  void OnNewBlocklistedHost(const std::string& host, base::Time time) override;
+  void OnUserBlocklistedStatusChange(bool blocklisted) override;
+  void OnBlocklistCleared(base::Time time) override;
 
-  // Initializes the blacklist and and stores the passed in members.
+  // Initializes the blocklist and and stores the passed in members.
   // |previews_ui_service| owns |this|, and shares the same lifetime.
   virtual void Initialize(
       PreviewsUIService* previews_ui_service,
-      std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store,
+      std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store,
       std::unique_ptr<PreviewsOptimizationGuide> previews_opt_guide,
       const PreviewsIsEnabledCallback& is_enabled_callback,
-      blacklist::BlacklistData::AllowedTypesAndVersions allowed_previews);
+      blocklist::BlocklistData::AllowedTypesAndVersions allowed_previews);
 
   // Adds log message of the navigation asynchronously.
   void LogPreviewNavigation(const GURL& url,
@@ -90,24 +90,24 @@
       std::vector<PreviewsEligibilityReason>&& passed_reasons,
       PreviewsUserData* user_data) const;
 
-  // Adds a navigation to |url| to the black list with result |opt_out|.
+  // Adds a navigation to |url| to the block list with result |opt_out|.
   void AddPreviewNavigation(const GURL& url,
                             bool opt_out,
                             PreviewsType type,
                             uint64_t page_id);
 
-  // Clears the history of the black list between |begin_time| and |end_time|,
+  // Clears the history of the block list between |begin_time| and |end_time|,
   // both inclusive. Additional, clears the appropriate data from the hint
   // cache. TODO(mcrouse): Rename to denote clearing all necessary data,
-  // including the Fetched hints and the blacklist.
-  void ClearBlackList(base::Time begin_time, base::Time end_time);
+  // including the Fetched hints and the blocklist.
+  void ClearBlockList(base::Time begin_time, base::Time end_time);
 
   // Change the status of whether to ignore the decisions made by
-  // PreviewsBlackList to |ignored|. Virtualized in testing.
-  virtual void SetIgnorePreviewsBlacklistDecision(bool ignored);
+  // PreviewsBlockList to |ignored|. Virtualized in testing.
+  virtual void SetIgnorePreviewsBlocklistDecision(bool ignored);
 
-  // The previews black list that decides whether a navigation can use previews.
-  PreviewsBlackList* black_list() const { return previews_black_list_.get(); }
+  // The previews block list that decides whether a navigation can use previews.
+  PreviewsBlockList* block_list() const { return previews_block_list_.get(); }
 
   // PreviewsDecider implementation:
   bool ShouldAllowPreviewAtNavigationStart(
@@ -119,9 +119,9 @@
                            content::NavigationHandle* navigation_handle,
                            PreviewsType type) const override;
 
-  // Set whether to ignore the long term blacklist rules for server previews.
-  void SetIgnoreLongTermBlackListForServerPreviews(
-      bool ignore_long_term_blacklist_for_server_previews);
+  // Set whether to ignore the long term blocklist rules for server previews.
+  void SetIgnoreLongTermBlockListForServerPreviews(
+      bool ignore_long_term_blocklist_for_server_previews);
 
   bool AreCommitTimePreviewsAvailable(
       content::NavigationHandle* navigation_handle) override;
@@ -142,9 +142,9 @@
   void AddPreviewReload();
 
  protected:
-  // Sets a blacklist for testing.
-  void SetPreviewsBlacklistForTesting(
-      std::unique_ptr<PreviewsBlackList> previews_back_list);
+  // Sets a blocklist for testing.
+  void SetPreviewsBlocklistForTesting(
+      std::unique_ptr<PreviewsBlockList> previews_back_list);
 
  private:
   // Returns whether the preview |type| should be considered for |url|.
@@ -163,8 +163,8 @@
       bool is_drp_server_preview,
       std::vector<PreviewsEligibilityReason>* passed_reasons) const;
 
-  // Returns previews eligibility with respect to the local blacklist.
-  PreviewsEligibilityReason CheckLocalBlacklist(
+  // Returns previews eligibility with respect to the local blocklist.
+  PreviewsEligibilityReason CheckLocalBlocklist(
       const GURL& url,
       PreviewsType type,
       bool is_drp_server_preview,
@@ -192,20 +192,20 @@
   // The UI service object owns |this| and exists as long as |this| does.
   PreviewsUIService* previews_ui_service_;
 
-  std::unique_ptr<PreviewsBlackList> previews_black_list_;
+  std::unique_ptr<PreviewsBlockList> previews_block_list_;
 
   // Holds optimization guidance from the server.
   std::unique_ptr<PreviewsOptimizationGuide> previews_opt_guide_;
 
-  // Whether the decisions made by PreviewsBlackList should be ignored or not.
+  // Whether the decisions made by PreviewsBlockList should be ignored or not.
   // This can be changed by chrome://interventions-internals to test/debug the
   // behavior of Previews decisions.
   // This is related to a test flag and should only be true when the user has
-  // set it in flags. See previews::IsPreviewsBlacklistIgnoredViaFlag.
-  bool blacklist_ignored_;
+  // set it in flags. See previews::IsPreviewsBlocklistIgnoredViaFlag.
+  bool blocklist_ignored_;
 
-  // Whether to ignore the blacklist for server previews.
-  bool ignore_long_term_blacklist_for_server_previews_ = false;
+  // Whether to ignore the blocklist for server previews.
+  bool ignore_long_term_blocklist_for_server_previews_ = false;
 
   // The estimate of how slow a user's connection is. Used for triggering
   // Previews.
diff --git a/components/previews/content/previews_decider_impl_unittest.cc b/components/previews/content/previews_decider_impl_unittest.cc
index d03f79a..7b52d067 100644
--- a/components/previews/content/previews_decider_impl_unittest.cc
+++ b/components/previews/content/previews_decider_impl_unittest.cc
@@ -62,15 +62,15 @@
 
 // TODO(crbug.com/961023): Fix memory leaks in tests and re-enable on LSAN.
 #ifdef LEAK_SANITIZER
-#define MAYBE_TestSetBlacklistBoolDueToBlackListState \
-  DISABLED_TestSetBlacklistBoolDueToBlackListState
-#define MAYBE_TestDisallowPreviewBecauseOfBlackListState \
-  DISABLED_TestDisallowPreviewBecauseOfBlackListState
+#define MAYBE_TestSetBlocklistBoolDueToBlockListState \
+  DISABLED_TestSetBlocklistBoolDueToBlockListState
+#define MAYBE_TestDisallowPreviewBecauseOfBlockListState \
+  DISABLED_TestDisallowPreviewBecauseOfBlockListState
 #else
-#define MAYBE_TestSetBlacklistBoolDueToBlackListState \
-  TestSetBlacklistBoolDueToBlackListState
-#define MAYBE_TestDisallowPreviewBecauseOfBlackListState \
-  TestDisallowPreviewBecauseOfBlackListState
+#define MAYBE_TestSetBlocklistBoolDueToBlockListState \
+  TestSetBlocklistBoolDueToBlockListState
+#define MAYBE_TestDisallowPreviewBecauseOfBlockListState \
+  TestDisallowPreviewBecauseOfBlockListState
 #endif
 
 namespace previews {
@@ -109,32 +109,32 @@
   return false;
 }
 
-// Stub class of PreviewsBlackList to control IsLoadedAndAllowed outcome when
+// Stub class of PreviewsBlockList to control IsLoadedAndAllowed outcome when
 // testing PreviewsDeciderImpl.
-class TestPreviewsBlackList : public PreviewsBlackList {
+class TestPreviewsBlockList : public PreviewsBlockList {
  public:
-  TestPreviewsBlackList(PreviewsEligibilityReason status,
-                        blacklist::OptOutBlacklistDelegate* blacklist_delegate)
-      : PreviewsBlackList(nullptr,
+  TestPreviewsBlockList(PreviewsEligibilityReason status,
+                        blocklist::OptOutBlocklistDelegate* blocklist_delegate)
+      : PreviewsBlockList(nullptr,
                           base::DefaultClock::GetInstance(),
-                          blacklist_delegate,
+                          blocklist_delegate,
                           {}),
         status_(status) {}
-  ~TestPreviewsBlackList() override {}
+  ~TestPreviewsBlockList() override = default;
 
-  // PreviewsBlackList:
+  // PreviewsBlockList:
   PreviewsEligibilityReason IsLoadedAndAllowed(
       const GURL& url,
       PreviewsType type,
-      bool ignore_long_term_black_list_rules,
+      bool ignore_long_term_block_list_rules,
       std::vector<PreviewsEligibilityReason>* passed_reasons) const override {
     std::vector<PreviewsEligibilityReason> ordered_reasons = {
-        PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+        PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
         PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT};
 
-    if (!ignore_long_term_black_list_rules) {
-      ordered_reasons.push_back(PreviewsEligibilityReason::USER_BLACKLISTED);
-      ordered_reasons.push_back(PreviewsEligibilityReason::HOST_BLACKLISTED);
+    if (!ignore_long_term_block_list_rules) {
+      ordered_reasons.push_back(PreviewsEligibilityReason::USER_BLOCKLISTED);
+      ordered_reasons.push_back(PreviewsEligibilityReason::HOST_BLOCKLISTED);
     }
 
     for (auto reason : ordered_reasons) {
@@ -189,19 +189,19 @@
 
     const GURL url = navigation_handle->GetURL();
     if (type == PreviewsType::NOSCRIPT) {
-      return url.host().compare("whitelisted.example.com") == 0 ||
-             url.host().compare("noscript_only_whitelisted.example.com") == 0;
+      return url.host().compare("allowlisted.example.com") == 0 ||
+             url.host().compare("noscript_only_allowlisted.example.com") == 0;
     }
     if (type == PreviewsType::RESOURCE_LOADING_HINTS ||
         type == PreviewsType::DEFER_ALL_SCRIPT) {
-      return url.host().compare("whitelisted.example.com") == 0;
+      return url.host().compare("allowlisted.example.com") == 0;
     }
     return false;
   }
 
   // Returns whether the URL associated with |navigation_handle| should be
-  // blacklisted from |type|.
-  bool IsBlacklisted(content::NavigationHandle* navigation_handle,
+  // blocklisted from |type|.
+  bool IsBlocklisted(content::NavigationHandle* navigation_handle,
                      PreviewsType type) const {
     return false;
   }
@@ -218,11 +218,11 @@
  public:
   TestPreviewsUIService(
       std::unique_ptr<PreviewsDeciderImpl> previews_decider_impl,
-      std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store,
+      std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store,
       std::unique_ptr<PreviewsOptimizationGuide> previews_opt_guide,
       const PreviewsIsEnabledCallback& is_enabled_callback,
       std::unique_ptr<PreviewsLogger> logger,
-      blacklist::BlacklistData::AllowedTypesAndVersions allowed_types,
+      blocklist::BlocklistData::AllowedTypesAndVersions allowed_types,
       network::NetworkQualityTracker* network_quality_tracker)
       : PreviewsUIService(std::move(previews_decider_impl),
                           std::move(previews_opt_out_store),
@@ -231,22 +231,22 @@
                           std::move(logger),
                           std::move(allowed_types),
                           network_quality_tracker),
-        user_blacklisted_(false),
-        blacklist_ignored_(false) {}
+        user_blocklisted_(false),
+        blocklist_ignored_(false) {}
 
   // PreviewsUIService:
-  void OnNewBlacklistedHost(const std::string& host, base::Time time) override {
-    host_blacklisted_ = host;
-    host_blacklisted_time_ = time;
+  void OnNewBlocklistedHost(const std::string& host, base::Time time) override {
+    host_blocklisted_ = host;
+    host_blocklisted_time_ = time;
   }
-  void OnUserBlacklistedStatusChange(bool blacklisted) override {
-    user_blacklisted_ = blacklisted;
+  void OnUserBlocklistedStatusChange(bool blocklisted) override {
+    user_blocklisted_ = blocklisted;
   }
-  void OnBlacklistCleared(base::Time time) override {
-    blacklist_cleared_time_ = time;
+  void OnBlocklistCleared(base::Time time) override {
+    blocklist_cleared_time_ = time;
   }
-  void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) override {
-    blacklist_ignored_ = ignored;
+  void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) override {
+    blocklist_ignored_ = ignored;
   }
 
   // Expose passed in LogPreviewDecision parameters.
@@ -281,14 +281,14 @@
     return navigation_page_ids_;
   }
 
-  // Expose passed in params for hosts and user blacklist event.
-  std::string host_blacklisted() const { return host_blacklisted_; }
-  base::Time host_blacklisted_time() const { return host_blacklisted_time_; }
-  bool user_blacklisted() const { return user_blacklisted_; }
-  base::Time blacklist_cleared_time() const { return blacklist_cleared_time_; }
+  // Expose passed in params for hosts and user blocklist event.
+  std::string host_blocklisted() const { return host_blocklisted_; }
+  base::Time host_blocklisted_time() const { return host_blocklisted_time_; }
+  bool user_blocklisted() const { return user_blocklisted_; }
+  base::Time blocklist_cleared_time() const { return blocklist_cleared_time_; }
 
-  // Expose the status of blacklist decisions ignored.
-  bool blacklist_ignored() const { return blacklist_ignored_; }
+  // Expose the status of blocklist decisions ignored.
+  bool blocklist_ignored() const { return blocklist_ignored_; }
 
  private:
   // PreviewsUIService:
@@ -319,11 +319,11 @@
     decision_ids_.push_back(page_id);
   }
 
-  // Passed in params for blacklist status events.
-  std::string host_blacklisted_;
-  base::Time host_blacklisted_time_;
-  bool user_blacklisted_;
-  base::Time blacklist_cleared_time_;
+  // Passed in params for blocklist status events.
+  std::string host_blocklisted_;
+  base::Time host_blocklisted_time_;
+  bool user_blocklisted_;
+  base::Time blocklist_cleared_time_;
 
   // Passed in LogPreviewDecision parameters.
   std::vector<PreviewsEligibilityReason> decision_reasons_;
@@ -340,8 +340,8 @@
   std::vector<PreviewsType> navigation_types_;
   std::vector<uint64_t> navigation_page_ids_;
 
-  // Whether the blacklist decisions are ignored or not.
-  bool blacklist_ignored_;
+  // Whether the blocklist decisions are ignored or not.
+  bool blocklist_ignored_;
 };
 
 class TestPreviewsDeciderImpl : public PreviewsDeciderImpl {
@@ -350,38 +350,38 @@
       : PreviewsDeciderImpl(clock) {}
   ~TestPreviewsDeciderImpl() override {}
 
-  // Expose the injecting blacklist method from PreviewsDeciderImpl, and inject
-  // |blacklist| into |this|.
-  void InjectTestBlacklist(std::unique_ptr<PreviewsBlackList> blacklist) {
-    SetPreviewsBlacklistForTesting(std::move(blacklist));
+  // Expose the injecting blocklist method from PreviewsDeciderImpl, and inject
+  // |blocklist| into |this|.
+  void InjectTestBlocklist(std::unique_ptr<PreviewsBlockList> blocklist) {
+    SetPreviewsBlocklistForTesting(std::move(blocklist));
   }
 };
 
-void RunLoadCallback(blacklist::LoadBlackListCallback callback,
-                     std::unique_ptr<blacklist::BlacklistData> data) {
+void RunLoadCallback(blocklist::LoadBlockListCallback callback,
+                     std::unique_ptr<blocklist::BlocklistData> data) {
   std::move(callback).Run(std::move(data));
 }
 
-class TestOptOutStore : public blacklist::OptOutStore {
+class TestOptOutStore : public blocklist::OptOutStore {
  public:
   TestOptOutStore() {}
   ~TestOptOutStore() override {}
 
  private:
-  // blacklist::OptOutStore implementation:
+  // blocklist::OptOutStore implementation:
   void AddEntry(bool opt_out,
                 const std::string& host_name,
                 int type,
                 base::Time now) override {}
 
-  void LoadBlackList(std::unique_ptr<blacklist::BlacklistData> data,
-                     blacklist::LoadBlackListCallback callback) override {
+  void LoadBlockList(std::unique_ptr<blocklist::BlocklistData> data,
+                     blocklist::LoadBlockListCallback callback) override {
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
         base::BindOnce(&RunLoadCallback, std::move(callback), std::move(data)));
   }
 
-  void ClearBlackList(base::Time begin_time, base::Time end_time) override {}
+  void ClearBlockList(base::Time begin_time, base::Time end_time) override {}
 };
 
 class PreviewsDeciderImplTest
@@ -412,9 +412,9 @@
     ui_service_.reset();
   }
 
-  void InitializeUIServiceWithoutWaitingForBlackList(
+  void InitializeUIServiceWithoutWaitingForBlockList(
       bool include_previews_opt_guide) {
-    blacklist::BlacklistData::AllowedTypesAndVersions allowed_types;
+    blocklist::BlocklistData::AllowedTypesAndVersions allowed_types;
     allowed_types[static_cast<int>(PreviewsType::OFFLINE)] = 0;
     allowed_types[static_cast<int>(PreviewsType::LITE_PAGE)] = 0;
     allowed_types[static_cast<int>(PreviewsType::NOSCRIPT)] = 0;
@@ -439,7 +439,7 @@
   }
 
   void InitializeUIService(bool include_previews_opt_guide = true) {
-    InitializeUIServiceWithoutWaitingForBlackList(include_previews_opt_guide);
+    InitializeUIServiceWithoutWaitingForBlockList(include_previews_opt_guide);
     task_environment_.RunUntilIdle();
     base::RunLoop().RunUntilIdle();
   }
@@ -508,10 +508,10 @@
 }
 
 // Tests most of the reasons that a preview could be disallowed because of the
-// state of the blacklist. Excluded values are USER_RECENTLY_OPTED_OUT,
-// USER_BLACKLISTED, HOST_BLACKLISTED. These are internal to the blacklist.
+// state of the blocklist. Excluded values are USER_RECENTLY_OPTED_OUT,
+// USER_BLOCKLISTED, HOST_BLOCKLISTED. These are internal to the blocklist.
 TEST_F(PreviewsDeciderImplTest,
-       MAYBE_TestDisallowPreviewBecauseOfBlackListState) {
+       MAYBE_TestDisallowPreviewBecauseOfBlockListState) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
@@ -521,46 +521,46 @@
   content::MockNavigationHandle navigation_handle;
   navigation_handle.set_url(GURL("https://www.google.com"));
 
-  InitializeUIServiceWithoutWaitingForBlackList(
+  InitializeUIServiceWithoutWaitingForBlockList(
       /*include_previews_opt_guide=*/true);
 
-  // The blacklist is not loaded yet.
+  // The blocklist is not loaded yet.
   EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
   histogram_tester.ExpectBucketCount(
       "Previews.EligibilityReason",
-      static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED),
+      static_cast<int>(PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED),
       1);
   histogram_tester.ExpectBucketCount(
       "Previews.EligibilityReason.Offline",
-      static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED),
+      static_cast<int>(PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED),
       1);
 
   base::RunLoop().RunUntilIdle();
 
   histogram_tester.ExpectTotalCount("Previews.EligibilityReason.Offline", 1);
 
-  // Return one of the failing statuses from the blacklist; cause the blacklist
-  // to not be loaded by clearing the blacklist.
+  // Return one of the failing statuses from the blocklist; cause the blocklist
+  // to not be loaded by clearing the blocklist.
   base::Time now = base::Time::Now();
-  previews_decider_impl()->ClearBlackList(now, now);
+  previews_decider_impl()->ClearBlockList(now, now);
 
   EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::OFFLINE));
   histogram_tester.ExpectBucketCount(
       "Previews.EligibilityReason.Offline",
-      static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED),
+      static_cast<int>(PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED),
       2);
   histogram_tester.ExpectBucketCount(
       "Previews.EligibilityReason",
-      static_cast<int>(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED),
+      static_cast<int>(PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED),
       2);
   histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
 
   variations::testing::ClearAllVariationParams();
 }
 
-TEST_F(PreviewsDeciderImplTest, MAYBE_TestSetBlacklistBoolDueToBlackListState) {
+TEST_F(PreviewsDeciderImplTest, MAYBE_TestSetBlocklistBoolDueToBlockListState) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
@@ -570,16 +570,16 @@
   navigation_handle.set_url(GURL("https://www.google.com"));
 
   base::HistogramTester histogram_tester;
-  InitializeUIServiceWithoutWaitingForBlackList(
+  InitializeUIServiceWithoutWaitingForBlockList(
       /*include_previews_opt_guide=*/true);
   base::RunLoop().RunUntilIdle();
   previews_decider_impl()->AddPreviewNavigation(
       GURL("https://www.google.com"), true, PreviewsType::LITE_PAGE, 1);
 
-  EXPECT_FALSE(user_data.black_listed_for_lite_page());
+  EXPECT_FALSE(user_data.block_listed_for_lite_page());
   EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE));
-  EXPECT_TRUE(user_data.black_listed_for_lite_page());
+  EXPECT_TRUE(user_data.block_listed_for_lite_page());
 }
 
 TEST_F(PreviewsDeciderImplTest,
@@ -860,22 +860,11 @@
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
   navigation_handle.set_url(GURL("https://www.google.com"));
-#if defined(OS_ANDROID)
-  // Enabled by default on Android. NOSCRIPT always allowed at navigation start
-  // to handle asynchronous loading of page hints; non-whitelisted ones are
-  // later blocked on commit.
-  EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
-      &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
-  histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 1);
-  histogram_tester.ExpectBucketCount(
-      "Previews.EligibilityReason.NoScript",
-      static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
-#else   // !defined(OS_ANDROID)
+
   // Disabled by default on non-Android.
   EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
   histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
-#endif  // defined(OS_ANDROID)
 }
 
 TEST_F(PreviewsDeciderImplTest, NoScriptNotAllowedWithoutOptimizationHints) {
@@ -904,7 +893,7 @@
   }
 }
 
-TEST_F(PreviewsDeciderImplTest, NoScriptAllowedByFeatureWithWhitelist) {
+TEST_F(PreviewsDeciderImplTest, NoScriptAllowedByFeatureWithAllowlist) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kNoScriptPreviews}, {});
@@ -915,14 +904,14 @@
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
   navigation_handle.set_url(GURL("https://www.google.com"));
-  // First verify preview allowed for non-whitelisted url; they're always
+  // First verify preview allowed for non-allowlisted url; they're always
   // allowed at navigation start to enable asynchronous loading of page hints.
   EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
 
-  // Now verify preview allowed for whitelisted url.
-  content::MockNavigationHandle whitelisted_navigation_handle;
-  whitelisted_navigation_handle.set_url(GURL("https://www.google.com"));
+  // Now verify preview allowed for allowlisted url.
+  content::MockNavigationHandle allowlisted_navigation_handle;
+  allowlisted_navigation_handle.set_url(GURL("https://www.google.com"));
   EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::NOSCRIPT));
 
@@ -931,13 +920,13 @@
       static_cast<int>(PreviewsEligibilityReason::ALLOWED), 2);
 }
 
-TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeWhitelistCheck) {
+TEST_F(PreviewsDeciderImplTest, NoScriptCommitTimeAllowlistCheck) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kNoScriptPreviews}, {});
   InitializeUIService();
 
-  // First verify not allowed for non-whitelisted url.
+  // First verify not allowed for non-allowlisted url.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
     base::HistogramTester histogram_tester;
@@ -954,13 +943,13 @@
         1);
   }
 
-  // Now verify preview for whitelisted url.
+  // Now verify preview for allowlisted url.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
 
@@ -968,13 +957,13 @@
     histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
   }
 
-  // Verify preview not allowed for whitelisted url when network is not slow.
+  // Verify preview not allowed for allowlisted url when network is not slow.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_3G);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
 
@@ -985,13 +974,13 @@
         1);
   }
 
-  // Verify preview not allowed for whitelisted url for unknown network quality.
+  // Verify preview not allowed for allowlisted url for unknown network quality.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
     EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
@@ -1014,7 +1003,7 @@
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN);
     EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
@@ -1022,21 +1011,21 @@
     histogram_tester.ExpectTotalCount("Previews.EligibilityReason.NoScript", 0);
   }
 
-  // Verify preview not allowed when blacklist is unavailable.
+  // Verify preview not allowed when blocklist is unavailable.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
     base::HistogramTester histogram_tester;
-    previews_decider_impl()->InjectTestBlacklist(nullptr /* blacklist */);
+    previews_decider_impl()->InjectTestBlocklist(nullptr /* blocklist */);
     PreviewsUserData user_data(kDefaultPageId);
     user_data.set_navigation_ect(net::EFFECTIVE_CONNECTION_TYPE_2G);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::NOSCRIPT));
 
     histogram_tester.ExpectUniqueSample(
         "Previews.EligibilityReason.NoScript",
-        static_cast<int>(PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE), 1);
+        static_cast<int>(PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE), 1);
   }
 }
 
@@ -1065,7 +1054,7 @@
   base::HistogramTester histogram_tester;
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
-  navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+  navigation_handle.set_url(GURL("https://allowlisted.example.com"));
   EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false,
       PreviewsType::RESOURCE_LOADING_HINTS));
@@ -1082,7 +1071,7 @@
 }
 
 TEST_F(PreviewsDeciderImplTest,
-       ResourceLoadingHintsAllowedByFeatureAndWhitelist) {
+       ResourceLoadingHintsAllowedByFeatureAndAllowlist) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kResourceLoadingHints}, {});
@@ -1096,9 +1085,9 @@
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
 
-    // Check whitelisted URL.
+    // Check allowlisted URL.
     EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
         &user_data, &navigation_handle, false,
         PreviewsType::RESOURCE_LOADING_HINTS));
@@ -1131,13 +1120,13 @@
       static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
 }
 
-TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsCommitTimeWhitelistCheck) {
+TEST_F(PreviewsDeciderImplTest, ResourceLoadingHintsCommitTimeAllowlistCheck) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kResourceLoadingHints}, {});
   InitializeUIService();
 
-  // First verify not allowed for non-whitelisted url.
+  // First verify not allowed for non-allowlisted url.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
     base::HistogramTester histogram_tester;
@@ -1154,13 +1143,13 @@
         1);
   }
 
-  // Now verify preview for whitelisted url.
+  // Now verify preview for allowlisted url.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
 
@@ -1169,13 +1158,13 @@
         "Previews.EligibilityReason.ResourceLoadingHints", 0);
   }
 
-  // Verify preview not allowed for whitelisted url when network is not slow.
+  // Verify preview not allowed for allowlisted url when network is not slow.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_4G);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
 
@@ -1186,13 +1175,13 @@
         1);
   }
 
-  // Verify preview not allowed for whitelisted url for offline network quality.
+  // Verify preview not allowed for allowlisted url for offline network quality.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::RESOURCE_LOADING_HINTS));
 
@@ -1233,7 +1222,7 @@
   base::HistogramTester histogram_tester;
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
-  navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+  navigation_handle.set_url(GURL("https://allowlisted.example.com"));
   EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
   histogram_tester.ExpectUniqueSample(
@@ -1248,7 +1237,7 @@
       1);
 }
 
-TEST_F(PreviewsDeciderImplTest, DeferAllScriptAllowedByFeatureAndWhitelist) {
+TEST_F(PreviewsDeciderImplTest, DeferAllScriptAllowedByFeatureAndAllowlist) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kDeferAllScriptPreviews}, {});
@@ -1262,9 +1251,9 @@
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
 
-    // Check whitelisted URL.
+    // Check allowlisted URL.
     EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
         &user_data, &navigation_handle, false, PreviewsType::DEFER_ALL_SCRIPT));
     EXPECT_EQ(test_ect, user_data.navigation_ect());
@@ -1295,13 +1284,13 @@
       static_cast<int>(PreviewsEligibilityReason::ALLOWED), 1);
 }
 
-TEST_F(PreviewsDeciderImplTest, DeferAllScriptCommitTimeWhitelistCheck) {
+TEST_F(PreviewsDeciderImplTest, DeferAllScriptCommitTimeAllowlistCheck) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kDeferAllScriptPreviews}, {});
   InitializeUIService();
 
-  // First verify not allowed for non-whitelisted url.
+  // First verify not allowed for non-allowlisted url.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
     base::HistogramTester histogram_tester;
@@ -1318,13 +1307,13 @@
         1);
   }
 
-  // Now verify preview for whitelisted url.
+  // Now verify preview for allowlisted url.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
 
@@ -1333,13 +1322,13 @@
         "Previews.EligibilityReason.DeferAllScript", 0);
   }
 
-  // Verify preview not allowed for whitelisted url when network is not slow.
+  // Verify preview not allowed for allowlisted url when network is not slow.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_4G);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
 
@@ -1350,13 +1339,13 @@
         1);
   }
 
-  // Verify preview not allowed for whitelisted url for offline network quality.
+  // Verify preview not allowed for allowlisted url for offline network quality.
   {
     ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_OFFLINE);
     base::HistogramTester histogram_tester;
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
-    navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+    navigation_handle.set_url(GURL("https://allowlisted.example.com"));
     EXPECT_FALSE(previews_decider_impl()->ShouldCommitPreview(
         &user_data, &navigation_handle, PreviewsType::DEFER_ALL_SCRIPT));
 
@@ -1394,7 +1383,7 @@
   scoped_feature_list.InitAndEnableFeature(features::kPreviews);
   InitializeUIService();
   const PreviewsEligibilityReason reason(
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE);
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE);
   const GURL url("http://www.url_a.com/url_a");
   const base::Time time = base::Time::Now();
   const PreviewsType type = PreviewsType::OFFLINE;
@@ -1429,16 +1418,16 @@
 
 TEST_F(
     PreviewsDeciderImplTest,
-    LogDecisionMadeBlacklistUnavailableAtNavigationStartForNonCommitTimePreview) {
+    LogDecisionMadeBlocklistUnavailableAtNavigationStartForNonCommitTimePreview) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
 
   InitializeUIService();
-  auto expected_reason = PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE;
+  auto expected_reason = PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE;
   auto expected_type = PreviewsType::OFFLINE;
 
-  previews_decider_impl()->InjectTestBlacklist(nullptr /* blacklist */);
+  previews_decider_impl()->InjectTestBlocklist(nullptr /* blocklist */);
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
   navigation_handle.set_url(GURL("https://www.google.com"));
@@ -1454,7 +1443,7 @@
 
 TEST_F(
     PreviewsDeciderImplTest,
-    LogDecisionMadeBlacklistUnavailableAtNavigationStartForCommitTimePreview) {
+    LogDecisionMadeBlocklistUnavailableAtNavigationStartForCommitTimePreview) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kNoScriptPreviews}, {});
@@ -1463,7 +1452,7 @@
   auto expected_reason = PreviewsEligibilityReason::ALLOWED;
   auto expected_type = PreviewsType::NOSCRIPT;
 
-  previews_decider_impl()->InjectTestBlacklist(nullptr /* blacklist */);
+  previews_decider_impl()->InjectTestBlocklist(nullptr /* blocklist */);
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
   navigation_handle.set_url(GURL("https://www.google.com"));
@@ -1477,17 +1466,17 @@
               ::testing::Contains(expected_type));
 }
 
-TEST_F(PreviewsDeciderImplTest, LogDecisionMadeBlacklistStatusesDefault) {
+TEST_F(PreviewsDeciderImplTest, LogDecisionMadeBlocklistStatusesDefault) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
   InitializeUIService();
 
   PreviewsEligibilityReason expected_reasons[] = {
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
       PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-      PreviewsEligibilityReason::USER_BLACKLISTED,
-      PreviewsEligibilityReason::HOST_BLACKLISTED,
+      PreviewsEligibilityReason::USER_BLOCKLISTED,
+      PreviewsEligibilityReason::HOST_BLOCKLISTED,
   };
 
   auto expected_type = PreviewsType::OFFLINE;
@@ -1496,10 +1485,10 @@
   for (size_t i = 0; i < reasons_size; i++) {
     auto expected_reason = expected_reasons[i];
 
-    std::unique_ptr<TestPreviewsBlackList> blacklist =
-        std::make_unique<TestPreviewsBlackList>(expected_reason,
+    std::unique_ptr<TestPreviewsBlockList> blocklist =
+        std::make_unique<TestPreviewsBlockList>(expected_reason,
                                                 previews_decider_impl());
-    previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+    previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
@@ -1518,7 +1507,7 @@
   }
 }
 
-TEST_F(PreviewsDeciderImplTest, ShouldCommitPreviewBlacklistStatuses) {
+TEST_F(PreviewsDeciderImplTest, ShouldCommitPreviewBlocklistStatuses) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kNoScriptPreviews}, {});
@@ -1527,15 +1516,15 @@
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
   navigation_handle.set_url(GURL("https://www.google.com"));
-  // First verify URL is allowed for no blacklist status.
+  // First verify URL is allowed for no blocklist status.
   EXPECT_TRUE(previews_decider_impl()->ShouldCommitPreview(
       &user_data, &navigation_handle, expected_type));
 
   PreviewsEligibilityReason expected_reasons[] = {
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
       PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-      PreviewsEligibilityReason::USER_BLACKLISTED,
-      PreviewsEligibilityReason::HOST_BLACKLISTED,
+      PreviewsEligibilityReason::USER_BLOCKLISTED,
+      PreviewsEligibilityReason::HOST_BLOCKLISTED,
   };
 
   const size_t reasons_size = 4;
@@ -1543,10 +1532,10 @@
   for (size_t i = 0; i < reasons_size; i++) {
     auto expected_reason = expected_reasons[i];
 
-    std::unique_ptr<TestPreviewsBlackList> blacklist =
-        std::make_unique<TestPreviewsBlackList>(expected_reason,
+    std::unique_ptr<TestPreviewsBlockList> blocklist =
+        std::make_unique<TestPreviewsBlockList>(expected_reason,
                                                 previews_decider_impl());
-    previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+    previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
     navigation_handle.set_url(GURL("https://www.google.com"));
@@ -1564,7 +1553,7 @@
   }
 }
 
-TEST_F(PreviewsDeciderImplTest, LogDecisionMadeBlacklistStatusesIgnore) {
+TEST_F(PreviewsDeciderImplTest, LogDecisionMadeBlocklistStatusesIgnore) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
@@ -1572,21 +1561,21 @@
   auto expected_reason = PreviewsEligibilityReason::ALLOWED;
   auto expected_type = PreviewsType::OFFLINE;
 
-  PreviewsEligibilityReason blacklist_decisions[] = {
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+  PreviewsEligibilityReason blocklist_decisions[] = {
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
       PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-      PreviewsEligibilityReason::USER_BLACKLISTED,
-      PreviewsEligibilityReason::HOST_BLACKLISTED,
+      PreviewsEligibilityReason::USER_BLOCKLISTED,
+      PreviewsEligibilityReason::HOST_BLOCKLISTED,
   };
 
-  previews_decider_impl()->SetIgnorePreviewsBlacklistDecision(
+  previews_decider_impl()->SetIgnorePreviewsBlocklistDecision(
       true /* ignored */);
 
-  for (auto blacklist_decision : blacklist_decisions) {
-    std::unique_ptr<TestPreviewsBlackList> blacklist =
-        std::make_unique<TestPreviewsBlackList>(blacklist_decision,
+  for (auto blocklist_decision : blocklist_decisions) {
+    std::unique_ptr<TestPreviewsBlockList> blocklist =
+        std::make_unique<TestPreviewsBlockList>(blocklist_decision,
                                                 previews_decider_impl());
-    previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+    previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
     navigation_handle.set_url(GURL("https://www.google.com"));
@@ -1610,15 +1599,15 @@
   auto expected_reason = PreviewsEligibilityReason::EXCLUDED_BY_MEDIA_SUFFIX;
   auto expected_type = PreviewsType::RESOURCE_LOADING_HINTS;
 
-  PreviewsEligibilityReason blacklist_decisions[] = {
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+  PreviewsEligibilityReason blocklist_decisions[] = {
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
   };
 
-  for (auto blacklist_decision : blacklist_decisions) {
-    std::unique_ptr<TestPreviewsBlackList> blacklist =
-        std::make_unique<TestPreviewsBlackList>(blacklist_decision,
+  for (auto blocklist_decision : blocklist_decisions) {
+    std::unique_ptr<TestPreviewsBlockList> blocklist =
+        std::make_unique<TestPreviewsBlockList>(blocklist_decision,
                                                 previews_decider_impl());
-    previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+    previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
     PreviewsUserData user_data(kDefaultPageId);
     content::MockNavigationHandle navigation_handle;
     navigation_handle.set_url(GURL("https://www.google.com/video.mp4"));
@@ -1634,14 +1623,14 @@
   }
 }
 
-TEST_F(PreviewsDeciderImplTest, IgnoreFlagDoesNotCheckBlacklist) {
+TEST_F(PreviewsDeciderImplTest, IgnoreFlagDoesNotCheckBlocklist) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
   InitializeUIService();
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
 
-  previews_decider_impl()->SetIgnorePreviewsBlacklistDecision(
+  previews_decider_impl()->SetIgnorePreviewsBlocklistDecision(
       true /* ignored */);
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
@@ -1694,10 +1683,10 @@
       {features::kPreviews, features::kResourceLoadingHints}, {});
   InitializeUIService();
 
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
           PreviewsEligibilityReason::ALLOWED, previews_decider_impl());
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
   auto expected_reason = PreviewsEligibilityReason::ALLOWED;
   auto expected_type = PreviewsType::RESOURCE_LOADING_HINTS;
@@ -1736,10 +1725,10 @@
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
   InitializeUIService(/*include_previews_opt_guide=*/true);
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
           PreviewsEligibilityReason::ALLOWED, previews_decider_impl());
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_4G);
 
@@ -1778,10 +1767,10 @@
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
   InitializeUIService(/*include_previews_opt_guide=*/false);
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
           PreviewsEligibilityReason::ALLOWED, previews_decider_impl());
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_4G);
 
@@ -1819,10 +1808,10 @@
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
   InitializeUIService();
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
           PreviewsEligibilityReason::ALLOWED, previews_decider_impl());
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
   PreviewsUserData user_data(kDefaultPageId);
@@ -1858,21 +1847,21 @@
   }
 }
 
-TEST_F(PreviewsDeciderImplTest, IgnoreBlacklistEnabledViaFlag) {
+TEST_F(PreviewsDeciderImplTest, IgnoreBlocklistEnabledViaFlag) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitWithFeatures(
       {features::kPreviews, features::kOfflinePreviews}, {});
   base::test::ScopedCommandLine scoped_command_line;
   base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
-  command_line->AppendSwitch(switches::kIgnorePreviewsBlacklist);
-  ASSERT_TRUE(switches::ShouldIgnorePreviewsBlacklist());
+  command_line->AppendSwitch(switches::kIgnorePreviewsBlocklist);
+  ASSERT_TRUE(switches::ShouldIgnorePreviewsBlocklist());
 
   InitializeUIService();
 
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
-          PreviewsEligibilityReason::HOST_BLACKLISTED, previews_decider_impl());
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
+          PreviewsEligibilityReason::HOST_BLOCKLISTED, previews_decider_impl());
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
@@ -1892,11 +1881,11 @@
       {features::kPreviews, features::kOfflinePreviews}, {});
   InitializeUIService();
 
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
           PreviewsEligibilityReason::ALLOWED, previews_decider_impl());
 
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
 
@@ -1910,11 +1899,11 @@
       PreviewsEligibilityReason::DEVICE_OFFLINE,
       PreviewsEligibilityReason::PAGE_LOAD_PREDICTION_NOT_PAINFUL,
       PreviewsEligibilityReason::RELOAD_DISALLOWED,
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE,
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE,
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
       PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT,
-      PreviewsEligibilityReason::USER_BLACKLISTED,
-      PreviewsEligibilityReason::HOST_BLACKLISTED,
+      PreviewsEligibilityReason::USER_BLOCKLISTED,
+      PreviewsEligibilityReason::HOST_BLOCKLISTED,
   };
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
@@ -1943,11 +1932,11 @@
       {features::kPreviews, features::kNoScriptPreviews}, {});
   InitializeUIService();
 
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
           PreviewsEligibilityReason::ALLOWED, previews_decider_impl());
 
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_2G);
 
@@ -1961,7 +1950,7 @@
   };
   PreviewsUserData user_data(kDefaultPageId);
   content::MockNavigationHandle navigation_handle;
-  navigation_handle.set_url(GURL("https://whitelisted.example.com"));
+  navigation_handle.set_url(GURL("https://allowlisted.example.com"));
   EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, expected_type));
   base::RunLoop().RunUntilIdle();
@@ -1980,53 +1969,53 @@
   }
 }
 
-TEST_F(PreviewsDeciderImplTest, OnNewBlacklistedHostCallsUIMethodCorrectly) {
+TEST_F(PreviewsDeciderImplTest, OnNewBlocklistedHostCallsUIMethodCorrectly) {
   InitializeUIService();
   std::string expected_host = "example.com";
   base::Time expected_time = base::Time::Now();
-  previews_decider_impl()->OnNewBlacklistedHost(expected_host, expected_time);
+  previews_decider_impl()->OnNewBlocklistedHost(expected_host, expected_time);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(expected_host, ui_service()->host_blacklisted());
-  EXPECT_EQ(expected_time, ui_service()->host_blacklisted_time());
+  EXPECT_EQ(expected_host, ui_service()->host_blocklisted());
+  EXPECT_EQ(expected_time, ui_service()->host_blocklisted_time());
 }
 
-TEST_F(PreviewsDeciderImplTest, OnUserBlacklistedCallsUIMethodCorrectly) {
+TEST_F(PreviewsDeciderImplTest, OnUserBlocklistedCallsUIMethodCorrectly) {
   InitializeUIService();
-  previews_decider_impl()->OnUserBlacklistedStatusChange(
-      true /* blacklisted */);
+  previews_decider_impl()->OnUserBlocklistedStatusChange(
+      true /* blocklisted */);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(ui_service()->user_blacklisted());
+  EXPECT_TRUE(ui_service()->user_blocklisted());
 
-  previews_decider_impl()->OnUserBlacklistedStatusChange(
-      false /* blacklisted */);
+  previews_decider_impl()->OnUserBlocklistedStatusChange(
+      false /* blocklisted */);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_FALSE(ui_service()->user_blacklisted());
+  EXPECT_FALSE(ui_service()->user_blocklisted());
 }
 
-TEST_F(PreviewsDeciderImplTest, OnBlacklistClearedCallsUIMethodCorrectly) {
+TEST_F(PreviewsDeciderImplTest, OnBlocklistClearedCallsUIMethodCorrectly) {
   InitializeUIService();
   base::Time expected_time = base::Time::Now();
-  previews_decider_impl()->OnBlacklistCleared(expected_time);
+  previews_decider_impl()->OnBlocklistCleared(expected_time);
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_EQ(expected_time, ui_service()->blacklist_cleared_time());
+  EXPECT_EQ(expected_time, ui_service()->blocklist_cleared_time());
 }
 
 TEST_F(PreviewsDeciderImplTest,
-       OnIgnoreBlacklistDecisionStatusChangedCalledCorrect) {
+       OnIgnoreBlocklistDecisionStatusChangedCalledCorrect) {
   InitializeUIService();
-  previews_decider_impl()->SetIgnorePreviewsBlacklistDecision(
+  previews_decider_impl()->SetIgnorePreviewsBlocklistDecision(
       true /* ignored */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(ui_service()->blacklist_ignored());
+  EXPECT_TRUE(ui_service()->blocklist_ignored());
 
-  previews_decider_impl()->SetIgnorePreviewsBlacklistDecision(
+  previews_decider_impl()->SetIgnorePreviewsBlocklistDecision(
       false /* ignored */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(ui_service()->blacklist_ignored());
+  EXPECT_FALSE(ui_service()->blocklist_ignored());
 }
 
 TEST_F(PreviewsDeciderImplTest, GeneratePageIdMakesUniqueNonZero) {
@@ -2048,10 +2037,10 @@
       {features::kPreviews, features::kOfflinePreviews}, {});
   InitializeUIService();
 
-  std::unique_ptr<TestPreviewsBlackList> blacklist =
-      std::make_unique<TestPreviewsBlackList>(
-          PreviewsEligibilityReason::HOST_BLACKLISTED, previews_decider_impl());
-  previews_decider_impl()->InjectTestBlacklist(std::move(blacklist));
+  std::unique_ptr<TestPreviewsBlockList> blocklist =
+      std::make_unique<TestPreviewsBlockList>(
+          PreviewsEligibilityReason::HOST_BLOCKLISTED, previews_decider_impl());
+  previews_decider_impl()->InjectTestBlocklist(std::move(blocklist));
 
   // DataReductionProxy LitePage checks NQE on their own.
   ReportEffectiveConnectionType(net::EFFECTIVE_CONNECTION_TYPE_3G);
@@ -2059,11 +2048,11 @@
   content::MockNavigationHandle navigation_handle;
   navigation_handle.set_url(GURL("https://www.google.com"));
   base::HistogramTester histogram_tester;
-  previews_decider_impl()->SetIgnoreLongTermBlackListForServerPreviews(false);
+  previews_decider_impl()->SetIgnoreLongTermBlockListForServerPreviews(false);
   EXPECT_FALSE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE));
 
-  previews_decider_impl()->SetIgnoreLongTermBlackListForServerPreviews(true);
+  previews_decider_impl()->SetIgnoreLongTermBlockListForServerPreviews(true);
   EXPECT_TRUE(previews_decider_impl()->ShouldAllowPreviewAtNavigationStart(
       &user_data, &navigation_handle, false, PreviewsType::LITE_PAGE));
 }
diff --git a/components/previews/content/previews_optimization_guide_unittest.cc b/components/previews/content/previews_optimization_guide_unittest.cc
index 2067dae4..884b40b 100644
--- a/components/previews/content/previews_optimization_guide_unittest.cc
+++ b/components/previews/content/previews_optimization_guide_unittest.cc
@@ -187,7 +187,7 @@
     optimization_guide_decider()->SetResponses(responses);
   }
 
-  GURL blacklisted_lpr_url() { return GURL("https://blacklistedlpr.com/123"); }
+  GURL blocklisted_lpr_url() { return GURL("https://blocklistedlpr.com/123"); }
 
   GURL hint_not_loaded_url() { return GURL("https://hintnotloaded.com/123"); }
 
diff --git a/components/previews/content/previews_ui_service.cc b/components/previews/content/previews_ui_service.cc
index a4e3fe4..421ccc2 100644
--- a/components/previews/content/previews_ui_service.cc
+++ b/components/previews/content/previews_ui_service.cc
@@ -14,11 +14,11 @@
 
 PreviewsUIService::PreviewsUIService(
     std::unique_ptr<PreviewsDeciderImpl> previews_decider_impl,
-    std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store,
+    std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store,
     std::unique_ptr<PreviewsOptimizationGuide> previews_opt_guide,
     const PreviewsIsEnabledCallback& is_enabled_callback,
     std::unique_ptr<PreviewsLogger> logger,
-    blacklist::BlacklistData::AllowedTypesAndVersions allowed_previews,
+    blocklist::BlocklistData::AllowedTypesAndVersions allowed_previews,
     network::NetworkQualityTracker* network_quality_tracker)
     : previews_decider_impl_(std::move(previews_decider_impl)),
       logger_(std::move(logger)),
@@ -66,30 +66,30 @@
                                   std::move(passed_reasons), page_id);
 }
 
-void PreviewsUIService::OnNewBlacklistedHost(const std::string& host,
+void PreviewsUIService::OnNewBlocklistedHost(const std::string& host,
                                              base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  logger_->OnNewBlacklistedHost(host, time);
+  logger_->OnNewBlocklistedHost(host, time);
 }
 
-void PreviewsUIService::OnUserBlacklistedStatusChange(bool blacklisted) {
+void PreviewsUIService::OnUserBlocklistedStatusChange(bool blocklisted) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  logger_->OnUserBlacklistedStatusChange(blacklisted);
+  logger_->OnUserBlocklistedStatusChange(blocklisted);
 }
 
-void PreviewsUIService::OnBlacklistCleared(base::Time time) {
+void PreviewsUIService::OnBlocklistCleared(base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  logger_->OnBlacklistCleared(time);
+  logger_->OnBlocklistCleared(time);
 }
 
-void PreviewsUIService::SetIgnorePreviewsBlacklistDecision(bool ignored) {
+void PreviewsUIService::SetIgnorePreviewsBlocklistDecision(bool ignored) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  previews_decider_impl_->SetIgnorePreviewsBlacklistDecision(ignored);
+  previews_decider_impl_->SetIgnorePreviewsBlocklistDecision(ignored);
 }
 
-void PreviewsUIService::OnIgnoreBlacklistDecisionStatusChanged(bool ignored) {
+void PreviewsUIService::OnIgnoreBlocklistDecisionStatusChanged(bool ignored) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  logger_->OnIgnoreBlacklistDecisionStatusChanged(ignored);
+  logger_->OnIgnoreBlocklistDecisionStatusChanged(ignored);
 }
 
 PreviewsLogger* PreviewsUIService::previews_logger() const {
@@ -102,19 +102,19 @@
   return previews_decider_impl_.get();
 }
 
-// When triggering previews, prevent long term black list rules.
-void PreviewsUIService::SetIgnoreLongTermBlackListForServerPreviews(
-    bool ignore_long_term_black_list_rules_allowed) {
+// When triggering previews, prevent long term block list rules.
+void PreviewsUIService::SetIgnoreLongTermBlockListForServerPreviews(
+    bool ignore_long_term_block_list_rules_allowed) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  previews_decider_impl_->SetIgnoreLongTermBlackListForServerPreviews(
-      ignore_long_term_black_list_rules_allowed);
+  previews_decider_impl_->SetIgnoreLongTermBlockListForServerPreviews(
+      ignore_long_term_block_list_rules_allowed);
 }
 
-void PreviewsUIService::ClearBlackList(base::Time begin_time,
+void PreviewsUIService::ClearBlockList(base::Time begin_time,
                                        base::Time end_time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  previews_decider_impl_->ClearBlackList(begin_time, end_time);
+  previews_decider_impl_->ClearBlockList(begin_time, end_time);
 }
 
 void PreviewsUIService::OnEffectiveConnectionTypeChanged(
diff --git a/components/previews/content/previews_ui_service.h b/components/previews/content/previews_ui_service.h
index f54a2a2d..ad53865 100644
--- a/components/previews/content/previews_ui_service.h
+++ b/components/previews/content/previews_ui_service.h
@@ -36,11 +36,11 @@
  public:
   PreviewsUIService(
       std::unique_ptr<PreviewsDeciderImpl> previews_decider_impl,
-      std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store,
+      std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store,
       std::unique_ptr<PreviewsOptimizationGuide> previews_opt_guide,
       const PreviewsIsEnabledCallback& is_enabled_callback,
       std::unique_ptr<PreviewsLogger> logger,
-      blacklist::BlacklistData::AllowedTypesAndVersions allowed_previews,
+      blocklist::BlocklistData::AllowedTypesAndVersions allowed_previews,
       network::NetworkQualityTracker* network_quality_tracker);
   ~PreviewsUIService() override;
 
@@ -48,39 +48,39 @@
   void OnEffectiveConnectionTypeChanged(
       net::EffectiveConnectionType type) override;
 
-  // Adds a navigation to |url| to the black list with result |opt_out|.
+  // Adds a navigation to |url| to the block list with result |opt_out|.
   void AddPreviewNavigation(const GURL& url,
                             PreviewsType type,
                             bool opt_out,
                             uint64_t page_id);
 
-  // Clears the history of the black list between |begin_time| and |end_time|.
-  void ClearBlackList(base::Time begin_time, base::Time end_time);
+  // Clears the history of the block list between |begin_time| and |end_time|.
+  void ClearBlockList(base::Time begin_time, base::Time end_time);
 
-  // Notifies |logger_| that |host| has been blacklisted at |time|. Virtualized
+  // Notifies |logger_| that |host| has been blocklisted at |time|. Virtualized
   // in testing.
-  virtual void OnNewBlacklistedHost(const std::string& host, base::Time time);
+  virtual void OnNewBlocklistedHost(const std::string& host, base::Time time);
 
-  // Notifies |logger_| that the user blacklisted state has changed. Where
-  // |blacklisted| is the new user blacklisted status. Virtualized in testing.
-  virtual void OnUserBlacklistedStatusChange(bool blacklisted);
+  // Notifies |logger_| that the user blocklisted state has changed. Where
+  // |blocklisted| is the new user blocklisted status. Virtualized in testing.
+  virtual void OnUserBlocklistedStatusChange(bool blocklisted);
 
-  // Notifies |logger_| that the blacklist is cleared at |time|. Virtualized in
+  // Notifies |logger_| that the blocklist is cleared at |time|. Virtualized in
   // testing.
-  virtual void OnBlacklistCleared(base::Time time);
+  virtual void OnBlocklistCleared(base::Time time);
 
-  // Change the status of whether to ignored or consider PreviewsBlackList
+  // Change the status of whether to ignored or consider PreviewsBlockList
   // decisions in |previews_decider_impl_|. This method is called when users
-  // interact with the UI (i.e. click on the "Ignore Blacklist" button).
+  // interact with the UI (i.e. click on the "Ignore Blocklist" button).
   // Virtualized in testing.
-  virtual void SetIgnorePreviewsBlacklistDecision(bool ignored);
+  virtual void SetIgnorePreviewsBlocklistDecision(bool ignored);
 
-  // Notifies |logger_| whether PreviewsBlackList decisions are ignored or not.
+  // Notifies |logger_| whether PreviewsBlockList decisions are ignored or not.
   // This method is listening for notification from PreviewsDeciderImpl for when
-  // the blacklist ignore status is changed so that |logger_| can update all
+  // the blocklist ignore status is changed so that |logger_| can update all
   // PreviewsLoggerObservers so that multiple instances of the page have the
   // same status. Virtualized in testing.
-  virtual void OnIgnoreBlacklistDecisionStatusChanged(bool ignored);
+  virtual void OnIgnoreBlocklistDecisionStatusChanged(bool ignored);
 
   // Log the navigation to PreviewsLogger. Virtualized in testing.
   virtual void LogPreviewNavigation(const GURL& url,
@@ -120,9 +120,9 @@
   // non-null.
   PreviewsDeciderImpl* previews_decider_impl() const;
 
-  // When triggering previews, prevent long term black list rules.
-  void SetIgnoreLongTermBlackListForServerPreviews(
-      bool ignore_long_term_black_list_rules_allowed);
+  // When triggering previews, prevent long term block list rules.
+  void SetIgnoreLongTermBlockListForServerPreviews(
+      bool ignore_long_term_block_list_rules_allowed);
 
  private:
   // The decision making object for Previews triggering. Guaranteed to be
@@ -130,7 +130,7 @@
   std::unique_ptr<previews::PreviewsDeciderImpl> previews_decider_impl_;
 
   // A log object to keep track of events such as previews navigations,
-  // blacklist actions, etc.
+  // blocklist actions, etc.
   std::unique_ptr<PreviewsLogger> logger_;
 
   // Used to remove |this| from observing.
diff --git a/components/previews/content/previews_ui_service_unittest.cc b/components/previews/content/previews_ui_service_unittest.cc
index fa84e64..a68a47e 100644
--- a/components/previews/content/previews_ui_service_unittest.cc
+++ b/components/previews/content/previews_ui_service_unittest.cc
@@ -33,7 +33,7 @@
  public:
   TestPreviewsUIService(
       std::unique_ptr<PreviewsDeciderImpl> previews_decider_impl,
-      std::unique_ptr<blacklist::OptOutStore> previews_opt_out_store,
+      std::unique_ptr<blocklist::OptOutStore> previews_opt_out_store,
       std::unique_ptr<PreviewsOptimizationGuide> previews_opt_guide,
       std::unique_ptr<PreviewsLogger> logger,
       network::TestNetworkQualityTracker* test_network_quality_tracker)
@@ -42,7 +42,7 @@
                           std::move(previews_opt_guide),
                           base::BindRepeating(&MockedPreviewsIsEnabled),
                           std::move(logger),
-                          blacklist::BlacklistData::AllowedTypesAndVersions(),
+                          blocklist::BlocklistData::AllowedTypesAndVersions(),
                           test_network_quality_tracker) {}
   ~TestPreviewsUIService() override {}
 };
@@ -50,11 +50,7 @@
 // Mock class of PreviewsLogger for checking passed in parameters.
 class TestPreviewsLogger : public PreviewsLogger {
  public:
-  TestPreviewsLogger()
-      : decision_page_id_(0),
-        navigation_opt_out_(false),
-        user_blacklisted_(false),
-        blacklist_ignored_(false) {}
+  TestPreviewsLogger() : decision_page_id_(0), navigation_opt_out_(false) {}
 
   // PreviewsLogger:
   void LogPreviewNavigation(const GURL& url,
@@ -84,21 +80,21 @@
     decision_page_id_ = page_id;
   }
 
-  void OnNewBlacklistedHost(const std::string& host, base::Time time) override {
-    host_blacklisted_ = host;
-    host_blacklisted_time_ = time;
+  void OnNewBlocklistedHost(const std::string& host, base::Time time) override {
+    host_blocklisted_ = host;
+    host_blocklisted_time_ = time;
   }
 
-  void OnUserBlacklistedStatusChange(bool blacklisted) override {
-    user_blacklisted_ = blacklisted;
+  void OnUserBlocklistedStatusChange(bool blocklisted) override {
+    user_blocklisted_ = blocklisted;
   }
 
-  void OnBlacklistCleared(base::Time time) override {
-    blacklist_cleared_time_ = time;
+  void OnBlocklistCleared(base::Time time) override {
+    blocklist_cleared_time_ = time;
   }
 
-  void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) override {
-    blacklist_ignored_ = ignored;
+  void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) override {
+    blocklist_ignored_ = ignored;
   }
 
   // Return the passed in LogPreviewDecision parameters.
@@ -119,14 +115,14 @@
   PreviewsType navigation_type() const { return navigation_type_; }
   uint64_t navigation_page_id() const { return navigation_page_id_; }
 
-  // Return the passed in OnBlacklist events.
-  std::string host_blacklisted() const { return host_blacklisted_; }
-  base::Time host_blacklisted_time() const { return host_blacklisted_time_; }
-  bool user_blacklisted() const { return user_blacklisted_; }
-  base::Time blacklist_cleared_time() const { return blacklist_cleared_time_; }
+  // Return the passed in OnBlocklist events.
+  std::string host_blocklisted() const { return host_blocklisted_; }
+  base::Time host_blocklisted_time() const { return host_blocklisted_time_; }
+  bool user_blocklisted() const { return user_blocklisted_; }
+  base::Time blocklist_cleared_time() const { return blocklist_cleared_time_; }
 
-  // Return the status of blacklist ignored.
-  bool blacklist_ignored() const { return blacklist_ignored_; }
+  // Return the status of blocklist ignored.
+  bool blocklist_ignored() const { return blocklist_ignored_; }
 
  private:
   // Passed in LogPreviewDecision parameters.
@@ -144,34 +140,33 @@
   PreviewsType navigation_type_;
   uint64_t navigation_page_id_;
 
-  // Passed in OnBlacklist events.
-  std::string host_blacklisted_;
-  base::Time host_blacklisted_time_;
-  bool user_blacklisted_;
-  base::Time blacklist_cleared_time_;
+  // Passed in OnBlocklist events.
+  std::string host_blocklisted_;
+  base::Time host_blocklisted_time_;
+  bool user_blocklisted_ = false;
+  base::Time blocklist_cleared_time_;
 
-  // Passed in blacklist ignored status.
-  bool blacklist_ignored_;
+  // Passed in blocklist ignored status.
+  bool blocklist_ignored_ = false;
 };
 
 class TestPreviewsDeciderImpl : public PreviewsDeciderImpl {
  public:
   TestPreviewsDeciderImpl()
-      : PreviewsDeciderImpl(base::DefaultClock::GetInstance()),
-        blacklist_ignored_(false) {}
+      : PreviewsDeciderImpl(base::DefaultClock::GetInstance()) {}
 
   // PreviewsDeciderImpl:
-  void SetIgnorePreviewsBlacklistDecision(bool ignored) override {
-    blacklist_ignored_ = ignored;
+  void SetIgnorePreviewsBlocklistDecision(bool ignored) override {
+    blocklist_ignored_ = ignored;
   }
 
-  // Exposed the status of blacklist decisions ignored for testing
+  // Exposed the status of blocklist decisions ignored for testing
   // PreviewsUIService.
-  bool blacklist_ignored() const { return blacklist_ignored_; }
+  bool blocklist_ignored() const { return blocklist_ignored_; }
 
  private:
-  // Whether the blacklist decisions are ignored or not.
-  bool blacklist_ignored_;
+  // Whether the blocklist decisions are ignored or not.
+  bool blocklist_ignored_ = false;
 };
 
 class PreviewsUIServiceTest : public testing::Test {
@@ -256,7 +251,7 @@
 
 TEST_F(PreviewsUIServiceTest, TestLogPreviewDecisionMadePassesCorrectParams) {
   PreviewsEligibilityReason reason_a =
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE;
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE;
   const GURL url_a("http://www.url_a.com/url_a");
   const base::Time time_a = base::Time::Now();
   PreviewsType type_a = PreviewsType::OFFLINE;
@@ -314,47 +309,47 @@
   }
 }
 
-TEST_F(PreviewsUIServiceTest, TestOnNewBlacklistedHostPassesCorrectParams) {
+TEST_F(PreviewsUIServiceTest, TestOnNewBlocklistedHostPassesCorrectParams) {
   const std::string expected_host = "example.com";
   const base::Time expected_time = base::Time::Now();
-  ui_service()->OnNewBlacklistedHost(expected_host, expected_time);
+  ui_service()->OnNewBlocklistedHost(expected_host, expected_time);
 
-  EXPECT_EQ(expected_host, logger_ptr_->host_blacklisted());
-  EXPECT_EQ(expected_time, logger_ptr_->host_blacklisted_time());
+  EXPECT_EQ(expected_host, logger_ptr_->host_blocklisted());
+  EXPECT_EQ(expected_time, logger_ptr_->host_blocklisted_time());
 }
 
-TEST_F(PreviewsUIServiceTest, TestOnUserBlacklistedPassesCorrectParams) {
-  ui_service()->OnUserBlacklistedStatusChange(true /* blacklisted */);
-  EXPECT_TRUE(logger_ptr_->user_blacklisted());
+TEST_F(PreviewsUIServiceTest, TestOnUserBlocklistedPassesCorrectParams) {
+  ui_service()->OnUserBlocklistedStatusChange(true /* blocklisted */);
+  EXPECT_TRUE(logger_ptr_->user_blocklisted());
 
-  ui_service()->OnUserBlacklistedStatusChange(false /* blacklisted */);
-  EXPECT_FALSE(logger_ptr_->user_blacklisted());
+  ui_service()->OnUserBlocklistedStatusChange(false /* blocklisted */);
+  EXPECT_FALSE(logger_ptr_->user_blocklisted());
 }
 
-TEST_F(PreviewsUIServiceTest, TestOnBlacklistClearedPassesCorrectParams) {
+TEST_F(PreviewsUIServiceTest, TestOnBlocklistClearedPassesCorrectParams) {
   const base::Time expected_time = base::Time::Now();
-  ui_service()->OnBlacklistCleared(expected_time);
+  ui_service()->OnBlocklistCleared(expected_time);
 
-  EXPECT_EQ(expected_time, logger_ptr_->blacklist_cleared_time());
+  EXPECT_EQ(expected_time, logger_ptr_->blocklist_cleared_time());
 }
 
 TEST_F(PreviewsUIServiceTest,
-       TestSetIgnorePreviewsBlacklistDecisionPassesCorrectParams) {
-  ui_service()->SetIgnorePreviewsBlacklistDecision(true /* ignored */);
+       TestSetIgnorePreviewsBlocklistDecisionPassesCorrectParams) {
+  ui_service()->SetIgnorePreviewsBlocklistDecision(true /* ignored */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(previews_decider_impl()->blacklist_ignored());
+  EXPECT_TRUE(previews_decider_impl()->blocklist_ignored());
 
-  ui_service()->SetIgnorePreviewsBlacklistDecision(false /* ignored */);
+  ui_service()->SetIgnorePreviewsBlocklistDecision(false /* ignored */);
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(previews_decider_impl()->blacklist_ignored());
+  EXPECT_FALSE(previews_decider_impl()->blocklist_ignored());
 }
 
-TEST_F(PreviewsUIServiceTest, TestOnIgnoreBlacklistDecisionStatusChanged) {
-  ui_service()->OnIgnoreBlacklistDecisionStatusChanged(true /* ignored */);
-  EXPECT_TRUE(logger_ptr_->blacklist_ignored());
+TEST_F(PreviewsUIServiceTest, TestOnIgnoreBlocklistDecisionStatusChanged) {
+  ui_service()->OnIgnoreBlocklistDecisionStatusChanged(true /* ignored */);
+  EXPECT_TRUE(logger_ptr_->blocklist_ignored());
 
-  ui_service()->OnIgnoreBlacklistDecisionStatusChanged(false /* ignored */);
-  EXPECT_FALSE(logger_ptr_->blacklist_ignored());
+  ui_service()->OnIgnoreBlocklistDecisionStatusChanged(false /* ignored */);
+  EXPECT_FALSE(logger_ptr_->blocklist_ignored());
 }
 
 }  // namespace previews
diff --git a/components/previews/content/previews_user_data.cc b/components/previews/content/previews_user_data.cc
index 626cf48..abf9231 100644
--- a/components/previews/content/previews_user_data.cc
+++ b/components/previews/content/previews_user_data.cc
@@ -24,7 +24,7 @@
       cache_control_no_transform_directive_(
           other.cache_control_no_transform_directive_),
       offline_preview_used_(other.offline_preview_used_),
-      black_listed_for_lite_page_(other.black_listed_for_lite_page_),
+      block_listed_for_lite_page_(other.block_listed_for_lite_page_),
       committed_previews_type_without_holdback_(
           other.committed_previews_type_without_holdback_),
       allowed_previews_state_without_holdback_(
diff --git a/components/previews/content/previews_user_data.h b/components/previews/content/previews_user_data.h
index bf0c0d6e..b1f1c34 100644
--- a/components/previews/content/previews_user_data.h
+++ b/components/previews/content/previews_user_data.h
@@ -72,12 +72,12 @@
   }
 
   // Whether a lite page preview was prevented from being shown due to the
-  // blacklist.
-  bool black_listed_for_lite_page() const {
-    return black_listed_for_lite_page_;
+  // blocklist.
+  bool block_listed_for_lite_page() const {
+    return block_listed_for_lite_page_;
   }
-  void set_black_listed_for_lite_page(bool black_listed_for_lite_page) {
-    black_listed_for_lite_page_ = black_listed_for_lite_page;
+  void set_block_listed_for_lite_page(bool block_listed_for_lite_page) {
+    block_listed_for_lite_page_ = block_listed_for_lite_page;
   }
 
   // Returns whether the Cache-Control:no-transform directive has been
@@ -176,8 +176,8 @@
   bool offline_preview_used_ = false;
 
   // Whether a lite page preview was prevented from being shown due to the
-  // blacklist.
-  bool black_listed_for_lite_page_ = false;
+  // blocklist.
+  bool block_listed_for_lite_page_ = false;
 
   // The committed previews type, if any. Is not influenced by the coin flip
   // holdback.
diff --git a/components/previews/content/previews_user_data_unittest.cc b/components/previews/content/previews_user_data_unittest.cc
index 54b3103..4dfda8c5e 100644
--- a/components/previews/content/previews_user_data_unittest.cc
+++ b/components/previews/content/previews_user_data_unittest.cc
@@ -23,14 +23,14 @@
             data.EligibilityReasonForPreview(PreviewsType::OFFLINE));
 
   data.SetEligibilityReasonForPreview(
-      PreviewsType::NOSCRIPT, PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE);
+      PreviewsType::NOSCRIPT, PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE);
   data.SetEligibilityReasonForPreview(
       PreviewsType::NOSCRIPT,
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED);
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED);
 
   EXPECT_EQ(base::nullopt,
             data.EligibilityReasonForPreview(PreviewsType::OFFLINE));
-  EXPECT_EQ(PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+  EXPECT_EQ(PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
             data.EligibilityReasonForPreview(PreviewsType::NOSCRIPT));
 }
 
@@ -43,14 +43,14 @@
   EXPECT_EQ(0, data->data_savings_inflation_percent());
   EXPECT_FALSE(data->cache_control_no_transform_directive());
   EXPECT_EQ(previews::PreviewsType::NONE, data->CommittedPreviewsType());
-  EXPECT_FALSE(data->black_listed_for_lite_page());
+  EXPECT_FALSE(data->block_listed_for_lite_page());
   EXPECT_FALSE(data->offline_preview_used());
 
   data->set_data_savings_inflation_percent(123);
   data->set_cache_control_no_transform_directive();
   data->SetCommittedPreviewsType(previews::PreviewsType::NOSCRIPT);
   data->set_offline_preview_used(true);
-  data->set_black_listed_for_lite_page(true);
+  data->set_block_listed_for_lite_page(true);
 
   PreviewsUserData data_copy(*data);
   EXPECT_EQ(id, data_copy.page_id());
@@ -59,7 +59,7 @@
   EXPECT_TRUE(data_copy.cache_control_no_transform_directive());
   EXPECT_EQ(previews::PreviewsType::NOSCRIPT,
             data_copy.CommittedPreviewsType());
-  EXPECT_TRUE(data_copy.black_listed_for_lite_page());
+  EXPECT_TRUE(data_copy.block_listed_for_lite_page());
   EXPECT_TRUE(data_copy.offline_preview_used());
 }
 
diff --git a/components/previews/core/previews_black_list.cc b/components/previews/core/previews_black_list.cc
index 93cdaba..94046c5 100644
--- a/components/previews/core/previews_black_list.cc
+++ b/components/previews/core/previews_black_list.cc
@@ -20,41 +20,41 @@
 
 namespace {
 
-PreviewsEligibilityReason BlacklistReasonToPreviewsReason(
-    blacklist::BlacklistReason reason) {
+PreviewsEligibilityReason BlocklistReasonToPreviewsReason(
+    blocklist::BlocklistReason reason) {
   switch (reason) {
-    case blacklist::BlacklistReason::kBlacklistNotLoaded:
-      return PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED;
-    case blacklist::BlacklistReason::kUserOptedOutInSession:
+    case blocklist::BlocklistReason::kBlocklistNotLoaded:
+      return PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED;
+    case blocklist::BlocklistReason::kUserOptedOutInSession:
       return PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT;
-    case blacklist::BlacklistReason::kUserOptedOutInGeneral:
-      return PreviewsEligibilityReason::USER_BLACKLISTED;
-    case blacklist::BlacklistReason::kUserOptedOutOfHost:
-      return PreviewsEligibilityReason::HOST_BLACKLISTED;
-    case blacklist::BlacklistReason::kUserOptedOutOfType:
-      NOTREACHED() << "Previews does not support type-base blacklisting";
+    case blocklist::BlocklistReason::kUserOptedOutInGeneral:
+      return PreviewsEligibilityReason::USER_BLOCKLISTED;
+    case blocklist::BlocklistReason::kUserOptedOutOfHost:
+      return PreviewsEligibilityReason::HOST_BLOCKLISTED;
+    case blocklist::BlocklistReason::kUserOptedOutOfType:
+      NOTREACHED() << "Previews does not support type-base blocklisting";
       return PreviewsEligibilityReason::ALLOWED;
-    case blacklist::BlacklistReason::kAllowed:
+    case blocklist::BlocklistReason::kAllowed:
       return PreviewsEligibilityReason::ALLOWED;
   }
 }
 
-}
+}  // namespace
 
-PreviewsBlackList::PreviewsBlackList(
-    std::unique_ptr<blacklist::OptOutStore> opt_out_store,
+PreviewsBlockList::PreviewsBlockList(
+    std::unique_ptr<blocklist::OptOutStore> opt_out_store,
     base::Clock* clock,
-    blacklist::OptOutBlacklistDelegate* blacklist_delegate,
-    blacklist::BlacklistData::AllowedTypesAndVersions allowed_types)
-    : blacklist::OptOutBlacklist(std::move(opt_out_store),
+    blocklist::OptOutBlocklistDelegate* blocklist_delegate,
+    blocklist::BlocklistData::AllowedTypesAndVersions allowed_types)
+    : blocklist::OptOutBlocklist(std::move(opt_out_store),
                                  clock,
-                                 blacklist_delegate),
+                                 blocklist_delegate),
       allowed_types_(std::move(allowed_types)) {
-  DCHECK(blacklist_delegate);
+  DCHECK(blocklist_delegate);
   Init();
 }
 
-bool PreviewsBlackList::ShouldUseSessionPolicy(base::TimeDelta* duration,
+bool PreviewsBlockList::ShouldUseSessionPolicy(base::TimeDelta* duration,
                                                size_t* history,
                                                int* threshold) const {
   *duration = params::SingleOptOutDuration();
@@ -63,38 +63,38 @@
   return true;
 }
 
-bool PreviewsBlackList::ShouldUsePersistentPolicy(base::TimeDelta* duration,
+bool PreviewsBlockList::ShouldUsePersistentPolicy(base::TimeDelta* duration,
                                                   size_t* history,
                                                   int* threshold) const {
-  *history = params::MaxStoredHistoryLengthForHostIndifferentBlackList();
-  *threshold = params::HostIndifferentBlackListOptOutThreshold();
-  *duration = params::HostIndifferentBlackListPerHostDuration();
+  *history = params::MaxStoredHistoryLengthForHostIndifferentBlockList();
+  *threshold = params::HostIndifferentBlockListOptOutThreshold();
+  *duration = params::HostIndifferentBlockListPerHostDuration();
   return true;
 }
-bool PreviewsBlackList::ShouldUseHostPolicy(base::TimeDelta* duration,
+bool PreviewsBlockList::ShouldUseHostPolicy(base::TimeDelta* duration,
                                             size_t* history,
                                             int* threshold,
                                             size_t* max_hosts) const {
-  *max_hosts = params::MaxInMemoryHostsInBlackList();
-  *history = params::MaxStoredHistoryLengthForPerHostBlackList();
-  *threshold = params::PerHostBlackListOptOutThreshold();
-  *duration = params::PerHostBlackListDuration();
+  *max_hosts = params::MaxInMemoryHostsInBlockList();
+  *history = params::MaxStoredHistoryLengthForPerHostBlockList();
+  *threshold = params::PerHostBlockListOptOutThreshold();
+  *duration = params::PerHostBlockListDuration();
   return true;
 }
-bool PreviewsBlackList::ShouldUseTypePolicy(base::TimeDelta* duration,
+bool PreviewsBlockList::ShouldUseTypePolicy(base::TimeDelta* duration,
                                             size_t* history,
                                             int* threshold) const {
   return false;
 }
 
-blacklist::BlacklistData::AllowedTypesAndVersions
-PreviewsBlackList::GetAllowedTypes() const {
+blocklist::BlocklistData::AllowedTypesAndVersions
+PreviewsBlockList::GetAllowedTypes() const {
   return allowed_types_;
 }
 
-PreviewsBlackList::~PreviewsBlackList() {}
+PreviewsBlockList::~PreviewsBlockList() = default;
 
-base::Time PreviewsBlackList::AddPreviewNavigation(const GURL& url,
+base::Time PreviewsBlockList::AddPreviewNavigation(const GURL& url,
                                                    bool opt_out,
                                                    PreviewsType type) {
   DCHECK(url.has_host());
@@ -105,27 +105,27 @@
       base::HistogramBase::kUmaTargetedHistogramFlag)
       ->Add(opt_out);
 
-  return blacklist::OptOutBlacklist::AddEntry(url.host(), opt_out,
+  return blocklist::OptOutBlocklist::AddEntry(url.host(), opt_out,
                                               static_cast<int>(type));
 }
 
-PreviewsEligibilityReason PreviewsBlackList::IsLoadedAndAllowed(
+PreviewsEligibilityReason PreviewsBlockList::IsLoadedAndAllowed(
     const GURL& url,
     PreviewsType type,
-    bool ignore_long_term_black_list_rules,
+    bool ignore_long_term_block_list_rules,
     std::vector<PreviewsEligibilityReason>* passed_reasons) const {
   DCHECK(url.has_host());
 
-  std::vector<blacklist::BlacklistReason> passed_blacklist_reasons;
-  blacklist::BlacklistReason reason =
-      blacklist::OptOutBlacklist::IsLoadedAndAllowed(
-          url.host(), static_cast<int>(type), ignore_long_term_black_list_rules,
-          &passed_blacklist_reasons);
-  for (auto passed_reason : passed_blacklist_reasons) {
-    passed_reasons->push_back(BlacklistReasonToPreviewsReason(passed_reason));
+  std::vector<blocklist::BlocklistReason> passed_blocklist_reasons;
+  blocklist::BlocklistReason reason =
+      blocklist::OptOutBlocklist::IsLoadedAndAllowed(
+          url.host(), static_cast<int>(type), ignore_long_term_block_list_rules,
+          &passed_blocklist_reasons);
+  for (auto passed_reason : passed_blocklist_reasons) {
+    passed_reasons->push_back(BlocklistReasonToPreviewsReason(passed_reason));
   }
 
-  return BlacklistReasonToPreviewsReason(reason);
+  return BlocklistReasonToPreviewsReason(reason);
 }
 
 }  // namespace previews
diff --git a/components/previews/core/previews_black_list.h b/components/previews/core/previews_black_list.h
index 31946d1..c5886cf3 100644
--- a/components/previews/core/previews_black_list.h
+++ b/components/previews/core/previews_black_list.h
@@ -34,34 +34,34 @@
 enum class PreviewsEligibilityReason {
   // The preview navigation was allowed.
   ALLOWED = 0,
-  // The black list was not initialized.
-  BLACKLIST_UNAVAILABLE = 1,
-  // The black list has not loaded from disk yet.
-  BLACKLIST_DATA_NOT_LOADED = 2,
+  // The block list was not initialized.
+  BLOCKLIST_UNAVAILABLE = 1,
+  // The block list has not loaded from disk yet.
+  BLOCKLIST_DATA_NOT_LOADED = 2,
   // The user has opted out of a preview recently.
   USER_RECENTLY_OPTED_OUT = 3,
   // The user has opted out of previews often, and is no longer shown previews
   // on any host.
-  USER_BLACKLISTED = 4,
+  USER_BLOCKLISTED = 4,
   // The user has opted out of previews on a specific host often, and was not
   // not shown a previews on that host.
-  HOST_BLACKLISTED = 5,
+  HOST_BLOCKLISTED = 5,
   // The network quality estimate is not available.
   NETWORK_QUALITY_UNAVAILABLE = 6,
   // The network was fast enough to not warrant previews.
   NETWORK_NOT_SLOW = 7,
   // If the page was reloaded, the user should not be shown a stale preview.
   RELOAD_DISALLOWED = 8,
-  // DEPRECATED: The host is explicitly blacklisted by the server, so the user
+  // DEPRECATED: The host is explicitly blocklisted by the server, so the user
   // was not shown
   // a preview.
   // Replaced by NOT_ALLOWED_BY_OPTIMIZATION_GUIDE.
-  DEPRECATED_HOST_BLACKLISTED_BY_SERVER = 9,
-  // DEPRECATED: The host is not whitelisted by the server for a preview
+  DEPRECATED_HOST_BLOCKLISTED_BY_SERVER = 9,
+  // DEPRECATED: The host is not allowlisted by the server for a preview
   // decision that uses
   // server optimization hints.
   // Replaced by NOT_ALLOWED_BY_OPTIMIZATION_GUIDE.
-  DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER = 10,
+  DEPRECATED_HOST_NOT_ALLOWLISTED_BY_SERVER = 10,
   // The preview is allowed but without an expected check of server optimization
   // hints because they are not enabled (features::kOptimizationHints).
   ALLOWED_WITHOUT_OPTIMIZATION_HINTS = 11,
@@ -95,25 +95,25 @@
   LAST,
 };
 
-// Manages the state of black listed domains for the previews experiment. Loads
-// the stored black list from |opt_out_store| and manages an in memory black
-// list on the IO thread. Updates to the black list are stored in memory and
+// Manages the state of block listed domains for the previews experiment. Loads
+// the stored block list from |opt_out_store| and manages an in memory block
+// list on the IO thread. Updates to the block list are stored in memory and
 // pushed to the store. Asynchronous modifications are stored in a queue and
-// executed in order. Reading from the black list is always synchronous, and if
-// the black list is not currently loaded (e.g., at startup, after clearing
-// browsing history), domains are reported as black listed. The list stores no
-// more than previews::params::MaxInMemoryHostsInBlackList hosts in-memory,
+// executed in order. Reading from the block list is always synchronous, and if
+// the block list is not currently loaded (e.g., at startup, after clearing
+// browsing history), domains are reported as block listed. The list stores no
+// more than previews::params::MaxInMemoryHostsInBlockList hosts in-memory,
 // which defaults to 100.
-class PreviewsBlackList : public blacklist::OptOutBlacklist {
+class PreviewsBlockList : public blocklist::OptOutBlocklist {
  public:
-  PreviewsBlackList(
-      std::unique_ptr<blacklist::OptOutStore> opt_out_store,
+  PreviewsBlockList(
+      std::unique_ptr<blocklist::OptOutStore> opt_out_store,
       base::Clock* clock,
-      blacklist::OptOutBlacklistDelegate* blacklist_delegate,
-      blacklist::BlacklistData::AllowedTypesAndVersions allowed_types);
-  ~PreviewsBlackList() override;
+      blocklist::OptOutBlocklistDelegate* blocklist_delegate,
+      blocklist::BlocklistData::AllowedTypesAndVersions allowed_types);
+  ~PreviewsBlockList() override;
 
-  // Asynchronously adds a new navigation to to the in-memory black list and
+  // Asynchronously adds a new navigation to to the in-memory block list and
   // backing store. |opt_out| is whether the user opted out of the preview or
   // navigated away from the page without opting out. |type| is only passed to
   // the backing store. If the in memory map has reached the max number of hosts
@@ -125,17 +125,17 @@
                                   PreviewsType type);
 
   // Synchronously determines if |host_name| should be allowed to show previews.
-  // Returns the reason the blacklist disallowed the preview, or
+  // Returns the reason the blocklist disallowed the preview, or
   // PreviewsEligibilityReason::ALLOWED if the preview is allowed. Record
   // checked reasons in |passed_reasons|. Virtualized in testing.
   virtual PreviewsEligibilityReason IsLoadedAndAllowed(
       const GURL& url,
       PreviewsType type,
-      bool ignore_long_term_black_list_rules,
+      bool ignore_long_term_block_list_rules,
       std::vector<PreviewsEligibilityReason>* passed_reasons) const;
 
  protected:
-  // blacklist::OptOutBlacklist (virtual for testing):
+  // blocklist::OptOutBlocklist (virtual for testing):
   bool ShouldUseSessionPolicy(base::TimeDelta* duration,
                               size_t* history,
                               int* threshold) const override;
@@ -149,13 +149,13 @@
   bool ShouldUseTypePolicy(base::TimeDelta* duration,
                            size_t* history,
                            int* threshold) const override;
-  blacklist::BlacklistData::AllowedTypesAndVersions GetAllowedTypes()
+  blocklist::BlocklistData::AllowedTypesAndVersions GetAllowedTypes()
       const override;
 
  private:
-  const blacklist::BlacklistData::AllowedTypesAndVersions allowed_types_;
+  const blocklist::BlocklistData::AllowedTypesAndVersions allowed_types_;
 
-  DISALLOW_COPY_AND_ASSIGN(PreviewsBlackList);
+  DISALLOW_COPY_AND_ASSIGN(PreviewsBlockList);
 };
 
 }  // namespace previews
diff --git a/components/previews/core/previews_black_list_unittest.cc b/components/previews/core/previews_black_list_unittest.cc
index 88d79f5..21cc702 100644
--- a/components/previews/core/previews_black_list_unittest.cc
+++ b/components/previews/core/previews_black_list_unittest.cc
@@ -35,62 +35,62 @@
 
 namespace {
 
-// Mock class to test that PreviewsBlackList notifies the delegate with correct
-// events (e.g. New host blacklisted, user blacklisted, and blacklist cleared).
-class TestOptOutBlacklistDelegate : public blacklist::OptOutBlacklistDelegate {
+// Mock class to test that PreviewsBlockList notifies the delegate with correct
+// events (e.g. New host blocklisted, user blocklisted, and blocklist cleared).
+class TestOptOutBlocklistDelegate : public blocklist::OptOutBlocklistDelegate {
  public:
-  TestOptOutBlacklistDelegate() {}
+  TestOptOutBlocklistDelegate() = default;
 
-  // blacklist::OptOutBlacklistDelegate:
-  void OnNewBlacklistedHost(const std::string& host, base::Time time) override {
+  // blocklist::OptOutBlocklistDelegate:
+  void OnNewBlocklistedHost(const std::string& host, base::Time time) override {
   }
-  void OnUserBlacklistedStatusChange(bool blacklisted) override {}
-  void OnBlacklistCleared(base::Time time) override {}
+  void OnUserBlocklistedStatusChange(bool blocklisted) override {}
+  void OnBlocklistCleared(base::Time time) override {}
 };
 
-class TestPreviewsBlackList : public PreviewsBlackList {
+class TestPreviewsBlockList : public PreviewsBlockList {
  public:
-  TestPreviewsBlackList(
-      std::unique_ptr<blacklist::OptOutStore> opt_out_store,
+  TestPreviewsBlockList(
+      std::unique_ptr<blocklist::OptOutStore> opt_out_store,
       base::Clock* clock,
-      blacklist::OptOutBlacklistDelegate* blacklist_delegate,
-      blacklist::BlacklistData::AllowedTypesAndVersions allowed_types)
-      : PreviewsBlackList(std::move(opt_out_store),
+      blocklist::OptOutBlocklistDelegate* blocklist_delegate,
+      blocklist::BlocklistData::AllowedTypesAndVersions allowed_types)
+      : PreviewsBlockList(std::move(opt_out_store),
                           clock,
-                          blacklist_delegate,
+                          blocklist_delegate,
                           allowed_types) {}
-  ~TestPreviewsBlackList() override {}
+  ~TestPreviewsBlockList() override = default;
 
   bool ShouldUseSessionPolicy(base::TimeDelta* duration,
                               size_t* history,
                               int* threshold) const override {
-    return PreviewsBlackList::ShouldUseSessionPolicy(duration, history,
+    return PreviewsBlockList::ShouldUseSessionPolicy(duration, history,
                                                      threshold);
   }
   bool ShouldUsePersistentPolicy(base::TimeDelta* duration,
                                  size_t* history,
                                  int* threshold) const override {
-    return PreviewsBlackList::ShouldUsePersistentPolicy(duration, history,
+    return PreviewsBlockList::ShouldUsePersistentPolicy(duration, history,
                                                         threshold);
   }
   bool ShouldUseHostPolicy(base::TimeDelta* duration,
                            size_t* history,
                            int* threshold,
                            size_t* max_hosts) const override {
-    return PreviewsBlackList::ShouldUseHostPolicy(duration, history, threshold,
+    return PreviewsBlockList::ShouldUseHostPolicy(duration, history, threshold,
                                                   max_hosts);
   }
   bool ShouldUseTypePolicy(base::TimeDelta* duration,
                            size_t* history,
                            int* threshold) const override {
-    return PreviewsBlackList::ShouldUseTypePolicy(duration, history, threshold);
+    return PreviewsBlockList::ShouldUseTypePolicy(duration, history, threshold);
   }
 };
 
-class PreviewsBlackListTest : public testing::Test {
+class PreviewsBlockListTest : public testing::Test {
  public:
-  PreviewsBlackListTest() : passed_reasons_({}) {}
-  ~PreviewsBlackListTest() override {}
+  PreviewsBlockListTest() : passed_reasons_({}) {}
+  ~PreviewsBlockListTest() override = default;
 
   void TearDown() override { variations::testing::ClearAllVariationParams(); }
 
@@ -103,10 +103,10 @@
       params_.clear();
     }
 
-    blacklist::BlacklistData::AllowedTypesAndVersions allowed_types;
+    blocklist::BlocklistData::AllowedTypesAndVersions allowed_types;
     allowed_types[static_cast<int>(PreviewsType::OFFLINE)] = 0;
-    black_list_ = std::make_unique<TestPreviewsBlackList>(
-        nullptr, &test_clock_, &blacklist_delegate_, std::move(allowed_types));
+    block_list_ = std::make_unique<TestPreviewsBlockList>(
+        nullptr, &test_clock_, &blocklist_delegate_, std::move(allowed_types));
 
     passed_reasons_ = {};
   }
@@ -132,11 +132,14 @@
   }
 
   void SetHostDurationParam(int duration_in_days) {
+    // TODO(crbug.com/1092102): Migrate to per_host_black_list_duration_in_days
     params_["per_host_black_list_duration_in_days"] =
         base::NumberToString(duration_in_days);
   }
 
   void SetHostIndifferentDurationParam(int duration_in_days) {
+    // TODO(crbug.com/1092102): Migrate to
+    // host_indifferent_block_list_duration_in_days
     params_["host_indifferent_black_list_duration_in_days"] =
         base::NumberToString(duration_in_days);
   }
@@ -146,44 +149,45 @@
         base::NumberToString(single_opt_out_duration);
   }
 
-  void SetMaxHostInBlackListParam(size_t max_hosts_in_blacklist) {
+  void SetMaxHostInBlockListParam(size_t max_hosts_in_blocklist) {
+    // TODO(crbug.com/1092102): Migrate to max_hosts_in_blocklist
     params_["max_hosts_in_blacklist"] =
-        base::NumberToString(max_hosts_in_blacklist);
+        base::NumberToString(max_hosts_in_blocklist);
   }
 
  protected:
   base::test::SingleThreadTaskEnvironment task_environment_;
 
-  // Observer to |black_list_|.
-  TestOptOutBlacklistDelegate blacklist_delegate_;
+  // Observer to |block_list_|.
+  TestOptOutBlocklistDelegate blocklist_delegate_;
 
   base::SimpleTestClock test_clock_;
   std::map<std::string, std::string> params_;
 
-  std::unique_ptr<TestPreviewsBlackList> black_list_;
+  std::unique_ptr<TestPreviewsBlockList> block_list_;
   std::vector<PreviewsEligibilityReason> passed_reasons_;
 
  private:
-  DISALLOW_COPY_AND_ASSIGN(PreviewsBlackListTest);
+  DISALLOW_COPY_AND_ASSIGN(PreviewsBlockListTest);
 };
 
-TEST_F(PreviewsBlackListTest, AddPreviewUMA) {
+TEST_F(PreviewsBlockListTest, AddPreviewUMA) {
   base::HistogramTester histogram_tester;
   const GURL url("http://www.url.com");
 
   StartTest();
 
-  black_list_->AddPreviewNavigation(url, false, PreviewsType::OFFLINE);
+  block_list_->AddPreviewNavigation(url, false, PreviewsType::OFFLINE);
   histogram_tester.ExpectUniqueSample("Previews.OptOut.UserOptedOut.Offline", 0,
                                       1);
   histogram_tester.ExpectUniqueSample("Previews.OptOut.UserOptedOut", 0, 1);
-  black_list_->AddPreviewNavigation(url, true, PreviewsType::OFFLINE);
+  block_list_->AddPreviewNavigation(url, true, PreviewsType::OFFLINE);
   histogram_tester.ExpectBucketCount("Previews.OptOut.UserOptedOut.Offline", 1,
                                      1);
   histogram_tester.ExpectBucketCount("Previews.OptOut.UserOptedOut", 1, 1);
 }
 
-TEST_F(PreviewsBlackListTest, SessionParams) {
+TEST_F(PreviewsBlockListTest, SessionParams) {
   int duration_seconds = 5;
   SetSingleOptOutDurationParam(duration_seconds);
 
@@ -194,13 +198,13 @@
   int threshold = 0;
 
   EXPECT_TRUE(
-      black_list_->ShouldUseSessionPolicy(&duration, &history, &threshold));
+      block_list_->ShouldUseSessionPolicy(&duration, &history, &threshold));
   EXPECT_EQ(base::TimeDelta::FromSeconds(duration_seconds), duration);
   EXPECT_EQ(1u, history);
   EXPECT_EQ(1, threshold);
 }
 
-TEST_F(PreviewsBlackListTest, PersistentParams) {
+TEST_F(PreviewsBlockListTest, PersistentParams) {
   int duration_days = 5;
   size_t expected_history = 6;
   int expected_threshold = 4;
@@ -215,13 +219,13 @@
   int threshold = 0;
 
   EXPECT_TRUE(
-      black_list_->ShouldUsePersistentPolicy(&duration, &history, &threshold));
+      block_list_->ShouldUsePersistentPolicy(&duration, &history, &threshold));
   EXPECT_EQ(base::TimeDelta::FromDays(duration_days), duration);
   EXPECT_EQ(expected_history, history);
   EXPECT_EQ(expected_threshold, threshold);
 }
 
-TEST_F(PreviewsBlackListTest, HostParams) {
+TEST_F(PreviewsBlockListTest, HostParams) {
   int duration_days = 5;
   size_t expected_history = 6;
   int expected_threshold = 4;
@@ -229,7 +233,7 @@
   SetHostThresholdParam(expected_threshold);
   SetHostHistoryParam(expected_history);
   SetHostDurationParam(duration_days);
-  SetMaxHostInBlackListParam(expected_max_hosts);
+  SetMaxHostInBlockListParam(expected_max_hosts);
 
   StartTest();
 
@@ -238,7 +242,7 @@
   int threshold = 0;
   size_t max_hosts = 0;
 
-  EXPECT_TRUE(black_list_->ShouldUseHostPolicy(&duration, &history, &threshold,
+  EXPECT_TRUE(block_list_->ShouldUseHostPolicy(&duration, &history, &threshold,
                                                &max_hosts));
   EXPECT_EQ(base::TimeDelta::FromDays(duration_days), duration);
   EXPECT_EQ(expected_history, history);
@@ -246,9 +250,9 @@
   EXPECT_EQ(expected_max_hosts, max_hosts);
 }
 
-TEST_F(PreviewsBlackListTest, TypeParams) {
+TEST_F(PreviewsBlockListTest, TypeParams) {
   StartTest();
-  EXPECT_FALSE(black_list_->ShouldUseTypePolicy(nullptr, nullptr, nullptr));
+  EXPECT_FALSE(block_list_->ShouldUseTypePolicy(nullptr, nullptr, nullptr));
 }
 
 }  // namespace
diff --git a/components/previews/core/previews_experiments.cc b/components/previews/core/previews_experiments.cc
index 6b3f87d..25d29b1 100644
--- a/components/previews/core/previews_experiments.cc
+++ b/components/previews/core/previews_experiments.cc
@@ -21,12 +21,12 @@
 
 namespace {
 
-// The group of client-side previews experiments. This controls paramters of the
-// client side blacklist.
+// The group of client-side previews experiments. This controls parameters of
+// the client side blocklist.
 const char kClientSidePreviewsFieldTrial[] = "ClientSidePreviews";
 
 // Name for the version parameter of a field trial. Version changes will
-// result in older blacklist entries being removed.
+// result in older blocklist entries being removed.
 const char kVersion[] = "version";
 
 // Parameter to clarify that the preview for a UserConsistent study should
@@ -128,38 +128,44 @@
 
 namespace params {
 
-size_t MaxStoredHistoryLengthForPerHostBlackList() {
+size_t MaxStoredHistoryLengthForPerHostBlockList() {
   return GetParamValueAsSizeT(kClientSidePreviewsFieldTrial,
                               "per_host_max_stored_history_length", 4);
 }
 
-size_t MaxStoredHistoryLengthForHostIndifferentBlackList() {
+size_t MaxStoredHistoryLengthForHostIndifferentBlockList() {
   return GetParamValueAsSizeT(kClientSidePreviewsFieldTrial,
                               "host_indifferent_max_stored_history_length", 10);
 }
 
-size_t MaxInMemoryHostsInBlackList() {
+size_t MaxInMemoryHostsInBlockList() {
+  // TODO(crbug.com/1092102): Migrate exeriment parameter name to
+  // max_hosts_in_blocklist.
   return GetParamValueAsSizeT(kClientSidePreviewsFieldTrial,
                               "max_hosts_in_blacklist", 100);
 }
 
-int PerHostBlackListOptOutThreshold() {
+int PerHostBlockListOptOutThreshold() {
   return GetParamValueAsInt(kClientSidePreviewsFieldTrial,
                             "per_host_opt_out_threshold", 2);
 }
 
-int HostIndifferentBlackListOptOutThreshold() {
+int HostIndifferentBlockListOptOutThreshold() {
   return GetParamValueAsInt(kClientSidePreviewsFieldTrial,
                             "host_indifferent_opt_out_threshold", 6);
 }
 
-base::TimeDelta PerHostBlackListDuration() {
+base::TimeDelta PerHostBlockListDuration() {
+  // TODO(crbug.com/1092102): Migrate exeriment parameter name to
+  // per_host_block_list_duration_in_days.
   return base::TimeDelta::FromDays(
       GetParamValueAsInt(kClientSidePreviewsFieldTrial,
                          "per_host_black_list_duration_in_days", 30));
 }
 
-base::TimeDelta HostIndifferentBlackListPerHostDuration() {
+base::TimeDelta HostIndifferentBlockListPerHostDuration() {
+  // TODO(crbug.com/1092102): Migrate exeriment parameter name to
+  // host_indifferent_block_list_duration_in_days/
   return base::TimeDelta::FromDays(
       GetParamValueAsInt(kClientSidePreviewsFieldTrial,
                          "host_indifferent_black_list_duration_in_days", 30));
@@ -278,7 +284,7 @@
 }
 
 int NoScriptPreviewsInflationPercent() {
-  // The default value was determined from lab experiment data of whitelisted
+  // The default value was determined from lab experiment data of allowlisted
   // URLs. It may be improved once there is enough UKM live experiment data
   // via the field trial param.
   return GetFieldTrialParamByFeatureAsInt(GetNoScriptPreviewsFeature(),
diff --git a/components/previews/core/previews_experiments.h b/components/previews/core/previews_experiments.h
index 29ad994..7c461a1 100644
--- a/components/previews/core/previews_experiments.h
+++ b/components/previews/core/previews_experiments.h
@@ -76,30 +76,30 @@
 
 namespace params {
 
-// The maximum number of recent previews navigations the black list looks at to
-// determine if a host is blacklisted.
-size_t MaxStoredHistoryLengthForPerHostBlackList();
+// The maximum number of recent previews navigations the block list looks at to
+// determine if a host is blocklisted.
+size_t MaxStoredHistoryLengthForPerHostBlockList();
 
-// The maximum number of recent previews navigations the black list looks at to
+// The maximum number of recent previews navigations the block list looks at to
 // determine if all previews navigations are disallowed.
-size_t MaxStoredHistoryLengthForHostIndifferentBlackList();
+size_t MaxStoredHistoryLengthForHostIndifferentBlockList();
 
-// The maximum number of hosts allowed in the in memory black list.
-size_t MaxInMemoryHostsInBlackList();
+// The maximum number of hosts allowed in the in memory block list.
+size_t MaxInMemoryHostsInBlockList();
 
 // The number of recent navigations that were opted out of for a given host that
-// would trigger that host to be blacklisted.
-int PerHostBlackListOptOutThreshold();
+// would trigger that host to be blocklisted.
+int PerHostBlockListOptOutThreshold();
 
 // The number of recent navigations that were opted out of that would trigger
 // all previews navigations to be disallowed.
-int HostIndifferentBlackListOptOutThreshold();
+int HostIndifferentBlockListOptOutThreshold();
 
-// The amount of time a host remains blacklisted due to opt outs.
-base::TimeDelta PerHostBlackListDuration();
+// The amount of time a host remains blocklisted due to opt outs.
+base::TimeDelta PerHostBlockListDuration();
 
 // The amount of time all previews navigations are disallowed due to opt outs.
-base::TimeDelta HostIndifferentBlackListPerHostDuration();
+base::TimeDelta HostIndifferentBlockListPerHostDuration();
 
 // The amount of time after any opt out that no previews should be shown.
 base::TimeDelta SingleOptOutDuration();
@@ -128,7 +128,7 @@
 bool IsResourceLoadingHintsEnabled();
 bool IsDeferAllScriptPreviewsEnabled();
 
-// The blacklist version for each preview type.
+// The blocklist version for each preview type.
 int OfflinePreviewsVersion();
 int NoScriptPreviewsVersion();
 int ResourceLoadingHintsVersion();
diff --git a/components/previews/core/previews_experiments_unittest.cc b/components/previews/core/previews_experiments_unittest.cc
index 13c8fde..99a89906 100644
--- a/components/previews/core/previews_experiments_unittest.cc
+++ b/components/previews/core/previews_experiments_unittest.cc
@@ -29,17 +29,17 @@
 const char kEnabled[] = "Enabled";
 
 // Verifies that the default params are correct, and that custom params can be
-// set, for both the previews blacklist and offline previews.
-TEST(PreviewsExperimentsTest, TestParamsForBlackListAndOffline) {
+// set, for both the previews blocklist and offline previews.
+TEST(PreviewsExperimentsTest, TestParamsForBlockListAndOffline) {
   // Verify that the default params are correct.
-  EXPECT_EQ(4u, params::MaxStoredHistoryLengthForPerHostBlackList());
-  EXPECT_EQ(10u, params::MaxStoredHistoryLengthForHostIndifferentBlackList());
-  EXPECT_EQ(100u, params::MaxInMemoryHostsInBlackList());
-  EXPECT_EQ(2, params::PerHostBlackListOptOutThreshold());
-  EXPECT_EQ(6, params::HostIndifferentBlackListOptOutThreshold());
-  EXPECT_EQ(base::TimeDelta::FromDays(30), params::PerHostBlackListDuration());
+  EXPECT_EQ(4u, params::MaxStoredHistoryLengthForPerHostBlockList());
+  EXPECT_EQ(10u, params::MaxStoredHistoryLengthForHostIndifferentBlockList());
+  EXPECT_EQ(100u, params::MaxInMemoryHostsInBlockList());
+  EXPECT_EQ(2, params::PerHostBlockListOptOutThreshold());
+  EXPECT_EQ(6, params::HostIndifferentBlockListOptOutThreshold());
+  EXPECT_EQ(base::TimeDelta::FromDays(30), params::PerHostBlockListDuration());
   EXPECT_EQ(base::TimeDelta::FromDays(30),
-            params::HostIndifferentBlackListPerHostDuration());
+            params::HostIndifferentBlockListPerHostDuration());
   EXPECT_EQ(base::TimeDelta::FromSeconds(60 * 5),
             params::SingleOptOutDuration());
   EXPECT_EQ(base::TimeDelta::FromDays(7),
@@ -51,6 +51,7 @@
   EXPECT_EQ(0, params::OfflinePreviewsVersion());
 
   // Set some custom params. Somewhat random yet valid values.
+  // TODO(crbug.com/1092102) : Migrate blacklist names to blocklist.
   std::map<std::string, std::string> custom_params = {
       {"per_host_max_stored_history_length", "3"},
       {"host_indifferent_max_stored_history_length", "4"},
@@ -69,14 +70,14 @@
   EXPECT_TRUE(base::FieldTrialList::CreateFieldTrial(
       kClientSidePreviewsFieldTrial, kEnabled));
 
-  EXPECT_EQ(3u, params::MaxStoredHistoryLengthForPerHostBlackList());
-  EXPECT_EQ(4u, params::MaxStoredHistoryLengthForHostIndifferentBlackList());
-  EXPECT_EQ(13u, params::MaxInMemoryHostsInBlackList());
-  EXPECT_EQ(12, params::PerHostBlackListOptOutThreshold());
-  EXPECT_EQ(84, params::HostIndifferentBlackListOptOutThreshold());
-  EXPECT_EQ(base::TimeDelta::FromDays(99), params::PerHostBlackListDuration());
+  EXPECT_EQ(3u, params::MaxStoredHistoryLengthForPerHostBlockList());
+  EXPECT_EQ(4u, params::MaxStoredHistoryLengthForHostIndifferentBlockList());
+  EXPECT_EQ(13u, params::MaxInMemoryHostsInBlockList());
+  EXPECT_EQ(12, params::PerHostBlockListOptOutThreshold());
+  EXPECT_EQ(84, params::HostIndifferentBlockListOptOutThreshold());
+  EXPECT_EQ(base::TimeDelta::FromDays(99), params::PerHostBlockListDuration());
   EXPECT_EQ(base::TimeDelta::FromDays(64),
-            params::HostIndifferentBlackListPerHostDuration());
+            params::HostIndifferentBlockListPerHostDuration());
   EXPECT_EQ(base::TimeDelta::FromSeconds(28), params::SingleOptOutDuration());
   EXPECT_EQ(base::TimeDelta::FromDays(12),
             params::OfflinePreviewFreshnessDuration());
diff --git a/components/previews/core/previews_features.cc b/components/previews/core/previews_features.cc
index d22d4021..3f4e492 100644
--- a/components/previews/core/previews_features.cc
+++ b/components/previews/core/previews_features.cc
@@ -29,11 +29,7 @@
 // Support for enabling NoScript previews which includes a base feature
 // and a UserConsistent-specific experiment feature.
 const base::FeatureState kNoScriptDefaultFeatureState =
-#if defined(OS_ANDROID)
-    base::FEATURE_ENABLED_BY_DEFAULT;
-#else   // !defined(OS_ANDROID)
     base::FEATURE_DISABLED_BY_DEFAULT;
-#endif  // defined(OS_ANDROID)
 const base::Feature kNoScriptPreviews{"NoScriptPreviews",
                                       kNoScriptDefaultFeatureState};
 const base::Feature kNoScriptPreviewsUserConsistentStudy{
diff --git a/components/previews/core/previews_logger.cc b/components/previews/core/previews_logger.cc
index fb1bc21..1216528 100644
--- a/components/previews/core/previews_logger.cc
+++ b/components/previews/core/previews_logger.cc
@@ -36,22 +36,22 @@
     case PreviewsEligibilityReason::ALLOWED:
       DCHECK(!want_inverse_description);
       return "Allowed";
-    case PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE:
-      return want_inverse_description ? "Blacklist not null"
-                                      : "Blacklist failed to be created";
-    case PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED:
-      return want_inverse_description ? "Blacklist loaded from disk"
-                                      : "Blacklist not loaded from disk yet";
+    case PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE:
+      return want_inverse_description ? "Blocklist not null"
+                                      : "Blocklist failed to be created";
+    case PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED:
+      return want_inverse_description ? "Blocklist loaded from disk"
+                                      : "Blocklist not loaded from disk yet";
     case PreviewsEligibilityReason::USER_RECENTLY_OPTED_OUT:
       return want_inverse_description ? "User did not opt out recently"
                                       : "User recently opted out";
-    case PreviewsEligibilityReason::USER_BLACKLISTED:
-      return want_inverse_description ? "Not all previews are blacklisted"
-                                      : "All previews are blacklisted";
-    case PreviewsEligibilityReason::HOST_BLACKLISTED:
+    case PreviewsEligibilityReason::USER_BLOCKLISTED:
+      return want_inverse_description ? "Not all previews are blocklisted"
+                                      : "All previews are blocklisted";
+    case PreviewsEligibilityReason::HOST_BLOCKLISTED:
       return want_inverse_description
-                 ? "Host is not blacklisted on all previews"
-                 : "All previews on this host are blacklisted";
+                 ? "Host is not blocklisted on all previews"
+                 : "All previews on this host are blocklisted";
     case PreviewsEligibilityReason::NETWORK_QUALITY_UNAVAILABLE:
       return want_inverse_description ? "Network quality available"
                                       : "Network quality unavailable";
@@ -61,12 +61,12 @@
       return want_inverse_description
                  ? "Page reloads allowed"
                  : "Page reloads do not show previews for this preview type";
-    case PreviewsEligibilityReason::DEPRECATED_HOST_BLACKLISTED_BY_SERVER:
-      return want_inverse_description ? "Host not blacklisted by server rules"
-                                      : "Host blacklisted by server rules";
-    case PreviewsEligibilityReason::DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER:
-      return want_inverse_description ? "Host whitelisted by server rules"
-                                      : "Host not whitelisted by server rules";
+    case PreviewsEligibilityReason::DEPRECATED_HOST_BLOCKLISTED_BY_SERVER:
+      return want_inverse_description ? "Host not blocklisted by server rules"
+                                      : "Host blocklisted by server rules";
+    case PreviewsEligibilityReason::DEPRECATED_HOST_NOT_ALLOWLISTED_BY_SERVER:
+      return want_inverse_description ? "Host allowlisted by server rules"
+                                      : "Host not allowlisted by server rules";
     case PreviewsEligibilityReason::ALLOWED_WITHOUT_OPTIMIZATION_HINTS:
       return want_inverse_description
                  ? "Not allowed (without server rule check)"
@@ -147,15 +147,15 @@
       page_id(other.page_id) {}
 
 PreviewsLogger::PreviewsLogger()
-    : blacklist_ignored_(switches::ShouldIgnorePreviewsBlacklist()) {}
+    : blocklist_ignored_(switches::ShouldIgnorePreviewsBlocklist()) {}
 
 PreviewsLogger::~PreviewsLogger() {}
 
 void PreviewsLogger::AddAndNotifyObserver(PreviewsLoggerObserver* observer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   observer_list_.AddObserver(observer);
-  // Notify the status of blacklist decisions ingored.
-  observer->OnIgnoreBlacklistDecisionStatusChanged(blacklist_ignored_);
+  // Notify the status of blocklist decisions ignored.
+  observer->OnIgnoreBlocklistDecisionStatusChanged(blocklist_ignored_);
 
   // Merge navigation logs and decision logs in chronological order, and push
   // them to |observer|.
@@ -182,11 +182,11 @@
     }
   }
 
-  // Push the current state of blacklist (user blacklisted state and all
-  // blacklisted hosts).
-  observer->OnUserBlacklistedStatusChange(user_blacklisted_status_);
-  for (auto entry : blacklisted_hosts_) {
-    observer->OnNewBlacklistedHost(entry.first, entry.second);
+  // Push the current state of blocklist (user blocklisted state and all
+  // blocklisted hosts).
+  observer->OnUserBlocklistedStatusChange(user_blocklisted_status_);
+  for (auto entry : blocklisted_hosts_) {
+    observer->OnNewBlocklistedHost(entry.first, entry.second);
   }
 }
 
@@ -264,38 +264,38 @@
                                time, page_id);
 }
 
-void PreviewsLogger::OnNewBlacklistedHost(const std::string& host,
+void PreviewsLogger::OnNewBlocklistedHost(const std::string& host,
                                           base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  blacklisted_hosts_[host] = time;
+  blocklisted_hosts_[host] = time;
   for (auto& observer : observer_list_) {
-    observer.OnNewBlacklistedHost(host, time);
+    observer.OnNewBlocklistedHost(host, time);
   }
 }
 
-void PreviewsLogger::OnUserBlacklistedStatusChange(bool blacklisted) {
+void PreviewsLogger::OnUserBlocklistedStatusChange(bool blocklisted) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  user_blacklisted_status_ = blacklisted;
+  user_blocklisted_status_ = blocklisted;
   for (auto& observer : observer_list_) {
-    observer.OnUserBlacklistedStatusChange(blacklisted);
+    observer.OnUserBlocklistedStatusChange(blocklisted);
   }
 }
 
-void PreviewsLogger::OnBlacklistCleared(base::Time time) {
+void PreviewsLogger::OnBlocklistCleared(base::Time time) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  blacklisted_hosts_.clear();
+  blocklisted_hosts_.clear();
   navigations_logs_.clear();
   decisions_logs_.clear();
   for (auto& observer : observer_list_) {
-    observer.OnBlacklistCleared(time);
+    observer.OnBlocklistCleared(time);
   }
 }
 
-void PreviewsLogger::OnIgnoreBlacklistDecisionStatusChanged(bool ignored) {
+void PreviewsLogger::OnIgnoreBlocklistDecisionStatusChanged(bool ignored) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  blacklist_ignored_ = ignored;
+  blocklist_ignored_ = ignored;
   for (auto& observer : observer_list_) {
-    observer.OnIgnoreBlacklistDecisionStatusChanged(ignored);
+    observer.OnIgnoreBlocklistDecisionStatusChanged(ignored);
   }
 }
 
diff --git a/components/previews/core/previews_logger.h b/components/previews/core/previews_logger.h
index 1e4ac44..dbc952ed 100644
--- a/components/previews/core/previews_logger.h
+++ b/components/previews/core/previews_logger.h
@@ -90,7 +90,7 @@
                                     uint64_t page_id);
 
   // Add a MessageLog for the a decision that was made about the state of
-  // previews and blacklist. |passed_reasons| is an ordered list of
+  // previews and blocklist. |passed_reasons| is an ordered list of
   // PreviewsEligibilityReasons that got pass the decision. The method takes
   // ownership of |passed_reasons|. |page_id| generated by PreviewsDeciderImpl,
   // used for grouping log messages together, messages that don't need to be
@@ -103,32 +103,32 @@
       std::vector<PreviewsEligibilityReason>&& passed_reasons,
       uint64_t page_id);
 
-  // Notify observers that |host| is blacklisted at |time|. Virtualized in
+  // Notify observers that |host| is blocklisted at |time|. Virtualized in
   // testing.
-  virtual void OnNewBlacklistedHost(const std::string& host, base::Time time);
+  virtual void OnNewBlocklistedHost(const std::string& host, base::Time time);
 
-  // Notify observers that user blacklisted state has changed to |blacklisted|.
+  // Notify observers that user blocklisted state has changed to |blocklisted|.
   // Virtualized in testing.
-  virtual void OnUserBlacklistedStatusChange(bool blacklisted);
+  virtual void OnUserBlocklistedStatusChange(bool blocklisted);
 
-  // Notify observers that the blacklist is cleared at |time|. Virtualized in
+  // Notify observers that the blocklist is cleared at |time|. Virtualized in
   // testing.
-  virtual void OnBlacklistCleared(base::Time time);
+  virtual void OnBlocklistCleared(base::Time time);
 
-  // Notify observers that the status of whether blacklist decisions are ignored
+  // Notify observers that the status of whether blocklist decisions are ignored
   // or not. Virtualized in testing.
-  virtual void OnIgnoreBlacklistDecisionStatusChanged(bool ignored);
+  virtual void OnIgnoreBlocklistDecisionStatusChanged(bool ignored);
 
  private:
-  // Keeping track of all blacklisted host to notify new observers.
-  std::unordered_map<std::string, base::Time> blacklisted_hosts_;
+  // Keeping track of all blocklisted host to notify new observers.
+  std::unordered_map<std::string, base::Time> blocklisted_hosts_;
 
-  // The current user blacklisted status.
-  bool user_blacklisted_status_ = false;
+  // The current user blocklisted status.
+  bool user_blocklisted_status_ = false;
 
-  // The current status of whether PreviewsBlackList decisions are ignored or
+  // The current status of whether PreviewsBlockList decisions are ignored or
   // not.
-  bool blacklist_ignored_ = false;
+  bool blocklist_ignored_ = false;
 
   // Collection of recorded navigation log messages.
   std::list<MessageLog> navigations_logs_;
diff --git a/components/previews/core/previews_logger_observer.h b/components/previews/core/previews_logger_observer.h
index 6b48e56..e1ebc798 100644
--- a/components/previews/core/previews_logger_observer.h
+++ b/components/previews/core/previews_logger_observer.h
@@ -19,19 +19,19 @@
   virtual void OnNewMessageLogAdded(
       const PreviewsLogger::MessageLog& message) = 0;
 
-  // Notifies this observer that |host| is blacklisted at |time|.
-  virtual void OnNewBlacklistedHost(const std::string& host,
+  // Notifies this observer that |host| is blocklisted at |time|.
+  virtual void OnNewBlocklistedHost(const std::string& host,
                                     base::Time time) = 0;
 
-  // Notifies this observer that the user blacklisted state has changed to
-  // |blacklisted|.
-  virtual void OnUserBlacklistedStatusChange(bool blacklisted) = 0;
+  // Notifies this observer that the user blocklisted state has changed to
+  // |blocklisted|.
+  virtual void OnUserBlocklistedStatusChange(bool blocklisted) = 0;
 
-  // Notifies this observer that the blacklist is cleared at |time|.
-  virtual void OnBlacklistCleared(base::Time time) = 0;
+  // Notifies this observer that the blocklist is cleared at |time|.
+  virtual void OnBlocklistCleared(base::Time time) = 0;
 
-  // Notify this observer that PreviewsBlackList decisions is ignored or not.
-  virtual void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) = 0;
+  // Notify this observer that PreviewsBlockList decisions is ignored or not.
+  virtual void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) = 0;
 
   // Notify this observer that |this| is the last observer to be removed from
   // the Logger's observers list.
diff --git a/components/previews/core/previews_logger_unittest.cc b/components/previews/core/previews_logger_unittest.cc
index b8bf2b4e..8ecbb1a 100644
--- a/components/previews/core/previews_logger_unittest.cc
+++ b/components/previews/core/previews_logger_unittest.cc
@@ -32,14 +32,9 @@
 // mojo::InterventionsInternalsPage.
 class TestPreviewsLoggerObserver : public PreviewsLoggerObserver {
  public:
-  TestPreviewsLoggerObserver()
-      : host_blacklisted_called_(false),
-        user_status_change_calls_(0),
-        blacklist_cleared_called_(false),
-        blacklist_ignored_(false),
-        last_removed_notified_(false) {}
+  TestPreviewsLoggerObserver() = default;
 
-  ~TestPreviewsLoggerObserver() override {}
+  ~TestPreviewsLoggerObserver() override = default;
 
   // PreviewsLoggerObserver:
   void OnNewMessageLogAdded(
@@ -47,20 +42,20 @@
     message_ = std::make_unique<PreviewsLogger::MessageLog>(message);
     messages_.push_back(*message_);
   }
-  void OnNewBlacklistedHost(const std::string& host, base::Time time) override {
-    host_blacklisted_called_ = true;
-    blacklisted_hosts_[host] = time;
+  void OnNewBlocklistedHost(const std::string& host, base::Time time) override {
+    host_blocklisted_called_ = true;
+    blocklisted_hosts_[host] = time;
   }
-  void OnUserBlacklistedStatusChange(bool blacklisted) override {
+  void OnUserBlocklistedStatusChange(bool blocklisted) override {
     ++user_status_change_calls_;
-    user_blacklisted_ = blacklisted;
+    user_blocklisted_ = blocklisted;
   }
-  void OnBlacklistCleared(base::Time time) override {
-    blacklist_cleared_called_ = true;
-    blacklist_cleared_time_ = time;
+  void OnBlocklistCleared(base::Time time) override {
+    blocklist_cleared_called_ = true;
+    blocklist_cleared_time_ = time;
   }
-  void OnIgnoreBlacklistDecisionStatusChanged(bool ignored) override {
-    blacklist_ignored_ = ignored;
+  void OnIgnoreBlocklistDecisionStatusChanged(bool ignored) override {
+    blocklist_ignored_ = ignored;
   }
   void OnLastObserverRemove() override { last_removed_notified_ = true; }
 
@@ -72,18 +67,18 @@
     return messages_;
   }
 
-  // Expose blacklist events info for testing.
-  const std::unordered_map<std::string, base::Time>& blacklisted_hosts() {
-    return blacklisted_hosts_;
+  // Expose blocklist events info for testing.
+  const std::unordered_map<std::string, base::Time>& blocklisted_hosts() {
+    return blocklisted_hosts_;
   }
-  bool host_blacklisted_called() const { return host_blacklisted_called_; }
+  bool host_blocklisted_called() const { return host_blocklisted_called_; }
   size_t user_status_change_calls() const { return user_status_change_calls_; }
-  bool blacklist_cleared_called() const { return blacklist_cleared_called_; }
-  bool user_blacklisted() const { return user_blacklisted_; }
-  base::Time blacklist_cleared_time() const { return blacklist_cleared_time_; }
+  bool blocklist_cleared_called() const { return blocklist_cleared_called_; }
+  bool user_blocklisted() const { return user_blocklisted_; }
+  base::Time blocklist_cleared_time() const { return blocklist_cleared_time_; }
 
-  // Expose whether PreviewsBlackList decisions are ignored or not.
-  bool blacklist_ignored() const { return blacklist_ignored_; }
+  // Expose whether PreviewsBlockList decisions are ignored or not.
+  bool blocklist_ignored() const { return blocklist_ignored_; }
 
   // Expose whether observer is notified that it is the last observer to be
   // removed for testing.
@@ -96,19 +91,19 @@
   // The passed in MessageLog in OnNewMessageLogAdded.
   std::unique_ptr<PreviewsLogger::MessageLog> message_;
 
-  // Received blacklisted event info.
-  std::unordered_map<std::string, base::Time> blacklisted_hosts_;
-  bool user_blacklisted_;
-  base::Time blacklist_cleared_time_;
-  bool host_blacklisted_called_;
-  size_t user_status_change_calls_;
-  bool blacklist_cleared_called_;
+  // Received blocklisted event info.
+  std::unordered_map<std::string, base::Time> blocklisted_hosts_;
+  bool user_blocklisted_;
+  base::Time blocklist_cleared_time_;
+  bool host_blocklisted_called_ = false;
+  size_t user_status_change_calls_ = 0;
+  bool blocklist_cleared_called_ = false;
 
-  // BlacklistPreviews decision is ignored or not.
-  bool blacklist_ignored_;
+  // BlocklistPreviews decision is ignored or not.
+  bool blocklist_ignored_ = false;
 
   // Whether |this| is the last observer to be removed.
-  bool last_removed_notified_;
+  bool last_removed_notified_ = false;
 };
 
 class PreviewsLoggerTest : public testing::Test {
@@ -160,7 +155,7 @@
   PreviewsType type_a = PreviewsType::OFFLINE;
   PreviewsType type_b = PreviewsType::LITE_PAGE;
   PreviewsEligibilityReason reason_a =
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE;
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE;
   std::vector<PreviewsEligibilityReason> passed_reasons_a = {};
   PreviewsEligibilityReason reason_b =
       PreviewsEligibilityReason::NETWORK_NOT_SLOW;
@@ -186,7 +181,7 @@
   EXPECT_EQ(expected_size, actual.size());
 
   std::string expected_description_a =
-      "Offline preview - Blacklist failed to be created";
+      "Offline preview - Blocklist failed to be created";
   EXPECT_EQ(kPreviewsDecisionMadeEventType, actual[0].event_type);
   EXPECT_EQ(expected_description_a, actual[0].event_description);
   EXPECT_EQ(url_a, actual[0].url);
@@ -257,7 +252,7 @@
 TEST_F(PreviewsLoggerTest, PreviewsLoggerOnlyKeepsCertainNumberOfDecisionLogs) {
   PreviewsType type = PreviewsType::OFFLINE;
   PreviewsEligibilityReason reason =
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE;
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE;
   const base::Time time = base::Time::Now();
   const GURL url("http://www.url_.com/url_");
   const uint64_t page_id = 1234;
@@ -298,7 +293,7 @@
 
   PreviewsType type = PreviewsType::OFFLINE;
   PreviewsEligibilityReason final_reason =
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE;
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE;
   std::vector<PreviewsEligibilityReason> passed_reasons = {
       PreviewsEligibilityReason::NETWORK_NOT_SLOW};
   const GURL urls[] = {
@@ -408,33 +403,33 @@
 
 TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionUnavailabeFailed) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE,
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE,
       true /* final_reason */);
-  std::string expected_description = "Blacklist failed to be created";
+  std::string expected_description = "Blocklist failed to be created";
   EXPECT_EQ(expected_description, actual_description);
 }
 
 TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionUnavailabeChecked) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::BLACKLIST_UNAVAILABLE,
+      PreviewsEligibilityReason::BLOCKLIST_UNAVAILABLE,
       false /* final_reason */);
-  std::string expected_description = "Blacklist not null";
+  std::string expected_description = "Blocklist not null";
   EXPECT_EQ(expected_description, actual_description);
 }
 
 TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionNotLoadedFailed) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
       true /* final_reason */);
-  std::string expected_description = "Blacklist not loaded from disk yet";
+  std::string expected_description = "Blocklist not loaded from disk yet";
   EXPECT_EQ(expected_description, actual_description);
 }
 
 TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionNotLoadedChecked) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::BLACKLIST_DATA_NOT_LOADED,
+      PreviewsEligibilityReason::BLOCKLIST_DATA_NOT_LOADED,
       false /* final_reason */);
-  std::string expected_description = "Blacklist loaded from disk";
+  std::string expected_description = "Blocklist loaded from disk";
   EXPECT_EQ(expected_description, actual_description);
 }
 
@@ -456,33 +451,33 @@
   EXPECT_EQ(expected_description, actual_description);
 }
 
-TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionBlacklistedFailed) {
+TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionBlocklistedFailed) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::USER_BLACKLISTED, true /* final_reason */);
-  std::string expected_description = "All previews are blacklisted";
+      PreviewsEligibilityReason::USER_BLOCKLISTED, true /* final_reason */);
+  std::string expected_description = "All previews are blocklisted";
   EXPECT_EQ(expected_description, actual_description);
 }
 
-TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionBlacklistedChecked) {
+TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionBlocklistedChecked) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::USER_BLACKLISTED, false /* final_reason */);
-  std::string expected_description = "Not all previews are blacklisted";
+      PreviewsEligibilityReason::USER_BLOCKLISTED, false /* final_reason */);
+  std::string expected_description = "Not all previews are blocklisted";
   EXPECT_EQ(expected_description, actual_description);
 }
 
-TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionHostBlacklistedFailed) {
+TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionHostBlocklistedFailed) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::HOST_BLACKLISTED, true /* final_reason */);
+      PreviewsEligibilityReason::HOST_BLOCKLISTED, true /* final_reason */);
   std::string expected_description =
-      "All previews on this host are blacklisted";
+      "All previews on this host are blocklisted";
   EXPECT_EQ(expected_description, actual_description);
 }
 
 TEST_F(PreviewsLoggerTest,
-       LogPreviewDecisionDescriptionHostBlacklistedChecked) {
+       LogPreviewDecisionDescriptionHostBlocklistedChecked) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::HOST_BLACKLISTED, false /* final_reason */);
-  std::string expected_description = "Host is not blacklisted on all previews";
+      PreviewsEligibilityReason::HOST_BLOCKLISTED, false /* final_reason */);
+  std::string expected_description = "Host is not blocklisted on all previews";
   EXPECT_EQ(expected_description, actual_description);
 }
 
@@ -539,35 +534,35 @@
 
 TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionServerRulesFailed) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::DEPRECATED_HOST_BLACKLISTED_BY_SERVER,
+      PreviewsEligibilityReason::DEPRECATED_HOST_BLOCKLISTED_BY_SERVER,
       true /* final_reason */);
-  std::string expected_description = "Host blacklisted by server rules";
+  std::string expected_description = "Host blocklisted by server rules";
   EXPECT_EQ(expected_description, actual_description);
 }
 
 TEST_F(PreviewsLoggerTest, LogPreviewDecisionDescriptionServerRulesChecked) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::DEPRECATED_HOST_BLACKLISTED_BY_SERVER,
+      PreviewsEligibilityReason::DEPRECATED_HOST_BLOCKLISTED_BY_SERVER,
       false /* final_reason */);
-  std::string expected_description = "Host not blacklisted by server rules";
+  std::string expected_description = "Host not blocklisted by server rules";
   EXPECT_EQ(expected_description, actual_description);
 }
 
 TEST_F(PreviewsLoggerTest,
-       LogPreviewDecisionDescriptionNotWhitelisedByServerFailed) {
+       LogPreviewDecisionDescriptionNotAllowistedByServerFailed) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER,
+      PreviewsEligibilityReason::DEPRECATED_HOST_NOT_ALLOWLISTED_BY_SERVER,
       true /* final_reason */);
-  std::string expected_description = "Host not whitelisted by server rules";
+  std::string expected_description = "Host not allowlisted by server rules";
   EXPECT_EQ(expected_description, actual_description);
 }
 
 TEST_F(PreviewsLoggerTest,
-       LogPreviewDecisionDescriptionNotWhitelisedByServerChecked) {
+       LogPreviewDecisionDescriptionNotAllowlistedByServerChecked) {
   std::string actual_description = LogPreviewDecisionAndGetReasonDescription(
-      PreviewsEligibilityReason::DEPRECATED_HOST_NOT_WHITELISTED_BY_SERVER,
+      PreviewsEligibilityReason::DEPRECATED_HOST_NOT_ALLOWLISTED_BY_SERVER,
       false /* final_reason */);
-  std::string expected_description = "Host whitelisted by server rules";
+  std::string expected_description = "Host allowlisted by server rules";
   EXPECT_EQ(expected_description, actual_description);
 }
 
@@ -641,7 +636,7 @@
   EXPECT_EQ(expected_description, actual_description);
 }
 
-TEST_F(PreviewsLoggerTest, NotifyObserversOfNewBlacklistedHost) {
+TEST_F(PreviewsLoggerTest, NotifyObserversOfNewBlocklistedHost) {
   TestPreviewsLoggerObserver observers[3];
 
   const size_t number_of_obs = 3;
@@ -655,20 +650,20 @@
   const std::string expected_host = "example.com";
   const base::Time expected_time = base::Time::Now();
   const size_t expected_size = 1;
-  logger_->OnNewBlacklistedHost(expected_host, expected_time);
+  logger_->OnNewBlocklistedHost(expected_host, expected_time);
 
   for (size_t i = 0; i < number_of_obs; i++) {
     if (i != removed_observer) {
-      EXPECT_TRUE(observers[i].host_blacklisted_called());
-      EXPECT_EQ(expected_size, observers[i].blacklisted_hosts().size());
+      EXPECT_TRUE(observers[i].host_blocklisted_called());
+      EXPECT_EQ(expected_size, observers[i].blocklisted_hosts().size());
       EXPECT_EQ(expected_time,
-                observers[i].blacklisted_hosts().find(expected_host)->second);
+                observers[i].blocklisted_hosts().find(expected_host)->second);
     }
   }
-  EXPECT_FALSE(observers[removed_observer].host_blacklisted_called());
+  EXPECT_FALSE(observers[removed_observer].host_blocklisted_called());
 }
 
-TEST_F(PreviewsLoggerTest, NotifyObserversWhenUserBlacklisted) {
+TEST_F(PreviewsLoggerTest, NotifyObserversWhenUserBlocklisted) {
   TestPreviewsLoggerObserver observers[3];
 
   const size_t number_of_obs = 3;
@@ -678,20 +673,20 @@
 
   const size_t removed_observer = 1;
   logger_->RemoveObserver(&observers[removed_observer]);
-  logger_->OnUserBlacklistedStatusChange(true /* blacklisted */);
+  logger_->OnUserBlocklistedStatusChange(true /* blocklisted */);
   const size_t expected_times = 2;
 
   for (size_t i = 0; i < number_of_obs; i++) {
     if (i != removed_observer) {
       EXPECT_EQ(expected_times, observers[i].user_status_change_calls());
-      EXPECT_TRUE(observers[i].user_blacklisted());
+      EXPECT_TRUE(observers[i].user_blocklisted());
     }
   }
   EXPECT_EQ(expected_times - 1,
             observers[removed_observer].user_status_change_calls());
 }
 
-TEST_F(PreviewsLoggerTest, NotifyObserversWhenUserNotBlacklisted) {
+TEST_F(PreviewsLoggerTest, NotifyObserversWhenUserNotBlocklisted) {
   TestPreviewsLoggerObserver observers[3];
 
   const size_t number_of_obs = 3;
@@ -701,20 +696,20 @@
 
   const size_t removed_observer = 1;
   logger_->RemoveObserver(&observers[removed_observer]);
-  logger_->OnUserBlacklistedStatusChange(false /* blacklisted */);
+  logger_->OnUserBlocklistedStatusChange(false /* blocklisted */);
   const size_t expected_times = 2;
 
   for (size_t i = 0; i < number_of_obs; i++) {
     if (i != removed_observer) {
       EXPECT_EQ(expected_times, observers[i].user_status_change_calls());
-      EXPECT_FALSE(observers[i].user_blacklisted());
+      EXPECT_FALSE(observers[i].user_blocklisted());
     }
   }
   EXPECT_EQ(expected_times - 1,
             observers[removed_observer].user_status_change_calls());
 }
 
-TEST_F(PreviewsLoggerTest, NotifyObserversWhenBlacklistCleared) {
+TEST_F(PreviewsLoggerTest, NotifyObserversWhenBlocklistCleared) {
   TestPreviewsLoggerObserver observers[3];
 
   const size_t number_of_obs = 3;
@@ -726,18 +721,18 @@
   logger_->RemoveObserver(&observers[removed_observer]);
 
   const base::Time expected_time = base::Time::Now();
-  logger_->OnBlacklistCleared(expected_time);
+  logger_->OnBlocklistCleared(expected_time);
 
   for (size_t i = 0; i < number_of_obs; i++) {
     if (i != removed_observer) {
-      EXPECT_TRUE(observers[i].blacklist_cleared_called());
-      EXPECT_EQ(expected_time, observers[i].blacklist_cleared_time());
+      EXPECT_TRUE(observers[i].blocklist_cleared_called());
+      EXPECT_EQ(expected_time, observers[i].blocklist_cleared_time());
     }
   }
-  EXPECT_FALSE(observers[removed_observer].blacklist_cleared_called());
+  EXPECT_FALSE(observers[removed_observer].blocklist_cleared_called());
 }
 
-TEST_F(PreviewsLoggerTest, ObserverNotifiedOfUserBlacklistedStateWhenAdded) {
+TEST_F(PreviewsLoggerTest, ObserverNotifiedOfUserBlocklistedStateWhenAdded) {
   TestPreviewsLoggerObserver observer;
 
   const std::string host0 = "example0.com";
@@ -745,20 +740,20 @@
   const base::Time time0 = base::Time::Now();
   const base::Time time1 = base::Time::Now();
 
-  logger_->OnUserBlacklistedStatusChange(true /* blacklisted */);
-  logger_->OnNewBlacklistedHost(host0, time0);
-  logger_->OnNewBlacklistedHost(host1, time1);
+  logger_->OnUserBlocklistedStatusChange(true /* blocklisted */);
+  logger_->OnNewBlocklistedHost(host0, time0);
+  logger_->OnNewBlocklistedHost(host1, time1);
   logger_->AddAndNotifyObserver(&observer);
 
   const size_t expected_times = 1;
   EXPECT_EQ(expected_times, observer.user_status_change_calls());
   const size_t expected_size = 2;
-  EXPECT_EQ(expected_size, observer.blacklisted_hosts().size());
-  EXPECT_EQ(time0, observer.blacklisted_hosts().find(host0)->second);
-  EXPECT_EQ(time1, observer.blacklisted_hosts().find(host1)->second);
+  EXPECT_EQ(expected_size, observer.blocklisted_hosts().size());
+  EXPECT_EQ(time0, observer.blocklisted_hosts().find(host0)->second);
+  EXPECT_EQ(time1, observer.blocklisted_hosts().find(host1)->second);
 }
 
-TEST_F(PreviewsLoggerTest, NotifyObserversBlacklistIgnoredUpdate) {
+TEST_F(PreviewsLoggerTest, NotifyObserversBlocklistIgnoredUpdate) {
   TestPreviewsLoggerObserver observers[3];
   const size_t number_of_obs = 3;
   for (size_t i = 0; i < number_of_obs; i++) {
@@ -766,50 +761,50 @@
   }
 
   for (size_t i = 0; i < number_of_obs; i++) {
-    EXPECT_FALSE(observers[i].blacklist_ignored());
+    EXPECT_FALSE(observers[i].blocklist_ignored());
   }
 
   const size_t removed_observer = 1;
   logger_->RemoveObserver(&observers[removed_observer]);
-  logger_->OnIgnoreBlacklistDecisionStatusChanged(true /* ignored */);
+  logger_->OnIgnoreBlocklistDecisionStatusChanged(true /* ignored */);
   for (size_t i = 0; i < number_of_obs; i++) {
     if (i != removed_observer) {
-      EXPECT_TRUE(observers[i].blacklist_ignored());
+      EXPECT_TRUE(observers[i].blocklist_ignored());
     }
   }
-  EXPECT_FALSE(observers[removed_observer].blacklist_ignored());
+  EXPECT_FALSE(observers[removed_observer].blocklist_ignored());
 }
 
-TEST_F(PreviewsLoggerTest, ObserverNotifiedOfBlacklistIgnoreStatusOnAdd) {
-  logger_->OnIgnoreBlacklistDecisionStatusChanged(true /* ignored */);
+TEST_F(PreviewsLoggerTest, ObserverNotifiedOfBlocklistIgnoreStatusOnAdd) {
+  logger_->OnIgnoreBlocklistDecisionStatusChanged(true /* ignored */);
   TestPreviewsLoggerObserver observer;
-  EXPECT_FALSE(observer.blacklist_ignored());
+  EXPECT_FALSE(observer.blocklist_ignored());
   logger_->AddAndNotifyObserver(&observer);
-  EXPECT_TRUE(observer.blacklist_ignored());
+  EXPECT_TRUE(observer.blocklist_ignored());
 }
 
 TEST_F(PreviewsLoggerTest,
-       ObserverNotifiedOfBlacklistIgnoreStatusDisabledViaFlag) {
+       ObserverNotifiedOfBlocklistIgnoreStatusDisabledViaFlag) {
   ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
-      switches::kIgnorePreviewsBlacklist));
+      switches::kIgnorePreviewsBlocklist));
 
   TestPreviewsLoggerObserver observer;
   PreviewsLogger logger;
   logger.AddAndNotifyObserver(&observer);
-  EXPECT_FALSE(observer.blacklist_ignored());
+  EXPECT_FALSE(observer.blocklist_ignored());
 }
 
 TEST_F(PreviewsLoggerTest,
-       ObserverNotifiedOfBlacklistIgnoreStatusEnabledViaFlag) {
+       ObserverNotifiedOfBlocklistIgnoreStatusEnabledViaFlag) {
   base::test::ScopedCommandLine scoped_command_line;
   base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
-  command_line->AppendSwitch(switches::kIgnorePreviewsBlacklist);
-  ASSERT_TRUE(switches::ShouldIgnorePreviewsBlacklist());
+  command_line->AppendSwitch(switches::kIgnorePreviewsBlocklist);
+  ASSERT_TRUE(switches::ShouldIgnorePreviewsBlocklist());
 
   TestPreviewsLoggerObserver observer;
   PreviewsLogger logger;
   logger.AddAndNotifyObserver(&observer);
-  EXPECT_TRUE(observer.blacklist_ignored());
+  EXPECT_TRUE(observer.blocklist_ignored());
 }
 
 TEST_F(PreviewsLoggerTest, LastObserverRemovedIsNotified) {
@@ -824,7 +819,7 @@
   EXPECT_TRUE(observers[number_of_obs - 1].last_removed_notified());
 }
 
-TEST_F(PreviewsLoggerTest, ClearBufferLogsWhenBlacklistCleared) {
+TEST_F(PreviewsLoggerTest, ClearBufferLogsWhenBlocklistCleared) {
   const std::string type = "Event_";
   const std::string description = "Some description";
   const GURL url("http://www.url_.com/url_");
@@ -833,7 +828,7 @@
 
   logger_->LogMessage(type, description, url, now, page_id);
 
-  logger_->OnBlacklistCleared(base::Time::Now());
+  logger_->OnBlocklistCleared(base::Time::Now());
 
   TestPreviewsLoggerObserver observer;
   logger_->AddAndNotifyObserver(&observer);
diff --git a/components/previews/core/previews_switches.cc b/components/previews/core/previews_switches.cc
index 2ec70f0..4bc1ac0 100644
--- a/components/previews/core/previews_switches.cc
+++ b/components/previews/core/previews_switches.cc
@@ -9,9 +9,9 @@
 namespace previews {
 namespace switches {
 
-bool ShouldIgnorePreviewsBlacklist() {
+bool ShouldIgnorePreviewsBlocklist() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
-             kIgnorePreviewsBlacklist) ||
+             kIgnorePreviewsBlocklist) ||
          base::CommandLine::ForCurrentProcess()->HasSwitch(
              kForceEnablePreviews);
 }
@@ -21,8 +21,9 @@
 const char kDoNotRequireLitePageRedirectInfoBar[] =
     "dont-require-litepage-redirect-infobar";
 
-// Ignore decisions made by PreviewsBlackList.
-const char kIgnorePreviewsBlacklist[] = "ignore-previews-blacklist";
+// Ignore decisions made by PreviewsBlockList.
+// TODO(crbug.com/1092105) : Migrate this to ignore-previews-blacklist.
+const char kIgnorePreviewsBlocklist[] = "ignore-previews-blacklist";
 
 // Force enable all available previews on every page load.
 const char kForceEnablePreviews[] = "force-enable-lite-pages";
diff --git a/components/previews/core/previews_switches.h b/components/previews/core/previews_switches.h
index 7a20630..4fa61a4a 100644
--- a/components/previews/core/previews_switches.h
+++ b/components/previews/core/previews_switches.h
@@ -8,12 +8,12 @@
 namespace previews {
 namespace switches {
 
-// Whether the previews blacklist should be ignored, according to command line
+// Whether the previews blocklist should be ignored, according to command line
 // switches.
-bool ShouldIgnorePreviewsBlacklist();
+bool ShouldIgnorePreviewsBlocklist();
 
 extern const char kDoNotRequireLitePageRedirectInfoBar[];
-extern const char kIgnorePreviewsBlacklist[];
+extern const char kIgnorePreviewsBlocklist[];
 extern const char kForceEnablePreviews[];
 extern const char kEnableDeferAllScriptWithoutOptimizationHints[];
 
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index c09b649..d96a17e5 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -2455,7 +2455,7 @@
   // http://crbug.com/1039817
   if (snapshotter_ && page_number == 0) {
     ui::AXTreeUpdate accessibility_tree;
-    snapshotter_->Snapshot(ui::kAXModeComplete, 0, &accessibility_tree);
+    snapshotter_->Snapshot(ui::AXMode::kPDF, 0, &accessibility_tree);
     Send(new PrintHostMsg_AccessibilityTree(
         routing_id(), print_pages_params_->params.document_cookie,
         accessibility_tree));
diff --git a/components/safe_browsing/core/db/v4_store.cc b/components/safe_browsing/core/db/v4_store.cc
index 2d12ab5..0d9b1497 100644
--- a/components/safe_browsing/core/db/v4_store.cc
+++ b/components/safe_browsing/core/db/v4_store.cc
@@ -64,43 +64,17 @@
                                     int32_t value,
                                     int32_t maximum,
                                     const base::FilePath& file_path) {
-  // The histograms below are an expansion of the UMA_HISTOGRAM_ENUMERATION
-  // macro adapted to allow for a dynamically suffixed histogram name.
-  // Note: The factory creates and owns the histogram.
-  base::HistogramBase* histogram = base::LinearHistogram::FactoryGet(
-      metric + kResult, 1, maximum, maximum + 1,
-      base::HistogramBase::kUmaTargetedHistogramFlag);
-  if (histogram) {
-    histogram->Add(value);
-  }
-
+  base::UmaHistogramExactLinear(metric + kResult, value, maximum);
   std::string suffix = GetUmaSuffixForStore(file_path);
-  base::HistogramBase* histogram_suffix = base::LinearHistogram::FactoryGet(
-      metric + kResult + suffix, 1, maximum, maximum + 1,
-      base::HistogramBase::kUmaTargetedHistogramFlag);
-  if (histogram_suffix) {
-    histogram_suffix->Add(value);
-  }
+  base::UmaHistogramExactLinear(metric + kResult + suffix, value, maximum);
 }
 
 void RecordBooleanWithAndWithoutSuffix(const std::string& metric,
                                        bool value,
                                        const base::FilePath& file_path) {
-  // The histograms below are an expansion of the UMA_HISTOGRAM_BOOLEAN
-  // macro adapted to allow for a dynamically suffixed histogram name.
-  // Note: The factory creates and owns the histogram.
-  base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet(
-      metric, base::HistogramBase::kUmaTargetedHistogramFlag);
-  if (histogram) {
-    histogram->Add(value);
-  }
-
+  base::UmaHistogramBoolean(metric, value);
   std::string suffix = GetUmaSuffixForStore(file_path);
-  base::HistogramBase* histogram_suffix = base::BooleanHistogram::FactoryGet(
-      metric + suffix, base::HistogramBase::kUmaTargetedHistogramFlag);
-  if (histogram_suffix) {
-    histogram_suffix->Add(value);
-  }
+  base::UmaHistogramBoolean(metric + suffix, value);
 }
 
 void RecordCountWithAndWithoutSuffix(const std::string& metric,
@@ -841,14 +815,8 @@
 
 int64_t V4Store::RecordAndReturnFileSize(const std::string& base_metric) {
   std::string suffix = GetUmaSuffixForStore(store_path_);
-  // Histogram properties as in UMA_HISTOGRAM_COUNTS_1M macro.
-  base::HistogramBase* histogram = base::Histogram::FactoryGet(
-      base_metric + suffix, 1, 1000000, 50,
-      base::HistogramBase::kUmaTargetedHistogramFlag);
-  if (histogram) {
-    const int64_t file_size_kilobytes = file_size_ / 1024;
-    histogram->Add(file_size_kilobytes);
-  }
+  const int64_t file_size_kilobytes = file_size_ / 1024;
+  base::UmaHistogramCounts1M(base_metric + suffix, file_size_kilobytes);
   return file_size_;
 }
 
diff --git a/components/safe_browsing/core/features.cc b/components/safe_browsing/core/features.cc
index 7deb24e..cd7147b10 100644
--- a/components/safe_browsing/core/features.cc
+++ b/components/safe_browsing/core/features.cc
@@ -69,6 +69,10 @@
     "SafeBrowsingRealTimeUrlLookupEnabledForAllAndroidDevices",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kRealTimeUrlLookupEnabledForEnterprise{
+    "SafeBrowsingRealTimeUrlLookupEnabledForEnterprise",
+    base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kRealTimeUrlLookupEnabledForEP{
     "SafeBrowsingRealTimeUrlLookupEnabledForEP",
     base::FEATURE_ENABLED_BY_DEFAULT};
@@ -131,6 +135,7 @@
     {&kRealTimeUrlLookupEnabled, true},
     {&kRealTimeUrlLookupEnabledForAllAndroidDevices, true},
     {&kRealTimeUrlLookupEnabledForEP, true},
+    {&kRealTimeUrlLookupEnabledForEnterprise, true},
     {&kRealTimeUrlLookupEnabledForEPWithToken, true},
     {&kRealTimeUrlLookupEnabledWithToken, true},
     {&kRealTimeUrlLookupNonMainframeEnabledForEP, true},
diff --git a/components/safe_browsing/core/features.h b/components/safe_browsing/core/features.h
index 805ab14..25c4959 100644
--- a/components/safe_browsing/core/features.h
+++ b/components/safe_browsing/core/features.h
@@ -84,6 +84,12 @@
 // This flag is in effect only if |kRealTimeUrlLookupEnabled| is true.
 extern const base::Feature kRealTimeUrlLookupEnabledForAllAndroidDevices;
 
+// Controls whether to do real time URL lookup for enterprise users. If both
+// this feature and the enterprise policies are enabled, the enterprise real
+// time URL lookup will be enabled and the consumer real time URL lookup will be
+// disabled.
+extern const base::Feature kRealTimeUrlLookupEnabledForEnterprise;
+
 // Controls whether the real time URL lookup is enabled for Enhanced Protection
 // users.
 extern const base::Feature kRealTimeUrlLookupEnabledForEP;
diff --git a/components/safe_browsing/core/realtime/policy_engine.cc b/components/safe_browsing/core/realtime/policy_engine.cc
index 3c8ac527..1b5e90c 100644
--- a/components/safe_browsing/core/realtime/policy_engine.cc
+++ b/components/safe_browsing/core/realtime/policy_engine.cc
@@ -158,6 +158,26 @@
 }
 
 // static
+bool RealTimePolicyEngine::CanPerformEnterpriseFullURLLookup(
+    bool has_valid_dm_token,
+    bool is_off_the_record) {
+  if (is_off_the_record) {
+    return false;
+  }
+
+  if (!base::FeatureList::IsEnabled(kRealTimeUrlLookupEnabledForEnterprise)) {
+    return false;
+  }
+
+  if (!has_valid_dm_token) {
+    return false;
+  }
+
+  // TODO(crbug.com/1085261): Check the enterprise real time URL check policy.
+  return false;
+}
+
+// static
 bool RealTimePolicyEngine::CanPerformFullURLLookupForResourceType(
     ResourceType resource_type,
     bool can_rt_check_subresource_url) {
diff --git a/components/safe_browsing/core/realtime/policy_engine.h b/components/safe_browsing/core/realtime/policy_engine.h
index 5b436d66..f615043 100644
--- a/components/safe_browsing/core/realtime/policy_engine.h
+++ b/components/safe_browsing/core/realtime/policy_engine.h
@@ -69,6 +69,9 @@
       signin::IdentityManager* identity_manager,
       variations::VariationsService* variations_service);
 
+  static bool CanPerformEnterpriseFullURLLookup(bool has_valid_dm_token,
+                                                bool is_off_the_record);
+
   friend class SafeBrowsingService;
   friend class SafeBrowsingUIHandler;
 
diff --git a/components/safe_browsing/core/realtime/policy_engine_unittest.cc b/components/safe_browsing/core/realtime/policy_engine_unittest.cc
index 7793dc5..c4cd89d 100644
--- a/components/safe_browsing/core/realtime/policy_engine_unittest.cc
+++ b/components/safe_browsing/core/realtime/policy_engine_unittest.cc
@@ -53,6 +53,12 @@
         /*variations_service=*/nullptr);
   }
 
+  bool CanPerformEnterpriseFullURLLookup(bool has_valid_dm_token,
+                                         bool is_off_the_record) {
+    return RealTimePolicyEngine::CanPerformEnterpriseFullURLLookup(
+        has_valid_dm_token, is_off_the_record);
+  }
+
   bool IsInExcludedCountry(const std::string& country_code) {
     return RealTimePolicyEngine::IsInExcludedCountry(country_code);
   }
@@ -328,6 +334,30 @@
       /*is_off_the_record=*/false, &sync_service, identity_manager));
 }
 
+TEST_F(RealTimePolicyEngineTest, TestCanPerformEnterpriseFullURLLookup) {
+  // Is off the record profile.
+  {
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndEnableFeature(kRealTimeUrlLookupEnabledForEnterprise);
+    EXPECT_FALSE(CanPerformEnterpriseFullURLLookup(/*has_valid_dm_token=*/true,
+                                                   /*is_off_the_record=*/true));
+  }
+  // Feature flag disabled.
+  {
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndDisableFeature(kRealTimeUrlLookupEnabledForEnterprise);
+    EXPECT_FALSE(CanPerformEnterpriseFullURLLookup(
+        /*has_valid_dm_token=*/true, /*is_off_the_record=*/false));
+  }
+  // No valid DM token.
+  {
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndEnableFeature(kRealTimeUrlLookupEnabledForEnterprise);
+    EXPECT_FALSE(CanPerformEnterpriseFullURLLookup(
+        /*has_valid_dm_token=*/false, /*is_off_the_record=*/false));
+  }
+}
+
 TEST_F(
     RealTimePolicyEngineTest,
     TestCanPerformFullURLLookup_EnabledMainFrameOnlyForSubresourceDisabledUser) {
diff --git a/components/signin/core/browser/android/BUILD.gn b/components/signin/core/browser/android/BUILD.gn
index 30f2dbc..51351ed 100644
--- a/components/signin/core/browser/android/BUILD.gn
+++ b/components/signin/core/browser/android/BUILD.gn
@@ -26,6 +26,7 @@
   ]
 
   sources = [
+    "java/src/org/chromium/components/signin/AccessTokenData.java",
     "java/src/org/chromium/components/signin/AccountManagerDelegate.java",
     "java/src/org/chromium/components/signin/AccountManagerDelegateException.java",
     "java/src/org/chromium/components/signin/AccountManagerFacade.java",
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccessTokenData.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccessTokenData.java
new file mode 100644
index 0000000..19435f4e
--- /dev/null
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccessTokenData.java
@@ -0,0 +1,54 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.components.signin;
+
+/**
+ * AccessTokenData encapsulates result of getToken method call from GoogleAuthUtil. It is a
+ * holder that contains the access token and its expiration time.
+ */
+public class AccessTokenData {
+    /**
+     * The expiration time value when there's no known expiration time for the token.
+     */
+    public static final long NO_KNOWN_EXPIRATION_TIME = 0;
+
+    private final String mToken;
+    private final long mExpirationTimeSecs;
+
+    /**
+     * Construct an access token data with its value and its expiration time in seconds.
+     * @param token the value of the access token.
+     * @param expirationTimeSecs the number of seconds (NOT milliseconds) after the Unix epoch when
+     *         the token is scheduled to expire. It is set to 0 if there's no known expiration time.
+     */
+    public AccessTokenData(String token, long expirationTimeSecs) {
+        assert token != null;
+        this.mToken = token;
+        this.mExpirationTimeSecs = expirationTimeSecs;
+    }
+
+    /**
+     * Constructor for when there's no known expiration time, set the expiration time to 0.
+     * @param token the string value of the access token.
+     */
+    public AccessTokenData(String token) {
+        this(token, NO_KNOWN_EXPIRATION_TIME);
+    }
+
+    /**
+     * Returns the value of the access token.
+     */
+    public String getToken() {
+        return this.mToken;
+    }
+
+    /**
+     * Returns the number of seconds (NOT milliseconds) after the Unix epoch when the token is
+     * scheduled to expire. Returns 0 if there's no known expiration time.
+     */
+    public long getExpirationTimeSecs() {
+        return this.mExpirationTimeSecs;
+    }
+}
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
index 3e4f343b..4bfadef 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerDelegate.java
@@ -53,13 +53,13 @@
      *
      * @param account The {@link Account} for which the auth token is requested.
      * @param authTokenScope The scope of the authToken being requested.
-     * @return The auth token fetched from the authenticator.
+     * @return The access token data fetched from the authenticator.
      * @throws AuthException Indicates a failure in fetching the auth token perhaps due to a
      * transient error or when user intervention is required (like confirming the credentials)
      * which is expressed as an {@link Intent} to the handler.
      */
     @WorkerThread
-    String getAuthToken(Account account, String authTokenScope) throws AuthException;
+    AccessTokenData getAuthToken(Account account, String authTokenScope) throws AuthException;
 
     /**
      * @param authToken The auth token to invalidate.
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
index 067b440c..afcaf9a 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java
@@ -104,10 +104,10 @@
      * {@link #invalidateAccessToken} to invalidate a token in the cache.
      * @param account The {@link Account} for which the token is requested.
      * @param scope OAuth2 scope for which the requested token should be valid.
-     * @return The OAuth2 access token as a string.
+     * @return The OAuth2 access token as an AccessTokenData with a string and an expiration time.
      */
     @WorkerThread
-    String getAccessToken(Account account, String scope) throws AuthException;
+    AccessTokenData getAccessToken(Account account, String scope) throws AuthException;
 
     /**
      * Synchronously clears an OAuth2 access token from the cache. Use {@link #getAccessToken}
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java
index f0b0dda6..c619d13 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeImpl.java
@@ -196,10 +196,10 @@
      * {@link #invalidateAccessToken} to invalidate a token in the cache.
      * @param account The {@link Account} for which the token is requested.
      * @param scope OAuth2 scope for which the requested token should be valid.
-     * @return The OAuth2 access token as a string.
+     * @return The OAuth2 access token as an AccessTokenData with a string and an expiration time..
      */
     @Override
-    public String getAccessToken(Account account, String scope) throws AuthException {
+    public AccessTokenData getAccessToken(Account account, String scope) throws AuthException {
         assert account != null;
         assert scope != null;
         // TODO(bsazonov): Rename delegate's getAuthToken to getAccessToken.
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
index 4fb1f3d8..5788782b 100644
--- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
+++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/SystemAccountManagerDelegate.java
@@ -134,12 +134,13 @@
     }
 
     @Override
-    public String getAuthToken(Account account, String authTokenScope) throws AuthException {
+    public AccessTokenData getAuthToken(Account account, String authTokenScope)
+            throws AuthException {
         assert !ThreadUtils.runningOnUiThread();
         assert AccountUtils.GOOGLE_ACCOUNT_TYPE.equals(account.type);
         try {
-            return GoogleAuthUtil.getTokenWithNotification(
-                    ContextUtils.getApplicationContext(), account, authTokenScope, null);
+            return new AccessTokenData(GoogleAuthUtil.getTokenWithNotification(
+                    ContextUtils.getApplicationContext(), account, authTokenScope, null));
         } catch (GoogleAuthException ex) {
             // This case includes a UserRecoverableNotifiedException, but most clients will have
             // their own retry mechanism anyway.
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java
index 305aaf1..387b8a4 100644
--- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java
+++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java
@@ -7,6 +7,9 @@
 import android.accounts.Account;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import org.chromium.components.signin.AccessTokenData;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -46,8 +49,9 @@
         return mAuthTokens.containsKey(authTokenType);
     }
 
-    public String getAuthToken(String authTokenType) {
-        return mAuthTokens.get(authTokenType);
+    public @Nullable AccessTokenData getAuthToken(String authTokenType) {
+        String authTokenString = mAuthTokens.get(authTokenType);
+        return authTokenString == null ? null : new AccessTokenData(authTokenString);
     }
 
     public boolean hasBeenAccepted(String authTokenType) {
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
index 0e0739d..979eded 100644
--- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
+++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerDelegate.java
@@ -18,6 +18,7 @@
 import org.chromium.base.Log;
 import org.chromium.base.ObserverList;
 import org.chromium.base.ThreadUtils;
+import org.chromium.components.signin.AccessTokenData;
 import org.chromium.components.signin.AccountManagerDelegate;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
@@ -220,7 +221,8 @@
     }
 
     @Override
-    public String getAuthToken(Account account, String authTokenScope) throws AuthException {
+    public AccessTokenData getAuthToken(Account account, String authTokenScope)
+            throws AuthException {
         AccountHolder ah = tryGetAccountHolder(account);
         if (ah == null) {
             throw new AuthException(AuthException.NONTRANSIENT,
diff --git a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java
index 2d5571e..d64fc8bf 100644
--- a/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java
+++ b/components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/FakeAccountManagerFacade.java
@@ -13,6 +13,7 @@
 
 import org.chromium.base.Callback;
 import org.chromium.base.ThreadUtils;
+import org.chromium.components.signin.AccessTokenData;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountManagerResult;
 import org.chromium.components.signin.AccountsChangeObserver;
@@ -22,6 +23,7 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.UUID;
 
 /**
  * FakeAccountManagerFacade is an {@link AccountManagerFacade} stub intended
@@ -33,9 +35,6 @@
     @GuardedBy("mLock")
     private final Set<AccountHolder> mAccountHolders = new LinkedHashSet<>();
 
-    @GuardedBy("mLock")
-    private boolean mIsCachePopulated = true;
-
     private final @Nullable FakeProfileDataSource mFakeProfileDataSource;
 
     /**
@@ -62,13 +61,13 @@
     public void removeObserver(AccountsChangeObserver observer) {}
 
     @Override
-    public void runAfterCacheIsPopulated(Runnable runnable) {}
+    public void runAfterCacheIsPopulated(Runnable runnable) {
+        runnable.run();
+    }
 
     @Override
     public boolean isCachePopulated() {
-        synchronized (mLock) {
-            return mIsCachePopulated;
-        }
+        return true;
     }
 
     @Override
@@ -91,12 +90,26 @@
     }
 
     @Override
-    public String getAccessToken(Account account, String scope) {
-        return "";
+    public AccessTokenData getAccessToken(Account account, String scope) {
+        synchronized (mLock) {
+            AccountHolder accountHolder = getAccountHolder(account);
+            if (accountHolder.getAuthToken(scope) == null) {
+                accountHolder.withAuthToken(scope, UUID.randomUUID().toString());
+            }
+            return accountHolder.getAuthToken(scope);
+        }
     }
 
     @Override
-    public void invalidateAccessToken(String accessToken) {}
+    public void invalidateAccessToken(String accessToken) {
+        synchronized (mLock) {
+            for (AccountHolder accountHolder : mAccountHolders) {
+                if (accountHolder.removeAuthToken(accessToken)) {
+                    break;
+                }
+            }
+        }
+    }
 
     @Override
     public void checkChildAccountStatus(Account account, Callback<Integer> callback) {}
@@ -119,15 +132,6 @@
     }
 
     /**
-     * Sets the boolean for whether the account cache has already been populated.
-     */
-    public void setIsCachePopulated(boolean isCachePopulated) {
-        synchronized (mLock) {
-            mIsCachePopulated = isCachePopulated;
-        }
-    }
-
-    /**
      * Adds an account to the fake AccountManagerFacade.
      */
     public void addAccount(Account account) {
@@ -148,4 +152,14 @@
         ThreadUtils.runOnUiThreadBlocking(
                 () -> mFakeProfileDataSource.setProfileData(accountId, profileData));
     }
+
+    @GuardedBy("mLock")
+    private AccountHolder getAccountHolder(Account account) {
+        for (AccountHolder accountHolder : mAccountHolders) {
+            if (accountHolder.getAccount().equals(account)) {
+                return accountHolder;
+            }
+        }
+        throw new IllegalArgumentException("Cannot find account:" + account);
+    }
 }
diff --git a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
index 4e8dff2c..f7c4831b 100644
--- a/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
+++ b/components/signin/internal/identity_manager/profile_oauth2_token_service_delegate_android.cc
@@ -509,11 +509,16 @@
 }
 
 namespace signin {
+
 // Called from Java when fetching of an OAuth2 token is finished. The
 // |authToken| param is only valid when |result| is true.
+// |expiration_time_secs| param is the number of seconds (NOT milliseconds)
+// after the Unix epoch when the token is scheduled to expire.
+// It is set to 0 if there's no known expiration time.
 void JNI_ProfileOAuth2TokenServiceDelegate_OnOAuth2TokenFetched(
     JNIEnv* env,
     const JavaParamRef<jstring>& authToken,
+    const jlong expiration_time_secs,
     jboolean isTransientError,
     jlong nativeCallback) {
   std::string token;
@@ -530,6 +535,12 @@
                   GoogleServiceAuthError::InvalidGaiaCredentialsReason::
                       CREDENTIALS_REJECTED_BY_SERVER);
   }
-  std::move(*heap_callback).Run(err, token, base::Time());
+
+  const base::Time expiration_time =
+      expiration_time_secs == 0
+          ? base::Time()
+          : base::Time::FromJavaTime(expiration_time_secs * 1000);
+
+  std::move(*heap_callback).Run(err, token, expiration_time);
 }
 }  // namespace signin
diff --git a/components/signin/public/android/DEPS b/components/signin/public/android/DEPS
index 735a6e7..d9513d7 100644
--- a/components/signin/public/android/DEPS
+++ b/components/signin/public/android/DEPS
@@ -11,11 +11,13 @@
     "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountUtils.java",
     "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AuthException.java",
     "+components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java",
+    "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccessTokenData.java",
   ],
   "ProfileOAuth2TokenServiceDelegateTest.java": [
     "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacade.java",
     "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccountManagerFacadeProvider.java",
     "+components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountHolder.java",
     "+components/signin/core/browser/android/javatests/src/org/chromium/components/signin/test/util/AccountManagerTestRule.java",
+    "+components/signin/core/browser/android/java/src/org/chromium/components/signin/AccessTokenData.java",
   ],
 }
diff --git a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java
index 0c73929..a65d67b6 100644
--- a/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java
+++ b/components/signin/public/android/java/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegate.java
@@ -17,6 +17,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.task.AsyncTask;
+import org.chromium.components.signin.AccessTokenData;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountTrackerService;
 import org.chromium.components.signin.AccountUtils;
@@ -48,7 +49,7 @@
          *
          * @param token Access token, guaranteed not to be null.
          */
-        void onGetTokenSuccess(String token);
+        void onGetTokenSuccess(AccessTokenData token);
 
         /**
          * Invoked on the UI thread if no token is available.
@@ -140,22 +141,22 @@
         if (account == null) {
             ThreadUtils.postOnUiThread(() -> {
                 ProfileOAuth2TokenServiceDelegateJni.get().onOAuth2TokenFetched(
-                        null, false, nativeCallback);
+                        null, AccessTokenData.NO_KNOWN_EXPIRATION_TIME, false, nativeCallback);
             });
             return;
         }
         String oauth2Scope = OAUTH2_SCOPE_PREFIX + scope;
         getAccessToken(account, oauth2Scope, new GetAccessTokenCallback() {
             @Override
-            public void onGetTokenSuccess(String token) {
+            public void onGetTokenSuccess(AccessTokenData token) {
                 ProfileOAuth2TokenServiceDelegateJni.get().onOAuth2TokenFetched(
-                        token, false, nativeCallback);
+                        token.getToken(), token.getExpirationTimeSecs(), false, nativeCallback);
             }
 
             @Override
             public void onGetTokenFailure(boolean isTransientError) {
-                ProfileOAuth2TokenServiceDelegateJni.get().onOAuth2TokenFetched(
-                        null, isTransientError, nativeCallback);
+                ProfileOAuth2TokenServiceDelegateJni.get().onOAuth2TokenFetched(null,
+                        AccessTokenData.NO_KNOWN_EXPIRATION_TIME, isTransientError, nativeCallback);
             }
         });
     }
@@ -188,13 +189,13 @@
     @Deprecated
     static void getAccessTokenWithFacade(AccountManagerFacade accountManagerFacade, Account account,
             String scope, GetAccessTokenCallback callback) {
-        ConnectionRetry.runAuthTask(new AuthTask<String>() {
+        ConnectionRetry.runAuthTask(new AuthTask<AccessTokenData>() {
             @Override
-            public String run() throws AuthException {
+            public AccessTokenData run() throws AuthException {
                 return accountManagerFacade.getAccessToken(account, scope);
             }
             @Override
-            public void onSuccess(String token) {
+            public void onSuccess(AccessTokenData token) {
                 callback.onGetTokenSuccess(token);
             }
             @Override
@@ -244,16 +245,16 @@
     static void getNewAccessTokenWithFacade(AccountManagerFacade accountManagerFacade,
             Account account, @Nullable String oldToken, String scope,
             GetAccessTokenCallback callback) {
-        ConnectionRetry.runAuthTask(new AuthTask<String>() {
+        ConnectionRetry.runAuthTask(new AuthTask<AccessTokenData>() {
             @Override
-            public String run() throws AuthException {
+            public AccessTokenData run() throws AuthException {
                 if (!TextUtils.isEmpty(oldToken)) {
                     accountManagerFacade.invalidateAccessToken(oldToken);
                 }
                 return accountManagerFacade.getAccessToken(account, scope);
             }
             @Override
-            public void onSuccess(String token) {
+            public void onSuccess(AccessTokenData token) {
                 callback.onGetTokenSuccess(token);
             }
             @Override
@@ -394,7 +395,18 @@
 
     @NativeMethods
     interface Natives {
-        void onOAuth2TokenFetched(String authToken, boolean isTransientError, long nativeCallback);
+        /**
+         * Called to C++ when fetching of an OAuth2 token is finished.
+         * @param authToken The string value of the OAuth2 token.
+         * @param expirationTimeSecs The number of seconds after the Unix epoch when the token is
+         *         scheduled to expire. It is set to 0 if there's no known expiration time.
+         * @param isTransientError Indicates if the error is transient (network timeout or
+         *          * unavailable, etc) or persistent (bad credentials, permission denied, etc).
+         * @param nativeCallback the pointer to the native callback that should be run upon
+         *         completion.
+         */
+        void onOAuth2TokenFetched(String authToken, long expirationTimeSecs,
+                boolean isTransientError, long nativeCallback);
         void reloadAllAccountsWithPrimaryAccountAfterSeeding(
                 long nativeProfileOAuth2TokenServiceDelegateAndroid, @Nullable String accountId);
     }
diff --git a/components/signin/public/android/javatests/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java b/components/signin/public/android/javatests/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java
index 4b200a9..5a3292b 100644
--- a/components/signin/public/android/javatests/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java
+++ b/components/signin/public/android/javatests/src/org/chromium/components/signin/identitymanager/ProfileOAuth2TokenServiceDelegateTest.java
@@ -19,6 +19,7 @@
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.AdvancedMockContext;
 import org.chromium.base.test.util.Feature;
+import org.chromium.components.signin.AccessTokenData;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.test.util.AccountHolder;
@@ -59,8 +60,8 @@
         }
 
         @Override
-        public void onGetTokenSuccess(String token) {
-            mToken = token;
+        public void onGetTokenSuccess(AccessTokenData token) {
+            mToken = token.getToken();
             mTokenRetrievedCountDown.countDown();
         }
 
diff --git a/components/sync/driver/data_type_manager.cc b/components/sync/driver/data_type_manager.cc
index daafef2..d89a697 100644
--- a/components/sync/driver/data_type_manager.cc
+++ b/components/sync/driver/data_type_manager.cc
@@ -24,8 +24,6 @@
       return "Ok";
     case ABORTED:
       return "Aborted";
-    case UNRECOVERABLE_ERROR:
-      return "Unrecoverable Error";
     case UNKNOWN:
       NOTREACHED();
       return std::string();
diff --git a/components/sync/driver/data_type_manager.h b/components/sync/driver/data_type_manager.h
index 372fb2b5..8af7c7f2 100644
--- a/components/sync/driver/data_type_manager.h
+++ b/components/sync/driver/data_type_manager.h
@@ -40,7 +40,6 @@
     OK,                  // Configuration finished some or all types.
     ABORTED,             // Start was aborted by calling Stop() before
                          // all types were started.
-    UNRECOVERABLE_ERROR  // We got an unrecoverable error during startup.
   };
 
   // Note: |errors| is only filled when status is not OK.
diff --git a/components/sync/driver/data_type_manager_impl.cc b/components/sync/driver/data_type_manager_impl.cc
index cbe7d0b3..0e4bb62 100644
--- a/components/sync/driver/data_type_manager_impl.cc
+++ b/components/sync/driver/data_type_manager_impl.cc
@@ -777,7 +777,7 @@
     return;
   }
 
-  if (result.status == ABORTED || result.status == UNRECOVERABLE_ERROR) {
+  if (result.status == ABORTED) {
     Abort(result.status);
     return;
   }
@@ -879,11 +879,6 @@
       DVLOG(1) << "NotifyDone called with result: ABORTED";
       base::UmaHistogramLongTimes(prefix_uma + ".ABORTED", configure_time);
       break;
-    case DataTypeManager::UNRECOVERABLE_ERROR:
-      DVLOG(1) << "NotifyDone called with result: UNRECOVERABLE_ERROR";
-      base::UmaHistogramLongTimes(prefix_uma + ".UNRECOVERABLE_ERROR",
-                                  configure_time);
-      break;
     case DataTypeManager::UNKNOWN:
       NOTREACHED();
       break;
diff --git a/components/sync/driver/profile_sync_service.cc b/components/sync/driver/profile_sync_service.cc
index 8ac9f24b..c9c44cb 100644
--- a/components/sync/driver/profile_sync_service.cc
+++ b/components/sync/driver/profile_sync_service.cc
@@ -114,8 +114,6 @@
   base::UmaHistogramEnumeration("Sync.InitialState", sync_state);
 }
 
-constexpr char kSyncUnrecoverableErrorHistogram[] = "Sync.UnrecoverableErrors";
-
 EngineComponentsFactory::Switches EngineSwitchesFromCommandLine() {
   EngineComponentsFactory::Switches factory_switches = {
       EngineComponentsFactory::ENCRYPTION_KEYSTORE,
@@ -921,8 +919,6 @@
   unrecoverable_error_message_ = message;
   unrecoverable_error_location_ = from_here;
 
-  UMA_HISTOGRAM_ENUMERATION(kSyncUnrecoverableErrorHistogram,
-                            unrecoverable_error_reason_, ERROR_REASON_LIMIT);
   LOG(ERROR) << "Unrecoverable error detected at " << from_here.ToString()
              << " -- ProfileSyncService unusable: " << message;
 
diff --git a/components/sync_preferences/pref_service_syncable.cc b/components/sync_preferences/pref_service_syncable.cc
index a9a1121..8685a265 100644
--- a/components/sync_preferences/pref_service_syncable.cc
+++ b/components/sync_preferences/pref_service_syncable.cc
@@ -10,7 +10,6 @@
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/strings/string_number_conversions.h"
-#include "base/value_conversions.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/default_pref_store.h"
 #include "components/prefs/in_memory_pref_store.h"
diff --git a/components/user_manager/BUILD.gn b/components/user_manager/BUILD.gn
index c4b12fd..66e1c5e3 100644
--- a/components/user_manager/BUILD.gn
+++ b/components/user_manager/BUILD.gn
@@ -16,6 +16,7 @@
 
   public_deps = [
     "//base",
+    "//base/util/values:values_util",
     "//components/account_id",
     "//ui/gfx",
   ]
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc
index a76a295..c07bfe8 100644
--- a/components/user_manager/known_user.cc
+++ b/components/user_manager/known_user.cc
@@ -12,7 +12,7 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/time/time.h"
-#include "base/value_conversions.h"
+#include "base/util/values/values_util.h"
 #include "base/values.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/scoped_user_pref_update.h"
@@ -625,33 +625,32 @@
 }
 
 void SetLastOnlineSignin(const AccountId& account_id, base::Time time) {
-  SetPref(account_id, kLastOnlineSignin, base::CreateTimeValue(time));
+  SetPref(account_id, kLastOnlineSignin, util::TimeToValue(time));
 }
 
 base::Time GetLastOnlineSignin(const AccountId& account_id) {
   const base::Value* value = nullptr;
-  base::Time time = base::Time();
   if (!GetPref(account_id, kLastOnlineSignin, &value))
     return base::Time();
-  if (!base::GetValueAsTime(*value, &time))
+  base::Optional<base::Time> time = util::ValueToTime(value);
+  if (!time)
     return base::Time();
-  return time;
+  return *time;
 }
 
 void SetOfflineSigninLimit(const AccountId& account_id,
                            base::TimeDelta time_delta) {
-  SetPref(account_id, kOfflineSigninLimit,
-          base::CreateTimeDeltaValue(time_delta));
+  SetPref(account_id, kOfflineSigninLimit, util::TimeDeltaToValue(time_delta));
 }
 
 base::TimeDelta GetOfflineSigninLimit(const AccountId& account_id) {
   const base::Value* value = nullptr;
-  base::TimeDelta time_delta = base::TimeDelta();
   if (!GetPref(account_id, kOfflineSigninLimit, &value))
     return base::TimeDelta();
-  if (!GetValueAsTimeDelta(*value, &time_delta))
+  base::Optional<base::TimeDelta> time_delta = util::ValueToTimeDelta(value);
+  if (!time_delta)
     return base::TimeDelta();
-  return time_delta;
+  return *time_delta;
 }
 
 void SetIsManaged(const AccountId& account_id, bool is_managed) {
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc
index 6d26c63..87de3ad53 100644
--- a/components/viz/service/display/surface_aggregator.cc
+++ b/components/viz/service/display/surface_aggregator.cc
@@ -118,39 +118,9 @@
   bool is_fast_rounded_corner;
 };
 
-struct SurfaceAggregator::ChildSurfaceInfo {
-  struct QuadStateInfo {
-    gfx::Transform transform_to_root_target;
-    gfx::Transform quad_to_target_transform;
-    gfx::Rect clip_rect;
-    bool is_clipped;
-  };
-
-  ChildSurfaceInfo(RenderPassId parent_pass_id,
-                   const gfx::Rect& quad_rect,
-                   bool stretch_content_to_fill_bounds)
-      : parent_pass_id(parent_pass_id),
-        quad_rect(quad_rect),
-        stretch_content_to_fill_bounds(stretch_content_to_fill_bounds) {
-    // In most cases there would be one or two different embeddings of a
-    // surface in the render pass tree. Reserve two elements to avoid
-    // unnecessary copies.
-    quad_state_infos.reserve(2);
-  }
-
-  RenderPassId parent_pass_id;
-  gfx::Rect quad_rect;
-  bool stretch_content_to_fill_bounds;
-  bool has_moved_pixels = false;
-  std::vector<QuadStateInfo> quad_state_infos;
-};
-
 struct SurfaceAggregator::RenderPassMapEntry {
-  RenderPassMapEntry(RenderPass* render_pass,
-                     bool has_pixel_moving_backdrop_filter)
-      : render_pass(render_pass),
-        damage_rect(render_pass->output_rect),
-        has_pixel_moving_backdrop_filter(has_pixel_moving_backdrop_filter) {}
+  explicit RenderPassMapEntry(RenderPass* render_pass)
+      : render_pass(render_pass) {}
 
   // Make this move-only.
   RenderPassMapEntry(RenderPassMapEntry&&) = default;
@@ -161,12 +131,8 @@
   RenderPass* render_pass;
   // Damage rect of the render pass in its own content space.
   gfx::Rect damage_rect;
-  bool has_pixel_moving_backdrop_filter;
 
   bool is_visited = false;
-  // If the render pass contains any surfaces in its quad list, either from
-  // SurfaceDrawQuads or from render passes referenced by RPDQs.
-  bool contains_surfaces = false;
 };
 
 SurfaceAggregator::SurfaceAggregator(SurfaceManager* manager,
@@ -198,18 +164,16 @@
   // This data is created once and typically small or empty. Collect all items
   // and pass to a flat_map to sort once.
   std::vector<std::pair<RenderPassId, RenderPassMapEntry>> render_pass_data;
+  render_pass_data.reserve(render_pass_list.size());
   for (const auto& render_pass : render_pass_list) {
-    bool has_pixel_moving_backdrop_filter =
-        render_pass->backdrop_filters.HasFilterThatMovesPixels();
-    if (has_pixel_moving_backdrop_filter) {
+    if (render_pass->backdrop_filters.HasFilterThatMovesPixels()) {
       DCHECK_NE(render_pass.get(), root_pass_in_root_surface)
           << "The root render pass on the root surface can not have backdrop "
              "affecting filters";
     }
-    render_pass_data.emplace_back(
-        std::piecewise_construct, std::forward_as_tuple(render_pass->id),
-        std::forward_as_tuple(render_pass.get(),
-                              has_pixel_moving_backdrop_filter));
+    render_pass_data.emplace_back(std::piecewise_construct,
+                                  std::forward_as_tuple(render_pass->id),
+                                  std::forward_as_tuple(render_pass.get()));
   }
   return base::flat_map<RenderPassId, RenderPassMapEntry>(
       std::move(render_pass_data));
@@ -1235,125 +1199,52 @@
   }
 }
 
-void SurfaceAggregator::FindChildSurfaces(
-    SurfaceId surface_id,
+gfx::Rect SurfaceAggregator::PrewalkRenderPass(
+    RenderPassId render_pass_id,
+    const Surface* surface,
     base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map,
-    RenderPassMapEntry* current_pass_entry,
+    bool will_draw,
     const gfx::Transform& transform_to_root_target,
-    base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces,
     std::vector<gfx::Rect>* pixel_moving_backdrop_filters_rects,
-    bool* has_backdrop_cache_flags_to_update) {
-  if (current_pass_entry->is_visited) {
-    // This means that this render pass is an ancestor of itself. This is not
-    // supported. Stop processing the render pass again.
-    return;
-  }
-  base::AutoReset<bool> reset_is_visited(&current_pass_entry->is_visited, true);
-  RenderPass* render_pass = current_pass_entry->render_pass;
-  if (current_pass_entry->has_pixel_moving_backdrop_filter) {
-    has_pixel_moving_backdrop_filter_ = true;
-    // If the render pass has a backdrop filter that moves pixels, its entire
-    // bounds, with proper transform applied, may be added to the damage
-    // rect if it intersects.
-    pixel_moving_backdrop_filters_rects->push_back(
-        cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target,
-                                              render_pass->output_rect));
-  }
-  RenderPassId remapped_pass_id = RemapPassId(render_pass->id, surface_id);
-  bool has_pixel_moving_filter =
-      render_pass->filters.HasFilterThatMovesPixels();
-  if (has_pixel_moving_filter)
-    moved_pixel_passes_.insert(remapped_pass_id);
-  bool in_moved_pixel_pass =
-      has_pixel_moving_filter ||
-      base::Contains(moved_pixel_passes_, remapped_pass_id);
-  for (auto* quad : render_pass->quad_list) {
-    if (quad->material == DrawQuad::Material::kSurfaceContent) {
-      // A child surface has been found. Add necessary info from this surface to
-      // the set of child surfaces that can be used to update damage rect for
-      // the parent surface. If this child surface has been visited previously,
-      // we only need to update |has_moved_pixels| and add the transform
-      // corresponding to this visit; rest of the info would remain the same.
-      const auto* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
-      auto it = child_surfaces->find(surface_quad->surface_range);
-      if (it == child_surfaces->end()) {
-        auto insert_pair = child_surfaces->emplace(
-            std::piecewise_construct,
-            std::forward_as_tuple(surface_quad->surface_range),
-            std::forward_as_tuple(
-                remapped_pass_id, surface_quad->rect,
-                surface_quad->stretch_content_to_fill_bounds));
-        DCHECK(insert_pair.second);
-        it = insert_pair.first;
-      }
-      auto& child_surface_info = it->second;
-      if (in_moved_pixel_pass)
-        child_surface_info.has_moved_pixels = true;
-      child_surface_info.quad_state_infos.push_back(
-          {transform_to_root_target,
-           surface_quad->shared_quad_state->quad_to_target_transform,
-           surface_quad->shared_quad_state->clip_rect,
-           surface_quad->shared_quad_state->is_clipped});
-      current_pass_entry->contains_surfaces = true;
-    } else if (quad->material == DrawQuad::Material::kRenderPass) {
-      // A child render pass has been found. Find its child surfaces
-      // recursively.
-      const auto* render_pass_quad = RenderPassDrawQuad::MaterialCast(quad);
-      *has_backdrop_cache_flags_to_update |=
-          render_pass_quad->can_use_backdrop_filter_cache;
-      RenderPassId child_pass_id = render_pass_quad->render_pass_id;
-      RenderPassId remapped_child_pass_id =
-          RemapPassId(child_pass_id, surface_id);
-      if (in_moved_pixel_pass)
-        moved_pixel_passes_.insert(remapped_child_pass_id);
-      auto child_pass_it = render_pass_map->find(child_pass_id);
-      DCHECK(child_pass_it != render_pass_map->end());
-      RenderPassMapEntry& child_pass_entry = child_pass_it->second;
-      // TODO(crbug/1011042): Here, we used to set |in_moved_pixel_pass| to true
-      // if the child render pass has a pixel-moving backdrop filter. This
-      // behavior was added in r687426 to fix another problem, but caused a huge
-      // performance issue in some cases that enabled background blur, by
-      // expanding the damage rect unnecessarily to the entire screen
-      // (crbug/1008740). This is removed now, but a proper fix for the
-      // pixel-moving backdrop filter should be implemented.
-      render_pass_dependencies_[remapped_pass_id].insert(
-          remapped_child_pass_id);
-      FindChildSurfaces(
-          surface_id, render_pass_map, &child_pass_entry,
-          gfx::Transform(
-              transform_to_root_target,
-              render_pass_quad->shared_quad_state->quad_to_target_transform),
-          child_surfaces, pixel_moving_backdrop_filters_rects,
-          has_backdrop_cache_flags_to_update);
-      current_pass_entry->contains_surfaces |=
-          child_pass_entry.contains_surfaces;
-    }
-  }
-}
-
-gfx::Rect
-SurfaceAggregator::UpdateRPDQCanUseBackdropFilterCacheWithSurfaceDamage(
-    RenderPassId id,
-    PrewalkResult* result,
-    base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map) {
-  auto render_pass_it = render_pass_map->find(id);
-  DCHECK(render_pass_it != render_pass_map->end());
-  RenderPassMapEntry& render_pass_entry = render_pass_it->second;
-
-  // If there's no surface embedded in the render pass, return an empty rect.
-  if (!render_pass_entry.contains_surfaces)
-    return gfx::Rect();
-
+    PrewalkResult* result) {
+  auto it = render_pass_map->find(render_pass_id);
+  DCHECK(it != render_pass_map->end());
+  RenderPassMapEntry& render_pass_entry = it->second;
   if (render_pass_entry.is_visited) {
     // This render pass is an ancestor of itself (not supported) or has been
     // processed.
     return render_pass_entry.damage_rect;
   }
   render_pass_entry.is_visited = true;
-
   const RenderPass& render_pass = *render_pass_entry.render_pass;
-  gfx::Rect damage_rect;
 
+  if (render_pass.backdrop_filters.HasFilterThatMovesPixels()) {
+    has_pixel_moving_backdrop_filter_ = true;
+    // If the render pass has a backdrop filter that moves pixels, its entire
+    // bounds, with proper transform applied, may be added to the damage
+    // rect if it intersects.
+    pixel_moving_backdrop_filters_rects->push_back(
+        cc::MathUtil::MapEnclosingClippedRect(transform_to_root_target,
+                                              render_pass.output_rect));
+  }
+
+  RenderPassId remapped_pass_id =
+      RemapPassId(render_pass.id, surface->surface_id());
+  // |moved_pixel_passes_| stores all the render passes affected by filters
+  // that move pixels, so |has_pixel_moving_filter| should be set to true either
+  // if the current render pass has pixel_moving_filter(s) or if it is inside an
+  // ancestor render pass that has pixel_moving_filter(s).
+  bool has_pixel_moving_filter = render_pass.filters.HasFilterThatMovesPixels();
+  if (has_pixel_moving_filter)
+    moved_pixel_passes_.insert(remapped_pass_id);
+  bool in_moved_pixel_pass =
+      has_pixel_moving_filter ||
+      base::Contains(moved_pixel_passes_, remapped_pass_id);
+
+  const CompositorFrame& frame = surface->GetActiveFrame();
+  gfx::Rect full_damage = frame.render_pass_list.back()->output_rect;
+
+  gfx::Rect damage_rect;
   // Iterate through the quad list back-to-front and accumulate damage from
   // all quads (only SurfaceDrawQuads and RenderPassDrawQuads can have damage
   // at this point). |damage_rect| has damage from all quads below the current
@@ -1362,36 +1253,50 @@
   for (QuadList::ConstReverseIterator it = render_pass.quad_list.rbegin();
        it != render_pass.quad_list.rend(); ++it) {
     const DrawQuad* quad = *it;
+    gfx::Rect quad_damage_rect;
     if (quad->material == DrawQuad::Material::kSurfaceContent) {
       const auto* surface_quad = SurfaceDrawQuad::MaterialCast(quad);
-      Surface* surface =
+      Surface* child_surface =
           manager_->GetLatestInFlightSurface(surface_quad->surface_range);
-      auto it = result->damage_on_surfaces.end();
-      if (surface)
-        it = result->damage_on_surfaces.find(surface->surface_id());
-      if (it != result->damage_on_surfaces.end()) {
-        gfx::Rect surface_damage_rect = it->second;
+      // If the primary surface is not available then we assume the damage is
+      // the full size of the SurfaceDrawQuad because we might need to introduce
+      // gutter.
+      if (!child_surface ||
+          child_surface->surface_id() != surface_quad->surface_range.end()) {
+        quad_damage_rect = quad->rect;
+      }
+
+      if (child_surface) {
+        gfx::Rect child_rect;
+        auto it = result->damage_on_surfaces.find(child_surface->surface_id());
+        if (it != result->damage_on_surfaces.end()) {
+          // the surface damage has been accummulated previously
+          child_rect = it->second;
+        } else {
+          // first encounter of the surface
+          child_rect = PrewalkSurface(child_surface, in_moved_pixel_pass,
+                                      remapped_pass_id, will_draw, result);
+        }
+
         if (surface_quad->stretch_content_to_fill_bounds) {
-          if (surface->size_in_pixels().GetCheckedArea().ValueOrDefault(0) >
-              0) {
+          if (!child_surface->size_in_pixels().IsEmpty()) {
             float y_scale = static_cast<float>(surface_quad->rect.height()) /
-                            surface->size_in_pixels().height();
+                            child_surface->size_in_pixels().height();
             float x_scale = static_cast<float>(surface_quad->rect.width()) /
-                            surface->size_in_pixels().width();
-            surface_damage_rect = gfx::ScaleToEnclosingRect(surface_damage_rect,
-                                                            x_scale, y_scale);
+                            child_surface->size_in_pixels().width();
+            child_rect =
+                gfx::ScaleToEnclosingRect(child_rect, x_scale, y_scale);
           }
         }
-        gfx::Rect rect_in_target_space = cc::MathUtil::MapEnclosingClippedRect(
-            quad->shared_quad_state->quad_to_target_transform,
-            surface_damage_rect);
-        damage_rect.Union(rect_in_target_space);
-      } else {
-        // The damage info was not found for the (probably invalid) surface,
-        // take the whole quad rect as damaged.
-        gfx::Rect rect_in_target_space = cc::MathUtil::MapEnclosingClippedRect(
-            quad->shared_quad_state->quad_to_target_transform, quad->rect);
-        damage_rect.Union(rect_in_target_space);
+        quad_damage_rect.Union(child_rect);
+      }
+
+      if (quad_damage_rect.IsEmpty())
+        continue;
+
+      if (in_moved_pixel_pass) {
+        damage_rect = full_damage;
+        continue;
       }
     } else if (quad->material == DrawQuad::Material::kRenderPass) {
       auto* render_pass_quad = RenderPassDrawQuad::MaterialCast(quad);
@@ -1406,28 +1311,42 @@
           render_pass_quad->can_use_backdrop_filter_cache = false;
       }
 
-      gfx::Rect render_pass_damage_rect =
-          UpdateRPDQCanUseBackdropFilterCacheWithSurfaceDamage(
-              render_pass_quad->render_pass_id, result, render_pass_map);
+      RenderPassId child_pass_id = render_pass_quad->render_pass_id;
+      RenderPassId remapped_child_pass_id =
+          RemapPassId(child_pass_id, surface->surface_id());
+      if (in_moved_pixel_pass)
+        moved_pixel_passes_.insert(remapped_child_pass_id);
 
-      gfx::Rect rect = cc::MathUtil::MapEnclosingClippedRect(
-          render_pass_quad->shared_quad_state->quad_to_target_transform,
-          render_pass_damage_rect);
-      damage_rect.Union(rect);
+      render_pass_dependencies_[remapped_pass_id].insert(
+          remapped_child_pass_id);
+      quad_damage_rect = PrewalkRenderPass(
+          child_pass_id, surface, render_pass_map, will_draw,
+          gfx::Transform(
+              transform_to_root_target,
+              render_pass_quad->shared_quad_state->quad_to_target_transform),
+          pixel_moving_backdrop_filters_rects, result);
+
+    } else {
+      continue;
     }
+    // Convert the quad damage rect into its target space and clip it
+    // if needed.
+    gfx::Rect rect_in_target_space = cc::MathUtil::MapEnclosingClippedRect(
+        quad->shared_quad_state->quad_to_target_transform, quad_damage_rect);
+    if (quad->shared_quad_state->is_clipped) {
+      rect_in_target_space.Intersect(quad->shared_quad_state->clip_rect);
+    }
+    damage_rect.Union(rect_in_target_space);
   }
   render_pass_entry.damage_rect = damage_rect;
   return damage_rect;
 }
 
-// Walk the Surface tree from surface_id. Validate the resources of the current
-// surface and its descendants, check if there are any copy requests, and
-// return the combined damage rect.
-gfx::Rect SurfaceAggregator::PrewalkTree(Surface* surface,
-                                         bool in_moved_pixel_surface,
-                                         int parent_pass_id,
-                                         bool will_draw,
-                                         PrewalkResult* result) {
+gfx::Rect SurfaceAggregator::PrewalkSurface(Surface* surface,
+                                            bool in_moved_pixel_surface,
+                                            int parent_pass_id,
+                                            bool will_draw,
+                                            PrewalkResult* result) {
   if (referenced_surfaces_.count(surface->surface_id()))
     return gfx::Rect();
 
@@ -1470,17 +1389,6 @@
   base::flat_map<RenderPassId, RenderPassMapEntry> render_pass_map =
       GenerateRenderPassMap(frame.render_pass_list, IsRootSurface(surface));
 
-  auto root_pass_it = render_pass_map.find(frame.render_pass_list.back()->id);
-  DCHECK(root_pass_it != render_pass_map.end());
-  RenderPassMapEntry& root_pass_entry = root_pass_it->second;
-  base::flat_map<SurfaceRange, ChildSurfaceInfo> child_surfaces;
-  std::vector<gfx::Rect> pixel_moving_backdrop_filters_rects;
-  bool has_backdrop_cache_flags_to_update = false;
-  FindChildSurfaces(surface->surface_id(), &render_pass_map, &root_pass_entry,
-                    root_pass_transform, &child_surfaces,
-                    &pixel_moving_backdrop_filters_rects,
-                    &has_backdrop_cache_flags_to_update);
-
   std::vector<ResourceId> referenced_resources;
   referenced_resources.reserve(frame.resource_list.size());
 
@@ -1518,82 +1426,12 @@
   // Avoid infinite recursion by adding current surface to
   // |referenced_surfaces_|.
   referenced_surfaces_.insert(surface->surface_id());
-  for (const auto& child_surface_info_pair : child_surfaces) {
-    auto& child_surface_range = child_surface_info_pair.first;
-    auto& child_surface_info = child_surface_info_pair.second;
-    // TODO(fsamuel): Consider caching this value somewhere so that
-    // HandleSurfaceQuad doesn't need to call it again.
-    Surface* child_surface =
-        manager_->GetLatestInFlightSurface(child_surface_range);
-
-    // If the primary surface is not available then we assume the damage is
-    // the full size of the SurfaceDrawQuad because we might need to introduce
-    // gutter.
-    gfx::Rect child_surface_damage;
-    if (!child_surface ||
-        child_surface->surface_id() != child_surface_range.end()) {
-      child_surface_damage = child_surface_info.quad_rect;
-    }
-
-    if (child_surface) {
-      if (child_surface_info.stretch_content_to_fill_bounds) {
-        // Scale up the damage_quad generated by the child_surface to fit
-        // the containing quad_rect.
-        gfx::Rect child_rect =
-            PrewalkTree(child_surface, child_surface_info.has_moved_pixels,
-                        child_surface_info.parent_pass_id, will_draw, result);
-        if (child_surface->size_in_pixels().GetCheckedArea().ValueOrDefault(0) >
-            0) {
-          float y_scale =
-              static_cast<float>(child_surface_info.quad_rect.height()) /
-              child_surface->size_in_pixels().height();
-          float x_scale =
-              static_cast<float>(child_surface_info.quad_rect.width()) /
-              child_surface->size_in_pixels().width();
-          child_surface_damage.Union(
-              gfx::ScaleToEnclosingRect(child_rect, x_scale, y_scale));
-        }
-      } else {
-        child_surface_damage.Union(
-            PrewalkTree(child_surface, child_surface_info.has_moved_pixels,
-                        child_surface_info.parent_pass_id, will_draw, result));
-      }
-    }
-
-    if (child_surface_damage.IsEmpty())
-      continue;
-
-    if (child_surface_info.has_moved_pixels) {
-      // Areas outside the rect hit by target_to_surface_transform may be
-      // modified if there is a filter that moves pixels.
-      damage_rect = full_damage;
-      continue;
-    }
-
-    // Add the child surface damage rect to the parent surface damage rect. The
-    // child surface damage rect is first transformed to the parent surface
-    // coordinate space. There would be multiple transforms for a child surface
-    // if it is embedded multiple times which means its damage rect should be
-    // added multiple times.
-    for (const auto& quad_state_info : child_surface_info.quad_state_infos) {
-      gfx::Transform target_to_surface_transform(
-          quad_state_info.transform_to_root_target,
-          quad_state_info.quad_to_target_transform);
-
-      gfx::Rect child_surface_damage_in_root_target_space =
-          cc::MathUtil::MapEnclosingClippedRect(target_to_surface_transform,
-                                                child_surface_damage);
-      if (quad_state_info.is_clipped) {
-        gfx::Rect clip_rect_in_root_target_space =
-            cc::MathUtil::MapEnclosingClippedRect(
-                quad_state_info.transform_to_root_target,
-                quad_state_info.clip_rect);
-        child_surface_damage_in_root_target_space.Intersect(
-            clip_rect_in_root_target_space);
-      }
-      damage_rect.Union(child_surface_damage_in_root_target_space);
-    }
-  }
+  std::vector<gfx::Rect> pixel_moving_backdrop_filters_rects;
+  const gfx::Rect surface_root_damage = PrewalkRenderPass(
+      frame.render_pass_list.back()->id, surface, &render_pass_map, will_draw,
+      root_pass_transform, &pixel_moving_backdrop_filters_rects, result);
+  damage_rect.Union(cc::MathUtil::MapEnclosedRectWith2dAxisAlignedTransform(
+      root_pass_transform, surface_root_damage));
 
   if (!damage_rect.IsEmpty()) {
     // The following call can cause one or more copy requests to be added to the
@@ -1635,7 +1473,7 @@
       result->undrawn_surfaces.insert(surface_id);
       Surface* undrawn_surface = manager_->GetSurfaceForId(surface_id);
       if (undrawn_surface)
-        PrewalkTree(undrawn_surface, false, 0, false /* will_draw */, result);
+        PrewalkSurface(undrawn_surface, false, 0, /*will_draw=*/false, result);
     }
   }
 
@@ -1673,11 +1511,6 @@
       std::forward_as_tuple(damage_rect));
   DCHECK(emplace_result.second);
 
-  if (has_backdrop_cache_flags_to_update) {
-    UpdateRPDQCanUseBackdropFilterCacheWithSurfaceDamage(
-        frame.render_pass_list.back()->id, result, &render_pass_map);
-  }
-
   return damage_rect;
 }
 
@@ -1812,12 +1645,13 @@
   DCHECK(referenced_surfaces_.empty());
   PrewalkResult prewalk_result;
   gfx::Rect surfaces_damage_rect =
-      PrewalkTree(surface, false, 0, true /* will_draw */, &prewalk_result);
+      PrewalkSurface(surface, false, 0, /*will_draw=*/true, &prewalk_result);
 
   root_damage_rect_ = surfaces_damage_rect;
   // |root_damage_rect_| is used to restrict aggregating quads only if they
   // intersect this area.
   root_damage_rect_.Union(target_damage);
+
   root_content_color_usage_ = prewalk_result.content_color_usage;
 
   if (prewalk_result.frame_sinks_changed)
diff --git a/components/viz/service/display/surface_aggregator.h b/components/viz/service/display/surface_aggregator.h
index bdc4db4..b8127141 100644
--- a/components/viz/service/display/surface_aggregator.h
+++ b/components/viz/service/display/surface_aggregator.h
@@ -186,61 +186,42 @@
       const gfx::Rect& occluding_damage_rect,
       bool occluding_damage_rect_valid);
 
-  // Helper function that uses backtracking on the render pass tree of a surface
-  // to find all surfaces embedded in it. If a surface is embedded multiple
-  // times (due to use of a MirrorLayer), it will be reachable via multiple
-  // paths from the root render pass. For each such a path the appropriate
-  // transform is calculated.
-  //  - |surface_id| specifies the surface to find all child surfaces of.
-  //  - |render_pass_map| is a pre-computed map from render pass id to some info
-  //    about the render pass, including the render pass itself and whether it
-  //    has pixel moving backdrop filter.
-  //  - |current_pass_entry| is the info about the current render pass to
-  //    process.
-  //  - |transform_to_root_target| is the accumulated transform of all render
-  //    passes along the way to the current render pass.
-  //  - |child_surfaces| is the main output of the function containing all child
-  //    surfaces found in the process.
-  //  - |pixel_moving_backdrop_filters_rect| is another output that is union of
-  //    bounds of render passes that have a pixel moving backdrop filter.
-  //  - |has_backdrop_cache_flags_to_update| indicates if any
-  //    RenderPassDrawQuad(s) contained in the surface have
-  //    |can_use_backdrop_filter_cache| flag set to true and having to be
-  //    updated. This is used to avoid iterating through all the render passes
-  //    in the surface frame when not needed (i.e. no flag needs to be
-  //    updated).
-  // TODO(mohsen): Consider refactoring this backtracking algorithm into a
-  // self-contained class.
-  void FindChildSurfaces(
-      SurfaceId surface_id,
-      base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map,
-      RenderPassMapEntry* current_pass_entry,
-      const gfx::Transform& transform_to_root_target,
-      base::flat_map<SurfaceRange, ChildSurfaceInfo>* child_surfaces,
-      std::vector<gfx::Rect>* pixel_moving_backdrop_filters_rects,
-      bool* has_backdrop_cache_flags_to_update);
-
-  // Recursively updates the |can_use_backdrop_filter_cache| flag on all
-  // RenderPassDrawQuads(RPDQ) in the specified render pass. The function
-  // recursively traverses any render pass referenced by a RPDQ but doesn't
-  // traverse any render passes in the frame of any embedded surfaces. The
-  // function returns the damage rect of the render pass in its own content
+  // Recursively walks through the render pass and updates the
+  // |can_use_backdrop_filter_cache| flag on all RenderPassDrawQuads(RPDQ).
+  // The function returns the damage rect of the render pass in its own content
   // space.
-  // - |id| specifies the render pass whose quads are to be updated
-  // - |result| is the result of a prewalk of a root surface that contains the
-  //   render pass
-  // - |render_pass_map| is a map that contains all render passes and their
-  // entry data
-  gfx::Rect UpdateRPDQCanUseBackdropFilterCacheWithSurfaceDamage(
-      RenderPassId id,
-      PrewalkResult* result,
-      base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map);
+  //  - |render_pass_id| specifies the id of the render pass.
+  //  - |surface| is the surface containing the render pass.
+  //  - |render_pass_map| is a map that contains all render passes and their
+  //    entry data.
+  //  - |will_draw| indicates that the surface can be aggregated into the final
+  //    frame and might be drawn (based on damage/occlusion/etc.) if it is set
+  //    to true. Or the surface isn't in the aggregated frame and is only
+  //    needed for CopyOutputRequests if set to false.
+  //  - |transform_to_root_target| is the accumulated transform of all render
+  //    passes in the containing surface along the way to the current render
+  //    pass.
+  //  - |pixel_moving_backdrop_filters_rects| is a vector of bounds of render
+  //    passes that have a pixel moving backdrop filter.
+  //  - |result| is the result of a prewalk of the surface that contains the
+  //    render pass.
+  gfx::Rect PrewalkRenderPass(
+      RenderPassId render_pass_id,
+      const Surface* surface,
+      base::flat_map<RenderPassId, RenderPassMapEntry>* render_pass_map,
+      bool will_draw,
+      const gfx::Transform& transform_to_root_target,
+      std::vector<gfx::Rect>* pixel_moving_backdrop_filters_rects,
+      PrewalkResult* result);
 
-  gfx::Rect PrewalkTree(Surface* surface,
-                        bool in_moved_pixel_surface,
-                        int parent_pass,
-                        bool will_draw,
-                        PrewalkResult* result);
+  // Walk the Surface tree from |surface|. Validate the resources of the
+  // current surface and its descendants, check if there are any copy requests,
+  // and return the combined damage rect.
+  gfx::Rect PrewalkSurface(Surface* surface,
+                           bool in_moved_pixel_surface,
+                           int parent_pass,
+                           bool will_draw,
+                           PrewalkResult* result);
   void CopyUndrawnSurfaces(PrewalkResult* prewalk);
   void CopyPasses(const CompositorFrame& frame, Surface* surface);
   void AddColorConversionPass();
diff --git a/components/viz/service/display/surface_aggregator_unittest.cc b/components/viz/service/display/surface_aggregator_unittest.cc
index 0f7dace..4302bc8 100644
--- a/components/viz/service/display/surface_aggregator_unittest.cc
+++ b/components/viz/service/display/surface_aggregator_unittest.cc
@@ -5961,7 +5961,9 @@
   std::vector<Quad> root_quads = {Quad::SurfaceQuad(
       SurfaceRange(primary_child_surface_id), SK_ColorWHITE, surface_quad_rect,
       /*stretch_content_to_fill_bounds=*/true)};
-  std::vector<Pass> root_passes = {Pass(root_quads, SurfaceSize())};
+
+  constexpr gfx::Size surface_size(60, 100);
+  std::vector<Pass> root_passes = {Pass(root_quads, surface_size)};
 
   MockAggregatedDamageCallback aggregated_damage_callback;
   root_sink_->SetAggregatedDamageCallbackForTesting(
@@ -5972,15 +5974,14 @@
   SubmitCompositorFrame(root_sink_.get(), root_passes, root_local_surface_id_,
                         0.5f);
 
-  EXPECT_CALL(
-      aggregated_damage_callback,
-      OnAggregatedDamage(root_local_surface_id_, SurfaceSize(),
-                         gfx::Rect(SurfaceSize()), next_display_time()));
+  EXPECT_CALL(aggregated_damage_callback,
+              OnAggregatedDamage(root_local_surface_id_, surface_size,
+                                 gfx::Rect(surface_size), next_display_time()));
 
-  gfx::Rect transformed_rect(SurfaceSize().height(), SurfaceSize().width());
   CompositorFrame frame =
       aggregator_.Aggregate(root_surface_id, GetNextDisplayTimeAndIncrement(),
                             gfx::OVERLAY_TRANSFORM_ROTATE_90);
+  gfx::Rect transformed_rect(surface_size.height(), surface_size.width());
   EXPECT_EQ(frame.render_pass_list.back()->output_rect, transformed_rect);
   EXPECT_EQ(frame.render_pass_list.back()->damage_rect, transformed_rect);
 }
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index cd47fd58..fede1ca 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -184,7 +184,7 @@
 }
 
 void CompositorFrameSinkSupport::OnSurfaceProcessed(Surface* surface) {
-  DidReceiveCompositorFrameAck(/*early_ack*/ false);
+  DidReceiveCompositorFrameAck();
 }
 
 void CompositorFrameSinkSupport::OnSurfaceAggregatedDamage(
@@ -556,37 +556,6 @@
       // Make sure we periodically check if the frame should activate.
       pending_surfaces_.insert(current_surface);
       UpdateNeedsBeginFramesInternal();
-#if defined(OS_ANDROID)
-      // Ack a pending surface early the client's scheduler to schedule frames
-      // for future surface changes This case happens when screen rotation takes
-      // place while there is an active frame when this takes place it has a
-      // unique signature of 2 consecutive submit frame requests with
-      // clients_needs_begin_frame_ is set (high) and 1st frame is not a new
-      // surface and 2nd frame is a new surface. For only this sequence send an
-      // early ack to the client by using OnSurfaceProcessed. Setting the
-      // early_ack during the call to denote that an early ACK took place. This
-      // prevents sending a second ack for the frame when it is activated. To
-      // ensure only this sequence is early acked, the
-      // last_pending_frame_was_new_surface_ flag is used to ensure the sequence
-      // is correct using current_surface == prev_surface => NOT new_surface ID,
-      // to limit the when the early ack is sent.
-      // In some cases the 2 frame comes and require early ack before the
-      // surface sync work is completed add counter early_acked_count_ to make
-      // sure right ack get cleared
-      if (client_needs_begin_frame_) {
-        if ((current_surface == prev_surface) ||
-            last_pending_frame_was_new_surface_) {
-          early_acked_count_++;
-          DidReceiveCompositorFrameAck(/*early_ack*/ true);
-          last_pending_frame_was_new_surface_ =
-              !last_pending_frame_was_new_surface_;
-        } else {
-          if (current_surface != prev_surface) {
-            last_pending_frame_was_new_surface_ = false;
-          }
-        }
-      }
-#endif
       break;
     case Surface::QueueFrameResult::ACCEPTED_ACTIVE:
       // Nothing to do here.
@@ -617,39 +586,22 @@
   surface_returned_resources_.clear();
 }
 
-void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck(bool early_ack) {
-  // Only do early ack on frame that don't have callback
-  if (early_ack) {
-    DCHECK_GT(early_acked_count_, 0);
-    if (!client_ || compositor_frame_callback_)
-      return;
-    // early Ack client
-    client_->DidReceiveCompositorFrameAck(surface_returned_resources_);
-    // don't clear resources_ as it is still been used by surface_manager
-  } else {  // actual ack
-    DCHECK_GT(ack_pending_count_, 0);
-    ack_pending_count_--;
-    if (!client_)
-      return;
+void CompositorFrameSinkSupport::DidReceiveCompositorFrameAck() {
+  DCHECK_GT(ack_pending_count_, 0);
+  ack_pending_count_--;
+  if (!client_)
+    return;
 
-    // If we have a callback, we only return the resource on onBeginFrame.
-    if (compositor_frame_callback_) {
-      if (early_acked_count_ > 0)  // if there was an early ack decrement it.
-        early_acked_count_--;
-      callback_received_receive_ack_ = true;
-      UpdateNeedsBeginFramesInternal();
-      HandleCallback();
-      return;
-    }
-
-    if (early_acked_count_ == 0) {  // no early ACK has been sent, send an ACK
-      client_->DidReceiveCompositorFrameAck(surface_returned_resources_);
-    } else {  // early count is bigger than zero, decrement it
-      early_acked_count_--;
-    }
-    // for any ack request, that is not early clear resources
-    surface_returned_resources_.clear();
+  // If we have a callback, we only return the resource on onBeginFrame.
+  if (compositor_frame_callback_) {
+    callback_received_receive_ack_ = true;
+    UpdateNeedsBeginFramesInternal();
+    HandleCallback();
+    return;
   }
+
+  client_->DidReceiveCompositorFrameAck(surface_returned_resources_);
+  surface_returned_resources_.clear();
 }
 
 void CompositorFrameSinkSupport::DidPresentCompositorFrame(
@@ -688,15 +640,15 @@
     std::vector<ui::LatencyInfo> latency_info) {
   TRACE_EVENT_INSTANT0("viz", "DidRejectCompositorFrame",
                        TRACE_EVENT_SCOPE_THREAD);
-  // TODO(eseckler): Should these be stored and attached to the next
-  // successful frame submission instead?
+  // TODO(eseckler): Should these be stored and attached to the next successful
+  // frame submission instead?
   for (ui::LatencyInfo& info : latency_info)
     info.Terminate();
 
   std::vector<ReturnedResource> resources =
       TransferableResource::ReturnResources(frame_resource_list);
   ReturnResources(resources);
-  DidReceiveCompositorFrameAck(/*early_ack*/ false);
+  DidReceiveCompositorFrameAck();
   DidPresentCompositorFrame(frame_token, base::TimeTicks(), gfx::SwapTimings(),
                             gfx::PresentationFeedback::Failure());
 }
@@ -883,8 +835,8 @@
     return false;
   }
 
-  // We might throttle this OnBeginFrame() if it's been less than a second
-  // since the last one was sent.
+  // We might throttle this OnBeginFrame() if it's been less than a second since
+  // the last one was sent.
   bool can_throttle =
       (frame_time - last_frame_time_) < base::TimeDelta::FromSeconds(1);
 
@@ -900,8 +852,8 @@
     return true;
   }
 
-  // We should never throttle BeginFrames if there is another client waiting
-  // for this client to submit a frame.
+  // We should never throttle BeginFrames if there is another client waiting for
+  // this client to submit a frame.
   if (surface_manager_->HasBlockedEmbedder(frame_sink_id_)) {
     RecordShouldSendBeginFrame(SendBeginFrameResult::kSendBlockedEmbedded);
     return true;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index ac53030..fe2449d8b 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -208,7 +208,7 @@
   // Creates a surface reference from the top-level root to |surface_id|.
   SurfaceReference MakeTopLevelRootReference(const SurfaceId& surface_id);
 
-  void DidReceiveCompositorFrameAck(bool early_ack);
+  void DidReceiveCompositorFrameAck();
   void DidPresentCompositorFrame(uint32_t frame_token,
                                  base::TimeTicks draw_start_timestamp,
                                  const gfx::SwapTimings& swap_timings,
@@ -322,8 +322,6 @@
       compositor_frame_callback_;
   bool callback_received_begin_frame_ = true;
   bool callback_received_receive_ack_ = true;
-  bool last_pending_frame_was_new_surface_ = false;
-  uint8_t early_acked_count_ = 0;
   uint32_t trace_sequence_ = 0;
 
   BeginFrameTracker begin_frame_tracker_;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index 9ca5a3c..a7603be 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -112,7 +112,6 @@
     manager_.InvalidateFrameSinkId(kArbitraryFrameSinkId);
     manager_.surface_manager()->RemoveObserver(&surface_observer_);
   }
-  bool GetEarlyAckCount() const { return support_->early_acked_count_; }
 
   void AddResourcesToFrame(CompositorFrame* frame,
                            ResourceId* resource_ids,
@@ -1439,76 +1438,4 @@
 
   support->SetNeedsBeginFrame(false);
 }
-#if defined(OS_ANDROID)
-// Check CompositorFrame get an early ack if the surface id needs to have
-// pending child needsBeginFrame = true, and NOT new surface ID, then followed
-// by needsBeginFrame = true, and new Surface ID, other classes should not get
-// an early ACK. crbug.com/1060058)
-TEST_F(CompositorFrameSinkSupportTest, PassesEarlyAcks) {
-  SurfaceId id(support_->frame_sink_id(), local_surface_id_);
-
-  LocalSurfaceId child_local_surface_id(1, kAnotherArbitraryToken);
-  SurfaceId child_id(kAnotherArbitraryFrameSinkId, child_local_surface_id);
-  MockCompositorFrameSinkClient mock_client;
-  uint8_t EarlyAckCount;
-  support_->SetNeedsBeginFrame(true);
-
-  // Submit a frame with size (5,5).
-  auto frame = CompositorFrameBuilder()
-                   .AddRenderPass(gfx::Rect(5, 5), gfx::Rect())
-                   .SetActivationDependencies({child_id})
-                   .Build();
-  auto result = support_->MaybeSubmitCompositorFrame(
-      local_surface_id_, std::move(frame), base::nullopt, 0,
-      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
-  // should get NOT early ACK, NeedsBeginFrame= true, and new surface ID (need
-  // to have a NOT new Surface ID)
-  EXPECT_EQ(GetEarlyAckCount(), 0);
-
-  // send a same surface id with new dependencies.
-  LocalSurfaceId child_local_surface_id2(2, kAnotherArbitraryToken);
-  SurfaceId child_id2(kAnotherArbitraryFrameSinkId, child_local_surface_id2);
-  frame = CompositorFrameBuilder()
-              .AddRenderPass(gfx::Rect(5, 5), gfx::Rect())
-              .SetActivationDependencies({child_id2})
-              .Build();
-  result = support_->MaybeSubmitCompositorFrame(
-      local_surface_id_, std::move(frame), base::nullopt, 0,
-      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
-  EXPECT_EQ(SubmitResult::ACCEPTED, result);
-  // should get early ACK, count should be 1, NeedsBeginFrame= true, and not new
-  // surface ID
-  EXPECT_EQ(GetEarlyAckCount(), 1);
-  EarlyAckCount = GetEarlyAckCount();
-
-  // send new surface id with dependencies.
-  LocalSurfaceId local_surface_id2(6, kArbitraryToken);
-  LocalSurfaceId child_local_surface_id3(2, kAnotherArbitraryToken);
-  SurfaceId child_id3(kAnotherArbitraryFrameSinkId, child_local_surface_id3);
-
-  frame = CompositorFrameBuilder()
-              .AddRenderPass(gfx::Rect(5, 5), gfx::Rect())
-              .SetActivationDependencies({child_id3})
-              .Build();
-
-  result = support_->MaybeSubmitCompositorFrame(
-      local_surface_id2, std::move(frame), base::nullopt, 0,
-      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
-  // should get early ACK, NeedsBeginFrame= true, and 1st new surface ID
-  // hence the count should not drop, it be either 1 or 2
-  EXPECT_GE(GetEarlyAckCount(), EarlyAckCount);
-  EarlyAckCount = GetEarlyAckCount();
-  // set a surface with needbeginframe = false, should not get early ack
-  support_->SetNeedsBeginFrame(false);
-  frame = CompositorFrameBuilder()
-              .AddRenderPass(gfx::Rect(5, 5), gfx::Rect())
-              .Build();
-  result = support_->MaybeSubmitCompositorFrame(
-      local_surface_id2, std::move(frame), base::nullopt, 0,
-      mojom::CompositorFrameSink::SubmitCompositorFrameSyncCallback());
-  // should get early NOT ACK, hence it the count should not increase, it could
-  // decrease
-  EXPECT_LE(GetEarlyAckCount(), EarlyAckCount);
-}
-#endif
 }  // namespace viz
diff --git a/content/app_shim_remote_cocoa/web_drag_source_mac.mm b/content/app_shim_remote_cocoa/web_drag_source_mac.mm
index 8513100..347aa7ef 100644
--- a/content/app_shim_remote_cocoa/web_drag_source_mac.mm
+++ b/content/app_shim_remote_cocoa/web_drag_source_mac.mm
@@ -103,9 +103,9 @@
   // HTML.
   if ([type isEqualToString:NSHTMLPboardType] ||
       [type isEqualToString:ui::kChromeDragImageHTMLPboardType]) {
-    DCHECK(!_dropData->html.string().empty());
+    DCHECK(_dropData->html && !_dropData->html->empty());
     // See comment on |kHtmlHeader| above.
-    [pboard setString:SysUTF16ToNSString(kHtmlHeader + _dropData->html.string())
+    [pboard setString:SysUTF16ToNSString(kHtmlHeader + *_dropData->html)
               forType:type];
 
   // URL.
@@ -136,8 +136,8 @@
 
   // Plain text.
   } else if ([type isEqualToString:NSStringPboardType]) {
-    DCHECK(!_dropData->text.string().empty());
-    [pboard setString:SysUTF16ToNSString(_dropData->text.string())
+    DCHECK(_dropData->text && !_dropData->text->empty());
+    [pboard setString:SysUTF16ToNSString(*_dropData->text)
               forType:NSStringPboardType];
 
   // Custom MIME data.
@@ -348,7 +348,7 @@
   }
 
   // HTML.
-  bool hasHTMLData = !_dropData->html.string().empty();
+  bool hasHTMLData = _dropData->html && !_dropData->html->empty();
   // Mail.app and TextEdit accept drags that have both HTML and image flavors on
   // them, but don't process them correctly <http://crbug.com/55879>. Therefore,
   // if there is an image flavor, don't put the HTML data on as HTML, but rather
@@ -369,7 +369,7 @@
   }
 
   // Plain text.
-  if (!_dropData->text.string().empty()) {
+  if (_dropData->text && !_dropData->text->empty()) {
     [_pasteboard addTypes:@[ NSStringPboardType ]
                     owner:_contentsView];
   }
diff --git a/content/browser/android/ime_adapter_android.cc b/content/browser/android/ime_adapter_android.cc
index 17fd17e..95747a2 100644
--- a/content/browser/android/ime_adapter_android.cc
+++ b/content/browser/android/ime_adapter_android.cc
@@ -366,7 +366,7 @@
     const JavaParamRef<jobject>&,
     int start,
     int end) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -400,7 +400,7 @@
                                            const JavaParamRef<jobject>&,
                                            int start,
                                            int end) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -418,7 +418,7 @@
                                               const JavaParamRef<jobject>&,
                                               int before,
                                               int after) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
   input_handler->DeleteSurroundingText(before, after);
@@ -429,7 +429,7 @@
     const JavaParamRef<jobject>&,
     int before,
     int after) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
   input_handler->DeleteSurroundingTextInCodePoints(before, after);
@@ -480,12 +480,12 @@
   return nullptr;
 }
 
-blink::mojom::FrameInputHandler*
-ImeAdapterAndroid::GetFocusedFrameInputHandler() {
-  auto* focused_frame = static_cast<RenderFrameHostImpl*>(GetFocusedFrame());
-  if (!focused_frame)
+blink::mojom::FrameWidgetInputHandler*
+ImeAdapterAndroid::GetFocusedFrameWidgetInputHandler() {
+  RenderWidgetHostImpl* rwhi = GetFocusedWidget();
+  if (!rwhi)
     return nullptr;
-  return focused_frame->GetFrameInputHandler();
+  return rwhi->GetFrameWidgetInputHandler();
 }
 
 std::vector<ui::ImeTextSpan> ImeAdapterAndroid::GetImeTextSpansFromJava(
diff --git a/content/browser/android/ime_adapter_android.h b/content/browser/android/ime_adapter_android.h
index d8d42694..5f25c27b8 100644
--- a/content/browser/android/ime_adapter_android.h
+++ b/content/browser/android/ime_adapter_android.h
@@ -24,7 +24,7 @@
 namespace blink {
 namespace mojom {
 
-class FrameInputHandler;
+class FrameWidgetInputHandler;
 
 }  // namespace mojom
 }  // namespace blink
@@ -124,7 +124,7 @@
  private:
   RenderWidgetHostImpl* GetFocusedWidget();
   RenderFrameHost* GetFocusedFrame();
-  blink::mojom::FrameInputHandler* GetFocusedFrameInputHandler();
+  blink::mojom::FrameWidgetInputHandler* GetFocusedFrameWidgetInputHandler();
   std::vector<ui::ImeTextSpan> GetImeTextSpansFromJava(
       JNIEnv* env,
       const base::android::JavaParamRef<jobject>& obj,
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
index 9e9379113..7644959c 100644
--- a/content/browser/back_forward_cache_browsertest.cc
+++ b/content/browser/back_forward_cache_browsertest.cc
@@ -2027,8 +2027,14 @@
       blink::scheduler::WebSchedulerTrackedFeature::kIdleManager, FROM_HERE);
 }
 
+// crbug.com/1090223
+#if defined(OS_LINUX) || defined(OS_MACOSX)
+#define MAYBE_DoesNotCachePaymentManager DISABLED_DoesNotCachePaymentManager
+#else
+#define MAYBE_DoesNotCachePaymentManager DoesNotCachePaymentManager
+#endif
 IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
-                       DoesNotCachePaymentManager) {
+                       MAYBE_DoesNotCachePaymentManager) {
   ASSERT_TRUE(CreateHttpsServer()->Start());
 
   // 1) Navigate to a page which includes PaymentManager functionality. Note
diff --git a/content/browser/browser_plugin/browser_plugin_guest.cc b/content/browser/browser_plugin/browser_plugin_guest.cc
index 4be6fb0..da656a7 100644
--- a/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -459,13 +459,12 @@
 
 void BrowserPluginGuest::OnExecuteEditCommand(int browser_plugin_instance_id,
                                               const std::string& name) {
-  RenderFrameHostImpl* focused_frame =
-      static_cast<RenderFrameHostImpl*>(web_contents()->GetFocusedFrame());
-  if (!focused_frame || !focused_frame->GetFrameInputHandler())
+  blink::mojom::FrameWidgetInputHandler* focused_frame_widget_input_handler =
+      GetWebContents()->GetFocusedFrameWidgetInputHandler();
+  if (!focused_frame_widget_input_handler)
     return;
 
-  focused_frame->GetFrameInputHandler()->ExecuteEditCommand(name,
-                                                            base::nullopt);
+  focused_frame_widget_input_handler->ExecuteEditCommand(name, base::nullopt);
 }
 
 void BrowserPluginGuest::OnImeCommitText(
@@ -497,10 +496,11 @@
     int browser_plugin_instance_id,
     int before,
     int after) {
-  RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
-      web_contents()->GetFocusedFrame());
-  if (rfh && rfh->GetFrameInputHandler())
-    rfh->GetFrameInputHandler()->ExtendSelectionAndDelete(before, after);
+  blink::mojom::FrameWidgetInputHandler* focused_frame_widget_input_handler =
+      GetWebContents()->GetFocusedFrameWidgetInputHandler();
+  if (!focused_frame_widget_input_handler)
+    return;
+  focused_frame_widget_input_handler->ExtendSelectionAndDelete(before, after);
 }
 
 void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id,
diff --git a/content/browser/cache_storage/cache_storage_quota_client.cc b/content/browser/cache_storage/cache_storage_quota_client.cc
index 2e6ec9e..63c2c03 100644
--- a/content/browser/cache_storage/cache_storage_quota_client.cc
+++ b/content/browser/cache_storage/cache_storage_quota_client.cc
@@ -25,8 +25,9 @@
                                              blink::mojom::StorageType type,
                                              GetUsageCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK_EQ(type, blink::mojom::StorageType::kTemporary);
 
-  if (!DoesSupport(type) || !CacheStorageManager::IsValidQuotaOrigin(origin)) {
+  if (!CacheStorageManager::IsValidQuotaOrigin(origin)) {
     std::move(callback).Run(0);
     return;
   }
@@ -37,11 +38,7 @@
 void CacheStorageQuotaClient::GetOriginsForType(blink::mojom::StorageType type,
                                                 GetOriginsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  if (!DoesSupport(type)) {
-    std::move(callback).Run(std::set<url::Origin>());
-    return;
-  }
+  DCHECK_EQ(type, blink::mojom::StorageType::kTemporary);
 
   cache_manager_->GetOrigins(owner_, std::move(callback));
 }
@@ -50,11 +47,7 @@
                                                 const std::string& host,
                                                 GetOriginsCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
-  if (!DoesSupport(type)) {
-    std::move(callback).Run(std::set<url::Origin>());
-    return;
-  }
+  DCHECK_EQ(type, blink::mojom::StorageType::kTemporary);
 
   cache_manager_->GetOriginsForHost(host, owner_, std::move(callback));
 }
@@ -63,8 +56,9 @@
                                                blink::mojom::StorageType type,
                                                DeletionCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  DCHECK_EQ(type, blink::mojom::StorageType::kTemporary);
 
-  if (!DoesSupport(type) || !CacheStorageManager::IsValidQuotaOrigin(origin)) {
+  if (!CacheStorageManager::IsValidQuotaOrigin(origin)) {
     std::move(callback).Run(blink::mojom::QuotaStatusCode::kOk);
     return;
   }
diff --git a/content/browser/cookie_store/cookie_change_subscription.cc b/content/browser/cookie_store/cookie_change_subscription.cc
index 5367928..6dff0ba3 100644
--- a/content/browser/cookie_store/cookie_change_subscription.cc
+++ b/content/browser/cookie_store/cookie_change_subscription.cc
@@ -169,7 +169,7 @@
       net::CookieOptions::SameSiteCookieContext::MakeInclusive());
 
   return cookie.IncludeForRequestURL(url_, net_options, access_semantics)
-      .IsInclude();
+      .status.IsInclude();
 }
 
 bool operator==(const CookieChangeSubscription& lhs,
diff --git a/content/browser/devtools/devtools_instrumentation.cc b/content/browser/devtools/devtools_instrumentation.cc
index f653fa34..1fab0df 100644
--- a/content/browser/devtools/devtools_instrumentation.cc
+++ b/content/browser/devtools/devtools_instrumentation.cc
@@ -598,7 +598,7 @@
     int process_id,
     int routing_id,
     const std::string& devtools_request_id,
-    const net::CookieStatusList& request_cookie_list,
+    const net::CookieAccessResultList& request_cookie_list,
     const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers) {
   FrameTreeNode* ftn = GetFtnForNetworkRequest(process_id, routing_id);
   if (ftn) {
diff --git a/content/browser/devtools/devtools_instrumentation.h b/content/browser/devtools/devtools_instrumentation.h
index 2889921c..78c9859f 100644
--- a/content/browser/devtools/devtools_instrumentation.h
+++ b/content/browser/devtools/devtools_instrumentation.h
@@ -136,7 +136,7 @@
     int process_id,
     int routing_id,
     const std::string& devtools_request_id,
-    const net::CookieStatusList& request_cookie_list,
+    const net::CookieAccessResultList& request_cookie_list,
     const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers);
 void OnResponseReceivedExtraInfo(
     int process_id,
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc
index 26b38fa..e8e78eac 100644
--- a/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -324,8 +324,8 @@
       network::mojom::CookieManager::GetCookieListCallback callback);
   void NotifyClientWithCookies(
       std::unique_ptr<InterceptedRequestInfo> request_info,
-      const net::CookieStatusList& cookie_list_with_statuses,
-      const net::CookieStatusList& excluded_cookies);
+      const net::CookieAccessResultList& cookies_with_access_result,
+      const net::CookieAccessResultList& excluded_cookies);
 
   void ResponseBodyComplete();
 
@@ -1271,14 +1271,14 @@
 
 void InterceptionJob::NotifyClientWithCookies(
     std::unique_ptr<InterceptedRequestInfo> request_info,
-    const net::CookieStatusList& cookie_list_with_statuses,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies_with_access_result,
+    const net::CookieAccessResultList& excluded_cookies) {
   if (!interceptor_)
     return;
   std::string cookie_line;
-  if (!cookie_list_with_statuses.empty()) {
+  if (!cookies_with_access_result.empty()) {
     cookie_line =
-        net::CanonicalCookie::BuildCookieLine(cookie_list_with_statuses);
+        net::CanonicalCookie::BuildCookieLine(cookies_with_access_result);
   }
   request_info->network_request =
       protocol::NetworkHandler::CreateRequestFromResourceRequest(
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 4b10ebd..979831d 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -182,10 +182,10 @@
   CookieRetrieverNetworkService(std::unique_ptr<GetCookiesCallback> callback)
       : callback_(std::move(callback)) {}
 
-  void GotCookies(const net::CookieStatusList& cookies,
-                  const net::CookieStatusList& excluded_cookies) {
-    for (const auto& cookie_with_status : cookies) {
-      const net::CanonicalCookie& cookie = cookie_with_status.cookie;
+  void GotCookies(const net::CookieAccessResultList& cookies,
+                  const net::CookieAccessResultList& excluded_cookies) {
+    for (const auto& cookie_with_access_result : cookies) {
+      const net::CanonicalCookie& cookie = cookie_with_access_result.cookie;
       std::string key = base::StringPrintf(
           "%s::%s::%s::%d", cookie.Name().c_str(), cookie.Domain().c_str(),
           cookie.Path().c_str(), cookie.IsSecure());
@@ -687,16 +687,16 @@
 }
 
 std::unique_ptr<Array<Network::BlockedCookieWithReason>>
-BuildProtocolAssociatedCookies(const net::CookieStatusList& net_list) {
+BuildProtocolAssociatedCookies(const net::CookieAccessResultList& net_list) {
   auto protocol_list =
       std::make_unique<Array<Network::BlockedCookieWithReason>>();
 
-  for (const net::CookieWithStatus& cookie : net_list) {
+  for (const net::CookieWithAccessResult& cookie : net_list) {
     std::unique_ptr<Array<Network::CookieBlockedReason>> blocked_reasons =
-        GetProtocolBlockedCookieReason(cookie.status);
+        GetProtocolBlockedCookieReason(cookie.access_result.status);
     // Note that the condition below is not always true,
     // as there might be blocked reasons that we do not report.
-    if (blocked_reasons->size() || cookie.status.IsInclude()) {
+    if (blocked_reasons->size() || cookie.access_result.status.IsInclude()) {
       protocol_list->push_back(
           Network::BlockedCookieWithReason::Create()
               .SetBlockedReasons(std::move(blocked_reasons))
@@ -2123,7 +2123,7 @@
 
 void NetworkHandler::OnRequestWillBeSentExtraInfo(
     const std::string& devtools_request_id,
-    const net::CookieStatusList& request_cookie_list,
+    const net::CookieAccessResultList& request_cookie_list,
     const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers) {
   if (!enabled_)
     return;
diff --git a/content/browser/devtools/protocol/network_handler.h b/content/browser/devtools/protocol/network_handler.h
index 52b3c34..e5f15a7 100644
--- a/content/browser/devtools/protocol/network_handler.h
+++ b/content/browser/devtools/protocol/network_handler.h
@@ -198,7 +198,7 @@
 
   void OnRequestWillBeSentExtraInfo(
       const std::string& devtools_request_id,
-      const net::CookieStatusList& request_cookie_list,
+      const net::CookieAccessResultList& request_cookie_list,
       const std::vector<network::mojom::HttpRawHeaderPairPtr>& request_headers);
   void OnResponseReceivedExtraInfo(
       const std::string& devtools_request_id,
diff --git a/content/browser/frame_host/ancestor_throttle.cc b/content/browser/frame_host/ancestor_throttle.cc
index b5b47d3..8630ace 100644
--- a/content/browser/frame_host/ancestor_throttle.cc
+++ b/content/browser/frame_host/ancestor_throttle.cc
@@ -305,7 +305,8 @@
 
     case HeaderDisposition::SAMEORIGIN: {
       // Block the request when any ancestor is not same-origin.
-      RenderFrameHostImpl* parent = request->GetParentFrame();
+      RenderFrameHostImpl* parent = ParentForAncestorThrottle(
+          request->frame_tree_node()->current_frame_host());
       url::Origin current_origin =
           url::Origin::Create(navigation_handle()->GetURL());
       while (parent) {
@@ -327,7 +328,7 @@
 
           return CheckResult::BLOCK;
         }
-        parent = parent->GetParent();
+        parent = ParentForAncestorThrottle(parent);
       }
       RecordXFrameOptionsUsage(XFrameOptionsHistogram::SAMEORIGIN);
       return CheckResult::PROCEED;
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index 833259d9..e70d6104 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -550,7 +550,6 @@
   virtual void CreateNewWidget(
       int32_t render_process_id,
       int32_t widget_route_id,
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {}
@@ -559,7 +558,6 @@
   virtual void CreateNewFullscreenWidget(
       int32_t render_process_id,
       int32_t widget_route_id,
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {}
@@ -606,6 +604,13 @@
   // links.
   virtual void SavableResourceLinksError(RenderFrameHostImpl* source) {}
 
+  // Called when |RenderFrameHostImpl::lifecycle_state()| changes i.e., when
+  // RenderFrameHost LifecycleState changes from old_state to new_state.
+  virtual void RenderFrameHostStateChanged(
+      RenderFrameHost* host,
+      RenderFrameHostImpl::LifecycleState old_state,
+      RenderFrameHostImpl::LifecycleState new_state) {}
+
  protected:
   virtual ~RenderFrameHostDelegate() = default;
 };
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 232b335..13046b2 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -137,7 +137,6 @@
 #include "content/common/render_message_filter.mojom.h"
 #include "content/common/renderer.mojom.h"
 #include "content/common/unfreezable_frame_messages.h"
-#include "content/common/widget.mojom.h"
 #include "content/public/browser/ax_event_notification_details.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/browser_context.h"
@@ -972,10 +971,6 @@
   //
   // Local roots require a RenderWidget for input/layout/painting.
   if (!parent_ || IsCrossProcessSubframe()) {
-    mojo::PendingRemote<mojom::Widget> widget;
-    GetRemoteInterfaces()->GetInterface(
-        widget.InitWithNewPipeAndPassReceiver());
-
     if (!parent_) {
       // For main frames, the RenderWidgetHost is owned by the RenderViewHost.
       // TODO(https://crbug.com/545684): Once RenderViewHostImpl has-a
@@ -983,10 +978,6 @@
       // owning the RenderWidgetHostImpl itself.
       DCHECK(GetLocalRenderWidgetHost());
       DCHECK(!GetLocalRenderWidgetHost()->owned_by_render_frame_host());
-
-      // Make the RenderWidgetHostImpl able to call the mojo Widget interface
-      // (implemented by the RenderWidgetImpl).
-      GetLocalRenderWidgetHost()->SetWidget(std::move(widget));
     } else {
       // For local child roots, the RenderFrameHost directly creates and owns
       // its RenderWidgetHost.
@@ -995,7 +986,7 @@
       DCHECK_EQ(nullptr, GetLocalRenderWidgetHost());
       owned_render_widget_host_ = RenderWidgetHostFactory::Create(
           frame_tree_->render_widget_delegate(), GetProcess(),
-          widget_routing_id, std::move(widget), /*hidden=*/true);
+          widget_routing_id, /*hidden=*/true);
       owned_render_widget_host_->set_owned_by_render_frame_host(true);
 #if defined(OS_ANDROID)
       owned_render_widget_host_->SetForceEnableZoom(
@@ -1006,8 +997,6 @@
     if (is_main_frame())
       GetLocalRenderWidgetHost()->SetIntersectsViewport(true);
     GetLocalRenderWidgetHost()->SetFrameDepth(frame_tree_node_->depth());
-    GetLocalRenderWidgetHost()->SetFrameInputHandler(
-        frame_input_handler_.get());
     GetLocalRenderWidgetHost()->input_router()->SetFrameTreeNodeId(
         frame_tree_node_->frame_tree_node_id());
   }
@@ -1151,9 +1140,6 @@
   if (owned_render_widget_host_)
     owned_render_widget_host_->ShutdownAndDestroyWidget(false);
 
-  // This needs to be deleted before |frame_input_handler_| so associated
-  // remotes can send messages during shutdown. See crbug.com/1010478 for
-  // details.
   render_view_host_.reset();
 
   // If another frame is waiting for a beforeunload completion callback from
@@ -1748,7 +1734,6 @@
     IPC_MESSAGE_HANDLER(FrameHostMsg_VisualStateResponse, OnVisualStateResponse)
     IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
     IPC_MESSAGE_HANDLER(FrameHostMsg_SelectionChanged, OnSelectionChanged)
-    IPC_MESSAGE_HANDLER(FrameHostMsg_FrameDidCallFocus, OnFrameDidCallFocus)
   IPC_END_MESSAGE_MAP()
 
   // No further actions here, since we may have been deleted.
@@ -2056,12 +2041,6 @@
   return base::Contains(bypassing_schemes, scheme);
 }
 
-blink::mojom::FrameInputHandler* RenderFrameHostImpl::GetFrameInputHandler() {
-  if (!frame_input_handler_)
-    return nullptr;
-  return frame_input_handler_.get();
-}
-
 bool RenderFrameHostImpl::CreateRenderFrame(
     int previous_routing_id,
     const base::Optional<base::UnguessableToken>& opener_frame_token,
@@ -2240,12 +2219,6 @@
     CHECK(frame_);
 
   if (created && GetLocalRenderWidgetHost()) {
-    mojo::PendingRemote<mojom::Widget> widget;
-    GetRemoteInterfaces()->GetInterface(
-        widget.InitWithNewPipeAndPassReceiver());
-    GetLocalRenderWidgetHost()->SetWidget(std::move(widget));
-    GetLocalRenderWidgetHost()->SetFrameInputHandler(
-        frame_input_handler_.get());
     GetLocalRenderWidgetHost()->input_router()->SetFrameTreeNodeId(
         frame_tree_node_->frame_tree_node_id());
     mojo::Remote<viz::mojom::InputTargetClient> input_target_client;
@@ -2672,6 +2645,10 @@
   delegate_->SetFocusedFrame(frame_tree_node_, GetSiteInstance());
 }
 
+void RenderFrameHostImpl::DidCallFocus() {
+  delegate_->DidCallFocus();
+}
+
 void RenderFrameHostImpl::DidAddContentSecurityPolicies(
     std::vector<network::mojom::ContentSecurityPolicyPtr> policies) {
   TRACE_EVENT1("navigation",
@@ -3400,6 +3377,10 @@
   delegate_->OnTextAutosizerPageInfoChanged(this, std::move(page_info));
 }
 
+void RenderFrameHostImpl::FocusPage() {
+  render_view_host_->OnFocus();
+}
+
 void RenderFrameHostImpl::UpdateFaviconURL(
     std::vector<blink::mojom::FaviconURLPtr> favicon_urls) {
   delegate_->UpdateFaviconURL(this, std::move(favicon_urls));
@@ -4484,10 +4465,6 @@
                                                          granularity);
 }
 
-void RenderFrameHostImpl::OnFrameDidCallFocus() {
-  delegate_->DidCallFocus();
-}
-
 void RenderFrameHostImpl::RenderFallbackContentInParentProcess() {
   bool is_object_type =
       frame_tree_node()->current_replication_state().frame_owner_element_type ==
@@ -5018,27 +4995,25 @@
 }
 
 void RenderFrameHostImpl::CreateNewWidget(
-    mojo::PendingRemote<mojom::Widget> widget,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
     CreateNewWidgetCallback callback) {
   int32_t widget_route_id = GetProcess()->GetNextRoutingID();
   std::move(callback).Run(widget_route_id);
   delegate_->CreateNewWidget(GetProcess()->GetID(), widget_route_id,
-                             std::move(widget), std::move(blink_widget_host),
+                             std::move(blink_widget_host),
                              std::move(blink_widget));
 }
 
 void RenderFrameHostImpl::CreateNewFullscreenWidget(
-    mojo::PendingRemote<mojom::Widget> widget,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
     CreateNewFullscreenWidgetCallback callback) {
   int32_t widget_route_id = GetProcess()->GetNextRoutingID();
   std::move(callback).Run(widget_route_id);
-  delegate_->CreateNewFullscreenWidget(
-      GetProcess()->GetID(), widget_route_id, std::move(widget),
-      std::move(blink_widget_host), std::move(blink_widget));
+  delegate_->CreateNewFullscreenWidget(GetProcess()->GetID(), widget_route_id,
+                                       std::move(blink_widget_host),
+                                       std::move(blink_widget));
 }
 
 void RenderFrameHostImpl::IssueKeepAliveHandle(
@@ -6415,9 +6390,6 @@
       remote_interfaces.InitWithNewPipeAndPassReceiver());
   remote_interfaces_.reset(new service_manager::InterfaceProvider);
   remote_interfaces_->Bind(std::move(remote_interfaces));
-
-  remote_interfaces_->GetInterface(
-      frame_input_handler_.BindNewPipeAndPassReceiver());
 }
 
 void RenderFrameHostImpl::InvalidateMojoConnection() {
@@ -6427,7 +6399,6 @@
   local_frame_.reset();
   local_main_frame_.reset();
   navigation_control_.reset();
-  frame_input_handler_.reset();
   find_in_page_.reset();
   render_accessibility_.reset();
 
@@ -9038,7 +9009,10 @@
           << "Unexpected LifeCycleState " << int(lifecycle_state_);
       break;
   }
+  LifecycleState old_state = lifecycle_state_;
   lifecycle_state_ = state;
+  // Notify the delegate about change in |lifecycle_state_|.
+  delegate_->RenderFrameHostStateChanged(this, old_state, lifecycle_state_);
 }
 
 void RenderFrameHostImpl::BindReportingObserver(
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 48ceca84..f66533ea 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -464,8 +464,6 @@
   void PerformAction(const ui::AXActionData& data) override;
   bool RequiresPerformActionPointInPixels() const override;
 
-  blink::mojom::FrameInputHandler* GetFrameInputHandler();
-
   viz::mojom::InputTargetClient* GetInputTargetClient() {
     return input_target_client_;
   }
@@ -1534,6 +1532,7 @@
   void DidChangeThemeColor(const base::Optional<SkColor>& theme_color) override;
   void DidFailLoadWithError(const GURL& url, int32_t error_code) override;
   void DidFocusFrame() override;
+  void DidCallFocus() override;
   void DidAddContentSecurityPolicies(
       std::vector<network::mojom::ContentSecurityPolicyPtr> policies) override;
   void EnforceInsecureRequestPolicy(
@@ -1613,6 +1612,7 @@
   void ContentsPreferredSizeChanged(const gfx::Size& pref_size) override;
   void TextAutosizerPageInfoChanged(
       blink::mojom::TextAutosizerPageInfoPtr page_info) override;
+  void FocusPage() override;
 
   void ReportNoBinderForInterface(const std::string& error);
 
@@ -1865,7 +1865,6 @@
                           uint32_t offset,
                           const gfx::Range& range);
   void OnSetNeedsOcclusionTracking(bool needs_tracking);
-  void OnFrameDidCallFocus();
   void OnSaveImageFromDataURL(const std::string& url_str);
 
   // Computes the IsolationInfo for both navigations and subresources.
@@ -1891,13 +1890,11 @@
   void AdoptPortal(const base::UnguessableToken& portal_token,
                    AdoptPortalCallback callback) override;
   void CreateNewWidget(
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
       CreateNewWidgetCallback callback) override;
   void CreateNewFullscreenWidget(
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
@@ -2852,7 +2849,6 @@
   const base::UnguessableToken frame_token_;
 
   viz::mojom::InputTargetClient* input_target_client_ = nullptr;
-  mojo::Remote<blink::mojom::FrameInputHandler> frame_input_handler_;
 
   // Binding to remote implementation of mojom::RenderAccessibility. Note that
   // this binding is done on-demand (in UpdateAccessibilityMode()) and will only
diff --git a/content/browser/frame_host/render_frame_host_impl_mac_browsertest.mm b/content/browser/frame_host/render_frame_host_impl_mac_browsertest.mm
index 6c74902..5bc2610d 100644
--- a/content/browser/frame_host/render_frame_host_impl_mac_browsertest.mm
+++ b/content/browser/frame_host/render_frame_host_impl_mac_browsertest.mm
@@ -6,6 +6,7 @@
 
 #include "base/mac/scoped_nsobject.h"
 #include "base/run_loop.h"
+#include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/content_browser_test.h"
@@ -33,8 +34,8 @@
   [pboard setFindText:@"test"];
   EXPECT_NSEQ(@"test", [pboard findText]);
 
-  auto* rfhi = static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame());
-  auto* input_handler = rfhi->GetFrameInputHandler();
+  auto* input_handler = static_cast<WebContentsImpl*>(web_contents)
+                            ->GetFocusedFrameWidgetInputHandler();
   input_handler->SelectAll();
   input_handler->CopyToFindPboard();
 
diff --git a/content/browser/frame_host/render_frame_host_impl_unittest.cc b/content/browser/frame_host/render_frame_host_impl_unittest.cc
index f350491..1740444 100644
--- a/content/browser/frame_host/render_frame_host_impl_unittest.cc
+++ b/content/browser/frame_host/render_frame_host_impl_unittest.cc
@@ -82,11 +82,7 @@
 
 // Create a full screen popup RenderWidgetHost and View.
 TEST_F(RenderFrameHostImplTest, CreateFullscreenWidget) {
-  mojo::PendingRemote<mojom::Widget> widget;
-  std::unique_ptr<MockWidgetImpl> widget_impl =
-      std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());
   main_test_rfh()->CreateNewFullscreenWidget(
-      std::move(widget),
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>(),
       mojo::PendingAssociatedRemote<blink::mojom::Widget>(), base::DoNothing());
 }
diff --git a/content/browser/frame_host/render_frame_message_filter_browsertest.cc b/content/browser/frame_host/render_frame_message_filter_browsertest.cc
index 4b872b2..e2f185d4 100644
--- a/content/browser/frame_host/render_frame_message_filter_browsertest.cc
+++ b/content/browser/frame_host/render_frame_message_filter_browsertest.cc
@@ -92,14 +92,14 @@
   base::RunLoop run_loop;
   BrowserContext::GetDefaultStoragePartition(tab->GetBrowserContext())
       ->GetCookieManagerForBrowserProcess()
-      ->GetCookieList(url, options,
-                      base::BindLambdaForTesting(
-                          [&](const net::CookieStatusList& cookie_list,
-                              const net::CookieStatusList& excluded_cookies) {
-                            result =
-                                net::cookie_util::StripStatuses(cookie_list);
-                            run_loop.Quit();
-                          }));
+      ->GetCookieList(
+          url, options,
+          base::BindLambdaForTesting(
+              [&](const net::CookieAccessResultList& cookie_list,
+                  const net::CookieAccessResultList& excluded_cookies) {
+                result = net::cookie_util::StripAccessResults(cookie_list);
+                run_loop.Quit();
+              }));
   run_loop.Run();
   return net::CanonicalCookie::BuildCookieLine(result);
 }
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc
index 64d4805..99bfa46 100644
--- a/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/content/browser/frame_host/render_frame_proxy_host.cc
@@ -299,6 +299,10 @@
     remote_frame_host_receiver_.Bind(
         mojo::PendingAssociatedReceiver<blink::mojom::RemoteFrameHost>(
             std::move(handle)));
+  } else if (interface_name == blink::mojom::RemoteMainFrameHost::Name_) {
+    remote_main_frame_host_receiver_.Bind(
+        mojo::PendingAssociatedReceiver<blink::mojom::RemoteMainFrameHost>(
+            std::move(handle)));
   }
 }
 
@@ -659,6 +663,10 @@
                                target_origin, std::move(message));
 }
 
+void RenderFrameProxyHost::FocusPage() {
+  frame_tree_node_->current_frame_host()->FocusPage();
+}
+
 void RenderFrameProxyHost::DidChangeOpener(
     const base::Optional<base::UnguessableToken>& opener_frame_token) {
   frame_tree_node_->render_manager()->DidChangeOpener(
diff --git a/content/browser/frame_host/render_frame_proxy_host.h b/content/browser/frame_host/render_frame_proxy_host.h
index 3b6e7af..37b51fdf 100644
--- a/content/browser/frame_host/render_frame_proxy_host.h
+++ b/content/browser/frame_host/render_frame_proxy_host.h
@@ -70,7 +70,8 @@
     : public IPC::Listener,
       public IPC::Sender,
       public mojom::RenderFrameProxyHost,
-      public blink::mojom::RemoteFrameHost {
+      public blink::mojom::RemoteFrameHost,
+      public blink::mojom::RemoteMainFrameHost {
  public:
   using CreatedCallback = base::RepeatingCallback<void(RenderFrameProxyHost*)>;
 
@@ -170,6 +171,9 @@
       const base::string16& target_origin,
       blink::TransferableMessage message) override;
 
+  // blink::mojom::RemoteMainFrameHost overrides:
+  void FocusPage() override;
+
   // Returns associated remote for the content::mojom::RenderFrameProxy Mojo
   // interface.
   const mojo::AssociatedRemote<mojom::RenderFrameProxy>&
@@ -259,6 +263,9 @@
   mojo::AssociatedReceiver<blink::mojom::RemoteFrameHost>
       remote_frame_host_receiver_{this};
 
+  mojo::AssociatedReceiver<blink::mojom::RemoteMainFrameHost>
+      remote_main_frame_host_receiver_{this};
+
   base::UnguessableToken frame_token_ = base::UnguessableToken::Create();
 
   DISALLOW_COPY_AND_ASSIGN(RenderFrameProxyHost);
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index 6a9d3d1..b93f088 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -405,9 +405,8 @@
   // be used for other purposes, such as WebGPU.
   const base::CommandLine* command_line =
       base::CommandLine::ForCurrentProcess();
-  gpu::GrContextType gr_context_type = gpu::gles2::ParseGrContextType();
   gpu::VulkanImplementationName use_vulkan =
-      gpu::gles2::ParseVulkanImplementationName(command_line, gr_context_type);
+      gpu::gles2::ParseVulkanImplementationName(command_line);
   return use_vulkan != gpu::VulkanImplementationName::kNone;
 #else
   return false;
diff --git a/content/browser/media/media_canplaytype_browsertest.cc b/content/browser/media/media_canplaytype_browsertest.cc
index 45a76bc..22ea057c 100644
--- a/content/browser/media/media_canplaytype_browsertest.cc
+++ b/content/browser/media/media_canplaytype_browsertest.cc
@@ -22,1630 +22,161 @@
 #include "base/android/build_info.h"
 #endif
 
-const char kProbably[] = "probably";
-const char kMaybe[] = "maybe";
-const char kNot[] = "";
-
-#if BUILDFLAG(USE_PROPRIETARY_CODECS)
-const char* kPropProbably = kProbably;
-const char* kPropMaybe = kMaybe;
-#else
-const char* kPropProbably = kNot;
-const char* kPropMaybe = kNot;
-#endif  // USE_PROPRIETARY_CODECS
-
-#if !defined(OS_ANDROID)
-const char* kOggVideoProbably = kProbably;
-const char* kOggVideoMaybe = kMaybe;
-const char* kTheoraProbably = kProbably;
-const char* kHlsProbably = kNot;
-const char* kHlsMaybe = kNot;
-#else
-const char* kOggVideoProbably = kNot;
-const char* kOggVideoMaybe = kNot;
-const char* kTheoraProbably = kNot;
-const char* kHlsProbably = kPropProbably;
-const char* kHlsMaybe = kPropMaybe;
-#endif  // !OS_ANDROID
-
-// Chrome doesn't support HEVC.
-const char* kHevcSupported = kNot;
-
-#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
-const char* kMp2tsMaybe = kPropMaybe;
-const char* kMp2tsProbably = kPropProbably;
-#else
-const char* kMp2tsMaybe = kNot;
-const char* kMp2tsProbably = kNot;
-#endif
-
-// High 10-bit profile is only available when we can use ffmpeg to decode H.264.
-// Even though FFmpeg is used on Android, we only use platform decoders for
-// H.264
-#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
-const char* kHi10pProbably = kPropProbably;
-#else
-const char* kHi10pProbably = kPropMaybe;
-#endif
-
 namespace content {
 
 class MediaCanPlayTypeTest : public MediaBrowserTest {
  public:
-  MediaCanPlayTypeTest() : url_("about:blank") {}
+  MediaCanPlayTypeTest() = default;
 
   void SetUpOnMainThread() override {
-    EXPECT_TRUE(NavigateToURL(shell(), url_));
+    EXPECT_TRUE(
+        NavigateToURL(shell(), GetTestUrl("media", "canplaytype_test.html")));
   }
 
-  std::string CanPlay(const std::string& type) {
-    std::string command("document.createElement('video').canPlayType(");
-    command.append(type);
-    command.append(")");
-
-    std::string result;
-    EXPECT_TRUE(ExecuteScriptAndExtractString(
+  void ExecuteTest(const std::string& command) {
+    bool result;
+    EXPECT_TRUE(ExecuteScriptAndExtractBool(
         shell(), "window.domAutomationController.send(" + command + ");",
         &result));
-    return result;
-  }
-
-  void TestMPEGUnacceptableCombinations(const std::string& mime) {
-    // AVC codecs must be followed by valid 6-digit hexadecimal number.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.12345\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.12345\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.1234567\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.1234567\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.number\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.number\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.12345.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.12345.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.123456.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.123456.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.123456.7\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.123456.7\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.x23456\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.1x3456\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.12x456\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.123x56\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.1234x6\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.12345x\"'"));
-
-    // Old-style avc1 codecs must be followed by two dot-separated decimal
-    // numbers (H.264 profile and level)
-    // Invalid formats
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1..\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.x66.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66x.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.x30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30x\"'"));
-    // Invalid level values
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.300\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.-1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.x\"'"));
-    // Invalid profile values
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.0.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.65.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.67.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.76.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.78.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.99.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.101.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.300.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.-1.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.x.30\"'"));
-    // Old-style avc1 codec ids are supported only for video/mp2t container.
-    if (mime != "video/mp2t") {
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.13\"'"));
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.77.30\"'"));
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.100.40\"'"));
-    }
-    // Old-style codec ids are not supported for avc3 codec strings.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.66.13\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.77.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.100.40\"'"));
-
-    // AAC codecs must be followed by one or two valid hexadecimal numbers.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.no\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.0k\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.0k.0k\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.4.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.0k\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40k\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2k\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2k\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2.0\"'"));
-
-    // Unlike just "avc1", just "mp4a" is not supported.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.\"'"));
-
-    // Other names for the codecs are not supported.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"h264\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"h.264\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"H264\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"H.264\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"aac\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AAC\"'"));
-
-    // Codecs must not end with a dot.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.\"'"));
-
-    // A simple substring match is not sufficient.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"lavc1337\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\";mp4a+\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\";mp4a.40+\"'"));
-
-    // Codecs not belonging to MPEG container.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, 1\"'"));
-
-    // Remove all but "audio/mpeg" when https://crbug.com/592889 is fixed.
-    if (mime != "audio/mpeg" && mime != "audio/mp4" && mime != "video/mp4" &&
-        mime != "video/mp2t" &&
-        !base::EndsWith(mime, "mpegurl", base::CompareCase::SENSITIVE)) {
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
-    }
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, vorbis\"'"));
-
-    if (mime != "audio/mp4" && mime != "video/mp4") {
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"opus\"'"));
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, opus\"'"));
-      EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, opus\"'"));
-    }
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp08\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\"vp08.00.01.08.02.01.01.00\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40.02\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40.02\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.02\"'"));
-
-    // Codecs are case sensitive.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC1.4d401e\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC3.64001f\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"MP4A\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"MP4A.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"MP4A.40.02\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC1, MP4\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"AVC3, MP4\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\", AVC1.4D401E, MP4.40.2\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\", AVC3.64001F, MP4.40.2\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\", AVC1.4D401E, MP4.40.02\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\", AVC3.64001F, MP4.40.02\"'"));
-
-    // Unknown codecs.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc4\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1x\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3x\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4ax\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-4\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-4\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a4\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a7\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a5.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a5.1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6.1\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
-
-    // Don't allow incomplete/ambiguous codec ids for HEVC.
-    // Codec string must have info about codec level/profile, as described in
-    // ISO/IEC FDIS 14496-15 section E.3, for example "hev1.1.6.L93.B0"
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1\"'"));
-
-    // Invalid codecs that look like something similar to HEVC/H.265
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1x\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1x\"'"));
-    // First component of codec id must be "hev1" or "hvc1" (case-sensitive)
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hevc.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev0.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc0.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev2.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc2.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"HEVC.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"HEV0.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"HVC0.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"HEV2.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"HVC2.1.6.L93.B0\"'"));
-
-    // Trailing dot is not allowed.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0.\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0.\"'"));
-    // Invalid general_profile_space/general_profile_idc
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.x.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.x.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.d1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.d1.6.L93.B0\"'"));
-    // Invalid general_profile_compatibility_flags
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.x.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.x.L93.B0\"'"));
-    // Invalid general_tier_flag
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.x.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.x.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.Lx.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.Lx.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.Hx.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.Hx.B0\"'"));
-    // Invalid constraint flags
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.x\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.x\"'"));
-  }
-
-  void TestOGGUnacceptableCombinations(const std::string& mime) {
-    // Codecs not belonging to OGG container.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, 1\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp08\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\"vp08.00.01.08.02.01.01.00\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09.00.10.08\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.67\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.68\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.69\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.6B\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.02\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.02\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A6\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6\"'"));
-
-    // Codecs are case sensitive.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Theora\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Theora, Opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Theora, Vorbis\"'"));
-
-    // Unknown codecs.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
-  }
-
-  void TestWEBMUnacceptableCombinations(const std::string& mime) {
-    // Codecs not belonging to WEBM container.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp08\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, opus\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.67\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.68\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.69\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.6B\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.02\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0, mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0, mp4a.40\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A6\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6\"'"));
-
-    // Codecs are case sensitive.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP8, Vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP8.0, Opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP9, Vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP9.0, Opus\"'"));
-
-    // Unknown codec.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
-  }
-
-  void TestWAVUnacceptableCombinations(const std::string& mime) {
-    // Codecs not belonging to WAV container.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp08\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09.00.10.08\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vorbis\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, 1\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, 1\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, 1\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.67\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.68\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.69\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.6B\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.02\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A6\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6\"'"));
-
-    // Unknown codec.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
-  }
-
-  void TestHLSCombinations(const std::string& mime) {
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "'"));
-
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "; codecs=\"avc1\"'"));
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "; codecs=\"avc3\"'"));
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "; codecs=\"mp4a.40\"'"));
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "; codecs=\"avc1, mp4a.40\"'"));
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "; codecs=\"avc3, mp4a.40\"'"));
-
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"avc1.42E01E\"'"));
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"avc1.42101E\"'"));
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"avc1.42701E\"'"));
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"avc1.42F01E\"'"));
-
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"avc3.42E01E\"'"));
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"avc3.42801E\"'"));
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"avc3.42C01E\"'"));
-
-    // Android, is the only platform that supports these types, and its HLS
-    // implementations uses platform codecs, which do not include MPEG-2 AAC.
-    // See https://crbug.com/544268.
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.67\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.68\"'"));
-
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"mp4a.69\"'"));
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"mp4a.6B\"'"));
-
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"mp4a.40.2\"'"));
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"mp4a.40.02\"'"));
-    EXPECT_EQ(kHlsProbably,
-              CanPlay("'" + mime + "; codecs=\"avc1.42E01E, mp4a.40.2\"'"));
-    EXPECT_EQ(kHlsProbably,
-              CanPlay("'" + mime + "; codecs=\"avc1.42E01E, mp4a.40.02\"'"));
-    EXPECT_EQ(kHlsProbably,
-              CanPlay("'" + mime + "; codecs=\"avc3.42E01E, mp4a.40.5\"'"));
-    EXPECT_EQ(kHlsProbably,
-              CanPlay("'" + mime + "; codecs=\"avc3.42E01E, mp4a.40.05\"'"));
-    EXPECT_EQ(kHlsProbably,
-              CanPlay("'" + mime + "; codecs=\"avc3.42E01E, mp4a.40.29\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,mp4a.40.5\"'"));
-    EXPECT_EQ(kNot,
-              CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,mp4a.40.5\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp09.00.10.08\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"flac\"'"));
-
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.A6\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a5\"'"));
-    EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6\"'"));
-
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "; codecs=\"avc1, mp4a.40.2\"'"));
-    EXPECT_EQ(kHlsMaybe,
-              CanPlay("'" + mime + "; codecs=\"avc1, mp4a.40.02\"'"));
-    EXPECT_EQ(kHlsMaybe, CanPlay("'" + mime + "; codecs=\"avc3, mp4a.40.2\"'"));
-    EXPECT_EQ(kHlsMaybe,
-              CanPlay("'" + mime + "; codecs=\"avc3, mp4a.40.02\"'"));
-    EXPECT_EQ(kHlsMaybe,
-              CanPlay("'" + mime + "; codecs=\"avc1.42E01E, mp4a.40\"'"));
-    EXPECT_EQ(kHlsMaybe,
-              CanPlay("'" + mime + "; codecs=\"avc3.42E01E, mp4a.40\"'"));
-
-    TestMPEGUnacceptableCombinations(mime);
-    // This result is incorrect. See https://crbug.com/592889.
-    EXPECT_EQ(kHlsProbably, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
+    EXPECT_TRUE(result);
   }
 
  private:
-  GURL url_;
   DISALLOW_COPY_AND_ASSIGN(MediaCanPlayTypeTest);
 };
 
-#if BUILDFLAG(ENABLE_AV1_DECODER)
 IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_av1) {
-  // Fully qualified codec strings are required. These tests are not exhaustive
-  // since codec string parsing is exhaustively tested elsewhere.
-  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"av1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"av1\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"av01.0.04M.08\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"av01.0.04M.08\"'"));
-}
+#if BUILDFLAG(ENABLE_AV1_DECODER)
+  ExecuteTest("testAv1Variants(true)");
 #else
-// AV1 is enabled by default. However, on platforms where it is not built, such
-// as ARM-based devices, av1 must be unsupported.
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_av1_unsupported) {
-  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"av01.0.04M.08\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"av01.0.04M.08\"'"));
-}
-#endif  // BUILDFLAG(ENABLE_AV1_DECODER)
-
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
-#if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_wav DISABLED_CodecSupportTest_wav
-#else
-#define MAYBE_CodecSupportTest_wav CodecSupportTest_wav
+  ExecuteTest("testAv1Variants(false)");
 #endif
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_wav) {
-  EXPECT_EQ(kMaybe, CanPlay("'audio/wav'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/wav; codecs=\"1\"'"));
-
-  TestWAVUnacceptableCombinations("audio/wav");
-
-  EXPECT_EQ(kMaybe, CanPlay("'audio/x-wav'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/x-wav; codecs=\"1\"'"));
-
-  TestWAVUnacceptableCombinations("audio/x-wav");
 }
 
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
-#if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_webm DISABLED_CodecSupportTest_webm
-#else
-#define MAYBE_CodecSupportTest_webm CodecSupportTest_webm
-#endif
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_webm) {
-  EXPECT_EQ(kMaybe, CanPlay("'video/webm'"));
-
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, vorbis\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, vorbis\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, opus\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, opus\"'"));
-
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9, vorbis\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0, vorbis\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9, opus\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0, opus\"'"));
-
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, vp9\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, vp9.0\"'"));
-
-  TestWEBMUnacceptableCombinations("video/webm");
-
-  EXPECT_EQ(kMaybe, CanPlay("'audio/webm'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"vorbis\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"opus\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"opus, vorbis\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8.0\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8, vorbis\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8.0, vorbis\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8, opus\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8.0, opus\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9.0\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9, vorbis\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9.0, vorbis\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9, opus\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp9.0, opus\"'"));
-
-  TestWEBMUnacceptableCombinations("audio/webm");
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_wav) {
+  ExecuteTest("testWavVariants()");
 }
 
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
-#if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_ogg DISABLED_CodecSupportTest_ogg
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) {
+  ExecuteTest("testWebmVariants()");
+}
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
+#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+  ExecuteTest("testOggVariants(true)");  // has_theora_support=true
 #else
-#define MAYBE_CodecSupportTest_ogg CodecSupportTest_ogg
+  ExecuteTest("testOggVariants(false)");  // has_theora_support=false
 #endif
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_ogg) {
-  EXPECT_EQ(kOggVideoMaybe, CanPlay("'video/ogg'"));
-  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"theora\"'"));
-  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"theora, flac\"'"));
-  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"theora, opus\"'"));
-  EXPECT_EQ(kOggVideoProbably,
-            CanPlay("'video/ogg; codecs=\"theora, vorbis\"'"));
-  EXPECT_EQ(kOggVideoProbably,
-            CanPlay("'video/ogg; codecs=\"flac, opus, vorbis\"'"));
-  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp8\"'"));
-  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp8.0\"'"));
-  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp8, opus\"'"));
-  EXPECT_EQ(kOggVideoProbably, CanPlay("'video/ogg; codecs=\"vp8, vorbis\"'"));
-
-  TestOGGUnacceptableCombinations("video/ogg");
-
-  EXPECT_EQ(kMaybe, CanPlay("'audio/ogg'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"flac\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"opus\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vorbis\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"flac, vorbis, opus\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora, flac\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora, opus\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora, vorbis\"'"));
-
-  TestOGGUnacceptableCombinations("audio/ogg");
-
-  EXPECT_EQ(kMaybe, CanPlay("'application/ogg'"));
-  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"flac\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"opus\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vorbis\"'"));
-  EXPECT_EQ(kProbably,
-            CanPlay("'application/ogg; codecs=\"flac, opus, vorbis\"'"));
-  EXPECT_EQ(kTheoraProbably, CanPlay("'application/ogg; codecs=\"theora\"'"));
-  EXPECT_EQ(kTheoraProbably,
-            CanPlay("'application/ogg; codecs=\"theora, flac\"'"));
-  EXPECT_EQ(kTheoraProbably,
-            CanPlay("'application/ogg; codecs=\"theora, opus\"'"));
-  EXPECT_EQ(kTheoraProbably,
-            CanPlay("'application/ogg; codecs=\"theora, vorbis\"'"));
-
-  TestOGGUnacceptableCombinations("application/ogg");
 }
 
 IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_flac) {
-  EXPECT_EQ(kProbably, CanPlay("'audio/flac'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"flac\"'"));
-
-  // See CodecSupportTest_mp4 for more flac combos.
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"flac\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"flac\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'video/flac'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-flac'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-flac'"));
-  EXPECT_EQ(kNot, CanPlay("'application/x-flac'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"flac\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'video/webm; codecs=\"flac\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"flac\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc3\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc1.4D401E\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"avc3.64001F\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/flac; codecs=\"mp4a.40.02\"'"));
+  ExecuteTest("testFlacVariants()");
 }
 
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
-#if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_mp3 DISABLED_CodecSupportTest_mp3
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
+  ExecuteTest("testMp3Variants()");
+}
+
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+  ExecuteTest("testMp4Variants(true)");  // has_proprietary_codecs=true
 #else
-#define MAYBE_CodecSupportTest_mp3 CodecSupportTest_mp3
+  ExecuteTest("testMp4Variants(false)");  // has_proprietary_codecs=false
 #endif
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_mp3) {
-  EXPECT_EQ(kNot, CanPlay("'video/mp3'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mpeg'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-mp3'"));
-
-  // audio/mpeg without a codecs parameter (RFC 3003 compliant)
-  EXPECT_EQ(kProbably, CanPlay("'audio/mpeg'"));
-
-  // audio/mpeg with mp3 in codecs parameter. (Not RFC compliant, but
-  // very common in the wild so it is a defacto standard).
-  EXPECT_EQ(kProbably, CanPlay("'audio/mpeg; codecs=\"mp3\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1.4D401E\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3.64001F\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.68\"'"));
-  // The next two results are wrong due to https://crbug.com/592889.
-  EXPECT_EQ(kProbably, CanPlay("'audio/mpeg; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/mpeg; codecs=\"mp4a.6B\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.40.02\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"flac\"'"));
-
-  TestMPEGUnacceptableCombinations("audio/mpeg");
-
-  // audio/mp3 does not allow any codecs parameter
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp3'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc3\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc1.4D401E\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc3.64001F\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.6B\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.40.02\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"flac\"'"));
-
-  TestMPEGUnacceptableCombinations("audio/mp3");
-  EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp3\"'"));
-
-  // audio/x-mp3 does not allow any codecs parameter
-  EXPECT_EQ(kProbably, CanPlay("'audio/x-mp3'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc3\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc1.4D401E\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc3.64001F\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.6B\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.02\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"flac\"'"));
-
-  TestMPEGUnacceptableCombinations("audio/x-mp3");
-  EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp3\"'"));
 }
 
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
-#if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_mp4 DISABLED_CodecSupportTest_mp4
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_AvcVariants) {
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+// High 10-bit profile is only available when we can use ffmpeg to decode H.264.
+// Even though FFmpeg is used on Android, we only use platform decoders for
+// H.264
+#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+  ExecuteTest("testAvcVariants(true, true)");  // has_proprietary_codecs=true,
+                                               // has_software_avc=true
 #else
-#define MAYBE_CodecSupportTest_mp4 CodecSupportTest_mp4
+  ExecuteTest("testAvcVariants(true, false)");  // has_proprietary_codecs=true,
+                                                // has_software_avc=false
 #endif
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_mp4) {
-  EXPECT_EQ(kMaybe, CanPlay("'video/mp4'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, avc3\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, flac\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, flac\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, opus\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, opus\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42101E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42701E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42F01E\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42E01E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42801E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42C01E\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"mp4a.6B\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.02\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc1.42E01E, mp4a.40.2\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc1.42E01E, mp4a.40.02\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc3.42E01E, mp4a.40.5\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc3.42E01E, mp4a.40.05\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc3.42E01E, mp4a.40.29\"'"));
-
-  // AC3 and EAC3 (aka Dolby Digital Plus, DD+) audio codecs. These are not
-  // supported by Chrome by default.
-  // TODO(servolk): Strictly speaking only mp4a.A5 and mp4a.A6 codec ids are
-  // valid according to RFC 6381 section 3.3, 3.4. Lower-case oti (mp4a.a5 and
-  // mp4a.a6) should be rejected. But we used to allow those in older versions
-  // of Chromecast firmware and some apps (notably MPL) depend on those codec
-  // types being supported, so they should be allowed for now (crbug.com/564960)
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"ac-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"mp4a.a5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"mp4a.A5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"ec-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"mp4a.a6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"mp4a.A6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.640028,ac-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.640028,mp4a.a5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.640028,mp4a.A5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.640028,ec-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.640028,mp4a.a6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.640028,mp4a.A6\"'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, mp4a.40.2\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, mp4a.40.02\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, mp4a.40.2\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3, mp4a.40.02\"'"));
-  EXPECT_EQ(kPropMaybe,
-            CanPlay("'video/mp4; codecs=\"avc1.42E01E, mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe,
-            CanPlay("'video/mp4; codecs=\"avc3.42E01E, mp4a.40\"'"));
-
-  EXPECT_EQ(kHevcSupported, CanPlay("'video/mp4; codecs=\"hev1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kHevcSupported, CanPlay("'video/mp4; codecs=\"hvc1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kHevcSupported,
-            CanPlay("'video/mp4; codecs=\"hev1.1.6.L93.B0, mp4a.40.5\"'"));
-  EXPECT_EQ(kHevcSupported,
-            CanPlay("'video/mp4; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
-
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"vp09.00.10.08\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"flac\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc1.4D401E, flac\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc3.64001F, flac\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"opus\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc1.4D401E, opus\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/mp4; codecs=\"avc3.64001F, opus\"'"));
-
-  TestMPEGUnacceptableCombinations("video/mp4");
-  // This result is incorrect. See https://crbug.com/592889.
-  EXPECT_EQ(kProbably, CanPlay("'video/mp4; codecs=\"mp3\"'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3, mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, avc3\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42E01E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42101E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42701E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42F01E\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42E01E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42801E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42C01E\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.6B\"'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.40.02\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/x-m4v; codecs=\"avc1.42E01E, mp4a.40.2\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/x-m4v; codecs=\"avc1.42E01E, mp4a.40.02\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/x-m4v; codecs=\"avc3.42E01E, mp4a.40.5\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/x-m4v; codecs=\"avc3.42E01E, mp4a.40.05\"'"));
-  EXPECT_EQ(kPropProbably,
-            CanPlay("'video/x-m4v; codecs=\"avc3.42E01E, mp4a.40.29\"'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, mp4a.40.2\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, mp4a.40.02\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3, mp4a.40.2\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc3, mp4a.40.02\"'"));
-  EXPECT_EQ(kPropMaybe,
-            CanPlay("'video/x-m4v; codecs=\"avc1.42E01E, mp4a.40\"'"));
-  EXPECT_EQ(kPropMaybe,
-            CanPlay("'video/x-m4v; codecs=\"avc3.42E01E, mp4a.40\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"hev1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"hvc1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kNot,
-            CanPlay("'video/x-m4v; codecs=\"hev1.1.6.L93.B0, mp4a.40.5\"'"));
-  EXPECT_EQ(kNot,
-            CanPlay("'video/x-m4v; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"vp09.00.10.08\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"ac-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.a5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.A5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"ec-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.a6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.A6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,ac-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.a5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,ec-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.a6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A6\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"flac\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"opus\"'"));
-
-  TestMPEGUnacceptableCombinations("video/x-m4v");
-
-  EXPECT_EQ(kMaybe, CanPlay("'audio/mp4'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"mp4a.6B\"'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"mp4a.40\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.02\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.5\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.05\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.29\"'"));
-
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"flac\"'"));
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"opus\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1, mp4a.40\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3, mp4a.40\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1.4D401E\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3.64001F\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"hev1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"hvc1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"hev1.1.6.L93.B0,mp4a.40.5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"hvc1.1.6.L93.B0,mp4a.40.5\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"vp09.00.10.08\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"ac-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.a5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.A5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"ec-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.a6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.A6\"'"));
-
-  TestMPEGUnacceptableCombinations("audio/mp4");
-  // This result is incorrect. See https://crbug.com/592889.
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"mp3\"'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a'"));
-
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.6B\"'"));
-
-  EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"mp4a.40\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.02\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.5\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.05\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.29\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1, mp4a\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc3, mp4a\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1.4D401E\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc3.64001F\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"hev1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"hvc1.1.6.L93.B0\"'"));
-  EXPECT_EQ(kNot,
-            CanPlay("'audio/x-m4a; codecs=\"hev1.1.6.L93.B0, mp4a.40.5\"'"));
-  EXPECT_EQ(kNot,
-            CanPlay("'audio/x-m4a; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"vp09.00.10.08\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"ac-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.a5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.A5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"ec-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.a6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.A6\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4a; codecs=\"flac\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/x-m4a; codecs=\"opus\"'"));
-
-  TestMPEGUnacceptableCombinations("audio/x-m4a");
+#else
+  ExecuteTest(
+      "testAvcVariants(false, false)");  // has_proprietary_codecs=false,
+                                         // has_software_avc=false
+#endif
 }
 
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Avc1Variants) {
-  // avc1 without extensions results in "maybe" for compatibility.
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1\"'"));
-
-  // A valid-looking 6-digit hexadecimal number will result in at least "maybe".
-  // But the first hex byte after the dot must be a valid profile_idc and the
-  // lower two bits of the second byte/4th digit must be zero.
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42AC23\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42ACDF\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42acdf\"'"));
-
-  // Invalid profile 0x12.
-  EXPECT_EQ(kNot,       CanPlay("'video/mp4; codecs=\"avc1.123456\"'"));
-  // Valid profile/level, but reserved bits are set to 1 (4th digit after dot).
-  EXPECT_EQ(kNot,       CanPlay("'video/mp4; codecs=\"avc1.42011E\"'"));
-  EXPECT_EQ(kNot,       CanPlay("'video/mp4; codecs=\"avc1.42021E\"'"));
-
-  // Both upper and lower case hexadecimal digits are accepted.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42e01e\"'"));
-
-  // From a YouTube DASH MSE test manifest.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4d401f\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4d401e\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4d4015\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.640028\"'"));
-
-  //
-  // Baseline Profile (66 == 0x42).
-  //  The first two digits after the dot must be 42. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42001E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42401E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42801E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E00A\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc1.42G01E\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc1.42000G\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E0FF\"'"));
-
-  //
-  // Main Profile (77 == 0x4D).
-  //  The first two digits after the dot must be 4D. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D001E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D400A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D800A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4DE00A\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc1.4DG01E\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc1.4D000G\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.4DE0FF\"'"));
-
-  //
-  // High Profile (100 == 0x64).
-  //  The first two digits after the dot must be 64. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64001E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64400A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64800A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64E00A\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc1.64G01E\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc1.64000G\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.64E0FF\"'"));
-
-  //
-  // High 10-bit Profile (110 == 0x6E).
-  //  The first two digits after the dot must be 6E. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kHi10pProbably, CanPlay("'video/mp4; codecs=\"avc1.6E001E\"'"));
-  EXPECT_EQ(kPropProbably,  CanPlay("'video/mp4; codecs=\"avc1.6E400A\"'"));
-  EXPECT_EQ(kPropProbably,  CanPlay("'video/mp4; codecs=\"avc1.6E800A\"'"));
-  EXPECT_EQ(kPropProbably,  CanPlay("'video/mp4; codecs=\"avc1.6EE00A\"'"));
-  EXPECT_EQ(kNot,           CanPlay("'video/mp4; codecs=\"avc1.6EG01E\"'"));
-  EXPECT_EQ(kNot,           CanPlay("'video/mp4; codecs=\"avc1.6E000G\"'"));
-  EXPECT_EQ(kPropMaybe,     CanPlay("'video/mp4; codecs=\"avc1.6EE0FF\"'"));
-
-  //
-  //  Other profiles are not known to be supported.
-  //
-
-  // Extended Profile (88 == 0x58).
-  //   Without any constraint flags.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.58001E\"'"));
-  //   With constraint_set0_flag==1 indicating compatibility with baseline
-  //   profile.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.58801E\"'"));
-  //   With constraint_set1_flag==1 indicating compatibility with main profile.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.58401E\"'"));
-  //   With constraint_set2_flag==1 indicating compatibility with extended
-  //   profile, the result is 'maybe' the same as for straight extended profile.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.58201E\"'"));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Avc3Variants) {
-  // avc3 without extensions results in "maybe" for compatibility.
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3\"'"));
-
-  // A valid-looking 6-digit hexadecimal number will result in at least "maybe".
-  // But the first hex byte after the dot must be a valid profile_idc and the
-  // lower two bits of the second byte/4th digit must be zero.
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42AC23\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42ACDF\"'"));
-  EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42acdf\"'"));
-
-  // Invalid profile 0x12.
-  EXPECT_EQ(kNot,       CanPlay("'video/mp4; codecs=\"avc3.123456\"'"));
-  // Valid profile/level, but reserved bits are set to 1 (4th digit after dot).
-  EXPECT_EQ(kNot,       CanPlay("'video/mp4; codecs=\"avc3.42011E\"'"));
-  EXPECT_EQ(kNot,       CanPlay("'video/mp4; codecs=\"avc3.42021E\"'"));
-
-  // Both upper and lower case hexadecimal digits are accepted.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42E01E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42e01e\"'"));
-
-  // From a YouTube DASH MSE test manifest.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4d401f\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4d401e\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4d4015\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.640028\"'"));
-
-  //
-  // Baseline Profile (66 == 0x42).
-  //  The first two digits after the dot must be 42. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42001E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42400A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42800A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42E00A\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc3.42G01E\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc3.42000G\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc3.42E0FF\"'"));
-
-  //
-  // Main Profile (77 == 0x4D).
-  //  The first two digits after the dot must be 4D. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4D001E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4D400A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4D800A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4DE00A\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc3.4DG01E\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc3.4D000G\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc3.4DE0FF\"'"));
-
-  //
-  // High Profile (100 == 0x64).
-  //  The first two digits after the dot must be 64. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64001E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64400A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64800A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64E00A\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc3.64G01E\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'video/mp4; codecs=\"avc3.64000G\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc3.64E0FF\"'"));
-
-  //
-  // High 10-bit Profile (110 == 0x6E).
-  //  The first two digits after the dot must be 6E. The third and fourth digits
-  //  contain constraint_set_flags and must be valid hex. The last two digits
-  //  should be any valid H.264 level. If the level value is invalid the result
-  //  will be kMaybe.
-  //
-  EXPECT_EQ(kHi10pProbably, CanPlay("'video/mp4; codecs=\"avc3.6E001E\"'"));
-  EXPECT_EQ(kPropProbably,  CanPlay("'video/mp4; codecs=\"avc3.6E400A\"'"));
-  EXPECT_EQ(kPropProbably,  CanPlay("'video/mp4; codecs=\"avc3.6E800A\"'"));
-  EXPECT_EQ(kPropProbably,  CanPlay("'video/mp4; codecs=\"avc3.6EE00A\"'"));
-  EXPECT_EQ(kNot,           CanPlay("'video/mp4; codecs=\"avc3.6EG01E\"'"));
-  EXPECT_EQ(kNot,           CanPlay("'video/mp4; codecs=\"avc3.6E000G\"'"));
-  EXPECT_EQ(kPropMaybe,     CanPlay("'video/mp4; codecs=\"avc3.6EE0FF\"'"));
-
-  //
-  //  Other profiles are not known to be supported.
-  //
-
-  // Extended Profile (88 == 0x58).
-  //   Without any constraint flags.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc3.58001E\"'"));
-  //   With constraint_set0_flag==1 indicating compatibility with baseline
-  //   profile.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.58801E\"'"));
-  //   With constraint_set1_flag==1 indicating compatibility with main profile.
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.58401E\"'"));
-  //   With constraint_set2_flag==1 indicating compatibility with extended
-  //   profile, the result is 'maybe' the same as for straight extended profile.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc3.58201E\"'"));
-}
-
-// Tests AVC levels using AVC1 Baseline (0x42E0zz).
-// Other supported values for the first four hexadecimal digits should behave
-// the same way but are not tested.
-// For each full level, the following are tested:
-// * The hexadecimal value before it is not supported.
-// * The hexadecimal value for the main level and all sub-levels are supported.
-// * The hexadecimal value after the last sub-level it is not supported.
-// * Decimal representations of the levels are not supported.
-
 IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_AvcLevels) {
-  // Level 0 is not supported.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E000\"'"));
-
-  // Levels 1 (0x0A), 1.1 (0x0B), 1.2 (0x0C), 1.3 (0x0D).
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E009\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E00A\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E00B\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E00C\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E00D\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E00E\"'"));
-  // Verify that decimal representations of levels are not supported.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E001\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E010\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E011\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E012\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E013\"'"));
-
-  // Levels 2 (0x14), 2.1 (0x15), 2.2 (0x16)
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E013\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E014\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E015\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E016\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E017\"'"));
-  // Verify that decimal representations of levels are not supported.
-  // However, 20 is level 3.2.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E002\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E020\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E021\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E022\"'"));
-
-  // Levels 3 (0x1e), 3.1 (0x1F), 3.2 (0x20)
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E01D\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01F\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E020\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E021\"'"));
-  // Verify that decimal representations of levels are not supported.
-  // However, 32 is level 5.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E003\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E030\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E031\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E032\"'"));
-
-  // Levels 4 (0x28), 4.1 (0x29), 4.2 (0x2A)
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E027\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E028\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E029\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E02A\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E02B\"'"));
-  // Verify that decimal representations of levels are not supported.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E004\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E040\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E041\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E042\"'"));
-
-  // Levels 5 (0x32), 5.1 (0x33), 5.2 (0x34).
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E031\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E032\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E033\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E034\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E035\"'"));
-  // Verify that decimal representations of levels are not supported.
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E005\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E050\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E051\"'"));
-  EXPECT_EQ(kPropMaybe,    CanPlay("'video/mp4; codecs=\"avc1.42E052\"'"));
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+  ExecuteTest("testAvcLevels(true)");  // has_proprietary_codecs=true
+#else
+  ExecuteTest("testAvcLevels(false)");   // has_proprietary_codecs=false
+#endif
 }
 
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mp4aVariants) {
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
 #if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_Mp4aVariants \
-  DISABLED_CodecSupportTest_Mp4aVariants
-#else
-#define MAYBE_CodecSupportTest_Mp4aVariants CodecSupportTest_Mp4aVariants
+  // xHE-AAC support is currently only available on P+.
+  if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+      base::android::SDK_VERSION_P) {
+    ExecuteTest(
+        "testMp4aVariants(true, true)");  // has_proprietary_codecs=true,
+                                          // has_xhe_aac_support=true
+    return;
+  }
 #endif
-
-// All values that return positive results are tested. There are also
-// negative tests for values around or that could potentially be confused with
-// (e.g. case, truncation, hex <-> deciemal conversion) those values that return
-// positive results.
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest,
-                       MAYBE_CodecSupportTest_Mp4aVariants) {
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.\"'"));
-
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.6\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.60\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.61\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.62\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.63\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.65\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.65\"'"));
-  // MPEG2 AAC Main, LC, and SSR are supported.
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.68\"'"));
-  // MP3.
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.6A\"'"));
-  // MP3.
-  EXPECT_EQ(kProbably, CanPlay("'audio/mp4; codecs=\"mp4a.6B\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.6b\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.6C\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.6D\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.6E\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.6F\"'"));
-
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.76\"'"));
-
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.4\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.39\"'"));
-
-  // mp4a.40 without further extension is ambiguous and results in "maybe".
-  EXPECT_EQ(kPropMaybe,    CanPlay("'audio/mp4; codecs=\"mp4a.40\"'"));
-
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.0\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.1\"'"));
-  // MPEG4 AAC LC.
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.2\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.3\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.4\"'"));
-  // MPEG4 AAC SBR v1.
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.5\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.6\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.7\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.8\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.9\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.10\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.20\"'"));
-  // MPEG4 AAC SBR PS v2.
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.29\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.30\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.40\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.50\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.290\"'"));
-  // Check conversions of decimal 29 to hex and hex 29 to decimal.
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.1d\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.1D\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.41\"'"));
-
-  // Allow leading zeros in aud-oti for specific MPEG4 AAC strings.
-  // See http://crbug.com/440607.
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.00\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.01\"'"));
-  // MPEG4 AAC LC.
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.02\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.03\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.04\"'"));
-  // MPEG4 AAC SBR v1.
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.05\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.40.029\"'"));
-
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.41\"'"));
-  EXPECT_EQ(kNot,          CanPlay("'audio/mp4; codecs=\"mp4a.41.2\"'"));
-
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.4.2\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.400.2\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.040.2\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.4.5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.400.5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.040.5\"'"));
-
-// xHE-AAC support is currently only available on P+.
-#if defined(OS_ANDROID)
-  const char* kXHE_AACProbably =
-      base::android::BuildInfo::GetInstance()->sdk_int() >=
-              base::android::SDK_VERSION_P
-          ? kProbably
-          : kNot;
+  ExecuteTest("testMp4aVariants(true, false)");  // has_proprietary_codecs=true,
+                                                 // has_xhe_aac_support=false
 #else
-  const char* kXHE_AACProbably = kNot;
+  ExecuteTest(
+      "testMp4aVariants(false, false)");    // has_proprietary_codecs=false,
+                                            // has_xhe_aac_support=false
 #endif
-  EXPECT_EQ(kXHE_AACProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.42\"'"));
-  EXPECT_EQ(kXHE_AACProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.42\"'"));
 }
 
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) {
 #if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_HLS DISABLED_CodecSupportTest_HLS
+  ExecuteTest("testHls(true)");  // has_hls_support=true
 #else
-#define MAYBE_CodecSupportTest_HLS CodecSupportTest_HLS
+  ExecuteTest("testHls(false)");            // has_hls_support=false
 #endif
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_HLS) {
-  TestHLSCombinations("application/vnd.apple.mpegurl");
-  TestHLSCombinations("application/x-mpegurl");
-  TestHLSCombinations("audio/mpegurl");
-  TestHLSCombinations("audio/x-mpegurl");
 }
 
 IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_AAC_ADTS) {
-  EXPECT_EQ(kPropProbably, CanPlay("'audio/aac'"));
-
-  // audio/aac doesn't support the codecs parameter.
-  EXPECT_EQ(kNot, CanPlay("'audio/aac; codecs=\"1\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/aac; codecs=\"aac\"'"));
-  EXPECT_EQ(kNot, CanPlay("'audio/aac; codecs=\"mp4a.40.2\"'"));
-}
-
-// Flaky on Lollipop and Marshmallow.  https://crbug.com/1090770
-#if defined(OS_ANDROID)
-#define MAYBE_CodecSupportTest_Mpeg2Ts DISABLED_CodecSupportTest_Mpeg2Ts
+#if BUILDFLAG(USE_PROPRIETARY_CODECS)
+  ExecuteTest("testAacAdts(true)");  // has_proprietary_codecs=true
 #else
-#define MAYBE_CodecSupportTest_Mpeg2Ts CodecSupportTest_Mpeg2Ts
+  ExecuteTest("testAacAdts(false)");        // has_proprietary_codecs=false
 #endif
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, MAYBE_CodecSupportTest_Mpeg2Ts) {
-  EXPECT_EQ(kMp2tsMaybe, CanPlay("'video/mp2t'"));
-
-  // video/mp2t must support standard RFC 6381 compliant H.264 / AAC codec ids.
-  // H.264 baseline, main, high profiles
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.42E01E\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.4D401E\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.640028\"'"));
-
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.66\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.67\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.68\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.69\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.6B\"'"));
-
-  // AAC LC audio
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.40.2\"'"));
-  // H.264 + AAC audio combinations
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.42E01E,mp4a.40.2\"'"));
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.4D401E,mp4a.40.2\"'"));
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.640028,mp4a.40.2\"'"));
-  // H.264 + AC3/EAC3 audio combinations
-  EXPECT_EQ(kNot, CanPlay("'video/mp2t; codecs=\"avc1.640028,ac-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp2t; codecs=\"avc1.640028,ec-3\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp2t; codecs=\"avc1.640028,mp4a.A5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp2t; codecs=\"avc1.640028,mp4a.A6\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp2t; codecs=\"avc1.640028,mp4a.a5\"'"));
-  EXPECT_EQ(kNot, CanPlay("'video/mp2t; codecs=\"avc1.640028,mp4a.a6\"'"));
-
-  TestMPEGUnacceptableCombinations("video/mp2t");
-  // This result is incorrect. See https://crbug.com/592889.
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp3\"'"));
 }
 
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest,
-                       CodecSupportTest_Mpeg2Ts_LegacyAvc1_codec_ids) {
-  // Old-style avc1/H.264 codec ids that are still being used by some HLS
-  // streaming apps for backward compatibility.
-  // H.264 baseline profile
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.10\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.13\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.20\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.22\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.30\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.32\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.40\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.66.42\"'"));
-  // H.264 main profile
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.10\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.13\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.20\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.22\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.30\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.32\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.40\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.77.42\"'"));
-  // H.264 high profile
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.10\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.13\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.20\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.22\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.30\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.32\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.40\"'"));
-  EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.100.42\"'"));
-
-  // H.264 + AAC audio combinations
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.66.10,mp4a.40.2\"'"));
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.66.30,mp4a.40.2\"'"));
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.77.10,mp4a.40.2\"'"));
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.77.30,mp4a.40.2\"'"));
-  EXPECT_EQ(kMp2tsProbably,
-            CanPlay("'video/mp2t; codecs=\"avc1.100.40,mp4a.40.2\"'"));
-}
-
-IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2TsAudio) {
-  // audio/mp2t is currently not supported (see also crbug.com/556837).
-  EXPECT_EQ(kNot, CanPlay("'audio/mp2t; codecs=\"mp4a.40.2\"'"));
+IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2Ts) {
+// TODO(crbug.com/1091962): This is actually wrong. We don't support mpeg2ts in
+// src=, only MSE playbacks, so this should actually indicate no support when
+// querying canPlayType().
+#if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) && \
+    BUILDFLAG(USE_PROPRIETARY_CODECS)
+  ExecuteTest("testMp2tsVariants(true)");  // has_mp2ts_support=true
+#else
+  ExecuteTest("testMp2tsVariants(false)");  // has_mp2ts_support=false
+#endif
 }
 
 // See more complete codec string testing in media/base/video_codecs_unittest.cc
 IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_NewVp9Variants) {
-  const std::string kSupportedMimeTypes[] = {"video/webm", "video/mp4"};
-  for (const auto& mime_type : kSupportedMimeTypes) {
 // Profile 2 and 3 support is currently disabled on Android prior to P and MIPS.
 #if (defined(ARCH_CPU_ARM_FAMILY) && !defined(OS_WIN)) || \
     defined(ARCH_CPU_MIPS_FAMILY)
 #if defined(OS_ANDROID)
-    const char* kVP9Profile2And3Probably =
-        base::android::BuildInfo::GetInstance()->sdk_int() >=
-                base::android::SDK_VERSION_P
-            ? kProbably
-            : kNot;
-#else
-    const char* kVP9Profile2And3Probably = kNot;
-#endif
-#else
-    const char* kVP9Profile2And3Probably = kProbably;
-#endif
-
-    // E.g. "'video/webm; "
-    std::string prefix = "'" + mime_type + "; ";
-
-    // Malformed codecs string never allowed.
-    EXPECT_EQ(kNot, CanPlay(prefix + "codecs=\"vp09.00.-1.08\"'"));
-
-    // Test a few valid strings.
-    EXPECT_EQ(kProbably, CanPlay(prefix + "codecs=\"vp09.00.10.08\"'"));
-    EXPECT_EQ(kProbably,
-              CanPlay(prefix + "codecs=\"vp09.00.10.08.00.01.01.01.00\"'"));
-    EXPECT_EQ(kProbably,
-              CanPlay(prefix + "codecs=\"vp09.00.10.08.01.02.02.02.00\"'"));
-
-    // Profiles 0 and 1 are always supported supported. Profiles 2 and 3 are
-    // only supported on certain architectures.
-    EXPECT_EQ(kProbably, CanPlay(prefix + "codecs=\"vp09.01.10.08\"'"));
-    EXPECT_EQ(kVP9Profile2And3Probably,
-              CanPlay(prefix + "codecs=\"vp09.02.10.08\"'"));
-    EXPECT_EQ(kVP9Profile2And3Probably,
-              CanPlay(prefix + "codecs=\"vp09.03.10.08\"'"));
+  if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+      base::android::SDK_VERSION_P) {
+    ExecuteTest("testNewVp9Variants(true)");  // has_profile_2_3_support=true
+    return;
   }
+#endif
+  ExecuteTest("testNewVp9Variants(false)");  // has_profile_2_3_support=false
+#else
+  ExecuteTest("testNewVp9Variants(true)");  // has_profile_2_3_support=true
+#endif
 }
 
 }  // namespace content
diff --git a/content/browser/network_service_client.cc b/content/browser/network_service_client.cc
index 214ca696..f95b14a0 100644
--- a/content/browser/network_service_client.cc
+++ b/content/browser/network_service_client.cc
@@ -211,10 +211,10 @@
     int32_t process_id,
     int32_t routing_id,
     const std::string& devtools_request_id,
-    const net::CookieStatusList& cookies_with_status,
+    const net::CookieAccessResultList& cookies_with_access_result,
     std::vector<network::mojom::HttpRawHeaderPairPtr> headers) {
   devtools_instrumentation::OnRequestWillBeSentExtraInfo(
-      process_id, routing_id, devtools_request_id, cookies_with_status,
+      process_id, routing_id, devtools_request_id, cookies_with_access_result,
       headers);
 }
 
diff --git a/content/browser/network_service_client.h b/content/browser/network_service_client.h
index c1d777cb..b023b3b 100644
--- a/content/browser/network_service_client.h
+++ b/content/browser/network_service_client.h
@@ -54,7 +54,7 @@
       int32_t process_id,
       int32_t routing_id,
       const std::string& devtools_request_id,
-      const net::CookieStatusList& cookies_with_status,
+      const net::CookieAccessResultList& cookies_with_access_result,
       std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override;
   void OnRawResponse(
       int32_t process_id,
diff --git a/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc b/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc
index 5b63925..81898cf 100644
--- a/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_content_browsertest.cc
@@ -44,7 +44,7 @@
     size_ = natural_size;
   }
   void SetPlaybackState(PlaybackState playback_state) override {}
-  void SetAlwaysHidePlayPauseButton(bool is_visible) override {}
+  void SetPlayPauseButtonVisibility(bool is_visible) override {}
   void SetSkipAdButtonVisibility(bool is_visible) override {}
   void SetNextTrackButtonVisibility(bool is_visible) override {}
   void SetPreviousTrackButtonVisibility(bool is_visible) override {}
diff --git a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
index f564c5d..925d178 100644
--- a/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_service_impl_unittest.cc
@@ -75,7 +75,7 @@
     size_ = natural_size;
   }
   void SetPlaybackState(PlaybackState playback_state) override {}
-  void SetAlwaysHidePlayPauseButton(bool is_visible) override {}
+  void SetPlayPauseButtonVisibility(bool is_visible) override {}
   void SetSkipAdButtonVisibility(bool is_visible) override {}
   void SetNextTrackButtonVisibility(bool is_visible) override {}
   void SetPreviousTrackButtonVisibility(bool is_visible) override {}
diff --git a/content/browser/picture_in_picture/picture_in_picture_session.cc b/content/browser/picture_in_picture/picture_in_picture_session.cc
index d9e3a63..cb45df5 100644
--- a/content/browser/picture_in_picture/picture_in_picture_session.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_session.cc
@@ -42,7 +42,7 @@
   player_id_ = MediaPlayerId(service_->render_frame_host(), player_id);
 
   GetController().EmbedSurface(surface_id.value(), natural_size);
-  GetController().SetAlwaysHidePlayPauseButton(show_play_pause_button);
+  GetController().SetShowPlayPauseButton(show_play_pause_button);
 }
 
 void PictureInPictureSession::NotifyWindowResized(const gfx::Size& size) {
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
index 3273f4d..06674e9 100644
--- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
+++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.cc
@@ -212,7 +212,7 @@
       std::move(observer));
 
   EmbedSurface(surface_id, natural_size);
-  SetAlwaysHidePlayPauseButton(show_play_pause_button);
+  SetShowPlayPauseButton(show_play_pause_button);
   Show();
 
   *window_size = GetSize();
@@ -228,9 +228,9 @@
   active_session_ = nullptr;
 }
 
-void PictureInPictureWindowControllerImpl::SetAlwaysHidePlayPauseButton(
-    bool is_visible) {
-  always_hide_play_pause_button_ = is_visible;
+void PictureInPictureWindowControllerImpl::SetShowPlayPauseButton(
+    bool show_play_pause_button) {
+  always_show_play_pause_button_ = show_play_pause_button;
   UpdatePlayPauseButtonVisibility();
 }
 
@@ -363,9 +363,9 @@
   if (!window_)
     return;
 
-  window_->SetAlwaysHidePlayPauseButton((media_session_action_pause_handled_ &&
+  window_->SetPlayPauseButtonVisibility((media_session_action_pause_handled_ &&
                                          media_session_action_play_handled_) ||
-                                        always_hide_play_pause_button_);
+                                        always_show_play_pause_button_);
 }
 
 WebContentsImpl* PictureInPictureWindowControllerImpl::GetWebContentsImpl() {
diff --git a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
index 9fe3f5c..6e3b020 100644
--- a/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
+++ b/content/browser/picture_in_picture/picture_in_picture_window_controller_impl.h
@@ -65,7 +65,6 @@
   bool TogglePlayPause() override;
   void UpdatePlaybackState(bool is_playing,
                            bool reached_end_of_stream) override;
-  void SetAlwaysHidePlayPauseButton(bool is_visible) override;
   void SkipAd() override;
   void NextTrack() override;
   void PreviousTrack() override;
@@ -87,6 +86,8 @@
   void EmbedSurface(const viz::SurfaceId& surface_id,
                     const gfx::Size& natural_size);
 
+  void SetShowPlayPauseButton(bool show_play_pause_button);
+
   // Called by PictureInPictureServiceImpl when a session request is received.
   // The call should return the |session_remote| and |window_size| as out
   // params. A failure to create the session should be expressed with an empty
@@ -153,7 +154,7 @@
   // Used to hide play/pause button if video is a MediaStream or has infinite
   // duration. Play/pause button visibility can be overridden by the Media
   // Session API in UpdatePlayPauseButtonVisibility().
-  bool always_hide_play_pause_button_ = false;
+  bool always_show_play_pause_button_ = false;
 
   // Session currently associated with the Picture-in-Picture window. The
   // session object makes the bridge with the renderer process by handling
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h
index 0ae78ea..ee162263 100644
--- a/content/browser/renderer_host/input/input_router.h
+++ b/content/browser/renderer_host/input/input_router.h
@@ -10,11 +10,11 @@
 #include "content/browser/renderer_host/event_with_latency_info.h"
 #include "content/browser/renderer_host/input/gesture_event_queue.h"
 #include "content/browser/renderer_host/input/passthrough_touch_event_queue.h"
-#include "content/common/widget.mojom.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "third_party/blink/public/mojom/input/input_event_result.mojom-shared.h"
+#include "third_party/blink/public/mojom/input/input_handler.mojom.h"
 
 namespace content {
 
@@ -89,10 +89,6 @@
   virtual mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost>
   BindNewHost() = 0;
 
-  // Create and bind a new frame based host channel.
-  virtual mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost>
-  BindNewFrameHost() = 0;
-
   // Used to stop an active fling if such exists.
   virtual void StopFling() = 0;
 
diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc
index b7ee8d1..29aef58 100644
--- a/content/browser/renderer_host/input/input_router_impl.cc
+++ b/content/browser/renderer_host/input/input_router_impl.cc
@@ -262,12 +262,6 @@
   return host_receiver_.BindNewPipeAndPassRemote();
 }
 
-mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost>
-InputRouterImpl::BindNewFrameHost() {
-  frame_host_receiver_.reset();
-  return frame_host_receiver_.BindNewPipeAndPassRemote();
-}
-
 void InputRouterImpl::StopFling() {
   gesture_event_queue_.StopFling();
 }
diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h
index 9f913e4..577b6416 100644
--- a/content/browser/renderer_host/input/input_router_impl.h
+++ b/content/browser/renderer_host/input/input_router_impl.h
@@ -24,7 +24,6 @@
 #include "content/browser/renderer_host/input/touch_action_filter.h"
 #include "content/browser/renderer_host/input/touchpad_pinch_event_queue.h"
 #include "content/common/input/input_event_stream_validator.h"
-#include "content/common/widget.mojom.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -85,8 +84,6 @@
   base::Optional<cc::TouchAction> ActiveTouchAction() override;
   mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> BindNewHost()
       override;
-  mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> BindNewFrameHost()
-      override;
   void StopFling() override;
   void OnSetTouchAction(cc::TouchAction touch_action) override;
   void ForceSetTouchActionAuto() override;
@@ -110,8 +107,8 @@
 
   // Exposed so that tests can swap out the implementation and intercept calls.
   mojo::Receiver<blink::mojom::WidgetInputHandlerHost>&
-  frame_host_receiver_for_testing() {
-    return frame_host_receiver_;
+  host_receiver_for_testing() {
+    return host_receiver_;
   }
 
   void ForceResetTouchActionForTest();
@@ -258,11 +255,6 @@
   // the widget.
   mojo::Receiver<blink::mojom::WidgetInputHandlerHost> host_receiver_{this};
 
-  // The host receiver associated with the widget input handler from
-  // the frame.
-  mojo::Receiver<blink::mojom::WidgetInputHandlerHost> frame_host_receiver_{
-      this};
-
   base::WeakPtr<InputRouterImpl> weak_this_;
   base::WeakPtrFactory<InputRouterImpl> weak_ptr_factory_{this};
 
diff --git a/content/browser/renderer_host/input/mock_input_router.cc b/content/browser/renderer_host/input/mock_input_router.cc
index 848dfc2..22abfeeb 100644
--- a/content/browser/renderer_host/input/mock_input_router.cc
+++ b/content/browser/renderer_host/input/mock_input_router.cc
@@ -50,11 +50,6 @@
   return mojo::NullRemote();
 }
 
-mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost>
-MockInputRouter::BindNewFrameHost() {
-  return mojo::NullRemote();
-}
-
 void MockInputRouter::OnHasTouchEventHandlers(bool has_handlers) {
   has_handlers_ = has_handlers;
 }
diff --git a/content/browser/renderer_host/input/mock_input_router.h b/content/browser/renderer_host/input/mock_input_router.h
index e0e6fa6c..de9cd99 100644
--- a/content/browser/renderer_host/input/mock_input_router.h
+++ b/content/browser/renderer_host/input/mock_input_router.h
@@ -46,8 +46,6 @@
   void SetForceEnableZoom(bool enabled) override {}
   mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> BindNewHost()
       override;
-  mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> BindNewFrameHost()
-      override;
   void StopFling() override {}
   void OnSetTouchAction(cc::TouchAction touch_action) override {}
   void ForceSetTouchActionAuto() override {}
diff --git a/content/browser/renderer_host/input/mouse_latency_browsertest.cc b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
index cfc239f3..d134d4d7 100644
--- a/content/browser/renderer_host/input/mouse_latency_browsertest.cc
+++ b/content/browser/renderer_host/input/mouse_latency_browsertest.cc
@@ -78,12 +78,10 @@
   TracingRenderWidgetHost(RenderWidgetHostDelegate* delegate,
                           RenderProcessHost* process,
                           int32_t routing_id,
-                          mojo::PendingRemote<mojom::Widget> widget,
                           bool hidden)
       : RenderWidgetHostImpl(delegate,
                              process,
                              routing_id,
-                             std::move(widget),
                              hidden,
                              std::make_unique<FrameTokenMessageQueue>()) {
   }
@@ -112,10 +110,9 @@
       RenderWidgetHostDelegate* delegate,
       RenderProcessHost* process,
       int32_t routing_id,
-      mojo::PendingRemote<mojom::Widget> widget_interface,
       bool hidden) override {
-    return std::make_unique<TracingRenderWidgetHost>(
-        delegate, process, routing_id, std::move(widget_interface), hidden);
+    return std::make_unique<TracingRenderWidgetHost>(delegate, process,
+                                                     routing_id, hidden);
   }
 
  private:
diff --git a/content/browser/renderer_host/mock_render_widget_host.cc b/content/browser/renderer_host/mock_render_widget_host.cc
index 7ddbca1..ac444ae 100644
--- a/content/browser/renderer_host/mock_render_widget_host.cc
+++ b/content/browser/renderer_host/mock_render_widget_host.cc
@@ -71,12 +71,7 @@
     RenderWidgetHostDelegate* delegate,
     RenderProcessHost* process,
     int32_t routing_id) {
-  mojo::PendingRemote<mojom::Widget> widget;
-  std::unique_ptr<MockWidgetImpl> widget_impl =
-      std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());
-
-  return new MockRenderWidgetHost(delegate, process, routing_id,
-                                  std::move(widget_impl), std::move(widget));
+  return new MockRenderWidgetHost(delegate, process, routing_id);
 }
 
 blink::mojom::WidgetInputHandler*
@@ -88,20 +83,15 @@
   new_content_rendering_timeout_fired_ = true;
 }
 
-MockRenderWidgetHost::MockRenderWidgetHost(
-    RenderWidgetHostDelegate* delegate,
-    RenderProcessHost* process,
-    int routing_id,
-    std::unique_ptr<MockWidgetImpl> widget_impl,
-    mojo::PendingRemote<mojom::Widget> widget)
+MockRenderWidgetHost::MockRenderWidgetHost(RenderWidgetHostDelegate* delegate,
+                                           RenderProcessHost* process,
+                                           int routing_id)
     : RenderWidgetHostImpl(delegate,
                            process,
                            routing_id,
-                           std::move(widget),
                            /*hidden=*/false,
                            std::make_unique<TestFrameTokenMessageQueue>()),
       new_content_rendering_timeout_fired_(false),
-      widget_impl_(std::move(widget_impl)),
       fling_scheduler_(std::make_unique<FlingScheduler>(this)) {
   acked_touch_event_type_ = blink::WebInputEvent::Type::kUndefined;
   mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
diff --git a/content/browser/renderer_host/mock_render_widget_host.h b/content/browser/renderer_host/mock_render_widget_host.h
index ba4e3b3..ea4c29d 100644
--- a/content/browser/renderer_host/mock_render_widget_host.h
+++ b/content/browser/renderer_host/mock_render_widget_host.h
@@ -9,7 +9,6 @@
 
 #include "content/browser/renderer_host/input/mock_input_router.h"
 #include "content/common/input/event_with_latency_info.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/mock_widget_input_handler.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
@@ -78,11 +77,7 @@
  private:
   MockRenderWidgetHost(RenderWidgetHostDelegate* delegate,
                        RenderProcessHost* process,
-                       int routing_id,
-                       std::unique_ptr<MockWidgetImpl> widget_impl,
-                       mojo::PendingRemote<mojom::Widget> widget);
-
-  std::unique_ptr<MockWidgetImpl> widget_impl_;
+                       int routing_id);
 
   std::unique_ptr<FlingScheduler> fling_scheduler_;
   DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHost);
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 28ab901..42d8ca7 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -219,6 +219,7 @@
 #include "storage/browser/database/database_tracker.h"
 #include "storage/browser/file_system/sandbox_file_system_backend.h"
 #include "third_party/blink/public/common/page/launching_process_state.h"
+#include "third_party/blink/public/common/switches.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
 #include "third_party/blink/public/mojom/disk_allocator.mojom.h"
 #include "third_party/blink/public/public_buildflags.h"
@@ -3240,7 +3241,6 @@
     service_manager::switches::kEnableSandboxLogging,
 #endif
     switches::kAgcStartupMinVolume,
-    switches::kAllowPreCommitInput,
     switches::kAllowLoopbackInPeerConnection,
     switches::kAndroidFontsPath,
     switches::kAudioBufferSize,
@@ -3367,6 +3367,8 @@
     switches::kVModule,
     switches::kWebglAntialiasingMode,
     switches::kWebglMSAASampleCount,
+    // Please keep these in alphabetical order.
+    blink::switches::kAllowPreCommitInput,
     // Please keep these in alphabetical order. Compositor switches here
     // should also be added to
     // chrome/browser/chromeos/login/chrome_restart_request.cc.
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index c34293bd..3dee9eb 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -15,7 +15,6 @@
 #include "content/browser/dom_storage/session_storage_namespace_impl.h"
 #include "content/common/content_export.h"
 #include "content/common/render_message_filter.mojom.h"
-#include "content/common/widget.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/base/load_states.h"
 
diff --git a/content/browser/renderer_host/render_view_host_factory.cc b/content/browser/renderer_host/render_view_host_factory.cc
index 305aba1..1db0c39 100644
--- a/content/browser/renderer_host/render_view_host_factory.cc
+++ b/content/browser/renderer_host/render_view_host_factory.cc
@@ -38,7 +38,7 @@
   RenderViewHostImpl* view_host = new RenderViewHostImpl(
       instance,
       RenderWidgetHostFactory::Create(widget_delegate, instance->GetProcess(),
-                                      widget_routing_id, mojo::NullRemote(),
+                                      widget_routing_id,
                                       /*hidden=*/true),
       delegate, routing_id, main_frame_routing_id, swapped_out,
       true /* has_initialized_audio_host */);
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index a2d1447..ae5aa12 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -897,7 +897,6 @@
     IPC_MESSAGE_HANDLER(ViewHostMsg_RouteCloseEvent, OnRouteCloseEvent)
     IPC_MESSAGE_HANDLER(ViewHostMsg_UpdateTargetURL, OnUpdateTargetURL)
     IPC_MESSAGE_HANDLER(ViewHostMsg_TakeFocus, OnTakeFocus)
-    IPC_MESSAGE_HANDLER(ViewHostMsg_Focus, OnFocus)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
diff --git a/content/browser/renderer_host/render_view_host_unittest.cc b/content/browser/renderer_host/render_view_host_unittest.cc
index 88d4d57..5539341 100644
--- a/content/browser/renderer_host/render_view_host_unittest.cc
+++ b/content/browser/renderer_host/render_view_host_unittest.cc
@@ -26,7 +26,6 @@
 #include "content/public/common/url_constants.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/navigation_simulator.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/navigation_simulator_impl.h"
 #include "content/test/test_content_browser_client.h"
 #include "content/test/test_render_view_host.h"
diff --git a/content/browser/renderer_host/render_widget_host_factory.cc b/content/browser/renderer_host/render_widget_host_factory.cc
index d13c1a7..c1c1476 100644
--- a/content/browser/renderer_host/render_widget_host_factory.cc
+++ b/content/browser/renderer_host/render_widget_host_factory.cc
@@ -17,14 +17,13 @@
     RenderWidgetHostDelegate* delegate,
     RenderProcessHost* process,
     int32_t routing_id,
-    mojo::PendingRemote<mojom::Widget> widget_interface,
     bool hidden) {
   if (factory_) {
-    return factory_->CreateRenderWidgetHost(
-        delegate, process, routing_id, std::move(widget_interface), hidden);
+    return factory_->CreateRenderWidgetHost(delegate, process, routing_id,
+                                            hidden);
   }
   return std::make_unique<RenderWidgetHostImpl>(
-      delegate, process, routing_id, std::move(widget_interface), hidden,
+      delegate, process, routing_id, hidden,
       std::make_unique<FrameTokenMessageQueue>());
 }
 
diff --git a/content/browser/renderer_host/render_widget_host_factory.h b/content/browser/renderer_host/render_widget_host_factory.h
index 1032e4a..3e263d6 100644
--- a/content/browser/renderer_host/render_widget_host_factory.h
+++ b/content/browser/renderer_host/render_widget_host_factory.h
@@ -10,7 +10,6 @@
 
 #include "base/macros.h"
 #include "content/common/content_export.h"
-#include "content/common/widget.mojom.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
 namespace content {
@@ -30,7 +29,6 @@
       RenderWidgetHostDelegate* delegate,
       RenderProcessHost* process,
       int32_t routing_id,
-      mojo::PendingRemote<mojom::Widget> widget_interface,
       bool hidden);
 
   // Returns true if there is currently a globally-registered factory.
@@ -46,7 +44,6 @@
       RenderWidgetHostDelegate* delegate,
       RenderProcessHost* process,
       int32_t routing_id,
-      mojo::PendingRemote<mojom::Widget> widget_interface,
       bool hidden) = 0;
 
   // Registers your factory to be called when new RenderWidgetHostImpls are
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index f994ebc..c4573af5 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -24,6 +24,7 @@
 #include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -198,7 +199,7 @@
 
 std::vector<DropData::Metadata> DropDataToMetaData(const DropData& drop_data) {
   std::vector<DropData::Metadata> metadata;
-  if (!drop_data.text.is_null()) {
+  if (drop_data.text) {
     metadata.push_back(DropData::Metadata::CreateForMimeType(
         DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeText)));
   }
@@ -208,7 +209,7 @@
         DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeURIList)));
   }
 
-  if (!drop_data.html.is_null()) {
+  if (drop_data.html) {
     metadata.push_back(DropData::Metadata::CreateForMimeType(
         DropData::Kind::STRING, base::ASCIIToUTF16(ui::kMimeTypeHTML)));
   }
@@ -302,6 +303,11 @@
           compositor_request) override {
     NOTREACHED() << "Input request on unbound interface";
   }
+  void GetFrameWidgetInputHandler(
+      mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler>
+          request) override {
+    NOTREACHED() << "Input request on unbound interface";
+  }
 };
 
 base::LazyInstance<UnboundWidgetInputHandler>::Leaky g_unbound_input_handler =
@@ -316,7 +322,6 @@
     RenderWidgetHostDelegate* delegate,
     RenderProcessHost* process,
     int32_t routing_id,
-    mojo::PendingRemote<mojom::Widget> widget,
     bool hidden,
     std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue)
     : delegate_(delegate),
@@ -365,7 +370,6 @@
   process_->AddPriorityClient(this);
 
   SetupInputRouter();
-  SetWidget(std::move(widget));
 
   const auto* command_line = base::CommandLine::ForCurrentProcess();
   if (!command_line->HasSwitch(switches::kDisableNewContentRenderingTimeout)) {
@@ -518,6 +522,15 @@
 
   set_renderer_initialized(true);
 
+  blink_widget_->GetWidgetInputHandler(
+      widget_input_handler_.BindNewPipeAndPassReceiver(),
+      input_router_->BindNewHost());
+  // If this is for a frame be sure to connect that handler too.
+  if (blink_frame_widget_) {
+    widget_input_handler_->GetFrameWidgetInputHandler(
+        frame_widget_input_handler_.BindNewEndpointAndPassReceiver());
+  }
+
   SendScreenRects();
   SynchronizeVisualProperties();
 
@@ -535,6 +548,7 @@
   // reused RenderViewHostImpl so we need to ensure old channels are dropped.
   blink_widget_host_receiver_.reset();
   blink_widget_.reset();
+  widget_input_handler_.reset();
   return std::make_pair(
       blink_widget_host_receiver_.BindNewEndpointAndPassRemote(),
       blink_widget_.BindNewEndpointAndPassReceiver());
@@ -547,6 +561,7 @@
   // reused RenderViewHostImpl so we need to ensure old channels are dropped.
   blink_widget_host_receiver_.reset();
   blink_widget_.reset();
+  widget_input_handler_.reset();
   blink_widget_host_receiver_.Bind(std::move(widget_host));
   blink_widget_.Bind(std::move(widget));
 }
@@ -558,6 +573,7 @@
   // reused RenderViewHostImpl so we need to ensure old channels are dropped.
   blink_frame_widget_host_receiver_.reset();
   blink_frame_widget_.reset();
+  frame_widget_input_handler_.reset();
   return std::make_pair(
       blink_frame_widget_host_receiver_.BindNewEndpointAndPassRemote(),
       blink_frame_widget_.BindNewEndpointAndPassReceiver());
@@ -571,6 +587,7 @@
   // reused RenderViewHostImpl so we need to ensure old channels are dropped.
   blink_frame_widget_host_receiver_.reset();
   blink_frame_widget_.reset();
+  frame_widget_input_handler_.reset();
   blink_frame_widget_host_receiver_.Bind(std::move(frame_widget_host));
   blink_frame_widget_.Bind(std::move(frame_widget));
 }
@@ -579,6 +596,18 @@
   DCHECK(process_->IsInitializedAndNotDead());
   set_renderer_initialized(true);
 
+  // In situations where RenderFrameHostImpl::CreateNewFrame calls this
+  // the |blink_widget_| will not be bound before this method is called.
+  // However RenderWidgetHostImpl::Init will be called once the widget
+  // is shown and these handlers will be bound there.
+  if (blink_widget_) {
+    blink_widget_->GetWidgetInputHandler(
+        widget_input_handler_.BindNewPipeAndPassReceiver(),
+        input_router_->BindNewHost());
+    widget_input_handler_->GetFrameWidgetInputHandler(
+        frame_widget_input_handler_.BindNewEndpointAndPassReceiver());
+  }
+
   if (view_)
     view_->OnRenderWidgetInit();
 }
@@ -622,8 +651,6 @@
     IPC_MESSAGE_HANDLER(DragHostMsg_UpdateDragCursor, OnUpdateDragCursor)
     IPC_MESSAGE_HANDLER(WidgetHostMsg_FrameSwapMessages,
                         OnFrameSwapMessagesReceived)
-    IPC_MESSAGE_HANDLER(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint,
-                        OnFirstVisuallyNonEmptyPaint)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
 
@@ -1114,8 +1141,6 @@
 }
 
 void RenderWidgetHostImpl::FlushForTesting() {
-  if (associated_widget_input_handler_)
-    return associated_widget_input_handler_.FlushForTesting();
   if (widget_input_handler_)
     return widget_input_handler_.FlushForTesting();
 }
@@ -1756,7 +1781,15 @@
 void RenderWidgetHostImpl::DragTargetDragLeave(
     const gfx::PointF& client_point,
     const gfx::PointF& screen_point) {
-  Send(new DragMsg_TargetDragLeave(GetRoutingID(), client_point, screen_point));
+  // TODO(dtapuska): Remove this null check once all of the Drag IPCs
+  // come over the mojo channels. It will be guaranteed that this
+  // will be non-null.
+  if (blink_frame_widget_) {
+    gfx::PointF viewport_point = client_point;
+    if (IsUseZoomForDSFEnabled())
+      viewport_point.Scale(GetScaleFactorForView(GetView()));
+    blink_frame_widget_->DragTargetDragLeave(viewport_point, screen_point);
+  }
 }
 
 void RenderWidgetHostImpl::DragTargetDrop(const DropData& drop_data,
@@ -1840,8 +1873,6 @@
 
 blink::mojom::WidgetInputHandler*
 RenderWidgetHostImpl::GetWidgetInputHandler() {
-  if (associated_widget_input_handler_)
-    return associated_widget_input_handler_.get();
   if (widget_input_handler_)
     return widget_input_handler_.get();
   // TODO(dtapuska): Remove the need for the unbound interface. It is
@@ -1973,11 +2004,6 @@
                                                           std::move(messages));
 }
 
-void RenderWidgetHostImpl::OnFirstVisuallyNonEmptyPaint() {
-  if (owner_delegate_)
-    owner_delegate_->RenderWidgetDidFirstVisuallyNonEmptyPaint();
-}
-
 void RenderWidgetHostImpl::RendererExited() {
   if (!renderer_initialized_)
     return;
@@ -2516,6 +2542,11 @@
       cancel_event, ui::LatencyInfo(ui::SourceEventType::OTHER));
 }
 
+void RenderWidgetHostImpl::DidFirstVisuallyNonEmptyPaint() {
+  if (owner_delegate_)
+    owner_delegate_->RenderWidgetDidFirstVisuallyNonEmptyPaint();
+}
+
 bool RenderWidgetHostImpl::IsAutoscrollInProgress() {
   return autoscroll_in_progress_;
 }
@@ -2822,6 +2853,13 @@
   return blink_frame_widget_;
 }
 
+blink::mojom::FrameWidgetInputHandler*
+RenderWidgetHostImpl::GetFrameWidgetInputHandler() {
+  if (!frame_widget_input_handler_)
+    return nullptr;
+  return frame_widget_input_handler_.get();
+}
+
 void RenderWidgetHostImpl::DispatchInputEventWithLatencyInfo(
     const blink::WebInputEvent& event,
     ui::LatencyInfo* latency) {
@@ -3155,8 +3193,6 @@
   suppress_events_until_keydown_ = false;
   monitoring_composition_info_ = false;
   StopInputEventAckTimeout();
-  associated_widget_input_handler_.reset();
-  widget_input_handler_.reset();
 
   input_router_ = std::make_unique<InputRouterImpl>(
       this, this, fling_scheduler_.get(), GetInputRouterConfigForPlatform());
@@ -3174,36 +3210,11 @@
   input_router_->SetForceEnableZoom(enabled);
 }
 
-void RenderWidgetHostImpl::SetFrameInputHandler(
-    blink::mojom::FrameInputHandler* frame_input_handler) {
-  if (!frame_input_handler)
-    return;
-  frame_input_handler->GetWidgetInputHandler(
-      associated_widget_input_handler_.BindNewEndpointAndPassReceiver(),
-      input_router_->BindNewFrameHost());
-}
-
 void RenderWidgetHostImpl::SetInputTargetClient(
     mojo::Remote<viz::mojom::InputTargetClient> input_target_client) {
   input_target_client_ = std::move(input_target_client);
 }
 
-void RenderWidgetHostImpl::SetWidget(
-    mojo::PendingRemote<mojom::Widget> widget_remote) {
-  if (!widget_remote)
-    return;
-
-  // If we have a bound handler ensure that we destroy the old input router
-  // while we reset the |widget_input_handler_|.
-  if (widget_input_handler_.is_bound())
-    SetupInputRouter();
-
-  mojo::Remote<mojom::Widget> widget(std::move(widget_remote));
-  widget->SetupWidgetInputHandler(
-      widget_input_handler_.BindNewPipeAndPassReceiver(),
-      input_router_->BindNewHost());
-}
-
 void RenderWidgetHostImpl::ProgressFlingIfNeeded(TimeTicks current_time) {
   fling_scheduler_->ProgressFlingOnBeginFrameIfneeded(current_time);
 }
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h
index 6029262e..fffde608 100644
--- a/content/browser/renderer_host/render_widget_host_impl.h
+++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -46,7 +46,6 @@
 #include "content/browser/renderer_host/render_widget_host_view_base.h"
 #include "content/common/drag_event_source_info.h"
 #include "content/common/render_frame_metadata.mojom.h"
-#include "content/common/widget.mojom.h"
 #include "content/public/browser/render_process_host_observer.h"
 #include "content/public/browser/render_widget_host.h"
 #include "content/public/common/page_zoom.h"
@@ -163,7 +162,6 @@
       RenderWidgetHostDelegate* delegate,
       RenderProcessHost* process,
       int32_t routing_id,
-      mojo::PendingRemote<mojom::Widget> widget_interface,
       bool hidden,
       std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue);
 
@@ -697,10 +695,6 @@
   // there are any queued messages belonging to it, they will be processed.
   void DidProcessFrame(uint32_t frame_token);
 
-  // Indicate the frame input handler is now available.
-  void SetFrameInputHandler(blink::mojom::FrameInputHandler*);
-  void SetWidget(mojo::PendingRemote<mojom::Widget> widget_remote);
-
   viz::mojom::InputTargetClient* input_target_client() {
     return input_target_client_.get();
   }
@@ -792,6 +786,8 @@
   const mojo::AssociatedRemote<blink::mojom::FrameWidget>&
   GetAssociatedFrameWidget();
 
+  blink::mojom::FrameWidgetInputHandler* GetFrameWidgetInputHandler();
+
   // Exposed so that tests can swap the implementation and intercept calls.
   mojo::AssociatedReceiver<blink::mojom::FrameWidgetHost>&
   frame_widget_host_receiver_for_testing() {
@@ -921,7 +917,6 @@
   void OnUpdateDragCursor(blink::WebDragOperation current_op);
   void OnFrameSwapMessagesReceived(uint32_t frame_token,
                                    std::vector<IPC::Message> messages);
-  void OnFirstVisuallyNonEmptyPaint();
 
   // blink::mojom::FrameWidgetHost overrides.
   void AnimateDoubleTapZoomInMainFrame(const gfx::Point& tap_point,
@@ -933,6 +928,7 @@
   void AutoscrollStart(const gfx::PointF& position) override;
   void AutoscrollFling(const gfx::Vector2dF& velocity) override;
   void AutoscrollEnd() override;
+  void DidFirstVisuallyNonEmptyPaint() override;
 
   // When the RenderWidget is destroyed and recreated, this resets states in the
   // browser to match the clean start for the renderer side.
@@ -1283,14 +1279,9 @@
 
   std::unique_ptr<FrameTokenMessageQueue> frame_token_message_queue_;
 
-  // If the |associated_widget_input_handler_| is set it should always be
-  // used to ensure in order delivery of related messages that may occur
-  // at the frame input level; see FrameInputHandler. Note that when the
-  // RWHI wraps a WebPagePopup widget it will only have a
-  // a |widget_input_handler_|.
-  mojo::AssociatedRemote<blink::mojom::WidgetInputHandler>
-      associated_widget_input_handler_;
   mojo::Remote<blink::mojom::WidgetInputHandler> widget_input_handler_;
+  mojo::AssociatedRemote<blink::mojom::FrameWidgetInputHandler>
+      frame_widget_input_handler_;
   mojo::Remote<viz::mojom::InputTargetClient> input_target_client_;
 
   base::Optional<uint16_t> screen_orientation_angle_for_testing_;
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
index 632b7742..555a9b1 100644
--- a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -21,7 +21,6 @@
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/test/mock_render_widget_host_delegate.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/test_render_view_host.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -204,12 +203,9 @@
 
     process_host_root_ =
         std::make_unique<MockRenderProcessHost>(browser_context_.get());
-    mojo::PendingRemote<mojom::Widget> widget_root;
-    widget_impl_root_ = std::make_unique<MockWidgetImpl>(
-        widget_root.InitWithNewPipeAndPassReceiver());
     widget_host_root_ = std::make_unique<RenderWidgetHostImpl>(
         &delegate_, process_host_root_.get(),
-        process_host_root_->GetNextRoutingID(), std::move(widget_root),
+        process_host_root_->GetNextRoutingID(),
         /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
     view_root_ =
         std::make_unique<MockRootRenderWidgetHostView>(widget_host_root_.get());
@@ -228,7 +224,6 @@
 
   struct ChildViewState {
     std::unique_ptr<MockRenderProcessHost> process_host;
-    std::unique_ptr<MockWidgetImpl> widget_impl;
     std::unique_ptr<RenderWidgetHostImpl> widget_host;
     std::unique_ptr<TestRenderWidgetHostViewChildFrame> view;
     std::unique_ptr<MockFrameConnectorDelegate> frame_connector;
@@ -239,12 +234,9 @@
 
     child.process_host =
         std::make_unique<MockRenderProcessHost>(browser_context_.get());
-    mojo::PendingRemote<mojom::Widget> widget_child;
-    child.widget_impl = std::make_unique<MockWidgetImpl>(
-        widget_child.InitWithNewPipeAndPassReceiver());
     child.widget_host = std::make_unique<RenderWidgetHostImpl>(
         &delegate_, child.process_host.get(),
-        child.process_host->GetNextRoutingID(), std::move(widget_child),
+        child.process_host->GetNextRoutingID(),
         /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
     child.view = std::make_unique<TestRenderWidgetHostViewChildFrame>(
         child.widget_host.get());
@@ -291,7 +283,6 @@
   std::unique_ptr<BrowserContext> browser_context_;
 
   std::unique_ptr<MockRenderProcessHost> process_host_root_;
-  std::unique_ptr<MockWidgetImpl> widget_impl_root_;
   std::unique_ptr<RenderWidgetHostImpl> widget_host_root_;
   std::unique_ptr<MockRootRenderWidgetHostView> view_root_;
 
diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc
index 178da25..eb65c448 100644
--- a/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -47,7 +47,6 @@
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/mock_widget_input_handler.h"
 #include "content/test/stub_render_widget_host_owner_delegate.h"
 #include "content/test/test_render_view_host.h"
@@ -2072,7 +2071,7 @@
 TEST_F(RenderWidgetHostTest, FrameToken_MessageThenFrame) {
   constexpr uint32_t frame_token = 1;
   std::vector<IPC::Message> messages;
-  messages.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
+  messages.push_back(WidgetHostMsg_Close(5));
 
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2092,7 +2091,7 @@
 TEST_F(RenderWidgetHostTest, FrameToken_FrameThenMessage) {
   constexpr uint32_t frame_token = 1;
   std::vector<IPC::Message> messages;
-  messages.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
+  messages.push_back(WidgetHostMsg_Close(5));
 
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2114,8 +2113,8 @@
   constexpr uint32_t frame_token2 = 2;
   std::vector<IPC::Message> messages1;
   std::vector<IPC::Message> messages2;
-  messages1.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
-  messages2.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(6));
+  messages1.push_back(WidgetHostMsg_Close(5));
+  messages2.push_back(WidgetHostMsg_Close(6));
 
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2145,8 +2144,8 @@
   constexpr uint32_t frame_token2 = 2;
   std::vector<IPC::Message> messages1;
   std::vector<IPC::Message> messages2;
-  messages1.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
-  messages2.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(6));
+  messages1.push_back(WidgetHostMsg_Close(5));
+  messages2.push_back(WidgetHostMsg_Close(6));
 
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2177,8 +2176,8 @@
   constexpr uint32_t frame_token2 = 2;
   std::vector<IPC::Message> messages1;
   std::vector<IPC::Message> messages2;
-  messages1.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(5));
-  messages2.push_back(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint(6));
+  messages1.push_back(WidgetHostMsg_Close(5));
+  messages2.push_back(WidgetHostMsg_Close(6));
 
   EXPECT_EQ(0u, host_->frame_token_message_queue_->size());
   EXPECT_EQ(0u, host_->processed_frame_messages_count());
@@ -2198,26 +2197,6 @@
   EXPECT_EQ(2u, host_->processed_frame_messages_count());
 }
 
-TEST_F(RenderWidgetHostTest, ForceEnableZoomShouldUpdateAfterRebind) {
-  SCOPED_TRACE("force_enable_zoom is false at start.");
-  host_->ExpectForceEnableZoom(false);
-
-  // Set force_enable_zoom true.
-  host_->SetForceEnableZoom(true);
-
-  SCOPED_TRACE("force_enable_zoom is true after set.");
-  host_->ExpectForceEnableZoom(true);
-
-  // Rebind should also update to the latest force_enable_zoom state.
-  mojo::PendingRemote<mojom::Widget> widget;
-  std::unique_ptr<MockWidgetImpl> widget_impl =
-      std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());
-  host_->SetWidget(std::move(widget));
-
-  SCOPED_TRACE("force_enable_zoom is true after rebind.");
-  host_->ExpectForceEnableZoom(true);
-}
-
 // If a navigation happens while the widget is hidden, we shouldn't show
 // contents of the previous page when we become visible.
 TEST_F(RenderWidgetHostTest, NavigateInBackgroundShowsBlank) {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc
index 737af5c..0c40da26 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -136,22 +136,6 @@
 
 namespace content {
 
-namespace {
-
-blink::mojom::FrameInputHandler* GetFrameInputHandlerForFocusedFrame(
-    RenderWidgetHostImpl* host) {
-  if (!host || !host->delegate()) {
-    return nullptr;
-  }
-  RenderFrameHostImpl* render_frame_host =
-      host->delegate()->GetFocusedFrameFromFocusedDelegate();
-  if (!render_frame_host)
-    return nullptr;
-  return render_frame_host->GetFrameInputHandler();
-}
-
-}  // namespace
-
 // We need to watch for mouse events outside a Web Popup or its parent
 // and dismiss the popup for certain events.
 class RenderWidgetHostViewAura::EventObserverForPopupExit
@@ -1358,10 +1342,7 @@
 bool RenderWidgetHostViewAura::SetEditableSelectionRange(
     const gfx::Range& range) {
   // TODO(crbug.com/915630): Write an unit test for this method.
-  RenderFrameHostImpl* rfh = GetFocusedFrame();
-  if (!rfh)
-    return false;
-  auto* input_handler = rfh->GetFrameInputHandler();
+  auto* input_handler = GetFrameWidgetInputHandlerForFocusedWidget();
   if (!input_handler)
     return false;
   input_handler->SetEditableSelectionOffsets(range.start(), range.end());
@@ -1417,7 +1398,7 @@
 
 void RenderWidgetHostViewAura::ExtendSelectionAndDelete(
     size_t before, size_t after) {
-  auto* input_handler = GetFrameInputHandlerForFocusedFrame(host());
+  auto* input_handler = GetFrameWidgetInputHandlerForFocusedWidget();
   if (!input_handler)
     return;
   input_handler->ExtendSelectionAndDelete(before, after);
@@ -1467,7 +1448,7 @@
 bool RenderWidgetHostViewAura::SetCompositionFromExistingText(
     const gfx::Range& range,
     const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
-  auto* input_handler = GetFrameInputHandlerForFocusedFrame(host());
+  auto* input_handler = GetFrameWidgetInputHandlerForFocusedWidget();
   if (!input_handler)
     return false;
   input_handler->SetCompositionFromExistingText(range.start(), range.end(),
@@ -2492,11 +2473,7 @@
 
 void RenderWidgetHostViewAura::ScrollFocusedEditableNodeIntoRect(
     const gfx::Rect& node_rect) {
-  RenderFrameHostImpl* rfh = GetFocusedFrame();
-  if (!rfh)
-    return;
-
-  auto* input_handler = rfh->GetFrameInputHandler();
+  auto* input_handler = GetFrameWidgetInputHandlerForFocusedWidget();
   if (!input_handler)
     return;
   input_handler->ScrollFocusedEditableNodeIntoRect(node_rect);
@@ -2595,4 +2572,12 @@
   env->gesture_recognizer()->CancelActiveTouches(window());
 }
 
+blink::mojom::FrameWidgetInputHandler*
+RenderWidgetHostViewAura::GetFrameWidgetInputHandlerForFocusedWidget() {
+  auto* focused_widget = GetFocusedWidget();
+  if (!focused_widget)
+    return nullptr;
+  return focused_widget->GetFrameWidgetInputHandler();
+}
+
 }  // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h
index e1316be..ab248e6 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura.h
+++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -565,6 +565,9 @@
   // Common part of Occluded() and Hide().
   void HideImpl();
 
+  blink::mojom::FrameWidgetInputHandler*
+  GetFrameWidgetInputHandlerForFocusedWidget();
+
   // NOTE: this is null if |is_mus_browser_plugin_guest_| is true.
   aura::Window* window_;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 9074a21e..65a8b60 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -66,7 +66,6 @@
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/test/mock_render_widget_host_delegate.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/test_overscroll_delegate.h"
 #include "content/test/test_render_view_host.h"
 #include "content/test/test_web_contents.h"
@@ -363,19 +362,14 @@
   static MockRenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate,
                                           RenderProcessHost* process,
                                           int32_t routing_id) {
-    mojo::PendingRemote<mojom::Widget> widget;
-    std::unique_ptr<MockWidgetImpl> widget_impl =
-        std::make_unique<MockWidgetImpl>(
-            widget.InitWithNewPipeAndPassReceiver());
-
-    return new MockRenderWidgetHostImpl(delegate, process, routing_id,
-                                        std::move(widget_impl),
-                                        std::move(widget));
+    return new MockRenderWidgetHostImpl(delegate, process, routing_id);
   }
   ui::LatencyInfo lastWheelOrTouchEventLatencyInfo;
 
-  MockWidgetInputHandler* input_handler() {
-    return widget_impl_->input_handler();
+  MockWidgetInputHandler* input_handler() { return &input_handler_; }
+
+  blink::mojom::WidgetInputHandler* GetWidgetInputHandler() override {
+    return &input_handler_;
   }
 
   void reset_new_content_rendering_timeout_fired() {
@@ -389,16 +383,12 @@
  private:
   MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
                            RenderProcessHost* process,
-                           int32_t routing_id,
-                           std::unique_ptr<MockWidgetImpl> widget_impl,
-                           mojo::PendingRemote<mojom::Widget> widget)
+                           int32_t routing_id)
       : RenderWidgetHostImpl(delegate,
                              process,
                              routing_id,
-                             std::move(widget),
                              /*hidden=*/false,
-                             std::make_unique<FrameTokenMessageQueue>()),
-        widget_impl_(std::move(widget_impl)) {
+                             std::make_unique<FrameTokenMessageQueue>()) {
     lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo();
     mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
     mojo::AssociatedRemote<blink::mojom::Widget> blink_widget;
@@ -414,7 +404,7 @@
   }
 
   bool new_content_rendering_timeout_fired_ = false;
-  std::unique_ptr<MockWidgetImpl> widget_impl_;
+  MockWidgetInputHandler input_handler_;
   base::Optional<WebGestureEvent> last_forwarded_gesture_event_;
 };
 
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
index d8999ca3..92dd78a 100644
--- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -33,7 +33,6 @@
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
 #include "content/test/mock_render_widget_host_delegate.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/test_render_view_host.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
@@ -122,11 +121,8 @@
     int32_t routing_id = process_host->GetNextRoutingID();
     sink_ = &process_host->sink();
 
-    mojo::PendingRemote<mojom::Widget> widget;
-    widget_impl_ = std::make_unique<MockWidgetImpl>(
-        widget.InitWithNewPipeAndPassReceiver());
     widget_host_ = new RenderWidgetHostImpl(
-        &delegate_, process_host, routing_id, std::move(widget),
+        &delegate_, process_host, routing_id,
         /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
 
     mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
@@ -187,7 +183,6 @@
 
   // Tests should set these to NULL if they've already triggered their
   // destruction.
-  std::unique_ptr<MockWidgetImpl> widget_impl_;
   RenderWidgetHostImpl* widget_host_;
   RenderWidgetHostViewChildFrame* view_;
   MockFrameConnectorDelegate* test_frame_connector_;
diff --git a/content/browser/renderer_host/render_widget_host_view_event_handler.cc b/content/browser/renderer_host/render_widget_host_view_event_handler.cc
index 112f547f..df6f607a 100644
--- a/content/browser/renderer_host/render_widget_host_view_event_handler.cc
+++ b/content/browser/renderer_host/render_widget_host_view_event_handler.cc
@@ -7,6 +7,7 @@
 #include "base/command_line.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
+#include "build/build_config.h"
 #include "components/viz/common/features.h"
 #include "content/browser/renderer_host/hit_test_debug_key_event_observer.h"
 #include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
@@ -335,6 +336,47 @@
     event->SetHandled();
 }
 
+void RenderWidgetHostViewEventHandler::HandleMouseWheelEvent(
+    ui::MouseEvent* event) {
+  DCHECK(event);
+  DCHECK_EQ(event->type(), ui::ET_MOUSEWHEEL);
+
+#if defined(OS_WIN)
+  if (!mouse_locked_) {
+    // We get mouse wheel/scroll messages even if we are not in the foreground.
+    // So here we check if we have any owned popup windows in the foreground and
+    // dismiss them.
+    aura::WindowTreeHost* host = window_->GetHost();
+    if (host) {
+      HWND parent = host->GetAcceleratedWidget();
+      HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
+      EnumThreadWindows(GetCurrentThreadId(), DismissOwnedPopups,
+                        reinterpret_cast<LPARAM>(toplevel_hwnd));
+    }
+  }
+#endif
+
+  blink::WebMouseWheelEvent mouse_wheel_event =
+      ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent());
+
+  if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
+    const bool should_route_event = ShouldRouteEvents();
+    // End the touchpad scrolling sequence (if such exists) before handling
+    // a ui::ET_MOUSEWHEEL event.
+    mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded(
+        should_route_event);
+
+    mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
+        mouse_wheel_event, should_route_event);
+    if (should_route_event) {
+      host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
+          host_view_, &mouse_wheel_event, *event->latency());
+    } else {
+      ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
+    }
+  }
+}
+
 void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) {
   TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnMouseEvent");
 
@@ -372,39 +414,9 @@
     return;
   }
 
-  if (event->type() == ui::ET_MOUSEWHEEL) {
-#if defined(OS_WIN)
-    // We get mouse wheel/scroll messages even if we are not in the foreground.
-    // So here we check if we have any owned popup windows in the foreground and
-    // dismiss them.
-    aura::WindowTreeHost* host = window_->GetHost();
-    if (host) {
-      HWND parent = host->GetAcceleratedWidget();
-      HWND toplevel_hwnd = ::GetAncestor(parent, GA_ROOT);
-      EnumThreadWindows(GetCurrentThreadId(), DismissOwnedPopups,
-                        reinterpret_cast<LPARAM>(toplevel_hwnd));
-    }
-#endif
-    blink::WebMouseWheelEvent mouse_wheel_event =
-        ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent());
-
-    if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
-      const bool should_route_event = ShouldRouteEvents();
-      // End the touchpad scrolling sequence (if such exists) before handling
-      // a ui::ET_MOUSEWHEEL event.
-      mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded(
-          should_route_event);
-
-      mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
-          mouse_wheel_event, should_route_event);
-      if (should_route_event) {
-        host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
-            host_view_, &mouse_wheel_event, *event->latency());
-      } else {
-        ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
-      }
-    }
-  } else {
+  if (event->type() == ui::ET_MOUSEWHEEL)
+    HandleMouseWheelEvent(event);
+  else {
     bool is_selection_popup = NeedsInputGrab(popup_child_host_view_);
     if (CanRendererHandleEvent(event, mouse_locked_, is_selection_popup) &&
         !(event->flags() & ui::EF_FROM_TOUCH)) {
@@ -746,26 +758,9 @@
 
   DCHECK(!cursor_client || !cursor_client->IsCursorVisible());
 
-  if (event->type() == ui::ET_MOUSEWHEEL) {
-    blink::WebMouseWheelEvent mouse_wheel_event =
-        ui::MakeWebMouseWheelEvent(*event->AsMouseWheelEvent());
-    if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) {
-      const bool should_route_event = ShouldRouteEvents();
-      // End the touchpad scrolling sequence (if such exists) before handling
-      // a ui::ET_MOUSEWHEEL event.
-      mouse_wheel_phase_handler_.SendWheelEndForTouchpadScrollingIfNeeded(
-          should_route_event);
-
-      mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
-          mouse_wheel_event, should_route_event);
-      if (should_route_event) {
-        host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
-            host_view_, &mouse_wheel_event, *event->latency());
-      } else {
-        ProcessMouseWheelEvent(mouse_wheel_event, *event->latency());
-      }
-    }
-  } else {
+  if (event->type() == ui::ET_MOUSEWHEEL)
+    HandleMouseWheelEvent(event);
+  else {
     // If we receive non client mouse messages while we are in the locked state
     // it probably means that the mouse left the borders of our window and
     // needs to be moved back to the center.
diff --git a/content/browser/renderer_host/render_widget_host_view_event_handler.h b/content/browser/renderer_host/render_widget_host_view_event_handler.h
index 6c306f4a..76f4978 100644
--- a/content/browser/renderer_host/render_widget_host_view_event_handler.h
+++ b/content/browser/renderer_host/render_widget_host_view_event_handler.h
@@ -251,6 +251,8 @@
   // Returns true if event is a reserved key for an active KeyboardLock request.
   bool IsKeyLocked(const ui::KeyEvent& event);
 
+  void HandleMouseWheelEvent(ui::MouseEvent* event);
+
   // Whether return characters should be passed on to the RenderWidgetHostImpl.
   bool accept_return_character_ = false;
 
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
index 2b0f113..3ed2a550 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper_unittest.mm
@@ -20,7 +20,6 @@
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_browser_context.h"
-#include "content/test/mock_widget_impl.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -147,13 +146,8 @@
 
   @autoreleasepool {
     int32_t routing_id = process_host->GetNextRoutingID();
-    mojo::PendingRemote<mojom::Widget> widget;
-    std::unique_ptr<MockWidgetImpl> widget_impl =
-        std::make_unique<MockWidgetImpl>(
-            widget.InitWithNewPipeAndPassReceiver());
-
     RenderWidgetHostImpl* render_widget = new RenderWidgetHostImpl(
-        &delegate, process_host, routing_id, std::move(widget),
+        &delegate, process_host, routing_id,
         /*hidden=*/false, std::make_unique<FrameTokenMessageQueue>());
 
     ui::WindowResizeHelperMac::Get()->Init(base::ThreadTaskRunnerHandle::Get());
diff --git a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
index 06978635..b135663 100644
--- a/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
+++ b/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm
@@ -44,7 +44,7 @@
 #include "content/public/test/test_browser_context.h"
 #include "content/public/test/test_utils.h"
 #include "content/test/mock_render_widget_host_delegate.h"
-#include "content/test/mock_widget_impl.h"
+#include "content/test/mock_widget_input_handler.h"
 #include "content/test/stub_render_widget_host_owner_delegate.h"
 #include "content/test/test_render_view_host.h"
 #include "gpu/ipc/common/gpu_messages.h"
@@ -339,36 +339,27 @@
   static MockRenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate,
                                           RenderProcessHost* process,
                                           int32_t routing_id) {
-    mojo::PendingRemote<mojom::Widget> widget;
-    std::unique_ptr<MockWidgetImpl> widget_impl =
-        std::make_unique<MockWidgetImpl>(
-            widget.InitWithNewPipeAndPassReceiver());
-
-    return new MockRenderWidgetHostImpl(delegate, process, routing_id,
-                                        std::move(widget_impl),
-                                        std::move(widget));
+    return new MockRenderWidgetHostImpl(delegate, process, routing_id);
   }
 
-  MockWidgetInputHandler* input_handler() {
-    return widget_impl_->input_handler();
-  }
+  MockWidgetInputHandler* input_handler() { return &input_handler_; }
   MockWidgetInputHandler::MessageVector GetAndResetDispatchedMessages() {
-    return input_handler()->GetAndResetDispatchedMessages();
+    return input_handler_.GetAndResetDispatchedMessages();
+  }
+
+  blink::mojom::WidgetInputHandler* GetWidgetInputHandler() override {
+    return &input_handler_;
   }
 
  private:
   MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
                            RenderProcessHost* process,
-                           int32_t routing_id,
-                           std::unique_ptr<MockWidgetImpl> widget_impl,
-                           mojo::PendingRemote<mojom::Widget> widget)
+                           int32_t routing_id)
       : RenderWidgetHostImpl(delegate,
                              process,
                              routing_id,
-                             std::move(widget),
                              /*hidden=*/false,
-                             std::make_unique<FrameTokenMessageQueue>()),
-        widget_impl_(std::move(widget_impl)) {
+                             std::make_unique<FrameTokenMessageQueue>()) {
     set_renderer_initialized(true);
     lastWheelEventLatencyInfo = ui::LatencyInfo();
 
@@ -383,7 +374,7 @@
   void FocusImpl() { RenderWidgetHostImpl::Focus(); }
   void BlurImpl() { RenderWidgetHostImpl::Blur(); }
 
-  std::unique_ptr<MockWidgetImpl> widget_impl_;
+  MockWidgetInputHandler input_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHostImpl);
 };
@@ -942,6 +933,12 @@
   ASSERT_TRUE(host_->lastWheelEventLatencyInfo.FindLatency(
       ui::INPUT_EVENT_LATENCY_UI_COMPONENT, nullptr));
 
+  MockWidgetInputHandler::MessageVector events =
+      host_->GetAndResetDispatchedMessages();
+  EXPECT_EQ("MouseWheel", GetMessageNames(events));
+  events[0]->ToEvent()->CallCallback(
+      blink::mojom::InputEventResultState::kNotConsumed);
+
   // Send a wheel event with phaseEnded.
   // Verifies that ui::INPUT_EVENT_LATENCY_UI_COMPONENT is added
   // properly in shortCircuitScrollWheelEvent function which is called
@@ -950,6 +947,9 @@
   [rwhv_mac_->GetInProcessNSView() scrollWheel:wheelEvent2];
   ASSERT_TRUE(host_->lastWheelEventLatencyInfo.FindLatency(
       ui::INPUT_EVENT_LATENCY_UI_COMPONENT, nullptr));
+
+  events = host_->GetAndResetDispatchedMessages();
+  EXPECT_EQ("GestureScrollBegin GestureScrollUpdate", GetMessageNames(events));
 }
 
 TEST_F(RenderWidgetHostViewMacTest, SourceEventTypeExistsInLatencyInfo) {
@@ -959,6 +959,13 @@
   // Verifies that SourceEventType exists in forwarded LatencyInfo object.
   NSEvent* wheelEvent = MockScrollWheelEventWithPhase(@selector(phaseBegan), 3);
   [rwhv_mac_->GetInProcessNSView() scrollWheel:wheelEvent];
+
+  MockWidgetInputHandler::MessageVector events =
+      host_->GetAndResetDispatchedMessages();
+  EXPECT_EQ("MouseWheel", GetMessageNames(events));
+  events[0]->ToEvent()->CallCallback(
+      blink::mojom::InputEventResultState::kConsumed);
+
   ASSERT_TRUE(host_->lastWheelEventLatencyInfo.source_event_type() ==
               ui::SourceEventType::WHEEL);
 }
@@ -1680,6 +1687,13 @@
   // Verify that Event.Latency.OS.MOUSE_WHEEL histogram is computed properly.
   NSEvent* wheelEvent = MockScrollWheelEventWithPhase(@selector(phaseBegan),3);
   [rwhv_mac_->GetInProcessNSView() scrollWheel:wheelEvent];
+
+  MockWidgetInputHandler::MessageVector events =
+      host_->GetAndResetDispatchedMessages();
+  EXPECT_EQ("MouseWheel", GetMessageNames(events));
+  events[0]->ToEvent()->CallCallback(
+      blink::mojom::InputEventResultState::kConsumed);
+
   histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1);
 }
 
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 965f228..f4d43e88 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -56,7 +56,6 @@
 #include "content/test/content_browser_test_utils_internal.h"
 #include "content/test/did_commit_navigation_interceptor.h"
 #include "content/test/frame_host_interceptor.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/test_content_browser_client.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_security_test_util.h"
@@ -372,16 +371,11 @@
       shell(), embedded_test_server(), &duplicate_routing_id);
   EXPECT_NE(MSG_ROUTING_NONE, duplicate_routing_id);
 
-  mojo::PendingRemote<mojom::Widget> widget;
-  std::unique_ptr<MockWidgetImpl> widget_impl =
-      std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());
-
   // Since this test executes on the UI thread and hopping threads might cause
   // different timing in the test, let's simulate a CreateNewWidget call coming
   // from the IO thread.  Use the existing window routing id to cause a
   // deliberate collision.
   pending_rfh->CreateNewWidget(
-      std::move(widget),
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>(),
       mojo::PendingAssociatedRemote<blink::mojom::Widget>(), base::DoNothing());
 
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc
index 7f4efe6b..99319c9 100644
--- a/content/browser/site_per_process_browsertest.cc
+++ b/content/browser/site_per_process_browsertest.cc
@@ -2380,7 +2380,8 @@
       GetBoundingClientRect(root, kIframeSelector)));
   root->child_at(0)
       ->current_frame_host()
-      ->GetFrameInputHandler()
+      ->GetRenderWidgetHost()
+      ->GetFrameWidgetInputHandler()
       ->ScrollFocusedEditableNodeIntoRect(gfx::Rect());
   WaitForElementVisible(root, kIframeSelector);
 #if defined(OS_ANDROID)
@@ -2412,7 +2413,8 @@
       GetBoundingClientRect(root, kIframeSelector)));
   root->child_at(0)
       ->current_frame_host()
-      ->GetFrameInputHandler()
+      ->GetRenderWidgetHost()
+      ->GetFrameWidgetInputHandler()
       ->ScrollFocusedEditableNodeIntoRect(gfx::Rect());
   WaitForElementVisible(root, kIframeSelector);
 #if defined(OS_ANDROID)
@@ -2455,7 +2457,8 @@
   // simulate the scroll into view we do when an input box is tapped.
   root->child_at(0)
       ->current_frame_host()
-      ->GetFrameInputHandler()
+      ->GetRenderWidgetHost()
+      ->GetFrameWidgetInputHandler()
       ->ScrollFocusedEditableNodeIntoRect(gfx::Rect());
 
   // The scroll into view is animated on the compositor. Make sure we wait
@@ -7476,7 +7479,11 @@
 
   // "Select all" in the subframe.  The bug only happens if there's a selection
   // change, which triggers the path through didChangeSelection.
-  root->child_at(0)->current_frame_host()->GetFrameInputHandler()->SelectAll();
+  root->child_at(0)
+      ->current_frame_host()
+      ->GetRenderWidgetHost()
+      ->GetFrameWidgetInputHandler()
+      ->SelectAll();
 
   // Prevent b.com process from terminating right away once the subframe
   // navigates away from b.com below.  This is necessary so that the renderer
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index e3184ea..bf20a158 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -633,7 +633,7 @@
 
   mojo::Receiver<blink::mojom::WidgetInputHandlerHost>& receiver() {
     return static_cast<InputRouterImpl*>(host_->input_router())
-        ->frame_host_receiver_for_testing();
+        ->host_receiver_for_testing();
   }
 
   std::unique_ptr<base::RunLoop> run_loop_;
diff --git a/content/browser/storage_partition_impl_unittest.cc b/content/browser/storage_partition_impl_unittest.cc
index 3804cf0..b5365e60 100644
--- a/content/browser/storage_partition_impl_unittest.cc
+++ b/content/browser/storage_partition_impl_unittest.cc
@@ -161,8 +161,9 @@
   }
 
  private:
-  void GetCookieListCallback(const net::CookieStatusList& cookie_list,
-                             const net::CookieStatusList& excluded_cookies) {
+  void GetCookieListCallback(
+      const net::CookieAccessResultList& cookie_list,
+      const net::CookieAccessResultList& excluded_cookies) {
     std::string cookie_line =
         net::CanonicalCookie::BuildCookieLine(cookie_list);
     if (cookie_line == "A=1") {
diff --git a/content/browser/web_contents/color_chooser_unittest.cc b/content/browser/web_contents/color_chooser_unittest.cc
new file mode 100644
index 0000000..26b37c9
--- /dev/null
+++ b/content/browser/web_contents/color_chooser_unittest.cc
@@ -0,0 +1,151 @@
+// Copyright (c) 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/test/scoped_feature_list.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/content_navigation_policy.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/common/content_features.h"
+#include "content/public/test/navigation_simulator.h"
+#include "content/test/test_render_frame_host.h"
+#include "content/test/test_render_view_host.h"
+#include "content/test/test_web_contents.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace content {
+
+namespace {
+
+// Mock content::ColorChooser to test whether End() is called.
+class MockColorChooser : public content::ColorChooser {
+ public:
+  MockColorChooser() = default;
+  ~MockColorChooser() override = default;
+
+  MOCK_METHOD0(End, void());
+  MOCK_METHOD1(SetSelectedColor, void(SkColor color));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockColorChooser);
+};
+
+// Delegate to override OpenColorChooser.
+class OpenColorChooserDelegate : public WebContentsDelegate {
+ public:
+  explicit OpenColorChooserDelegate(
+      std::unique_ptr<MockColorChooser> mock_color_chooser)
+      : mock_color_chooser_(std::move(mock_color_chooser)) {}
+
+  ~OpenColorChooserDelegate() override = default;
+
+  // WebContentsDelegate:
+  ColorChooser* OpenColorChooser(
+      WebContents* web_contents,
+      SkColor color,
+      const std::vector<blink::mojom::ColorSuggestionPtr>& suggestions)
+      override {
+    return std::move(mock_color_chooser_).release();
+  }
+
+ private:
+  std::unique_ptr<MockColorChooser> mock_color_chooser_;
+
+  DISALLOW_COPY_AND_ASSIGN(OpenColorChooserDelegate);
+};
+
+}  // namespace
+
+class ColorChooserUnitTest : public RenderViewHostImplTestHarness {};
+
+TEST_F(ColorChooserUnitTest, ColorChooserCallsEndOnNavigatingAway) {
+  GURL kUrl1("https://foo.com");
+  GURL kUrl2("https://bar.com");
+
+  // Navigate to A.
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1);
+
+  // End should be called at least once on navigating to a new URL.
+  std::unique_ptr<MockColorChooser> mock_color_chooser =
+      std::make_unique<MockColorChooser>();
+  EXPECT_CALL(*mock_color_chooser.get(), End()).Times(testing::AtLeast(1));
+
+  // Set OpenColorChooserDelegate as the new WebContentsDelegate.
+  std::unique_ptr<OpenColorChooserDelegate> delegate =
+      std::make_unique<OpenColorChooserDelegate>(std::move(mock_color_chooser));
+  contents()->SetDelegate(delegate.get());
+
+  mojo::PendingRemote<blink::mojom::ColorChooserClient> pending_client;
+  mojo::Remote<blink::mojom::ColorChooser> pending_remote;
+  mojo::PendingReceiver<blink::mojom::ColorChooser> pending_receiver =
+      pending_remote.BindNewPipeAndPassReceiver();
+
+  // Call WebContentsImpl::OpenColorChooser.
+  static_cast<WebContentsImpl*>(contents())
+      ->OpenColorChooser(std::move(pending_receiver), std::move(pending_client),
+                         SkColorSetRGB(0, 0, 1), {});
+
+  // Navigate to B.
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl2);
+
+  contents()->SetDelegate(nullptr);
+}
+
+// Run tests with BackForwardCache.
+class ColorChooserTestWithBackForwardCache : public ColorChooserUnitTest {
+ public:
+  ColorChooserTestWithBackForwardCache() {
+    scoped_feature_list_.InitWithFeaturesAndParameters(
+        {{features::kBackForwardCache, {GetFeatureParams()}}},
+        /*disabled_features=*/{});
+  }
+
+ protected:
+  base::FieldTrialParams GetFeatureParams() {
+    return {{"TimeToLiveInBackForwardCacheInSeconds", "3600"},
+            {"service_worker_supported", "true"}};
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(ColorChooserTestWithBackForwardCache,
+       ColorChooserCallsEndOnEnteringBackForwardCache) {
+  ASSERT_TRUE(IsBackForwardCacheEnabled());
+  GURL kUrl1("https://foo.com");
+  GURL kUrl2("https://bar.com");
+
+  // Navigate to A.
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl1);
+  RenderFrameHost* rfh_a = contents()->GetMainFrame();
+
+  // End should be called at least once on navigating to a new URL.
+  std::unique_ptr<MockColorChooser> mock_color_chooser =
+      std::make_unique<MockColorChooser>();
+  EXPECT_CALL(*mock_color_chooser.get(), End()).Times(testing::AtLeast(1));
+
+  // Set OpenColorChooserDelegate as the new WebContentsDelegate.
+  std::unique_ptr<OpenColorChooserDelegate> delegate =
+      std::make_unique<OpenColorChooserDelegate>(std::move(mock_color_chooser));
+  contents()->SetDelegate(delegate.get());
+
+  mojo::PendingRemote<blink::mojom::ColorChooserClient> pending_client;
+  mojo::Remote<blink::mojom::ColorChooser> pending_remote;
+  mojo::PendingReceiver<blink::mojom::ColorChooser> pending_receiver =
+      pending_remote.BindNewPipeAndPassReceiver();
+
+  // Call WebContentsImpl::OpenColorChooser.
+  static_cast<WebContentsImpl*>(contents())
+      ->OpenColorChooser(std::move(pending_receiver), std::move(pending_client),
+                         SkColorSetRGB(0, 0, 1), {});
+
+  // Navigate to B, A enters BackForwardCache.
+  NavigationSimulator::NavigateAndCommitFromBrowser(contents(), kUrl2);
+  EXPECT_TRUE(rfh_a->IsInBackForwardCache());
+
+  contents()->SetDelegate(nullptr);
+}
+
+}  // namespace content
diff --git a/content/browser/web_contents/web_contents_android.cc b/content/browser/web_contents/web_contents_android.cc
index 17b33aee..aadcfc1 100644
--- a/content/browser/web_contents/web_contents_android.cc
+++ b/content/browser/web_contents/web_contents_android.cc
@@ -465,7 +465,7 @@
 void WebContentsAndroid::ScrollFocusedEditableNodeIntoView(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  auto* input_handler = web_contents_->GetFocusedFrameInputHandler();
+  auto* input_handler = web_contents_->GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
   input_handler->ScrollFocusedEditableNodeIntoRect(gfx::Rect());
@@ -482,7 +482,7 @@
 void WebContentsAndroid::SelectWordAroundCaret(
     JNIEnv* env,
     const JavaParamRef<jobject>& obj) {
-  auto* input_handler = web_contents_->GetFocusedFrameInputHandler();
+  auto* input_handler = web_contents_->GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
   input_handler->SelectWordAroundCaret(
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index e5575bae..a1ae682 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -195,6 +195,8 @@
 const int kMinimumDelayBetweenLoadingUpdatesMS = 100;
 const char kDotGoogleDotCom[] = ".google.com";
 
+using LifecycleState = RenderFrameHostImpl::LifecycleState;
+
 // TODO(crbug.com/1059903): Clean up after the initial investigation.
 constexpr base::Feature kCheckWebContentsAccessFromNonCurrentFrame{
     "CheckWebContentsAccessFromNonCurrentFrame",
@@ -437,6 +439,8 @@
   DISALLOW_COPY_AND_ASSIGN(DestructionObserver);
 };
 
+// TODO(sreejakshetty): Make |WebContentsImpl::ColorChooser| per-frame instead
+// of WebContents-owned.
 // WebContentsImpl::ColorChooser ----------------------------------------------
 class WebContentsImpl::ColorChooser : public blink::mojom::ColorChooser {
  public:
@@ -3045,30 +3049,25 @@
 void WebContentsImpl::CreateNewWidget(
     int32_t render_process_id,
     int32_t widget_route_id,
-    mojo::PendingRemote<mojom::Widget> widget,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {
   CreateNewWidget(render_process_id, widget_route_id, /*is_fullscreen=*/false,
-                  std::move(widget), std::move(blink_widget_host),
-                  std::move(blink_widget));
+                  std::move(blink_widget_host), std::move(blink_widget));
 }
 
 void WebContentsImpl::CreateNewFullscreenWidget(
     int32_t render_process_id,
     int32_t widget_route_id,
-    mojo::PendingRemote<mojom::Widget> widget,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {
   CreateNewWidget(render_process_id, widget_route_id, /*is_fullscreen=*/true,
-                  std::move(widget), std::move(blink_widget_host),
-                  std::move(blink_widget));
+                  std::move(blink_widget_host), std::move(blink_widget));
 }
 
 void WebContentsImpl::CreateNewWidget(
     int32_t render_process_id,
     int32_t route_id,
     bool is_fullscreen,
-    mojo::PendingRemote<mojom::Widget> widget,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {
   RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
@@ -3080,9 +3079,9 @@
     return;
   }
 
-  RenderWidgetHostImpl* widget_host = new RenderWidgetHostImpl(
-      this, process, route_id, std::move(widget), IsHidden(),
-      std::make_unique<FrameTokenMessageQueue>());
+  RenderWidgetHostImpl* widget_host =
+      new RenderWidgetHostImpl(this, process, route_id, IsHidden(),
+                               std::make_unique<FrameTokenMessageQueue>());
 
   widget_host->BindWidgetInterfaces(std::move(blink_widget_host),
                                     std::move(blink_widget));
@@ -3495,7 +3494,7 @@
 void WebContentsImpl::ExecuteEditCommand(
     const std::string& command,
     const base::Optional<base::string16>& value) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3503,7 +3502,7 @@
 }
 
 void WebContentsImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3512,7 +3511,7 @@
 
 void WebContentsImpl::SelectRange(const gfx::Point& base,
                                   const gfx::Point& extent) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3520,7 +3519,7 @@
 }
 
 void WebContentsImpl::MoveCaret(const gfx::Point& extent) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3531,7 +3530,7 @@
     int start_adjust,
     int end_adjust,
     bool show_selection_menu) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3622,7 +3621,7 @@
 }
 
 void WebContentsImpl::Undo() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3631,7 +3630,7 @@
 }
 
 void WebContentsImpl::Redo() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3640,7 +3639,7 @@
 }
 
 void WebContentsImpl::Cut() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3649,7 +3648,7 @@
 }
 
 void WebContentsImpl::Copy() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3659,7 +3658,7 @@
 
 void WebContentsImpl::CopyToFindPboard() {
 #if defined(OS_MACOSX)
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3670,7 +3669,7 @@
 }
 
 void WebContentsImpl::Paste() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3681,7 +3680,7 @@
 }
 
 void WebContentsImpl::PasteAndMatchStyle() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3692,7 +3691,7 @@
 }
 
 void WebContentsImpl::Delete() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3701,7 +3700,7 @@
 }
 
 void WebContentsImpl::SelectAll() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3710,7 +3709,7 @@
 }
 
 void WebContentsImpl::CollapseSelection() {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3718,7 +3717,7 @@
 }
 
 void WebContentsImpl::Replace(const base::string16& word) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -3726,7 +3725,7 @@
 }
 
 void WebContentsImpl::ReplaceMisspelling(const base::string16& word) {
-  auto* input_handler = GetFocusedFrameInputHandler();
+  auto* input_handler = GetFocusedFrameWidgetInputHandler();
   if (!input_handler)
     return;
 
@@ -7463,12 +7462,13 @@
     NotifyPreferencesChanged();
 }
 
-blink::mojom::FrameInputHandler*
-WebContentsImpl::GetFocusedFrameInputHandler() {
-  auto* focused_frame = GetFocusedFrame();
-  if (!focused_frame)
+blink::mojom::FrameWidgetInputHandler*
+WebContentsImpl::GetFocusedFrameWidgetInputHandler() {
+  auto* focused_render_widget_host =
+      GetFocusedRenderWidgetHost(GetMainFrame()->GetRenderWidgetHost());
+  if (!focused_render_widget_host)
     return nullptr;
-  return focused_frame->GetFrameInputHandler();
+  return focused_render_widget_host->GetFrameWidgetInputHandler();
 }
 
 ukm::SourceId WebContentsImpl::GetCurrentPageUkmSourceId() {
@@ -7494,4 +7494,21 @@
   return render_view_hosts;
 }
 
+void WebContentsImpl::RenderFrameHostStateChanged(
+    RenderFrameHost* render_frame_host,
+    LifecycleState old_state,
+    LifecycleState new_state) {
+  if (render_frame_host->GetParent())
+    return;
+
+  if (old_state == LifecycleState::kActive &&
+      new_state != LifecycleState::kActive) {
+    // TODO(sreejakshetty): Remove this reset when ColorChooser becomes
+    // per-frame.
+    // Close the color chooser popup when RenderFrameHost changes state from
+    // kActive.
+    color_chooser_.reset();
+  }
+}
+
 }  // namespace content
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index 230fe78d..d86072b 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -710,7 +710,6 @@
   bool HasSeenRecentScreenOrientationChange() override;
   void CreateNewWidget(int32_t render_process_id,
                        int32_t route_id,
-                       mojo::PendingRemote<mojom::Widget> widget,
                        mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
                            blink_widget_host,
                        mojo::PendingAssociatedRemote<blink::mojom::Widget>
@@ -718,7 +717,6 @@
   void CreateNewFullscreenWidget(
       int32_t render_process_id,
       int32_t widget_route_id,
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget)
@@ -747,6 +745,12 @@
       const std::vector<blink::mojom::SavableSubframePtr>& subframes) override;
   void SavableResourceLinksError(RenderFrameHostImpl* source) override;
 
+  // Called when the |RenderFrameHostImpl::lifecycle_state()| changes.
+  void RenderFrameHostStateChanged(
+      RenderFrameHost* render_frame_host,
+      RenderFrameHostImpl::LifecycleState old_state,
+      RenderFrameHostImpl::LifecycleState new_state) override;
+
   // RenderViewHostDelegate ----------------------------------------------------
   RenderViewHostDelegateView* GetDelegateView() override;
   bool OnMessageReceived(RenderViewHostImpl* render_view_host,
@@ -1202,7 +1206,7 @@
   }
 
   // Returns the focused frame's input handler.
-  blink::mojom::FrameInputHandler* GetFocusedFrameInputHandler();
+  blink::mojom::FrameWidgetInputHandler* GetFocusedFrameWidgetInputHandler();
 
   // A render view-originated drag has ended. Informs the render view host and
   // WebContentsDelegate.
@@ -1517,7 +1521,6 @@
       int32_t render_process_id,
       int32_t route_id,
       bool is_fullscreen,
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget);
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc
index 1cc4129..45ec0a1 100644
--- a/content/browser/web_contents/web_contents_view_android.cc
+++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -9,6 +9,7 @@
 #include "base/android/jni_string.h"
 #include "base/check.h"
 #include "base/notreached.h"
+#include "base/optional.h"
 #include "cc/layers/layer.h"
 #include "content/browser/accessibility/browser_accessibility_manager_android.h"
 #include "content/browser/android/content_feature_list.h"
@@ -309,7 +310,7 @@
     const gfx::Vector2d& image_offset,
     const DragEventSourceInfo& event_info,
     RenderWidgetHostImpl* source_rwh) {
-  if (drop_data.text.is_null()) {
+  if (!drop_data.text) {
     // Need to clear drag and drop state in blink.
     OnSystemDragEnded();
     return;
@@ -337,7 +338,7 @@
 
   JNIEnv* env = AttachCurrentThread();
   ScopedJavaLocalRef<jstring> jtext =
-      ConvertUTF16ToJavaString(env, drop_data.text.string());
+      ConvertUTF16ToJavaString(env, *drop_data.text);
 
   if (!native_view->StartDragAndDrop(jtext, gfx::ConvertToJavaBitmap(bitmap))) {
     // Need to clear drag and drop state in blink.
@@ -382,9 +383,9 @@
         if (base::EqualsASCII(mime_type, ui::kMimeTypeURIList)) {
           drop_data.url = GURL(drop_content);
         } else if (base::EqualsASCII(mime_type, ui::kMimeTypeText)) {
-          drop_data.text = base::NullableString16(drop_content, false);
+          drop_data.text = drop_content;
         } else {
-          drop_data.html = base::NullableString16(drop_content, false);
+          drop_data.html = drop_content;
         }
       }
 
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
index 3b77ea4..db76f65 100644
--- a/content/browser/web_contents/web_contents_view_aura.cc
+++ b/content/browser/web_contents/web_contents_view_aura.cc
@@ -248,12 +248,12 @@
   // SetURL() will itself do SetString() when a string hasn't been set yet,
   // but we want to prefer drop_data.text.string() over the URL string if it
   // exists.
-  if (!drop_data.text.string().empty())
-    provider->SetString(drop_data.text.string());
+  if (drop_data.text && !drop_data.text->empty())
+    provider->SetString(*drop_data.text);
   if (drop_data.url.is_valid())
     provider->SetURL(drop_data.url, drop_data.url_title);
-  if (!drop_data.html.string().empty())
-    provider->SetHtml(drop_data.html.string(), drop_data.html_base_url);
+  if (drop_data.html && !drop_data.html->empty())
+    provider->SetHtml(*drop_data.html, drop_data.html_base_url);
   if (!drop_data.filenames.empty())
     provider->SetFilenames(drop_data.filenames);
   if (!drop_data.file_system_files.empty()) {
@@ -309,7 +309,7 @@
   base::string16 plain_text;
   data.GetString(&plain_text);
   if (!plain_text.empty())
-    drop_data->text = base::NullableString16(plain_text, false);
+    drop_data->text = plain_text;
 
   GURL url;
   base::string16 url_title;
@@ -324,7 +324,7 @@
   GURL html_base_url;
   data.GetHtml(&html, &html_base_url);
   if (!html.empty())
-    drop_data->html = base::NullableString16(html, false);
+    drop_data->html = html;
   if (html_base_url.is_valid())
     drop_data->html_base_url = html_base_url;
 
diff --git a/content/browser/web_contents/web_contents_view_aura_unittest.cc b/content/browser/web_contents/web_contents_view_aura_unittest.cc
index ca77acc..b2fa8c76 100644
--- a/content/browser/web_contents/web_contents_view_aura_unittest.cc
+++ b/content/browser/web_contents/web_contents_view_aura_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_command_line.h"
 #include "base/test/scoped_feature_list.h"
@@ -253,9 +254,10 @@
 #if defined(USE_X11)
   // By design, OSExchangeDataProviderX11::GetString returns an empty string
   // if file data is also present.
-  EXPECT_TRUE(view->current_drop_data_->text.string().empty());
+  EXPECT_TRUE(!view->current_drop_data_->text ||
+              view->current_drop_data_->text->empty());
 #else
-  EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+  EXPECT_EQ(string_data, view->current_drop_data_->text);
 #endif
 
   std::vector<ui::FileInfo> retrieved_file_infos =
@@ -283,9 +285,10 @@
 #if defined(USE_X11)
   // By design, OSExchangeDataProviderX11::GetString returns an empty string
   // if file data is also present.
-  EXPECT_TRUE(drop_complete_data_->drop_data.text.string().empty());
+  EXPECT_TRUE(!drop_complete_data_->drop_data.text ||
+              drop_complete_data_->drop_data.text->empty());
 #else
-  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text);
 #endif
 
   retrieved_file_infos = drop_complete_data_->drop_data.filenames;
@@ -342,9 +345,10 @@
 #if defined(USE_X11)
   // By design, OSExchangeDataProviderX11::GetString returns an empty string
   // if file data is also present.
-  EXPECT_TRUE(view->current_drop_data_->text.string().empty());
+  EXPECT_TRUE(!view->current_drop_data_->text ||
+              view->current_drop_data_->text->empty());
 #else
-  EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+  EXPECT_EQ(string_data, view->current_drop_data_->text);
 #endif
 
   ASSERT_TRUE(view->current_drop_data_->filenames.empty());
@@ -365,9 +369,10 @@
 #if defined(USE_X11)
   // By design, OSExchangeDataProviderX11::GetString returns an empty string
   // if file data is also present.
-  EXPECT_TRUE(drop_complete_data_->drop_data.text.string().empty());
+  EXPECT_TRUE(!drop_complete_data_->drop_data.text ||
+              drop_complete_data_->drop_data.text->empty());
 #else
-  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text);
 #endif
 
   ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty());
@@ -404,7 +409,7 @@
   view->OnDragEntered(event);
   ASSERT_NE(nullptr, view->current_drop_data_);
 
-  EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+  EXPECT_EQ(string_data, view->current_drop_data_->text);
 
   const base::FilePath path_placeholder(FILE_PATH_LITERAL("temp.tmp"));
   std::vector<ui::FileInfo> retrieved_file_infos =
@@ -430,7 +435,7 @@
 
   CheckDropData(view);
 
-  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text);
 
   std::string read_contents;
   base::FilePath temp_dir;
@@ -487,7 +492,7 @@
   view->OnDragEntered(event);
   ASSERT_NE(nullptr, view->current_drop_data_);
 
-  EXPECT_EQ(string_data, view->current_drop_data_->text.string());
+  EXPECT_EQ(string_data, view->current_drop_data_->text);
 
   ASSERT_TRUE(view->current_drop_data_->filenames.empty());
 
@@ -505,7 +510,7 @@
 
   CheckDropData(view);
 
-  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text.string());
+  EXPECT_EQ(string_data, drop_complete_data_->drop_data.text);
 
   ASSERT_TRUE(drop_complete_data_->drop_data.filenames.empty());
 }
diff --git a/content/browser/web_contents/web_drag_dest_mac.mm b/content/browser/web_contents/web_drag_dest_mac.mm
index 5cb5db0..a964f38b8 100644
--- a/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/content/browser/web_contents/web_drag_dest_mac.mm
@@ -6,6 +6,7 @@
 
 #import <Carbon/Carbon.h>
 
+#include "base/optional.h"
 #include "base/strings/sys_string_conversions.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/browser/renderer_host/render_widget_host_impl.h"
@@ -410,21 +411,20 @@
 
   // Get plain text.
   if ([types containsObject:NSStringPboardType]) {
-    data->text = base::NullableString16(
-        base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]),
-        false);
+    data->text =
+        base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]);
   }
 
   // Get HTML. If there's no HTML, try RTF.
   if ([types containsObject:NSHTMLPboardType]) {
     NSString* html = [pboard stringForType:NSHTMLPboardType];
-    data->html = base::NullableString16(base::SysNSStringToUTF16(html), false);
+    data->html = base::SysNSStringToUTF16(html);
   } else if ([types containsObject:ui::kChromeDragImageHTMLPboardType]) {
     NSString* html = [pboard stringForType:ui::kChromeDragImageHTMLPboardType];
-    data->html = base::NullableString16(base::SysNSStringToUTF16(html), false);
+    data->html = base::SysNSStringToUTF16(html);
   } else if ([types containsObject:NSRTFPboardType]) {
     NSString* html = ui::ClipboardUtil::GetHTMLFromRTFOnPasteboard(pboard);
-    data->html = base::NullableString16(base::SysNSStringToUTF16(html), false);
+    data->html = base::SysNSStringToUTF16(html);
   }
 
   // Get files.
diff --git a/content/browser/web_contents/web_drag_dest_mac_unittest.mm b/content/browser/web_contents/web_drag_dest_mac_unittest.mm
index b837cbd..7034271 100644
--- a/content/browser/web_contents/web_drag_dest_mac_unittest.mm
+++ b/content/browser/web_contents/web_drag_dest_mac_unittest.mm
@@ -141,6 +141,6 @@
   [pboard->get() setString:textString forType:NSStringPboardType];
   content::PopulateDropDataFromPasteboard(&data, pboard->get());
   EXPECT_EQ(data.url.spec(), "http://www.google.com/");
-  EXPECT_EQ(base::SysNSStringToUTF16(textString), data.text.string());
-  EXPECT_EQ(base::SysNSStringToUTF16(htmlString), data.html.string());
+  EXPECT_EQ(base::SysNSStringToUTF16(textString), data.text);
+  EXPECT_EQ(base::SysNSStringToUTF16(htmlString), data.html);
 }
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 501484f..8340148 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -451,8 +451,6 @@
 
   mojo::Remote<blink::mojom::Authenticator> ConstructAuthenticatorWithTimer(
       scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {
-    fake_hid_manager_ = std::make_unique<device::FakeFidoHidManager>();
-
     // Set up a timer for testing.
     auto timer =
         std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
@@ -531,7 +529,6 @@
 
  protected:
   std::unique_ptr<AuthenticatorImpl> authenticator_impl_;
-  std::unique_ptr<device::FakeFidoHidManager> fake_hid_manager_;
   base::Optional<base::test::ScopedFeatureList> scoped_feature_list_;
   std::unique_ptr<device::BluetoothAdapterFactory::GlobalValuesForTesting>
       bluetooth_global_values_ =
@@ -953,7 +950,7 @@
     auto auth_data = device::AuthenticatorData::DecodeAuthenticatorData(
         auth_data_it->second.GetBytestring());
     EXPECT_EQ(static_cast<int32_t>(algorithm),
-              auth_data->attested_data()->public_key()->algorithm());
+              auth_data->attested_data()->public_key()->algorithm);
   }
 }
 
@@ -1879,9 +1876,9 @@
   }
 }
 
-enum class IndividualAttestation {
-  REQUESTED,
-  NOT_REQUESTED,
+enum class EnterprisePolicy {
+  LISTED,
+  NOT_LISTED,
 };
 
 enum class AttestationConsent {
@@ -1920,13 +1917,13 @@
   TestAuthenticatorRequestDelegate(
       RenderFrameHost* render_frame_host,
       base::OnceClosure action_callbacks_registered_callback,
-      IndividualAttestation individual_attestation,
+      EnterprisePolicy enterprise_policy,
       AttestationConsent attestation_consent,
       bool is_focused,
       bool is_uvpaa)
       : action_callbacks_registered_callback_(
             std::move(action_callbacks_registered_callback)),
-        individual_attestation_(individual_attestation),
+        enterprise_policy_(enterprise_policy),
         attestation_consent_(attestation_consent),
         is_focused_(is_focused),
         is_uvpaa_(is_uvpaa) {}
@@ -1945,7 +1942,7 @@
 
   bool ShouldPermitIndividualAttestation(
       const std::string& relying_party_id) override {
-    return individual_attestation_ == IndividualAttestation::REQUESTED;
+    return enterprise_policy_ == EnterprisePolicy::LISTED;
   }
 
   void ShouldReturnAttestation(
@@ -1976,7 +1973,7 @@
 
   base::OnceClosure action_callbacks_registered_callback_;
   base::Optional<base::OnceClosure> cancel_callback_;
-  const IndividualAttestation individual_attestation_;
+  const EnterprisePolicy enterprise_policy_;
   const AttestationConsent attestation_consent_;
   const bool is_focused_;
   const bool is_uvpaa_;
@@ -1997,15 +1994,14 @@
         action_callbacks_registered_callback
             ? std::move(action_callbacks_registered_callback)
             : base::DoNothing(),
-        individual_attestation, attestation_consent, is_focused, is_uvpaa);
+        enterprise_policy, attestation_consent, is_focused, is_uvpaa);
   }
 
   // If set, this closure will be called when the subsequently constructed
   // delegate is informed that the request has started.
   base::OnceClosure action_callbacks_registered_callback;
 
-  IndividualAttestation individual_attestation =
-      IndividualAttestation::NOT_REQUESTED;
+  EnterprisePolicy enterprise_policy = EnterprisePolicy::NOT_LISTED;
   AttestationConsent attestation_consent = AttestationConsent::DENIED;
   bool is_focused = true;
 
@@ -2025,7 +2021,7 @@
 
   struct TestCase {
     AttestationConveyancePreference attestation_requested;
-    IndividualAttestation individual_attestation;
+    EnterprisePolicy enterprise_policy;
     AttestationConsent attestation_consent;
     AuthenticatorStatus expected_status;
     AttestationType expected_attestation;
@@ -2051,15 +2047,14 @@
       SCOPED_TRACE(test.attestation_consent == AttestationConsent::GRANTED
                        ? "consent granted"
                        : "consent denied");
-      SCOPED_TRACE(test.individual_attestation ==
-                           IndividualAttestation::REQUESTED
+      SCOPED_TRACE(test.enterprise_policy == EnterprisePolicy::LISTED
                        ? "individual attestation"
                        : "no individual attestation");
       SCOPED_TRACE(
           AttestationConveyancePreferenceToString(test.attestation_requested));
       SCOPED_TRACE(i);
 
-      test_client_.individual_attestation = test.individual_attestation;
+      test_client_.enterprise_policy = test.enterprise_policy;
       test_client_.attestation_consent = test.attestation_consent;
 
       PublicKeyCredentialCreationOptionsPtr options =
@@ -2229,7 +2224,7 @@
   const std::vector<TestCase> kTests = {
       {
           AttestationConveyancePreference::NONE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2237,7 +2232,7 @@
       },
       {
           AttestationConveyancePreference::NONE,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2245,7 +2240,7 @@
       },
       {
           AttestationConveyancePreference::INDIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2253,7 +2248,7 @@
       },
       {
           AttestationConveyancePreference::INDIRECT,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2261,7 +2256,7 @@
       },
       {
           AttestationConveyancePreference::INDIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::U2F,
@@ -2269,7 +2264,7 @@
       },
       {
           AttestationConveyancePreference::INDIRECT,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::U2F,
@@ -2277,7 +2272,7 @@
       },
       {
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2285,7 +2280,7 @@
       },
       {
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2293,7 +2288,7 @@
       },
       {
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::U2F,
@@ -2301,7 +2296,7 @@
       },
       {
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::U2F,
@@ -2309,7 +2304,7 @@
       },
       {
           AttestationConveyancePreference::ENTERPRISE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2317,7 +2312,7 @@
       },
       {
           AttestationConveyancePreference::ENTERPRISE,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2325,7 +2320,7 @@
       },
       {
           AttestationConveyancePreference::ENTERPRISE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::U2F,
@@ -2333,7 +2328,7 @@
       },
       {
           AttestationConveyancePreference::ENTERPRISE,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::U2F,
@@ -2359,7 +2354,7 @@
   const std::vector<TestCase> kTests = {
       {
           AttestationConveyancePreference::ENTERPRISE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2367,7 +2362,7 @@
       },
       {
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           // If individual attestation was not requested then the attestation
@@ -2378,7 +2373,7 @@
       },
       {
           AttestationConveyancePreference::ENTERPRISE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           // If individual attestation was not requested then the attestation
@@ -2390,7 +2385,7 @@
 
       {
           AttestationConveyancePreference::ENTERPRISE,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::U2F,
@@ -2428,7 +2423,7 @@
           // attestation is requested, the self-attestation will be removed but,
           // because the transport is kInternal, the AAGUID will be preserved.
           AttestationConveyancePreference::NONE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE_WITH_NONZERO_AAGUID,
@@ -2439,7 +2434,7 @@
           // attestation. But because the transport is kInternal, the AAGUID
           // will be preserved.
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE_WITH_NONZERO_AAGUID,
@@ -2449,7 +2444,7 @@
           // If attestation is requested and granted, the self attestation
           // will be returned.
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::SELF_WITH_NONZERO_AAGUID,
@@ -2471,7 +2466,7 @@
           // If no attestation is requested, we'll return the self attestation
           // rather than erasing it.
           AttestationConveyancePreference::NONE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::SELF,
@@ -2481,7 +2476,7 @@
           // If attestation is requested, but denied, we'll return none
           // attestation.
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2491,7 +2486,7 @@
           // If attestation is requested and granted, the self attestation will
           // be returned.
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::GRANTED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::SELF,
@@ -2517,7 +2512,7 @@
           // self-attestation should still be replaced with a "none"
           // attestation.
           AttestationConveyancePreference::NONE,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationConsent::DENIED,
           AuthenticatorStatus::SUCCESS,
           AttestationType::NONE,
@@ -2534,62 +2529,62 @@
   static constexpr struct {
     const char* domains;
     AttestationConveyancePreference attestation;
-    IndividualAttestation individual_attestation;
+    EnterprisePolicy enterprise_policy;
     AttestationType result;
   } kTests[] = {
       // Empty or nonsense parameter doesn't block anything.
       {
           "",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationType::U2F,
       },
       {
           " ,,   ,, ",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationType::U2F,
       },
       // Direct listing of domain blocks...
       {
           "foo.example.com",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationType::NONE,
       },
       // ... unless attestation is permitted by policy.
       {
           "foo.example.com",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationType::U2F,
       },
       // Additional stuff in the string doesn't break the blocking.
       {
           "other,foo.example.com,,nonsenseXYZ123",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationType::NONE,
       },
       // The whole domain can be blocked.
       {
           "(*.)example.com",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationType::NONE,
       },
       // Policy again overrides
       {
           "(*.)example.com",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::REQUESTED,
+          EnterprisePolicy::LISTED,
           AttestationType::U2F,
       },
       // Trying to block everything doesn't work.
       {
           "(*.)",
           AttestationConveyancePreference::DIRECT,
-          IndividualAttestation::NOT_REQUESTED,
+          EnterprisePolicy::NOT_LISTED,
           AttestationType::U2F,
       },
   };
@@ -2609,7 +2604,7 @@
     const std::vector<TestCase> kTestCase = {
         {
             test.attestation,
-            test.individual_attestation,
+            test.enterprise_policy,
             AttestationConsent::GRANTED,
             AuthenticatorStatus::SUCCESS,
             test.result,
@@ -2819,7 +2814,7 @@
       : TestAuthenticatorRequestDelegate(
             nullptr /* render_frame_host */,
             base::DoNothing() /* did_start_request_callback */,
-            IndividualAttestation::NOT_REQUESTED,
+            EnterprisePolicy::NOT_LISTED,
             AttestationConsent::DENIED,
             true /* is_focused */,
             /*is_uvpaa=*/false),
@@ -2899,8 +2894,6 @@
   mojo::Remote<blink::mojom::Authenticator> ConstructFakeAuthenticatorWithTimer(
       std::unique_ptr<MockAuthenticatorRequestDelegateObserver> delegate,
       scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {
-    fake_hid_manager_ = std::make_unique<device::FakeFidoHidManager>();
-
     // Set up a timer for testing.
     auto timer =
         std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
@@ -3476,6 +3469,38 @@
   }
 }
 
+TEST_F(AuthenticatorImplTest, ResetDiscoveryFactoryOverride) {
+  // This is a regression test for crbug.com/1087158.
+  NavigateAndCommit(GURL(kTestOrigin1));
+
+  base::RunLoop run_loop;
+  virtual_device_factory_->SetSupportedProtocol(
+      device::ProtocolVersion::kCtap2);
+  virtual_device_factory_->mutable_state()->simulate_press_callback =
+      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
+        run_loop.QuitClosure().Run();
+        return false;
+      });
+
+  auto task_runner = base::MakeRefCounted<base::TestMockTimeTaskRunner>(
+      base::Time::Now(), base::TimeTicks::Now());
+  mojo::Remote<blink::mojom::Authenticator> authenticator =
+      ConstructAuthenticatorWithTimer(task_runner);
+  PublicKeyCredentialCreationOptionsPtr options =
+      GetTestPublicKeyCredentialCreationOptions();
+  TestMakeCredentialCallback callback;
+  authenticator->MakeCredential(std::move(options), callback.callback());
+
+  // Reset the FidoDiscoveryFactory while the request is processing, then let it
+  // time out.
+  run_loop.Run();
+  ResetVirtualDevice();
+  task_runner->FastForwardBy(base::TimeDelta::FromMinutes(1));
+
+  callback.WaitForCallback();
+  EXPECT_EQ(callback.status(), AuthenticatorStatus::NOT_ALLOWED_ERROR);
+}
+
 static constexpr char kTestPIN[] = "1234";
 
 class UVTestAuthenticatorClientDelegate
@@ -3704,7 +3729,7 @@
 
   void TearDown() override {
     SetBrowserClientForTesting(old_client_);
-    AuthenticatorImplTest::TearDown();
+    UVAuthenticatorImplTest::TearDown();
   }
 
  protected:
@@ -4763,7 +4788,7 @@
 
   void TearDown() override {
     SetBrowserClientForTesting(old_client_);
-    AuthenticatorImplTest::TearDown();
+    UVAuthenticatorImplTest::TearDown();
   }
 
  protected:
@@ -5430,8 +5455,6 @@
   InternalAuthenticatorImpl* ConstructAuthenticatorWithTimer(
       const url::Origin& effective_origin_url,
       scoped_refptr<base::TestMockTimeTaskRunner> task_runner) {
-    fake_hid_manager_ = std::make_unique<device::FakeFidoHidManager>();
-
     // Set up a timer for testing.
     auto timer =
         std::make_unique<base::OneShotTimer>(task_runner->GetMockTickClock());
@@ -5441,7 +5464,6 @@
 
  protected:
   std::unique_ptr<InternalAuthenticatorImpl> internal_authenticator_impl_;
-  std::unique_ptr<device::FakeFidoHidManager> fake_hid_manager_;
 };
 
 // Verify behavior for various combinations of origins and RP IDs.
diff --git a/content/browser/xr/service/browser_xr_runtime_impl.cc b/content/browser/xr/service/browser_xr_runtime_impl.cc
index 3d05d04..03827f97 100644
--- a/content/browser/xr/service/browser_xr_runtime_impl.cc
+++ b/content/browser/xr/service/browser_xr_runtime_impl.cc
@@ -213,9 +213,11 @@
 
 BrowserXRRuntimeImpl::BrowserXRRuntimeImpl(
     device::mojom::XRDeviceId id,
+    device::mojom::XRDeviceDataPtr device_data,
     mojo::PendingRemote<device::mojom::XRRuntime> runtime,
     device::mojom::VRDisplayInfoPtr display_info)
     : id_(id),
+      device_data_(std::move(device_data)),
       runtime_(std::move(runtime)),
       display_info_(ValidateVRDisplayInfo(display_info.get(), id)) {
   DVLOG(2) << __func__ << ": id=" << id;
@@ -558,4 +560,10 @@
   StopImmersiveSession(base::DoNothing());
 }
 
+#if defined(OS_WIN)
+base::Optional<LUID> BrowserXRRuntimeImpl::GetLuid() const {
+  return device_data_->luid;
+}
+#endif
+
 }  // namespace content
diff --git a/content/browser/xr/service/browser_xr_runtime_impl.h b/content/browser/xr/service/browser_xr_runtime_impl.h
index 412f4d96..23a4ed1 100644
--- a/content/browser/xr/service/browser_xr_runtime_impl.h
+++ b/content/browser/xr/service/browser_xr_runtime_impl.h
@@ -10,6 +10,7 @@
 
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
+#include "build/build_config.h"
 #include "content/browser/xr/service/vr_service_impl.h"
 #include "content/public/browser/browser_xr_runtime.h"
 #include "content/public/browser/render_frame_host.h"
@@ -35,6 +36,7 @@
       base::OnceCallback<void(device::mojom::XRSessionPtr)>;
   explicit BrowserXRRuntimeImpl(
       device::mojom::XRDeviceId id,
+      device::mojom::XRDeviceDataPtr device_data,
       mojo::PendingRemote<device::mojom::XRRuntime> runtime,
       device::mojom::VRDisplayInfoPtr info);
   ~BrowserXRRuntimeImpl() override;
@@ -71,6 +73,10 @@
 
   device::mojom::XRDeviceId GetId() const { return id_; }
 
+#if defined(OS_WIN)
+  base::Optional<LUID> GetLuid() const;
+#endif
+
   // BrowserXRRuntime
   void AddObserver(Observer* observer) override;
   void RemoveObserver(Observer* observer) override;
@@ -100,6 +106,7 @@
   void OnInstallFinished(bool succeeded);
 
   device::mojom::XRDeviceId id_;
+  device::mojom::XRDeviceDataPtr device_data_;
   mojo::Remote<device::mojom::XRRuntime> runtime_;
   mojo::Remote<device::mojom::XRSessionController>
       immersive_session_controller_;
diff --git a/content/browser/xr/service/isolated_device_provider.cc b/content/browser/xr/service/isolated_device_provider.cc
index aae1ae6c6..650a8661 100644
--- a/content/browser/xr/service/isolated_device_provider.cc
+++ b/content/browser/xr/service/isolated_device_provider.cc
@@ -18,6 +18,7 @@
 void IsolatedVRDeviceProvider::Initialize(
     base::RepeatingCallback<void(device::mojom::XRDeviceId,
                                  device::mojom::VRDisplayInfoPtr,
+                                 device::mojom::XRDeviceDataPtr,
                                  mojo::PendingRemote<device::mojom::XRRuntime>)>
         add_device_callback,
     base::RepeatingCallback<void(device::mojom::XRDeviceId)>
@@ -37,8 +38,10 @@
 void IsolatedVRDeviceProvider::OnDeviceAdded(
     mojo::PendingRemote<device::mojom::XRRuntime> device,
     mojo::PendingRemote<device::mojom::XRCompositorHost> compositor_host,
+    device::mojom::XRDeviceDataPtr device_data,
     device::mojom::XRDeviceId device_id) {
-  add_device_callback_.Run(device_id, nullptr, std::move(device));
+  add_device_callback_.Run(device_id, nullptr, std::move(device_data),
+                           std::move(device));
 
   auto* integration_client = GetXrIntegrationClient();
   if (!integration_client)
diff --git a/content/browser/xr/service/isolated_device_provider.h b/content/browser/xr/service/isolated_device_provider.h
index e362f18..6495c37 100644
--- a/content/browser/xr/service/isolated_device_provider.h
+++ b/content/browser/xr/service/isolated_device_provider.h
@@ -30,6 +30,7 @@
       base::RepeatingCallback<void(
           device::mojom::XRDeviceId,
           device::mojom::VRDisplayInfoPtr,
+          device::mojom::XRDeviceDataPtr,
           mojo::PendingRemote<device::mojom::XRRuntime>)> add_device_callback,
       base::RepeatingCallback<void(device::mojom::XRDeviceId)>
           remove_device_callback,
@@ -43,6 +44,7 @@
   void OnDeviceAdded(
       mojo::PendingRemote<device::mojom::XRRuntime> device,
       mojo::PendingRemote<device::mojom::XRCompositorHost> compositor_host,
+      device::mojom::XRDeviceDataPtr device_data,
       device::mojom::XRDeviceId device_id) override;
   void OnDeviceRemoved(device::mojom::XRDeviceId id) override;
   void OnDevicesEnumerated() override;
@@ -53,8 +55,10 @@
   int retry_count_ = 0;
   mojo::Remote<device::mojom::IsolatedXRRuntimeProvider> device_provider_;
 
+  // TODO(crbug.com/1090029): Wrap XRDeviceId + VRDisplayInfo into XRDeviceData
   base::RepeatingCallback<void(device::mojom::XRDeviceId,
                                device::mojom::VRDisplayInfoPtr,
+                               device::mojom::XRDeviceDataPtr,
                                mojo::PendingRemote<device::mojom::XRRuntime>)>
       add_device_callback_;
   base::RepeatingCallback<void(device::mojom::XRDeviceId)>
diff --git a/content/browser/xr/service/xr_runtime_manager_impl.cc b/content/browser/xr/service/xr_runtime_manager_impl.cc
index 1774287..66befd7 100644
--- a/content/browser/xr/service/xr_runtime_manager_impl.cc
+++ b/content/browser/xr/service/xr_runtime_manager_impl.cc
@@ -392,14 +392,15 @@
 void XRRuntimeManagerImpl::AddRuntime(
     device::mojom::XRDeviceId id,
     device::mojom::VRDisplayInfoPtr info,
+    device::mojom::XRDeviceDataPtr device_data,
     mojo::PendingRemote<device::mojom::XRRuntime> runtime) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   DCHECK(runtimes_.find(id) == runtimes_.end());
 
   TRACE_EVENT_INSTANT1("xr", "AddRuntime", TRACE_EVENT_SCOPE_THREAD, "id", id);
 
-  runtimes_[id] = std::make_unique<BrowserXRRuntimeImpl>(id, std::move(runtime),
-                                                         std::move(info));
+  runtimes_[id] = std::make_unique<BrowserXRRuntimeImpl>(
+      id, std::move(device_data), std::move(runtime), std::move(info));
 
   for (Observer& obs : g_xr_runtime_manager_observers.Get())
     obs.OnRuntimeAdded(runtimes_[id].get());
diff --git a/content/browser/xr/service/xr_runtime_manager_impl.h b/content/browser/xr/service/xr_runtime_manager_impl.h
index 502b614..d7f03766 100644
--- a/content/browser/xr/service/xr_runtime_manager_impl.h
+++ b/content/browser/xr/service/xr_runtime_manager_impl.h
@@ -101,6 +101,7 @@
 
   void AddRuntime(device::mojom::XRDeviceId id,
                   device::mojom::VRDisplayInfoPtr info,
+                  device::mojom::XRDeviceDataPtr device_data,
                   mojo::PendingRemote<device::mojom::XRRuntime> runtime);
   void RemoveRuntime(device::mojom::XRDeviceId id);
 
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index ef16ed5a..2638a9b 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -354,6 +354,9 @@
           {"CSSReducedFontLoadingLayoutInvalidations",
            blink::features::kCSSReducedFontLoadingLayoutInvalidations,
            kUseFeatureState},
+          {"CSSMatchedPropertiesCacheDependencies",
+           blink::features::kCSSMatchedPropertiesCacheDependencies,
+           kUseFeatureState},
           {"FeaturePolicyForClientHints",
            features::kFeaturePolicyForClientHints, kUseFeatureState},
           {"FlexGaps", blink::features::kFlexGaps, kEnableOnly},
diff --git a/content/child/webthemeengine_impl_android.cc b/content/child/webthemeengine_impl_android.cc
index a879ed2..fe96bd1 100644
--- a/content/child/webthemeengine_impl_android.cc
+++ b/content/child/webthemeengine_impl_android.cc
@@ -84,6 +84,8 @@
       native_theme_extra_params->slider.thumb_x = extra_params->slider.thumb_x;
       native_theme_extra_params->slider.thumb_y = extra_params->slider.thumb_y;
       native_theme_extra_params->slider.zoom = extra_params->slider.zoom;
+      native_theme_extra_params->slider.right_to_left =
+          extra_params->slider.right_to_left;
       FALLTHROUGH;
     case WebThemeEngine::kPartSliderThumb:
       native_theme_extra_params->slider.vertical =
diff --git a/content/child/webthemeengine_impl_default.cc b/content/child/webthemeengine_impl_default.cc
index 0691820..3b81850 100644
--- a/content/child/webthemeengine_impl_default.cc
+++ b/content/child/webthemeengine_impl_default.cc
@@ -107,6 +107,8 @@
       native_theme_extra_params->slider.thumb_x = extra_params->slider.thumb_x;
       native_theme_extra_params->slider.thumb_y = extra_params->slider.thumb_y;
       native_theme_extra_params->slider.zoom = extra_params->slider.zoom;
+      native_theme_extra_params->slider.right_to_left =
+          extra_params->slider.right_to_left;
       FALLTHROUGH;
       // vertical and in_drag properties are used by both slider track and
       // slider thumb.
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 0841ebf..26a883c 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -458,7 +458,6 @@
     "renderer.mojom",
     "renderer_host.mojom",
     "renderer_variations_configuration.mojom",
-    "widget.mojom",
   ]
 
   enabled_features = []
diff --git a/content/common/drag_messages.h b/content/common/drag_messages.h
index 3eb2998..edc0de4 100644
--- a/content/common/drag_messages.h
+++ b/content/common/drag_messages.h
@@ -34,10 +34,6 @@
                     blink::WebDragOperationsMask /* ops_allowed */,
                     int /* key_modifiers */)
 
-IPC_MESSAGE_ROUTED2(DragMsg_TargetDragLeave,
-                    gfx::PointF /* client_point */,
-                    gfx::PointF /* screen_point */)
-
 IPC_MESSAGE_ROUTED4(DragMsg_TargetDrop,
                     content::DropData /* drop_data */,
                     gfx::PointF /* client_pt */,
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 89fe82e..26523f77 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -10,7 +10,6 @@
 import "content/common/native_types.mojom";
 import "content/common/navigation_client.mojom";
 import "content/common/navigation_params.mojom";
-import "content/common/widget.mojom";
 import "content/public/common/browser_controls_state.mojom";
 import "content/public/common/transferrable_url_loader.mojom";
 import "content/public/common/window_container_type.mojom";
@@ -382,13 +381,13 @@
 
   // Similar to CreateNewWindow, except used for sub-widgets, like <select>
   // dropdowns.
-  [Sync] CreateNewWidget(pending_remote<Widget> widget,
+  [Sync] CreateNewWidget(
          pending_associated_receiver<blink.mojom.WidgetHost> blink_widget_host,
          pending_associated_remote<blink.mojom.Widget> blink_widget)
       => (int32 routing_id);
 
   // Similar to CreateNewWidget except the widget is a full screen window.
-  [Sync] CreateNewFullscreenWidget(pending_remote<Widget> widget,
+  [Sync] CreateNewFullscreenWidget(
          pending_associated_receiver<blink.mojom.WidgetHost> blink_widget_host,
          pending_associated_remote<blink.mojom.Widget> blink_widget)
       => (int32 routing_id);
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 95992e1..2d704de1 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -716,9 +716,6 @@
                     std::string /* message */,
                     base::ListValue /* args */)
 
-// Sent to notify that a frame called |window.focus()|.
-IPC_MESSAGE_ROUTED0(FrameHostMsg_FrameDidCallFocus)
-
 // Ask the frame host to print a cross-process subframe.
 // The printed content of this subframe belongs to the document specified by
 // its document cookie. Document cookie is a unique id for a printed document
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index 85a8c7e..19fa7ac 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -144,8 +144,6 @@
 IPC_MESSAGE_ROUTED1(ViewHostMsg_UpdateTargetURL,
                     GURL)
 
-IPC_MESSAGE_ROUTED0(ViewHostMsg_Focus)
-
 #if BUILDFLAG(ENABLE_PLUGINS)
 // A renderer sends this to the browser process when it wants to access a PPAPI
 // broker. In contrast to FrameHostMsg_OpenChannelToPpapiBroker, this is called
diff --git a/content/common/widget.mojom b/content/common/widget.mojom
deleted file mode 100644
index 5373594..0000000
--- a/content/common/widget.mojom
+++ /dev/null
@@ -1,19 +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.
-
-module content.mojom;
-
-import "third_party/blink/public/mojom/input/input_handler.mojom";
-
-// Interface exposed by the renderer for Widgets.
-interface Widget {
-  // Setup the input channel for this widget. If the widget is a frame,
-  // then it will have a FrameInputHandler and the WidgetInputHandler should
-  // be obtained using that interface instead. The frame's FrameInputHandler
-  // uses associated receivers to ensure serial ordering with the frame
-  // input messages.
-  SetupWidgetInputHandler(
-    pending_receiver<blink.mojom.WidgetInputHandler> request,
-    pending_remote<blink.mojom.WidgetInputHandlerHost> host);
-};
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h
index d9efc5a..d1ea9482 100644
--- a/content/common/widget_messages.h
+++ b/content/common/widget_messages.h
@@ -210,8 +210,4 @@
 // Sent in reply to WidgetMsg_WaitForNextFrameForTests.
 IPC_MESSAGE_ROUTED0(WidgetHostMsg_WaitForNextFrameForTests_ACK)
 
-// Sent once a paint happens after the first non empty layout. In other words,
-// after the frame widget has painted something.
-IPC_MESSAGE_ROUTED0(WidgetHostMsg_DidFirstVisuallyNonEmptyPaint)
-
 #endif  //  CONTENT_COMMON_WIDGET_MESSAGES_H_
diff --git a/content/public/browser/overlay_window.h b/content/public/browser/overlay_window.h
index 361f8e1..644e5a4d 100644
--- a/content/public/browser/overlay_window.h
+++ b/content/public/browser/overlay_window.h
@@ -56,7 +56,7 @@
   virtual gfx::Rect GetBounds() = 0;
   virtual void UpdateVideoSize(const gfx::Size& natural_size) = 0;
   virtual void SetPlaybackState(PlaybackState playback_state) = 0;
-  virtual void SetAlwaysHidePlayPauseButton(bool is_visible) = 0;
+  virtual void SetPlayPauseButtonVisibility(bool is_visible) = 0;
   virtual void SetSkipAdButtonVisibility(bool is_visible) = 0;
   virtual void SetNextTrackButtonVisibility(bool is_visible) = 0;
   virtual void SetPreviousTrackButtonVisibility(bool is_visible) = 0;
diff --git a/content/public/browser/picture_in_picture_window_controller.h b/content/public/browser/picture_in_picture_window_controller.h
index ff58d85..1a54e5a 100644
--- a/content/public/browser/picture_in_picture_window_controller.h
+++ b/content/public/browser/picture_in_picture_window_controller.h
@@ -46,7 +46,6 @@
   virtual WebContents* GetWebContents() = 0;
   virtual void UpdatePlaybackState(bool is_playing,
                                    bool reached_end_of_stream) = 0;
-  virtual void SetAlwaysHidePlayPauseButton(bool is_visible) = 0;
 
   // Called when the user interacts with the "Skip Ad" control.
   virtual void SkipAd() = 0;
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index adda5022..61dc1e9 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -260,14 +260,6 @@
 const base::Feature kIdleDetection{"IdleDetection",
                                    base::FEATURE_ENABLED_BY_DEFAULT};
 
-// This flag is used to set field parameters to choose predictor we use when
-// kResamplingInputEvents is disabled. It's used for gatherig accuracy metrics
-// on finch and also for choosing predictor type for predictedEvents API without
-// enabling resampling. It does not have any effect when the resampling flag is
-// enabled.
-const base::Feature kInputPredictorTypeChoice{
-    "InputPredictorTypeChoice", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Kill switch for the GetInstalledRelatedApps API.
 const base::Feature kInstalledApp{"InstalledApp",
                                   base::FEATURE_ENABLED_BY_DEFAULT};
@@ -507,10 +499,6 @@
 const base::Feature kRequestUnbufferedDispatch{
     "RequestUnbufferedDispatch", base::FEATURE_ENABLED_BY_DEFAULT};
 
-// Enables resampling input events on main thread.
-const base::Feature kResamplingInputEvents{"ResamplingInputEvents",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Respect the MacOS system setting for subpixel text anti-aliasing.
 // https://crbug.com/1079418.
 const base::Feature kRespectMacLCDTextSetting{
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 7a05dd9..ba632866 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -65,7 +65,6 @@
 CONTENT_EXPORT extern const base::Feature kHistoryManipulationIntervention;
 CONTENT_EXPORT extern const base::Feature kHistoryPreventSandboxedNavigation;
 CONTENT_EXPORT extern const base::Feature kIdleDetection;
-CONTENT_EXPORT extern const base::Feature kInputPredictorTypeChoice;
 CONTENT_EXPORT extern const base::Feature kInstalledApp;
 CONTENT_EXPORT extern const base::Feature kInstalledAppProvider;
 CONTENT_EXPORT extern const base::Feature kInstalledAppsInCbd;
@@ -109,7 +108,6 @@
 CONTENT_EXPORT extern const base::Feature kReloadHiddenTabsWithCrashedSubframes;
 CONTENT_EXPORT extern const base::Feature kRenderDocument;
 CONTENT_EXPORT extern const base::Feature kRequestUnbufferedDispatch;
-CONTENT_EXPORT extern const base::Feature kResamplingInputEvents;
 CONTENT_EXPORT extern const base::Feature kRespectMacLCDTextSetting;
 CONTENT_EXPORT extern const base::Feature
     kRunVideoCaptureServiceInBrowserProcess;
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc
index 8b704a79..6e5c5ae3 100644
--- a/content/public/common/content_switches.cc
+++ b/content/public/common/content_switches.cc
@@ -13,11 +13,6 @@
 // have an effect. 0 disables MSAA.
 const char kAcceleratedCanvas2dMSAASampleCount[] = "canvas-msaa-sample-count";
 
-// Allows processing of input before a frame has been committed.
-// TODO(schenney): crbug.com/987626. Used by headless. Look for a way not
-// involving a command line switch.
-const char kAllowPreCommitInput[] = "allow-pre-commit-input";
-
 // By default, file:// URIs cannot read other file:// URIs. This is an
 // override for developers who need the old behavior for testing.
 const char kAllowFileAccessFromFiles[]      = "allow-file-access-from-files";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h
index 79315333..7d7f843 100644
--- a/content/public/common/content_switches.h
+++ b/content/public/common/content_switches.h
@@ -16,7 +16,6 @@
 // All switches in alphabetical order. The switches should be documented
 // alongside the definition of their values in the .cc file.
 CONTENT_EXPORT extern const char kAcceleratedCanvas2dMSAASampleCount[];
-CONTENT_EXPORT extern const char kAllowPreCommitInput[];
 CONTENT_EXPORT extern const char kAllowFileAccessFromFiles[];
 CONTENT_EXPORT extern const char kAllowInsecureLocalhost[];
 CONTENT_EXPORT extern const char kAllowLoopbackInPeerConnection[];
diff --git a/content/public/common/drop_data.h b/content/public/common/drop_data.h
index bbd24fa2..e4a2cad 100644
--- a/content/public/common/drop_data.h
+++ b/content/public/common/drop_data.h
@@ -17,7 +17,7 @@
 
 #include "base/files/file_path.h"
 #include "base/optional.h"
-#include "base/strings/nullable_string16.h"
+#include "base/strings/string16.h"
 #include "content/common/content_export.h"
 #include "ipc/ipc_message.h"
 #include "services/network/public/mojom/referrer_policy.mojom.h"
@@ -103,12 +103,12 @@
   std::vector<FileSystemFileInfo> file_system_files;
 
   // User is dragging plain text into the webview.
-  base::NullableString16 text;
+  base::Optional<base::string16> text;
 
   // User is dragging text/html into the webview (e.g., out of Firefox).
   // |html_base_url| is the URL that the html fragment is taken from (used to
   // resolve relative links).  It's ok for |html_base_url| to be empty.
-  base::NullableString16 html;
+  base::Optional<base::string16> html;
   GURL html_base_url;
 
   // User is dragging an image out of the WebView.
diff --git a/content/public/common/profiling.cc b/content/public/common/profiling.cc
index d083588..794ce4b 100644
--- a/content/public/common/profiling.cc
+++ b/content/public/common/profiling.cc
@@ -71,7 +71,7 @@
 
 class ProfilingThreadControl {
  public:
-  ProfilingThreadControl() : thread_(NULL) {}
+  ProfilingThreadControl() : thread_(nullptr) {}
 
   void Start() {
     base::AutoLock locked(lock_);
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ChildProcessAllocatorSettingsHook.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ChildProcessAllocatorSettingsHook.java
index f49f76b..4a9ea747 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ChildProcessAllocatorSettingsHook.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ChildProcessAllocatorSettingsHook.java
@@ -6,19 +6,19 @@
 
 import android.content.Context;
 
-import org.chromium.base.test.BaseTestResult.PreTestHook;
-import org.chromium.content.browser.ChildProcessLauncherHelperImpl;
+import org.junit.runners.model.FrameworkMethod;
 
-import java.lang.reflect.Method;
+import org.chromium.base.test.BaseJUnit4ClassRunner.TestHook;
+import org.chromium.content.browser.ChildProcessLauncherHelperImpl;
 
 /**
  * PreTestHook used to register the ChildProcessAllocatorSettings annotation.
  *
  * TODO(yolandyan): convert this to TestRule once content tests are changed JUnit4
  * */
-public final class ChildProcessAllocatorSettingsHook implements PreTestHook {
+public final class ChildProcessAllocatorSettingsHook implements TestHook {
     @Override
-    public void run(Context targetContext, Method testMethod) {
+    public void run(Context targetContext, FrameworkMethod testMethod) {
         ChildProcessAllocatorSettings annotation =
                 testMethod.getAnnotation(ChildProcessAllocatorSettings.class);
         if (annotation != null) {
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java
index 03b4716..ec13a5d6 100644
--- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java
+++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/ContentJUnit4ClassRunner.java
@@ -8,10 +8,7 @@
 
 import org.junit.runners.model.InitializationError;
 
-import org.chromium.base.CommandLineInitUtil;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
-import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.SkipCheck;
 import org.chromium.ui.test.util.UiDisableIfSkipCheck;
 import org.chromium.ui.test.util.UiRestrictionSkipCheck;
@@ -37,17 +34,12 @@
                 new UiRestrictionSkipCheck(InstrumentationRegistry.getTargetContext()),
                 new UiDisableIfSkipCheck(InstrumentationRegistry.getTargetContext()));
     }
+
     /**
      * Change this static function to add default {@code PreTestHook}s.
      */
     @Override
-    protected List<PreTestHook> getPreTestHooks() {
-        return addToList(super.getPreTestHooks(), CommandLineFlags.getRegistrationHook(),
-                new ChildProcessAllocatorSettingsHook());
-    }
-
-    @Override
-    protected void initCommandLineForTest() {
-        CommandLineInitUtil.initCommandLine(CommandLineFlags.getTestCmdLineFile());
+    protected List<TestHook> getPreTestHooks() {
+        return addToList(super.getPreTestHooks(), new ChildProcessAllocatorSettingsHook());
     }
 }
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 0c360ed..a000d0c6 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -1805,8 +1805,8 @@
       url, options,
       base::BindOnce(
           [](std::string* cookies_out, base::RunLoop* run_loop,
-             const net::CookieStatusList& cookies,
-             const net::CookieStatusList& excluded_cookies) {
+             const net::CookieAccessResultList& cookies,
+             const net::CookieAccessResultList& excluded_cookies) {
             *cookies_out = net::CanonicalCookie::BuildCookieLine(cookies);
             run_loop->Quit();
           },
@@ -1833,9 +1833,9 @@
       base::BindOnce(
           [](base::RunLoop* run_loop,
              std::vector<net::CanonicalCookie>* cookies_out,
-             const net::CookieStatusList& cookies,
-             const net::CookieStatusList& excluded_cookies) {
-            *cookies_out = net::cookie_util::StripStatuses(cookies);
+             const net::CookieAccessResultList& cookies,
+             const net::CookieAccessResultList& excluded_cookies) {
+            *cookies_out = net::cookie_util::StripAccessResults(cookies);
             run_loop->Quit();
           },
           &run_loop, &cookies));
diff --git a/content/public/test/fake_frame_widget.h b/content/public/test/fake_frame_widget.h
index bf22aa1..137e97c 100644
--- a/content/public/test/fake_frame_widget.h
+++ b/content/public/test/fake_frame_widget.h
@@ -24,6 +24,8 @@
   base::i18n::TextDirection GetTextDirection() const;
 
  private:
+  void DragTargetDragLeave(const gfx::PointF& point_in_viewport,
+                           const gfx::PointF& screen_point) override {}
   void DragSourceSystemDragEnded() override {}
   void SetBackgroundOpaque(bool value) override {}
   void SetTextDirection(base::i18n::TextDirection direction) override;
diff --git a/content/public/test/fake_render_widget_host.cc b/content/public/test/fake_render_widget_host.cc
index aadd508..ee0ef0c 100644
--- a/content/public/test/fake_render_widget_host.cc
+++ b/content/public/test/fake_render_widget_host.cc
@@ -50,10 +50,46 @@
     const base::string16& tooltip_text,
     base::i18n::TextDirection text_direction_hint) {}
 
+void FakeRenderWidgetHost::SetTouchActionFromMain(
+    cc::TouchAction touch_action) {}
+
+void FakeRenderWidgetHost::DidOverscroll(
+    blink::mojom::DidOverscrollParamsPtr params) {}
+
+void FakeRenderWidgetHost::DidStartScrollingViewport() {}
+
+void FakeRenderWidgetHost::ImeCancelComposition() {}
+
+void FakeRenderWidgetHost::ImeCompositionRangeChanged(
+    const gfx::Range& range,
+    const std::vector<gfx::Rect>& bounds) {}
+
+void FakeRenderWidgetHost::SetMouseCapture(bool capture) {}
+
+void FakeRenderWidgetHost::RequestMouseLock(bool from_user_gesture,
+                                            bool privileged,
+                                            bool unadjusted_movement,
+                                            RequestMouseLockCallback callback) {
+}
+
 void FakeRenderWidgetHost::AutoscrollStart(const gfx::PointF& position) {}
 
 void FakeRenderWidgetHost::AutoscrollFling(const gfx::Vector2dF& position) {}
 
 void FakeRenderWidgetHost::AutoscrollEnd() {}
 
+void FakeRenderWidgetHost::DidFirstVisuallyNonEmptyPaint() {}
+
+blink::mojom::FrameWidgetInputHandler*
+FakeRenderWidgetHost::GetFrameWidgetInputHandler() {
+  if (!frame_widget_input_handler_) {
+    widget_remote_->GetWidgetInputHandler(
+        widget_input_handler_.BindNewPipeAndPassReceiver(),
+        widget_input_handler_host_.BindNewPipeAndPassRemote());
+    widget_input_handler_->GetFrameWidgetInputHandler(
+        frame_widget_input_handler_.BindNewEndpointAndPassReceiver());
+  }
+  return frame_widget_input_handler_.get();
+}
+
 }  // namespace content
diff --git a/content/public/test/fake_render_widget_host.h b/content/public/test/fake_render_widget_host.h
index 0b04b32..30a8e11 100644
--- a/content/public/test/fake_render_widget_host.h
+++ b/content/public/test/fake_render_widget_host.h
@@ -10,13 +10,15 @@
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom-forward.h"
 #include "third_party/blink/public/mojom/page/widget.mojom.h"
 
 namespace content {
 
 class FakeRenderWidgetHost : public blink::mojom::FrameWidgetHost,
-                             public blink::mojom::WidgetHost {
+                             public blink::mojom::WidgetHost,
+                             public blink::mojom::WidgetInputHandlerHost {
  public:
   FakeRenderWidgetHost();
   ~FakeRenderWidgetHost() override;
@@ -39,17 +41,34 @@
   void AutoscrollStart(const gfx::PointF& position) override;
   void AutoscrollFling(const gfx::Vector2dF& position) override;
   void AutoscrollEnd() override;
+  void DidFirstVisuallyNonEmptyPaint() override;
 
   // blink::mojom::WidgetHost overrides.
   void SetCursor(const ui::Cursor& cursor) override;
   void SetToolTipText(const base::string16& tooltip_text,
                       base::i18n::TextDirection text_direction_hint) override;
 
+  // blink::mojom::WidgetInputHandlerHost overrides.
+  void SetTouchActionFromMain(cc::TouchAction touch_action) override;
+  void DidOverscroll(blink::mojom::DidOverscrollParamsPtr params) override;
+  void DidStartScrollingViewport() override;
+  void ImeCancelComposition() override;
+  void ImeCompositionRangeChanged(
+      const gfx::Range& range,
+      const std::vector<gfx::Rect>& bounds) override;
+  void SetMouseCapture(bool capture) override;
+  void RequestMouseLock(bool from_user_gesture,
+                        bool privileged,
+                        bool unadjusted_movement,
+                        RequestMouseLockCallback callback) override;
+
   mojo::AssociatedReceiver<blink::mojom::WidgetHost>&
   widget_host_receiver_for_testing() {
     return widget_host_receiver_;
   }
 
+  blink::mojom::FrameWidgetInputHandler* GetFrameWidgetInputHandler();
+
  private:
   mojo::AssociatedReceiver<blink::mojom::FrameWidgetHost>
       frame_widget_host_receiver_{this};
@@ -57,6 +76,11 @@
   mojo::AssociatedReceiver<blink::mojom::WidgetHost> widget_host_receiver_{
       this};
   mojo::AssociatedRemote<blink::mojom::Widget> widget_remote_;
+  mojo::Remote<blink::mojom::WidgetInputHandler> widget_input_handler_;
+  mojo::Receiver<blink::mojom::WidgetInputHandlerHost>
+      widget_input_handler_host_{this};
+  mojo::AssociatedRemote<blink::mojom::FrameWidgetInputHandler>
+      frame_widget_input_handler_;
 
   DISALLOW_COPY_AND_ASSIGN(FakeRenderWidgetHost);
 };
diff --git a/content/public/test/test_renderer_host.cc b/content/public/test/test_renderer_host.cc
index 6258c55..59cc113 100644
--- a/content/public/test/test_renderer_host.cc
+++ b/content/public/test/test_renderer_host.cc
@@ -93,7 +93,7 @@
 void RenderViewHostTester::SimulateFirstPaint(RenderViewHost* rvh) {
   static_cast<RenderViewHostImpl*>(rvh)
       ->GetWidget()
-      ->OnFirstVisuallyNonEmptyPaint();
+      ->DidFirstVisuallyNonEmptyPaint();
 }
 
 // static
diff --git a/content/renderer/drop_data_builder.cc b/content/renderer/drop_data_builder.cc
index ad2fa8d..f844da3 100644
--- a/content/renderer/drop_data_builder.cc
+++ b/content/renderer/drop_data_builder.cc
@@ -32,7 +32,7 @@
       case WebDragData::Item::kStorageTypeString: {
         base::string16 str_type(item.string_type.Utf16());
         if (base::EqualsASCII(str_type, ui::kMimeTypeText)) {
-          result.text = WebString::ToNullableString16(item.string_data);
+          result.text = WebString::ToOptionalString16(item.string_data);
           break;
         }
         if (base::EqualsASCII(str_type, ui::kMimeTypeURIList)) {
@@ -45,7 +45,7 @@
           break;
         }
         if (base::EqualsASCII(str_type, ui::kMimeTypeHTML)) {
-          result.html = WebString::ToNullableString16(item.string_data);
+          result.html = WebString::ToOptionalString16(item.string_data);
           result.html_base_url = item.base_url;
           break;
         }
diff --git a/content/renderer/input/frame_input_handler_impl.cc b/content/renderer/input/frame_input_handler_impl.cc
index e51cbd9..977ebdf25 100644
--- a/content/renderer/input/frame_input_handler_impl.cc
+++ b/content/renderer/input/frame_input_handler_impl.cc
@@ -10,8 +10,8 @@
 #include "base/check.h"
 #include "content/renderer/ime_event_guard.h"
 #include "content/renderer/input/widget_input_handler_manager.h"
+#include "content/renderer/render_frame_impl.h"
 #include "content/renderer/render_thread_impl.h"
-#include "content/renderer/render_view_impl.h"
 #include "content/renderer/render_widget.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -21,40 +21,15 @@
 namespace content {
 
 FrameInputHandlerImpl::FrameInputHandlerImpl(
-    base::WeakPtr<RenderFrameImpl> render_frame,
-    mojo::PendingReceiver<blink::mojom::FrameInputHandler> receiver)
-    : render_frame_(render_frame),
-      input_event_queue_(
-          render_frame->GetLocalRootRenderWidget()->GetInputEventQueue()),
-      main_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
-  weak_this_ = weak_ptr_factory_.GetWeakPtr();
-  // If we have created an input event queue move the mojo request over to the
-  // compositor thread.
-  if (RenderThreadImpl::current() &&
-      RenderThreadImpl::current()->compositor_task_runner() &&
-      input_event_queue_) {
-    // Mojo channel bound on compositor thread.
-    RenderThreadImpl::current()->compositor_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::BindNow,
-                                  base::Unretained(this), std::move(receiver)));
-  } else {
-    // Mojo channel bound on main thread.
-    BindNow(std::move(receiver));
-  }
-}
+    base::WeakPtr<RenderWidget> widget,
+    scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
+    scoped_refptr<MainThreadEventQueue> input_event_queue)
+    : widget_(widget),
+      input_event_queue_(input_event_queue),
+      main_thread_task_runner_(main_thread_task_runner) {}
 
 FrameInputHandlerImpl::~FrameInputHandlerImpl() {}
 
-// static
-void FrameInputHandlerImpl::CreateMojoService(
-    base::WeakPtr<RenderFrameImpl> render_frame,
-    mojo::PendingReceiver<blink::mojom::FrameInputHandler> receiver) {
-  DCHECK(render_frame);
-
-  // Owns itself. Will be deleted when message pipe is destroyed.
-  new FrameInputHandlerImpl(render_frame, std::move(receiver));
-}
-
 void FrameInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) {
   if (input_event_queue_) {
     input_event_queue_->QueueClosure(std::move(closure));
@@ -67,269 +42,316 @@
     int32_t start,
     int32_t end,
     const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::SetCompositionFromExistingText,
-                       weak_this_, start, end, ui_ime_text_spans));
-    return;
-  }
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end,
+         const std::vector<ui::ImeTextSpan>& ui_ime_text_spans) {
+        if (!widget)
+          return;
 
-  if (!render_frame_)
-    return;
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        ImeEventGuard guard(widget);
 
-  ImeEventGuard guard(render_frame_->GetLocalRootRenderWidget()->AsWeakPtr());
-
-  render_frame_->GetWebFrame()->SetCompositionFromExistingText(
-      start, end, ui_ime_text_spans);
+        focused_frame->SetCompositionFromExistingText(start, end,
+                                                      ui_ime_text_spans);
+      },
+      widget_, start, end, ui_ime_text_spans));
 }
 
 void FrameInputHandlerImpl::ExtendSelectionAndDelete(int32_t before,
                                                      int32_t after) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::ExtendSelectionAndDelete,
-                       weak_this_, before, after));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  render_frame_->GetWebFrame()->ExtendSelectionAndDelete(before, after);
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) {
+        if (!widget)
+          return;
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        focused_frame->ExtendSelectionAndDelete(before, after);
+      },
+      widget_, before, after));
 }
 
 void FrameInputHandlerImpl::DeleteSurroundingText(int32_t before,
                                                   int32_t after) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::DeleteSurroundingText,
-                       weak_this_, before, after));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  render_frame_->GetWebFrame()->DeleteSurroundingText(before, after);
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) {
+        if (!widget)
+          return;
+
+        if (!widget)
+          return;
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        focused_frame->DeleteSurroundingText(before, after);
+      },
+      widget_, before, after));
 }
 
 void FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints(int32_t before,
                                                               int32_t after) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(base::BindOnce(
-        &FrameInputHandlerImpl::DeleteSurroundingTextInCodePoints, weak_this_,
-        before, after));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  render_frame_->GetWebFrame()->DeleteSurroundingTextInCodePoints(before,
-                                                                  after);
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, int32_t before, int32_t after) {
+        if (!widget)
+          return;
+
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        focused_frame->DeleteSurroundingTextInCodePoints(before, after);
+      },
+      widget_, before, after));
 }
 
 void FrameInputHandlerImpl::SetEditableSelectionOffsets(int32_t start,
                                                         int32_t end) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::SetEditableSelectionOffsets,
-                       weak_this_, start, end));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
-  render_frame_->GetWebFrame()->SetEditableSelectionOffsets(start, end);
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end) {
+        if (!widget)
+          return;
+
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        HandlingState handling_state(widget, UpdateState::kIsSelectingRange);
+        focused_frame->SetEditableSelectionOffsets(start, end);
+      },
+      widget_, start, end));
 }
 
 void FrameInputHandlerImpl::ExecuteEditCommand(
     const std::string& command,
     const base::Optional<base::string16>& value) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ExecuteEditCommand,
-                                   weak_this_, command, value));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  if (value) {
-    render_frame_->GetWebFrame()->ExecuteCommand(
-        blink::WebString::FromUTF8(command),
-        blink::WebString::FromUTF16(value.value()));
-    return;
-  }
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, const std::string& command,
+         const base::Optional<base::string16>& value) {
+        if (!widget)
+          return;
 
-  render_frame_->GetWebFrame()->ExecuteCommand(
-      blink::WebString::FromUTF8(command));
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+
+        if (value) {
+          focused_frame->ExecuteCommand(
+              blink::WebString::FromUTF8(command),
+              blink::WebString::FromUTF16(value.value()));
+          return;
+        }
+
+        focused_frame->ExecuteCommand(blink::WebString::FromUTF8(command));
+      },
+      widget_, command, value));
 }
 
 void FrameInputHandlerImpl::Undo() {
   RunOnMainThread(
       base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
-                     weak_this_, "Undo", UpdateState::kNone));
+                     widget_, "Undo", UpdateState::kNone));
 }
 
 void FrameInputHandlerImpl::Redo() {
   RunOnMainThread(
       base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
-                     weak_this_, "Redo", UpdateState::kNone));
+                     widget_, "Redo", UpdateState::kNone));
 }
 
 void FrameInputHandlerImpl::Cut() {
   RunOnMainThread(
       base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
-                     weak_this_, "Cut", UpdateState::kIsSelectingRange));
+                     widget_, "Cut", UpdateState::kIsSelectingRange));
 }
 
 void FrameInputHandlerImpl::Copy() {
   RunOnMainThread(
       base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
-                     weak_this_, "Copy", UpdateState::kIsSelectingRange));
+                     widget_, "Copy", UpdateState::kIsSelectingRange));
 }
 
 void FrameInputHandlerImpl::CopyToFindPboard() {
 #if defined(OS_MACOSX)
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::CopyToFindPboard, weak_this_));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  render_frame_->OnCopyToFindPboard();
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget) {
+        if (!widget)
+          return;
+
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+
+        RenderFrameImpl* render_frame =
+            RenderFrameImpl::FromWebFrame(focused_frame);
+
+        if (!render_frame)
+          return;
+
+        render_frame->OnCopyToFindPboard();
+      },
+      widget_));
 #endif
 }
 
 void FrameInputHandlerImpl::Paste() {
   RunOnMainThread(
       base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
-                     weak_this_, "Paste", UpdateState::kIsPasting));
+                     widget_, "Paste", UpdateState::kIsPasting));
 }
 
 void FrameInputHandlerImpl::PasteAndMatchStyle() {
-  RunOnMainThread(base::BindOnce(
-      &FrameInputHandlerImpl::ExecuteCommandOnMainThread, weak_this_,
-      "PasteAndMatchStyle", UpdateState::kIsPasting));
+  RunOnMainThread(
+      base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
+                     widget_, "PasteAndMatchStyle", UpdateState::kIsPasting));
 }
 
 void FrameInputHandlerImpl::Replace(const base::string16& word) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::Replace, weak_this_, word));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
-  if (!frame->HasSelection())
-    frame->SelectWordAroundCaret();
-  frame->ReplaceSelection(blink::WebString::FromUTF16(word));
-  render_frame_->SyncSelectionIfRequired();
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, const base::string16& word) {
+        if (!widget)
+          return;
+
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+
+        RenderFrameImpl* render_frame =
+            RenderFrameImpl::FromWebFrame(focused_frame);
+
+        if (!render_frame)
+          return;
+
+        if (!focused_frame->HasSelection())
+          focused_frame->SelectWordAroundCaret();
+        focused_frame->ReplaceSelection(blink::WebString::FromUTF16(word));
+        render_frame->SyncSelectionIfRequired();
+      },
+      widget_, word));
 }
 
 void FrameInputHandlerImpl::ReplaceMisspelling(const base::string16& word) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::ReplaceMisspelling,
-                                   weak_this_, word));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
-  if (!frame->HasSelection())
-    return;
-  frame->ReplaceMisspelledRange(blink::WebString::FromUTF16(word));
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, const base::string16& word) {
+        if (!widget)
+          return;
+
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        if (!focused_frame->HasSelection())
+          return;
+        focused_frame->ReplaceMisspelledRange(
+            blink::WebString::FromUTF16(word));
+      },
+      widget_, word));
 }
 
 void FrameInputHandlerImpl::Delete() {
   RunOnMainThread(
       base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
-                     weak_this_, "Delete", UpdateState::kNone));
+                     widget_, "Delete", UpdateState::kNone));
 }
 
 void FrameInputHandlerImpl::SelectAll() {
   RunOnMainThread(
       base::BindOnce(&FrameInputHandlerImpl::ExecuteCommandOnMainThread,
-                     weak_this_, "SelectAll", UpdateState::kIsSelectingRange));
+                     widget_, "SelectAll", UpdateState::kIsSelectingRange));
 }
 
 void FrameInputHandlerImpl::CollapseSelection() {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::CollapseSelection, weak_this_));
-    return;
-  }
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget) {
+        if (!widget)
+          return;
 
-  if (!render_frame_)
-    return;
-  const blink::WebRange& range = render_frame_->GetWebFrame()
-                                     ->GetInputMethodController()
-                                     ->GetSelectionOffsets();
-  if (range.IsNull())
-    return;
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        const blink::WebRange& range =
+            focused_frame->GetInputMethodController()->GetSelectionOffsets();
+        if (range.IsNull())
+          return;
 
-  HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
-  render_frame_->GetWebFrame()->SelectRange(
-      blink::WebRange(range.EndOffset(), 0),
-      blink::WebLocalFrame::kHideSelectionHandle,
-      blink::mojom::SelectionMenuBehavior::kHide);
+        HandlingState handling_state(widget, UpdateState::kIsSelectingRange);
+        focused_frame->SelectRange(blink::WebRange(range.EndOffset(), 0),
+                                   blink::WebLocalFrame::kHideSelectionHandle,
+                                   blink::mojom::SelectionMenuBehavior::kHide);
+      },
+      widget_));
 }
 
 void FrameInputHandlerImpl::SelectRange(const gfx::Point& base,
                                         const gfx::Point& extent) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
     // TODO(dtapuska): This event should be coalesced. Chrome IPC uses
     // one outstanding event and an ACK to handle coalescing on the browser
     // side. We should be able to clobber them in the main thread event queue.
-    RunOnMainThread(base::BindOnce(&FrameInputHandlerImpl::SelectRange,
-                                   weak_this_, base, extent));
-    return;
-  }
+    RunOnMainThread(base::BindOnce(
+        [](base::WeakPtr<RenderWidget> widget, const gfx::Point& base,
+           const gfx::Point& extent) {
+          if (!widget)
+            return;
 
-  if (!render_frame_)
-    return;
-  RenderWidget* window_widget = render_frame_->GetLocalRootRenderWidget();
-  HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
-  render_frame_->GetWebFrame()->SelectRange(
-      window_widget->ConvertWindowPointToViewport(base),
-      window_widget->ConvertWindowPointToViewport(extent));
+          auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+          if (!focused_frame)
+            return;
+
+          HandlingState handling_state(widget, UpdateState::kIsSelectingRange);
+          focused_frame->SelectRange(
+              widget->ConvertWindowPointToViewport(base),
+              widget->ConvertWindowPointToViewport(extent));
+        },
+        widget_, base, extent));
 }
 
 #if defined(OS_ANDROID)
 void FrameInputHandlerImpl::SelectWordAroundCaret(
     SelectWordAroundCaretCallback callback) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::SelectWordAroundCaret,
-                       weak_this_, std::move(callback)));
-    return;
-  }
-
-  bool did_select = false;
-  int start_adjust = 0;
-  int end_adjust = 0;
-  if (render_frame_) {
-    blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
-    blink::WebRange initial_range = frame->SelectionRange();
-    render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(true);
-    if (!initial_range.IsNull())
-      did_select = frame->SelectWordAroundCaret();
-    if (did_select) {
-      blink::WebRange adjusted_range = frame->SelectionRange();
-      DCHECK(!adjusted_range.IsNull());
-      start_adjust = adjusted_range.StartOffset() - initial_range.StartOffset();
-      end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
-    }
-    render_frame_->GetLocalRootRenderWidget()->SetHandlingInputEvent(false);
-  }
-
   // If the mojom channel is registered with compositor thread, we have to run
   // the callback on compositor thread. Otherwise run it on main thread. Mojom
   // requires the callback runs on the same thread.
-  if (RenderThreadImpl::current() &&
-      RenderThreadImpl::current()->compositor_task_runner() &&
-      input_event_queue_) {
-    RenderThreadImpl::current()->compositor_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(std::move(callback), did_select, start_adjust,
-                                  end_adjust));
-  } else {
-    std::move(callback).Run(did_select, start_adjust, end_adjust);
+  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
+    callback = base::BindOnce(
+        [](scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
+           SelectWordAroundCaretCallback callback, bool did_select,
+           int32_t start_adjust, int32_t end_adjust) {
+          compositor_task_runner->PostTask(
+              FROM_HERE, base::BindOnce(std::move(callback), did_select,
+                                        start_adjust, end_adjust));
+        },
+        base::ThreadTaskRunnerHandle::Get(), std::move(callback));
   }
+
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget,
+         SelectWordAroundCaretCallback callback) {
+        if (!widget) {
+          std::move(callback).Run(false, 0, 0);
+          return;
+        }
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame) {
+          std::move(callback).Run(false, 0, 0);
+          return;
+        }
+
+        bool did_select = false;
+        int start_adjust = 0;
+        int end_adjust = 0;
+        blink::WebRange initial_range = focused_frame->SelectionRange();
+        widget->SetHandlingInputEvent(true);
+        if (!initial_range.IsNull())
+          did_select = focused_frame->SelectWordAroundCaret();
+        if (did_select) {
+          blink::WebRange adjusted_range = focused_frame->SelectionRange();
+          DCHECK(!adjusted_range.IsNull());
+          start_adjust =
+              adjusted_range.StartOffset() - initial_range.StartOffset();
+          end_adjust = adjusted_range.EndOffset() - initial_range.EndOffset();
+        }
+        widget->SetHandlingInputEvent(false);
+        std::move(callback).Run(did_select, start_adjust, end_adjust);
+      },
+      widget_, std::move(callback)));
 }
 #endif  // defined(OS_ANDROID)
 
@@ -337,147 +359,126 @@
     int32_t start,
     int32_t end,
     blink::mojom::SelectionMenuBehavior selection_menu_behavior) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::AdjustSelectionByCharacterOffset,
-                       weak_this_, start, end, selection_menu_behavior));
-    return;
-  }
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, int32_t start, int32_t end,
+         blink::mojom::SelectionMenuBehavior selection_menu_behavior) {
+        if (!widget)
+          return;
 
-  if (!render_frame_)
-    return;
-  blink::WebRange range = render_frame_->GetWebFrame()
-                              ->GetInputMethodController()
-                              ->GetSelectionOffsets();
-  if (range.IsNull())
-    return;
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
 
-  // Sanity checks to disallow empty and out of range selections.
-  if (start - end > range.length() || range.StartOffset() + start < 0)
-    return;
+        blink::WebRange range =
+            focused_frame->GetInputMethodController()->GetSelectionOffsets();
+        if (range.IsNull())
+          return;
 
-  HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
-  // A negative adjust amount moves the selection towards the beginning of
-  // the document, a positive amount moves the selection towards the end of
-  // the document.
-  render_frame_->GetWebFrame()->SelectRange(
-      blink::WebRange(range.StartOffset() + start,
-                      range.length() + end - start),
-      blink::WebLocalFrame::kPreserveHandleVisibility, selection_menu_behavior);
+        // Sanity checks to disallow empty and out of range selections.
+        if (start - end > range.length() || range.StartOffset() + start < 0)
+          return;
+
+        HandlingState handling_state(widget, UpdateState::kIsSelectingRange);
+        // A negative adjust amount moves the selection towards the beginning of
+        // the document, a positive amount moves the selection towards the end
+        // of the document.
+        focused_frame->SelectRange(
+            blink::WebRange(range.StartOffset() + start,
+                            range.length() + end - start),
+            blink::WebLocalFrame::kPreserveHandleVisibility,
+            selection_menu_behavior);
+      },
+      widget_, start, end, selection_menu_behavior));
 }
 
 void FrameInputHandlerImpl::MoveRangeSelectionExtent(const gfx::Point& extent) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    // TODO(dtapuska): This event should be coalesced. Chrome IPC uses
-    // one outstanding event and an ACK to handle coalescing on the browser
-    // side. We should be able to clobber them in the main thread event queue.
-    RunOnMainThread(base::BindOnce(
-        &FrameInputHandlerImpl::MoveRangeSelectionExtent, weak_this_, extent));
-    return;
-  }
+  // TODO(dtapuska): This event should be coalesced. Chrome IPC uses
+  // one outstanding event and an ACK to handle coalescing on the browser
+  // side. We should be able to clobber them in the main thread event queue.
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, const gfx::Point& extent) {
+        if (!widget)
+          return;
 
-  if (!render_frame_)
-    return;
-  HandlingState handling_state(render_frame_, UpdateState::kIsSelectingRange);
-  render_frame_->GetWebFrame()->MoveRangeSelectionExtent(
-      render_frame_->GetLocalRootRenderWidget()->ConvertWindowPointToViewport(
-          extent));
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+
+        HandlingState handling_state(widget, UpdateState::kIsSelectingRange);
+        focused_frame->MoveRangeSelectionExtent(
+            widget->ConvertWindowPointToViewport(extent));
+      },
+      widget_, extent));
 }
 
 void FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect(
     const gfx::Rect& rect) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(base::BindOnce(
-        &FrameInputHandlerImpl::ScrollFocusedEditableNodeIntoRect, weak_this_,
-        rect));
-    return;
-  }
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, const gfx::Rect& rect) {
+        if (!widget)
+          return;
 
-  if (!render_frame_)
-    return;
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
 
-  // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport
-  // on OOPIFs. Since we are starting a new scroll operation now, call
-  // DidChangeVisibleViewport to ensure that we don't assume the element
-  // is already in view and ignore the scroll.
-  render_frame_->ResetHasScrolledFocusedEditableIntoView();
-  render_frame_->ScrollFocusedEditableElementIntoRect(rect);
+        RenderFrameImpl* render_frame =
+            RenderFrameImpl::FromWebFrame(focused_frame);
+
+        if (!render_frame)
+          return;
+
+        // OnSynchronizeVisualProperties does not call DidChangeVisibleViewport
+        // on OOPIFs. Since we are starting a new scroll operation now, call
+        // DidChangeVisibleViewport to ensure that we don't assume the element
+        // is already in view and ignore the scroll.
+        render_frame->ResetHasScrolledFocusedEditableIntoView();
+        render_frame->ScrollFocusedEditableElementIntoRect(rect);
+      },
+      widget_, rect));
 }
 
 void FrameInputHandlerImpl::MoveCaret(const gfx::Point& point) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    RunOnMainThread(
-        base::BindOnce(&FrameInputHandlerImpl::MoveCaret, weak_this_, point));
-    return;
-  }
+  RunOnMainThread(base::BindOnce(
+      [](base::WeakPtr<RenderWidget> widget, const gfx::Point& point) {
+        if (!widget)
+          return;
 
-  if (!render_frame_)
-    return;
-
-  render_frame_->GetWebFrame()->MoveCaretSelection(
-      render_frame_->GetLocalRootRenderWidget()->ConvertWindowPointToViewport(
-          point));
-}
-
-void FrameInputHandlerImpl::GetWidgetInputHandler(
-    mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler> receiver,
-    mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    main_thread_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&FrameInputHandlerImpl::GetWidgetInputHandler,
-                       weak_this_, std::move(receiver), std::move(host)));
-    return;
-  }
-  if (!render_frame_)
-    return;
-  render_frame_->GetLocalRootRenderWidget()
-      ->widget_input_handler_manager()
-      ->AddAssociatedInterface(std::move(receiver), std::move(host));
+        auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+        if (!focused_frame)
+          return;
+        focused_frame->MoveCaretSelection(
+            widget->ConvertWindowPointToViewport(point));
+      },
+      widget_, point));
 }
 
 void FrameInputHandlerImpl::ExecuteCommandOnMainThread(
+    base::WeakPtr<RenderWidget> widget,
     const std::string& command,
     UpdateState update_state) {
-  if (!render_frame_)
+  if (!widget)
     return;
 
-  HandlingState handling_state(render_frame_, update_state);
-  render_frame_->GetWebFrame()->ExecuteCommand(
-      blink::WebString::FromUTF8(command));
-}
-
-void FrameInputHandlerImpl::Release() {
-  if (!main_thread_task_runner_->BelongsToCurrentThread()) {
-    // Close the receiver on the compositor thread first before telling the main
-    // thread to delete this object.
-    receiver_.reset();
-    main_thread_task_runner_->PostTask(
-        FROM_HERE, base::BindOnce(&FrameInputHandlerImpl::Release, weak_this_));
+  HandlingState handling_state(widget, update_state);
+  auto* focused_frame = widget->GetFocusedWebLocalFrameInWidget();
+  if (!focused_frame)
     return;
-  }
-  delete this;
-}
-
-void FrameInputHandlerImpl::BindNow(
-    mojo::PendingReceiver<blink::mojom::FrameInputHandler> receiver) {
-  receiver_.Bind(std::move(receiver));
-  receiver_.set_disconnect_handler(
-      base::BindOnce(&FrameInputHandlerImpl::Release, base::Unretained(this)));
+  focused_frame->ExecuteCommand(blink::WebString::FromUTF8(command));
 }
 
 FrameInputHandlerImpl::HandlingState::HandlingState(
-    const base::WeakPtr<RenderFrameImpl>& render_frame,
+    const base::WeakPtr<RenderWidget>& render_widget,
     UpdateState state)
-    : render_frame_(render_frame),
-      original_select_range_value_(render_frame->handling_select_range()),
-      original_pasting_value_(render_frame->IsPasting()) {
+    : render_widget_(render_widget),
+      original_select_range_value_(render_widget->handling_select_range()),
+      original_pasting_value_(render_widget->is_pasting()) {
   switch (state) {
     case UpdateState::kIsPasting:
-      render_frame->set_is_pasting(true);
+      render_widget->set_is_pasting(true);
       FALLTHROUGH;  // Matches RenderFrameImpl::OnPaste() which sets both.
     case UpdateState::kIsSelectingRange:
-      render_frame->set_handling_select_range(true);
+      render_widget->set_handling_select_range(true);
       break;
     case UpdateState::kNone:
       break;
@@ -486,10 +487,10 @@
 
 FrameInputHandlerImpl::HandlingState::~HandlingState() {
   // RenderFrame may have been destroyed while this object was on the stack.
-  if (!render_frame_)
+  if (!render_widget_)
     return;
-  render_frame_->set_handling_select_range(original_select_range_value_);
-  render_frame_->set_is_pasting(original_pasting_value_);
+  render_widget_->set_handling_select_range(original_select_range_value_);
+  render_widget_->set_is_pasting(original_pasting_value_);
 }
 
 }  // namespace content
diff --git a/content/renderer/input/frame_input_handler_impl.h b/content/renderer/input/frame_input_handler_impl.h
index e027806f..052a8be2 100644
--- a/content/renderer/input/frame_input_handler_impl.h
+++ b/content/renderer/input/frame_input_handler_impl.h
@@ -8,7 +8,7 @@
 #include "base/memory/ref_counted.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
-#include "content/renderer/render_frame_impl.h"
+#include "content/renderer/render_widget.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "third_party/blink/public/mojom/input/input_handler.mojom.h"
@@ -16,11 +16,11 @@
 namespace content {
 class MainThreadEventQueue;
 
-// This class provides an implementation of FrameInputHandler mojo interface.
-// When a compositor thread is being used in the renderer the mojo channel
-// is bound on the compositor thread. Method calls, and events received on the
-// compositor thread are then placed in the MainThreadEventQueue for
-// the associated RenderWidget. This is done as to ensure that input related
+// This class provides an implementation of FrameWidgetInputHandler mojo
+// interface. When a compositor thread is being used in the renderer the mojo
+// channel is bound on the compositor thread. Method calls, and events received
+// on the compositor thread are then placed in the MainThreadEventQueue for the
+// associated RenderWidget. This is done as to ensure that input related
 // messages and events that are handled on the compositor thread aren't
 // executed before other input events that need to be processed on the
 // main thread. ie. Since some messages flow to the compositor thread
@@ -39,11 +39,13 @@
 // When a compositor thread isn't used the mojo channel is just bound
 // on the main thread and messages are handled right away.
 class CONTENT_EXPORT FrameInputHandlerImpl
-    : public blink::mojom::FrameInputHandler {
+    : public blink::mojom::FrameWidgetInputHandler {
  public:
-  static void CreateMojoService(
-      base::WeakPtr<RenderFrameImpl> render_frame,
-      mojo::PendingReceiver<blink::mojom::FrameInputHandler> receiver);
+  FrameInputHandlerImpl(
+      base::WeakPtr<RenderWidget> widget,
+      scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
+      scoped_refptr<MainThreadEventQueue> input_event_queue);
+  ~FrameInputHandlerImpl() override;
 
   void SetCompositionFromExistingText(
       int32_t start,
@@ -79,49 +81,34 @@
   void MoveRangeSelectionExtent(const gfx::Point& extent) override;
   void ScrollFocusedEditableNodeIntoRect(const gfx::Rect& rect) override;
   void MoveCaret(const gfx::Point& point) override;
-  void GetWidgetInputHandler(
-      mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler>
-          receiver,
-      mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) override;
 
  private:
-  ~FrameInputHandlerImpl() override;
   enum class UpdateState { kNone, kIsPasting, kIsSelectingRange };
 
   class HandlingState {
    public:
-    HandlingState(const base::WeakPtr<RenderFrameImpl>& render_frame,
+    HandlingState(const base::WeakPtr<RenderWidget>& render_widget,
                   UpdateState state);
     ~HandlingState();
 
    private:
-    base::WeakPtr<RenderFrameImpl> render_frame_;
+    base::WeakPtr<RenderWidget> render_widget_;
     bool original_select_range_value_;
     bool original_pasting_value_;
   };
 
-  FrameInputHandlerImpl(
-      base::WeakPtr<RenderFrameImpl> render_frame,
-      mojo::PendingReceiver<blink::mojom::FrameInputHandler> receiver);
-
   void RunOnMainThread(base::OnceClosure closure);
-  void BindNow(mojo::PendingReceiver<blink::mojom::FrameInputHandler> receiver);
-  void ExecuteCommandOnMainThread(const std::string& command,
-                                  UpdateState state);
+  static void ExecuteCommandOnMainThread(base::WeakPtr<RenderWidget> widget,
+                                         const std::string& command,
+                                         UpdateState state);
   void Release();
 
-  mojo::Receiver<blink::mojom::FrameInputHandler> receiver_{this};
-
-  // |render_frame_| should only be accessed on the main thread. Use
-  // GetRenderFrame so that it will DCHECK this for you.
-  base::WeakPtr<RenderFrameImpl> render_frame_;
+  // |render_widget_| should only be accessed on the main thread.
+  base::WeakPtr<RenderWidget> widget_;
 
   scoped_refptr<MainThreadEventQueue> input_event_queue_;
   scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
 
-  base::WeakPtr<FrameInputHandlerImpl> weak_this_;
-  base::WeakPtrFactory<FrameInputHandlerImpl> weak_ptr_factory_{this};
-
   DISALLOW_COPY_AND_ASSIGN(FrameInputHandlerImpl);
 };
 
diff --git a/content/renderer/input/input_event_prediction.cc b/content/renderer/input/input_event_prediction.cc
index 30a63b7..b6632a6 100644
--- a/content/renderer/input/input_event_prediction.cc
+++ b/content/renderer/input/input_event_prediction.cc
@@ -8,7 +8,7 @@
 #include "base/metrics/field_trial.h"
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
-#include "content/public/common/content_features.h"
+#include "third_party/blink/public/common/features.h"
 
 using blink::WebInputEvent;
 using blink::WebMouseEvent;
@@ -44,10 +44,10 @@
   // flag.
   std::string predictor_name =
       enable_resampling_
-          ? GetFieldTrialParamValueByFeature(features::kResamplingInputEvents,
-                                             "predictor")
+          ? GetFieldTrialParamValueByFeature(
+                blink::features::kResamplingInputEvents, "predictor")
           : GetFieldTrialParamValueByFeature(
-                features::kInputPredictorTypeChoice, "predictor");
+                blink::features::kInputPredictorTypeChoice, "predictor");
 
   if (predictor_name.empty())
     selected_predictor_type_ =
diff --git a/content/renderer/input/input_event_prediction_unittest.cc b/content/renderer/input/input_event_prediction_unittest.cc
index 0ad1d1d..4ef987e9 100644
--- a/content/renderer/input/input_event_prediction_unittest.cc
+++ b/content/renderer/input/input_event_prediction_unittest.cc
@@ -8,7 +8,6 @@
 
 #include "base/test/scoped_feature_list.h"
 #include "content/common/input/synthetic_web_input_event_builders.h"
-#include "content/public/common/content_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/features.h"
 #include "ui/events/base_event_utils.h"
@@ -28,7 +27,7 @@
   InputEventPredictionTest() {
     // Default to enable resampling with empty predictor for testing.
     ConfigureFieldTrialAndInitialize(
-        features::kResamplingInputEvents,
+        blink::features::kResamplingInputEvents,
         blink::features::kScrollPredictorNameEmpty);
   }
 
@@ -70,7 +69,7 @@
                                         const std::string& predictor_type) {
     ConfigureFieldTrial(feature, predictor_type);
     event_predictor_ = std::make_unique<InputEventPrediction>(
-        base::FeatureList::IsEnabled(features::kResamplingInputEvents));
+        base::FeatureList::IsEnabled(blink::features::kResamplingInputEvents));
   }
 
  protected:
@@ -87,32 +86,32 @@
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
             PredictorType::kScrollPredictorTypeEmpty);
 
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents,
+  ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents,
                                    blink::features::kScrollPredictorNameEmpty);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
             PredictorType::kScrollPredictorTypeEmpty);
 
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents,
+  ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents,
                                    blink::features::kScrollPredictorNameKalman);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
             PredictorType::kScrollPredictorTypeKalman);
 
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents,
+  ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents,
                                    blink::features::kScrollPredictorNameKalman);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
             PredictorType::kScrollPredictorTypeKalman);
 
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents,
+  ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents,
                                    blink::features::kScrollPredictorNameLsq);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
             PredictorType::kScrollPredictorTypeLsq);
 
   // Default to Kalman predictor.
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents, "");
+  ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents, "");
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
             PredictorType::kScrollPredictorTypeKalman);
 
-  ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice,
+  ConfigureFieldTrialAndInitialize(blink::features::kInputPredictorTypeChoice,
                                    blink::features::kScrollPredictorNameLsq);
   EXPECT_FALSE(event_predictor_->enable_resampling_);
   // When enable_resampling_ is true, kInputPredictorTypeChoice flag has no
@@ -285,7 +284,8 @@
 
 TEST_F(InputEventPredictionTest, ResamplingDisabled) {
   // When resampling is disabled, default to use kalman filter.
-  ConfigureFieldTrialAndInitialize(features::kInputPredictorTypeChoice, "");
+  ConfigureFieldTrialAndInitialize(blink::features::kInputPredictorTypeChoice,
+                                   "");
   EXPECT_FALSE(event_predictor_->enable_resampling_);
   EXPECT_EQ(event_predictor_->selected_predictor_type_,
             PredictorType::kScrollPredictorTypeKalman);
@@ -321,7 +321,7 @@
 
 // Test that when dt > maxResampling, resampling is cut off .
 TEST_F(InputEventPredictionTest, NoResampleWhenExceedMaxResampleTime) {
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents,
+  ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents,
                                    blink::features::kScrollPredictorNameKalman);
 
   base::TimeDelta predictor_max_resample_time =
@@ -397,7 +397,7 @@
 
 // Test that when dt between events is 6ms, first predicted point is 6ms ahead.
 TEST_F(InputEventPredictionTest, PredictedEventsTimeIntervalEqualRealEvents) {
-  ConfigureFieldTrialAndInitialize(features::kResamplingInputEvents,
+  ConfigureFieldTrialAndInitialize(blink::features::kResamplingInputEvents,
                                    blink::features::kScrollPredictorNameKalman);
 
   base::TimeTicks event_time = ui::EventTimeForNow();
diff --git a/content/renderer/input/main_thread_event_queue.cc b/content/renderer/input/main_thread_event_queue.cc
index 7ad054ec..48bf221 100644
--- a/content/renderer/input/main_thread_event_queue.cc
+++ b/content/renderer/input/main_thread_event_queue.cc
@@ -12,6 +12,7 @@
 #include "content/common/input/event_with_latency_info.h"
 #include "content/common/input_messages.h"
 #include "content/renderer/render_widget.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
 #include "third_party/blink/public/common/input/web_input_event_attribution.h"
 
@@ -254,7 +255,7 @@
   raf_fallback_timer_.SetTaskRunner(main_task_runner);
 
   event_predictor_ = std::make_unique<InputEventPrediction>(
-      base::FeatureList::IsEnabled(features::kResamplingInputEvents));
+      base::FeatureList::IsEnabled(blink::features::kResamplingInputEvents));
 }
 
 MainThreadEventQueue::~MainThreadEventQueue() {}
diff --git a/content/renderer/input/widget_input_handler_impl.cc b/content/renderer/input/widget_input_handler_impl.cc
index df8cd6e33..ce94586f 100644
--- a/content/renderer/input/widget_input_handler_impl.cc
+++ b/content/renderer/input/widget_input_handler_impl.cc
@@ -10,9 +10,11 @@
 #include "base/check.h"
 #include "content/common/input_messages.h"
 #include "content/renderer/ime_event_guard.h"
+#include "content/renderer/input/frame_input_handler_impl.h"
 #include "content/renderer/input/widget_input_handler_manager.h"
 #include "content/renderer/render_thread_impl.h"
 #include "content/renderer/render_widget.h"
+#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
 #include "third_party/blink/public/common/input/web_coalesced_input_event.h"
 #include "third_party/blink/public/common/input/web_keyboard_event.h"
 #include "third_party/blink/public/platform/platform.h"
@@ -47,20 +49,6 @@
 
 WidgetInputHandlerImpl::~WidgetInputHandlerImpl() {}
 
-void WidgetInputHandlerImpl::SetAssociatedReceiver(
-    mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler>
-        receiver) {
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner;
-  if (content::RenderThreadImpl::current()) {
-    blink::scheduler::WebThreadScheduler* scheduler =
-        content::RenderThreadImpl::current()->GetWebMainThreadScheduler();
-    task_runner = scheduler->DeprecatedDefaultTaskRunner();
-  }
-  associated_receiver_.Bind(std::move(receiver), std::move(task_runner));
-  associated_receiver_.set_disconnect_handler(
-      base::BindOnce(&WidgetInputHandlerImpl::Release, base::Unretained(this)));
-}
-
 void WidgetInputHandlerImpl::SetReceiver(
     mojo::PendingReceiver<blink::mojom::WidgetInputHandler>
         interface_receiver) {
@@ -194,6 +182,15 @@
       std::move(control_host), std::move(host), std::move(compositor_receiver));
 }
 
+void WidgetInputHandlerImpl::GetFrameWidgetInputHandler(
+    mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler>
+        frame_receiver) {
+  mojo::MakeSelfOwnedAssociatedReceiver(
+      std::make_unique<FrameInputHandlerImpl>(
+          render_widget_, main_thread_task_runner_, input_event_queue_),
+      std::move(frame_receiver));
+}
+
 void WidgetInputHandlerImpl::RunOnMainThread(base::OnceClosure closure) {
   if (input_event_queue_) {
     input_event_queue_->QueueClosure(base::BindOnce(
@@ -216,7 +213,6 @@
   if (!main_thread_task_runner_->BelongsToCurrentThread()) {
     // Close the binding on the compositor thread first before telling the main
     // thread to delete this object.
-    associated_receiver_.reset();
     receiver_.reset();
     main_thread_task_runner_->PostTask(
         FROM_HERE, base::BindOnce(&WidgetInputHandlerImpl::Release,
diff --git a/content/renderer/input/widget_input_handler_impl.h b/content/renderer/input/widget_input_handler_impl.h
index 60799e4..61d239d 100644
--- a/content/renderer/input/widget_input_handler_impl.h
+++ b/content/renderer/input/widget_input_handler_impl.h
@@ -67,6 +67,9 @@
           host,
       mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor>
           compositor_receiver) override;
+  void GetFrameWidgetInputHandler(
+      mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler>
+          interface_request) override;
   void InputWasProcessed();
 
  private:
@@ -85,8 +88,6 @@
   WaitForInputProcessedCallback input_processed_ack_;
 
   mojo::Receiver<blink::mojom::WidgetInputHandler> receiver_{this};
-  mojo::AssociatedReceiver<blink::mojom::WidgetInputHandler>
-      associated_receiver_{this};
 
   base::WeakPtrFactory<WidgetInputHandlerImpl> weak_ptr_factory_{this};
 
diff --git a/content/renderer/input/widget_input_handler_manager.cc b/content/renderer/input/widget_input_handler_manager.cc
index 172cbd51..87b1dd2 100644
--- a/content/renderer/input/widget_input_handler_manager.cc
+++ b/content/renderer/input/widget_input_handler_manager.cc
@@ -202,25 +202,6 @@
 
 WidgetInputHandlerManager::~WidgetInputHandlerManager() = default;
 
-void WidgetInputHandlerManager::AddAssociatedInterface(
-    mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler> receiver,
-    mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) {
-  if (compositor_task_runner_) {
-    associated_host_ = mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost>(
-        std::move(host), compositor_task_runner_);
-    // Mojo channel bound on compositor thread.
-    compositor_task_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(&WidgetInputHandlerManager::BindAssociatedChannel, this,
-                       std::move(receiver)));
-  } else {
-    associated_host_ = mojo::SharedRemote<blink::mojom::WidgetInputHandlerHost>(
-        std::move(host));
-    // Mojo channel bound on main thread.
-    BindAssociatedChannel(std::move(receiver));
-  }
-}
-
 void WidgetInputHandlerManager::AddInterface(
     mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver,
     mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) {
@@ -551,19 +532,6 @@
 #endif
 }
 
-void WidgetInputHandlerManager::BindAssociatedChannel(
-    mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler>
-        receiver) {
-  if (!receiver.is_valid())
-    return;
-  // Don't pass the |input_event_queue_| on if we don't have a
-  // |compositor_task_runner_| as events might get out of order.
-  WidgetInputHandlerImpl* handler = new WidgetInputHandlerImpl(
-      this, main_thread_task_runner_,
-      compositor_task_runner_ ? input_event_queue_ : nullptr, render_widget_);
-  handler->SetAssociatedReceiver(std::move(receiver));
-}
-
 void WidgetInputHandlerManager::BindChannel(
     mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver) {
   if (!receiver.is_valid())
diff --git a/content/renderer/input/widget_input_handler_manager.h b/content/renderer/input/widget_input_handler_manager.h
index ebbd845d..9c25d12 100644
--- a/content/renderer/input/widget_input_handler_manager.h
+++ b/content/renderer/input/widget_input_handler_manager.h
@@ -67,10 +67,6 @@
       scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner,
       blink::scheduler::WebThreadScheduler* main_thread_scheduler,
       bool needs_input_handler);
-  void AddAssociatedInterface(
-      mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler>
-          receiver,
-      mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host);
 
   void AddInterface(
       mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver,
@@ -157,9 +153,6 @@
   void InitOnInputHandlingThread(
       const base::WeakPtr<cc::InputHandler>& input_handler,
       bool sync_compositing);
-  void BindAssociatedChannel(
-      mojo::PendingAssociatedReceiver<blink::mojom::WidgetInputHandler>
-          receiver);
   void BindChannel(
       mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver);
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 0eee1e5c..f7773d5 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -98,9 +98,7 @@
 #include "content/renderer/gpu_benchmarking_extension.h"
 #include "content/renderer/history_entry.h"
 #include "content/renderer/history_serialization.h"
-#include "content/renderer/ime_event_guard.h"
 #include "content/renderer/impression_conversions.h"
-#include "content/renderer/input/frame_input_handler_impl.h"
 #include "content/renderer/input/input_target_client_impl.h"
 #include "content/renderer/input/widget_input_handler_manager.h"
 #include "content/renderer/internal_document_state_data.h"
@@ -1434,9 +1432,9 @@
   render_widget->InitForMainFrame(std::move(show_callback), web_frame_widget,
                                   params->visual_properties.screen_info);
 
-  // The WebFrame created here was already attached to the Page as its
-  // main frame, and the WebFrameWidget has been initialized, so we can call
-  // WebViewImpl's DidAttachLocalMainFrame().
+  // The WebFrame created here was already attached to the Page as its main
+  // frame, and the WebFrameWidget has been initialized, so we can call
+  // WebView's DidAttachLocalMainFrame().
   render_view->GetWebView()->DidAttachLocalMainFrame();
 
   // The RenderWidget should start with valid VisualProperties, including a
@@ -1606,9 +1604,9 @@
     // TODO(crbug.com/419087): This could become part of RenderWidget Init.
     render_widget->OnUpdateVisualProperties(widget_params->visual_properties);
 
-    // Note that we do *not* call WebViewImpl's DidAttachLocalMainFrame() here
-    // for yet because this frame is provisional and not attached to the Page
-    // yet. We will tell WebViewImpl about it once it is swapped in.
+    // Note that we do *not* call WebView's DidAttachLocalMainFrame() here yet
+    // because this frame is provisional and not attached to the Page yet. We
+    // will tell WebViewImpl about it once it is swapped in.
 
     render_frame->render_widget_ = render_widget.get();
     render_frame->owned_render_widget_ = std::move(render_widget);
@@ -1816,10 +1814,8 @@
 #endif
       selection_text_offset_(0),
       selection_range_(gfx::Range::InvalidRange()),
-      handling_select_range_(false),
       render_accessibility_manager_(
           std::make_unique<RenderAccessibilityManager>(this)),
-      is_pasting_(false),
       blame_context_(nullptr),
 #if BUILDFLAG(ENABLE_PLUGINS)
       focused_pepper_plugin_(nullptr),
@@ -2043,10 +2039,6 @@
   if (main_frame->IsWebLocalFrame())
     main_frame_url = main_frame->ToWebLocalFrame()->GetDocument().Url();
 
-  mojo::PendingRemote<mojom::Widget> widget_channel;
-  mojo::PendingReceiver<mojom::Widget> widget_channel_receiver =
-      widget_channel.InitWithNewPipeAndPassReceiver();
-
   mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget;
   mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver =
       blink_widget.InitWithNewEndpointAndPassReceiver();
@@ -2059,8 +2051,8 @@
   // Synchronous IPC to obtain a routing id for the fullscreen widget.
   int32_t fullscreen_widget_routing_id = MSG_ROUTING_NONE;
   if (!GetFrameHost()->CreateNewFullscreenWidget(
-          std::move(widget_channel), std::move(blink_widget_host_receiver),
-          std::move(blink_widget), &fullscreen_widget_routing_id)) {
+          std::move(blink_widget_host_receiver), std::move(blink_widget),
+          &fullscreen_widget_routing_id)) {
     return nullptr;
   }
   RenderWidget::ShowCallback show_callback =
@@ -2071,8 +2063,8 @@
       fullscreen_widget_routing_id, std::move(show_callback),
       GetLocalRootRenderWidget()->compositor_deps(),
       GetLocalRootRenderWidget()->GetOriginalScreenInfo(), plugin,
-      std::move(main_frame_url), std::move(widget_channel_receiver),
-      std::move(blink_widget_host), std::move(blink_widget_receiver));
+      std::move(main_frame_url), std::move(blink_widget_host),
+      std::move(blink_widget_receiver));
   // TODO(nick): The show() handshake seems like unnecessary complexity here,
   // since there's no real delay between CreateFullscreenWidget and
   // ShowCreatedFullscreenWidget. Would it be simpler to have the
@@ -2336,6 +2328,11 @@
     // For main frames, the swap should have cleared the RenderView's pointer to
     // this frame.
     CHECK(!render_view->main_render_frame_);
+
+    // The RenderFrameProxy being swapped in here has now been attached to the
+    // Page as its main frame and properly initialized by the WebFrame::Swap()
+    // call, so we can call WebView's DidAttachRemoteMainFrame().
+    render_view->GetWebView()->DidAttachRemoteMainFrame();
   }
 
   if (!success) {
@@ -2939,7 +2936,7 @@
 }
 
 bool RenderFrameImpl::IsPasting() {
-  return is_pasting_;
+  return GetLocalRootRenderWidget()->is_pasting();
 }
 
 // blink::mojom::FullscreenVideoElementHandler implementation ------------------
@@ -4426,7 +4423,7 @@
 
 void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) {
   if (!GetLocalRootRenderWidget()->GetWebWidget()->HandlingInputEvent() &&
-      !handling_select_range_)
+      !GetLocalRootRenderWidget()->handling_select_range())
     return;
 
   if (is_empty_selection)
@@ -5346,8 +5343,7 @@
 
     // The WebFrame being swapped in here has now been attached to the Page as
     // its main frame, and the WebFrameWidget was previously initialized when
-    // the frame was created, so we can call WebViewImpl's
-    // DidAttachLocalMainFrame().
+    // the frame was created so we can call WebView's DidAttachLocalMainFrame().
     render_view_->GetWebView()->DidAttachLocalMainFrame();
   }
 
@@ -6223,16 +6219,10 @@
   GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
       &RenderFrameImpl::BindFullscreen, weak_factory_.GetWeakPtr()));
 
-  registry_.AddInterface(base::BindRepeating(
-      &FrameInputHandlerImpl::CreateMojoService, weak_factory_.GetWeakPtr()));
-
   registry_.AddInterface(
       base::BindRepeating(&InputTargetClientImpl::BindToReceiver,
                           base::Unretained(&input_target_client_impl_)));
 
-  registry_.AddInterface(base::BindRepeating(&RenderFrameImpl::BindWidget,
-                                             weak_factory_.GetWeakPtr()));
-
   GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating(
       &RenderFrameImpl::BindMhtmlFileWriter, base::Unretained(this)));
 
@@ -6327,10 +6317,6 @@
   return enabled_bindings_;
 }
 
-void RenderFrameImpl::FrameDidCallFocus() {
-  Send(new FrameHostMsg_FrameDidCallFocus(routing_id_));
-}
-
 void RenderFrameImpl::SetAccessibilityModeForTest(ui::AXMode new_mode) {
   render_accessibility_manager_->SetMode(new_mode.mode());
 }
@@ -6464,11 +6450,6 @@
 #endif
 }
 
-void RenderFrameImpl::BindWidget(
-    mojo::PendingReceiver<mojom::Widget> receiver) {
-  GetLocalRootRenderWidget()->SetWidgetReceiver(std::move(receiver));
-}
-
 blink::WebComputedAXTree* RenderFrameImpl::GetOrCreateWebComputedAXTree() {
   if (!computed_ax_tree_)
     computed_ax_tree_ = std::make_unique<AomContentAxTree>(this);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 3a3cba8..aa25497 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -40,7 +40,6 @@
 #include "content/common/render_accessibility.mojom.h"
 #include "content/common/renderer.mojom.h"
 #include "content/common/unique_name_helper.h"
-#include "content/common/widget.mojom.h"
 #include "content/public/common/browser_controls_state.h"
 #include "content/public/common/fullscreen_video_element.mojom.h"
 #include "content/public/common/previews_state.h"
@@ -812,12 +811,6 @@
 
   void NotifyObserversOfFailedProvisionalLoad();
 
-  bool handling_select_range() const { return handling_select_range_; }
-
-  void set_is_pasting(bool value) { is_pasting_ = value; }
-
-  void set_handling_select_range(bool value) { handling_select_range_ = value; }
-
   // Plugin-related functions --------------------------------------------------
 
 #if BUILDFLAG(ENABLE_PLUGINS)
@@ -863,10 +856,6 @@
   void ScrollFocusedEditableElementIntoRect(const gfx::Rect& rect);
   void ResetHasScrolledFocusedEditableIntoView();
 
-  // Called to notify a frame that it called |window.focus()| on a different
-  // frame.
-  void FrameDidCallFocus();
-
   // Called when an ongoing renderer-initiated navigation was dropped by the
   // browser.
   void OnDroppedNavigation();
@@ -1143,8 +1132,6 @@
   // call |callback| before returning.
   void RequestOverlayRoutingToken(media::RoutingTokenCallback callback);
 
-  void BindWidget(mojo::PendingReceiver<mojom::Widget> receiver);
-
   void ShowDeferredContextMenu(const UntrustworthyContextMenuParams& params);
 
   // Build DidCommitProvisionalLoad_Params based on the frame internal state.
@@ -1367,9 +1354,6 @@
   // Range over the document corresponding to the actual selected text (which
   // could correspond to a substring of |selection_text_|; see above).
   gfx::Range selection_range_;
-  // Used to inform didChangeSelection() when it is called in the context
-  // of handling a FrameInputHandler::SelectRange IPC.
-  bool handling_select_range_;
 
   // Implements getUserMedia() and related functionality.
   std::unique_ptr<blink::WebMediaStreamDeviceObserver>
@@ -1390,9 +1374,6 @@
   // Valid during the entire life time of the RenderFrame.
   std::unique_ptr<RenderAccessibilityManager> render_accessibility_manager_;
 
-  // Whether or not this RenderFrame is currently pasting.
-  bool is_pasting_;
-
   std::unique_ptr<FrameBlameContext> blame_context_;
 
   // Plugins -------------------------------------------------------------------
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index 13de149..e4f1588 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -144,11 +144,15 @@
   if (!parent) {
     // Create a top level WebRemoteFrame.
     render_view = RenderViewImpl::FromRoutingID(render_view_routing_id);
+    blink::WebView* web_view = render_view->GetWebView();
     web_frame = blink::WebRemoteFrame::CreateMainFrame(
-        render_view->GetWebView(), proxy.get(),
-        proxy->blink_interface_registry_.get(),
+        web_view, proxy.get(), proxy->blink_interface_registry_.get(),
         proxy->GetRemoteAssociatedInterfaces(), frame_token, opener);
     // Root frame proxy has no ancestors to point to their RenderWidget.
+
+    // The WebRemoteFrame created here was already attached to the Page as its
+    // main frame, so we can call WebView's DidAttachRemoteMainFrame().
+    web_view->DidAttachRemoteMainFrame();
   } else {
     // Create a frame under an existing parent. The parent is always expected
     // to be a RenderFrameProxy, because navigations initiated by local frames
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h
index 04e2e88..5aa6af9 100644
--- a/content/renderer/render_frame_proxy.h
+++ b/content/renderer/render_frame_proxy.h
@@ -179,6 +179,7 @@
 
   // blink::WebRemoteFrameClient implementation:
   void FrameDetached(DetachType type) override;
+  blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
 
   void Navigate(
       const blink::WebURLRequest& request,
@@ -220,7 +221,6 @@
   void ResendVisualProperties();
 
   mojom::RenderFrameProxyHost* GetFrameProxyHost();
-  blink::AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces();
 
   // IPC handlers
   void OnDeleteProxy();
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 7fa71ab..c0a5f159 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -42,6 +42,7 @@
 #include "content/public/common/use_zoom_for_dsf_policy.h"
 #include "content/public/renderer/content_renderer_client.h"
 #include "content/public/test/browser_test_utils.h"
+#include "content/public/test/fake_render_widget_host.h"
 #include "content/public/test/frame_load_waiter.h"
 #include "content/public/test/local_frame_host_interceptor.h"
 #include "content/public/test/render_view_test.h"
@@ -256,6 +257,10 @@
     return static_cast<TestRenderFrame*>(view()->GetMainRenderFrame());
   }
 
+  blink::mojom::FrameWidgetInputHandler* GetFrameWidgetInputHandler() {
+    return render_widget_host_->GetFrameWidgetInputHandler();
+  }
+
   RenderAccessibilityManager* GetRenderAccessibilityManager() {
     return frame()->GetRenderAccessibilityManager();
   }
@@ -2205,10 +2210,12 @@
            "<input id=\"test1\" value=\"some test text hello\"></input>"
            "</body>"
            "</html>");
+  auto* frame_widget_input_handler = GetFrameWidgetInputHandler();
   ExecuteJavaScriptForTests("document.getElementById('test1').focus();");
-  frame()->SetEditableSelectionOffsets(4, 8);
+  frame_widget_input_handler->SetEditableSelectionOffsets(4, 8);
   const std::vector<ui::ImeTextSpan> empty_ime_text_span;
-  frame()->SetCompositionFromExistingText(7, 10, empty_ime_text_span);
+  frame_widget_input_handler->SetCompositionFromExistingText(
+      7, 10, empty_ime_text_span);
   base::RunLoop().RunUntilIdle();
   blink::WebInputMethodController* controller =
       frame()->GetWebFrame()->GetInputMethodController();
@@ -2217,7 +2224,7 @@
   EXPECT_EQ(8, info.selection_end);
   EXPECT_EQ(7, info.composition_start);
   EXPECT_EQ(10, info.composition_end);
-  frame()->CollapseSelection();
+  frame_widget_input_handler->CollapseSelection();
   base::RunLoop().RunUntilIdle();
   info = controller->TextInputInfo();
   EXPECT_EQ(8, info.selection_start);
@@ -2233,9 +2240,10 @@
            "<input id=\"test1\" value=\"abcdefghijklmnopqrstuvwxyz\"></input>"
            "</body>"
            "</html>");
+  auto* frame_widget_input_handler = GetFrameWidgetInputHandler();
   ExecuteJavaScriptForTests("document.getElementById('test1').focus();");
-  frame()->SetEditableSelectionOffsets(10, 10);
-  frame()->ExtendSelectionAndDelete(3, 4);
+  frame_widget_input_handler->SetEditableSelectionOffsets(10, 10);
+  frame_widget_input_handler->ExtendSelectionAndDelete(3, 4);
   base::RunLoop().RunUntilIdle();
   blink::WebInputMethodController* controller =
       frame()->GetWebFrame()->GetInputMethodController();
@@ -2243,8 +2251,8 @@
   EXPECT_EQ("abcdefgopqrstuvwxyz", info.value);
   EXPECT_EQ(7, info.selection_start);
   EXPECT_EQ(7, info.selection_end);
-  frame()->SetEditableSelectionOffsets(4, 8);
-  frame()->ExtendSelectionAndDelete(2, 5);
+  frame_widget_input_handler->SetEditableSelectionOffsets(4, 8);
+  frame_widget_input_handler->ExtendSelectionAndDelete(2, 5);
   base::RunLoop().RunUntilIdle();
   info = controller->TextInputInfo();
   EXPECT_EQ("abuvwxyz", info.value);
@@ -2264,8 +2272,9 @@
       "</html>");
   ExecuteJavaScriptForTests("document.getElementById('test1').focus();");
 
-  frame()->SetEditableSelectionOffsets(10, 10);
-  frame()->DeleteSurroundingText(3, 4);
+  auto* frame_widget_input_handler = GetFrameWidgetInputHandler();
+  frame_widget_input_handler->SetEditableSelectionOffsets(10, 10);
+  frame_widget_input_handler->DeleteSurroundingText(3, 4);
   base::RunLoop().RunUntilIdle();
   blink::WebInputMethodController* controller =
       frame()->GetWebFrame()->GetInputMethodController();
@@ -2274,30 +2283,30 @@
   EXPECT_EQ(7, info.selection_start);
   EXPECT_EQ(7, info.selection_end);
 
-  frame()->SetEditableSelectionOffsets(4, 8);
-  frame()->DeleteSurroundingText(2, 5);
+  frame_widget_input_handler->SetEditableSelectionOffsets(4, 8);
+  frame_widget_input_handler->DeleteSurroundingText(2, 5);
   base::RunLoop().RunUntilIdle();
   info = controller->TextInputInfo();
   EXPECT_EQ("abefgouvwxyz", info.value);
   EXPECT_EQ(2, info.selection_start);
   EXPECT_EQ(6, info.selection_end);
 
-  frame()->SetEditableSelectionOffsets(5, 5);
-  frame()->DeleteSurroundingText(10, 0);
+  frame_widget_input_handler->SetEditableSelectionOffsets(5, 5);
+  frame_widget_input_handler->DeleteSurroundingText(10, 0);
   base::RunLoop().RunUntilIdle();
   info = controller->TextInputInfo();
   EXPECT_EQ("ouvwxyz", info.value);
   EXPECT_EQ(0, info.selection_start);
   EXPECT_EQ(0, info.selection_end);
 
-  frame()->DeleteSurroundingText(0, 10);
+  frame_widget_input_handler->DeleteSurroundingText(0, 10);
   base::RunLoop().RunUntilIdle();
   info = controller->TextInputInfo();
   EXPECT_EQ("", info.value);
   EXPECT_EQ(0, info.selection_start);
   EXPECT_EQ(0, info.selection_end);
 
-  frame()->DeleteSurroundingText(10, 10);
+  frame_widget_input_handler->DeleteSurroundingText(10, 10);
   base::RunLoop().RunUntilIdle();
   info = controller->TextInputInfo();
   EXPECT_EQ("", info.value);
@@ -2321,8 +2330,9 @@
       "<input id=\"test1\" value=\"ab&#x1f3c6; cdef&#x1f3c6; gh\">");
   ExecuteJavaScriptForTests("document.getElementById('test1').focus();");
 
-  frame()->SetEditableSelectionOffsets(4, 4);
-  frame()->DeleteSurroundingTextInCodePoints(2, 2);
+  auto* frame_widget_input_handler = GetFrameWidgetInputHandler();
+  frame_widget_input_handler->SetEditableSelectionOffsets(4, 4);
+  frame_widget_input_handler->DeleteSurroundingTextInCodePoints(2, 2);
   base::RunLoop().RunUntilIdle();
   blink::WebInputMethodController* controller =
       frame()->GetWebFrame()->GetInputMethodController();
@@ -2332,8 +2342,8 @@
   EXPECT_EQ(1, info.selection_start);
   EXPECT_EQ(1, info.selection_end);
 
-  frame()->SetEditableSelectionOffsets(1, 3);
-  frame()->DeleteSurroundingTextInCodePoints(1, 4);
+  frame_widget_input_handler->SetEditableSelectionOffsets(1, 3);
+  frame_widget_input_handler->DeleteSurroundingTextInCodePoints(1, 4);
   base::RunLoop().RunUntilIdle();
   info = controller->TextInputInfo();
   EXPECT_EQ("deh", info.value);
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 52896aa..e651e66 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -65,7 +65,6 @@
 #include "content/public/renderer/window_features_converter.h"
 #include "content/renderer/drop_data_builder.h"
 #include "content/renderer/history_serialization.h"
-#include "content/renderer/ime_event_guard.h"
 #include "content/renderer/internal_document_state_data.h"
 #include "content/renderer/loader/request_extra_data.h"
 #include "content/renderer/media/audio/audio_device_factory.h"
@@ -1345,10 +1344,6 @@
 
 blink::WebPagePopup* RenderViewImpl::CreatePopup(
     blink::WebLocalFrame* creator) {
-  mojo::PendingRemote<mojom::Widget> widget_channel;
-  mojo::PendingReceiver<mojom::Widget> widget_channel_receiver =
-      widget_channel.InitWithNewPipeAndPassReceiver();
-
   mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget;
   mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver =
       blink_widget.InitWithNewEndpointAndPassReceiver();
@@ -1362,8 +1357,8 @@
   int32_t widget_routing_id = MSG_ROUTING_NONE;
   bool success =
       RenderFrameImpl::FromWebFrame(creator)->GetFrameHost()->CreateNewWidget(
-          std::move(widget_channel), std::move(blink_widget_host_receiver),
-          std::move(blink_widget), &widget_routing_id);
+          std::move(blink_widget_host_receiver), std::move(blink_widget),
+          &widget_routing_id);
   if (!success) {
     // When the renderer is being killed the mojo message will fail.
     return nullptr;
@@ -1378,7 +1373,7 @@
   RenderWidget* popup_widget = RenderWidget::CreateForPopup(
       widget_routing_id, opener_render_widget->compositor_deps(),
       /*hidden=*/false,
-      /*never_composited=*/false, std::move(widget_channel_receiver));
+      /*never_composited=*/false);
 
   // The returned WebPagePopup is self-referencing, so the pointer here is not
   // an owning pointer. It is de-referenced by calling Close().
@@ -1754,20 +1749,6 @@
   main_render_frame_->GetLocalRootRenderWidget()->DidAutoResize(newSize);
 }
 
-void RenderViewImpl::DidFocus(blink::WebLocalFrame* calling_frame) {
-  // We only allow focus to move to this RenderView when the request comes from
-  // a user gesture. (See also https://bugs.webkit.org/show_bug.cgi?id=33389.)
-  if (calling_frame && calling_frame->HasTransientUserActivation()) {
-    Send(new ViewHostMsg_Focus(GetRoutingID()));
-
-    // Tattle on the frame that called |window.focus()|.
-    RenderFrameImpl* calling_render_frame =
-        RenderFrameImpl::FromWebFrame(calling_frame);
-    if (calling_render_frame)
-      calling_render_frame->FrameDidCallFocus();
-  }
-}
-
 #if defined(OS_ANDROID)
 void RenderViewImpl::SuspendVideoCaptureDevices(bool suspend) {
   if (!main_render_frame_)
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index dac8651a..79ffb7a 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -234,7 +234,6 @@
   int HistoryBackListCount() override;
   int HistoryForwardListCount() override;
   void DidAutoResize(const blink::WebSize& newSize) override;
-  void DidFocus(blink::WebLocalFrame* calling_frame) override;
   bool CanHandleGestureEvent() override;
   bool AllowPopupsDuringPageUnload() override;
   void OnPageVisibilityChanged(PageVisibilityState visibility) override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index f5b9808..b1ed0a0 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -19,6 +19,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/memory/singleton.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/optional.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
@@ -81,6 +82,7 @@
 #include "third_party/blink/public/common/input/web_input_event_attribution.h"
 #include "third_party/blink/public/common/input/web_mouse_event.h"
 #include "third_party/blink/public/common/page/web_drag_operation.h"
+#include "third_party/blink/public/common/switches.h"
 #include "third_party/blink/public/platform/file_path_conversion.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
@@ -274,11 +276,11 @@
   DCHECK(drop_data.file_contents.empty());
   DCHECK(drop_data.file_contents_content_disposition.empty());
 
-  if (!drop_data.text.is_null()) {
+  if (drop_data.text) {
     WebDragData::Item item;
     item.storage_type = WebDragData::Item::kStorageTypeString;
     item.string_type = WebString::FromUTF8(ui::kMimeTypeText);
-    item.string_data = WebString::FromUTF16(drop_data.text.string());
+    item.string_data = WebString::FromUTF16(*drop_data.text);
     item_list.push_back(item);
   }
 
@@ -291,11 +293,11 @@
     item_list.push_back(item);
   }
 
-  if (!drop_data.html.is_null()) {
+  if (drop_data.html) {
     WebDragData::Item item;
     item.storage_type = WebDragData::Item::kStorageTypeString;
     item.string_type = WebString::FromUTF8(ui::kMimeTypeHTML);
-    item.string_data = WebString::FromUTF16(drop_data.html.string());
+    item.string_data = WebString::FromUTF16(*drop_data.html);
     item.base_url = drop_data.html_base_url;
     item_list.push_back(item);
   }
@@ -414,37 +416,32 @@
     bool never_composited) {
   if (g_create_render_widget_for_frame) {
     return g_create_render_widget_for_frame(widget_routing_id, compositor_deps,
-                                            /*hidden=*/true, never_composited,
-                                            mojo::NullReceiver());
+                                            /*hidden=*/true, never_composited);
   }
 
   return std::make_unique<RenderWidget>(widget_routing_id, compositor_deps,
-                                        /*hidden=*/true, never_composited,
-                                        mojo::NullReceiver());
+                                        /*hidden=*/true, never_composited);
 }
 
 RenderWidget* RenderWidget::CreateForPopup(
     int32_t widget_routing_id,
     CompositorDependencies* compositor_deps,
     bool hidden,
-    bool never_composited,
-    mojo::PendingReceiver<mojom::Widget> widget_receiver) {
+    bool never_composited) {
   return new RenderWidget(widget_routing_id, compositor_deps, hidden,
-                          never_composited, std::move(widget_receiver));
+                          never_composited);
 }
 
 RenderWidget::RenderWidget(int32_t widget_routing_id,
                            CompositorDependencies* compositor_deps,
                            bool hidden,
-                           bool never_composited,
-                           mojo::PendingReceiver<mojom::Widget> widget_receiver)
+                           bool never_composited)
     : routing_id_(widget_routing_id),
       compositor_deps_(compositor_deps),
       is_hidden_(hidden),
       never_composited_(never_composited),
       next_previous_flags_(kInvalidNextPreviousFlagsValue),
-      frame_swap_message_queue_(new FrameSwapMessageQueue(routing_id_)),
-      widget_receiver_(this, std::move(widget_receiver)) {
+      frame_swap_message_queue_(new FrameSwapMessageQueue(routing_id_)) {
   DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
   DCHECK(RenderThread::IsMainThread());
   DCHECK(compositor_deps_);
@@ -597,7 +594,6 @@
                         OnWaitNextFrameForTests)
     IPC_MESSAGE_HANDLER(DragMsg_TargetDragEnter, OnDragTargetDragEnter)
     IPC_MESSAGE_HANDLER(DragMsg_TargetDragOver, OnDragTargetDragOver)
-    IPC_MESSAGE_HANDLER(DragMsg_TargetDragLeave, OnDragTargetDragLeave)
     IPC_MESSAGE_HANDLER(DragMsg_TargetDrop, OnDragTargetDrop)
     IPC_MESSAGE_HANDLER(DragMsg_SourceEnded, OnDragSourceEnded)
     IPC_MESSAGE_UNHANDLED(handled = false)
@@ -1324,6 +1320,16 @@
       HandledEventCallback());
 }
 
+void RenderWidget::GetWidgetInputHandler(
+    blink::CrossVariantMojoReceiver<
+        blink::mojom::WidgetInputHandlerInterfaceBase> widget_input_receiver,
+    blink::CrossVariantMojoRemote<
+        blink::mojom::WidgetInputHandlerHostInterfaceBase>
+        widget_input_host_remote) {
+  widget_input_handler_manager_->AddInterface(
+      std::move(widget_input_receiver), std::move(widget_input_host_remote));
+}
+
 void RenderWidget::ShowVirtualKeyboard() {
   UpdateTextInputStateInternal(true, false);
 }
@@ -1597,11 +1603,6 @@
 // WebWidgetClient
 
 void RenderWidget::DidMeaningfulLayout(blink::WebMeaningfulLayout layout_type) {
-  if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) {
-    QueueMessage(std::make_unique<WidgetHostMsg_DidFirstVisuallyNonEmptyPaint>(
-        routing_id_));
-  }
-
   for (auto& observer : render_frames_)
     observer.DidMeaningfulLayout(layout_type);
 }
@@ -1720,7 +1721,7 @@
       main_thread_scheduler, uses_input_handler);
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
-  if (command_line.HasSwitch(switches::kAllowPreCommitInput))
+  if (command_line.HasSwitch(blink::switches::kAllowPreCommitInput))
     widget_input_handler_manager_->AllowPreCommitInput();
 }
 
@@ -2194,17 +2195,6 @@
   Send(new DragHostMsg_UpdateDragCursor(routing_id(), operation));
 }
 
-void RenderWidget::OnDragTargetDragLeave(const gfx::PointF& client_point,
-                                         const gfx::PointF& screen_point) {
-  blink::WebFrameWidget* frame_widget = GetFrameWidget();
-  if (!frame_widget)
-    return;
-
-  frame_widget
-      ->DragTargetDragLeave(ConvertWindowPointToViewport(client_point),
-                            screen_point);
-}
-
 void RenderWidget::OnDragTargetDrop(const DropData& drop_data,
                                     const gfx::PointF& client_point,
                                     const gfx::PointF& screen_point,
@@ -3187,21 +3177,6 @@
   return nullptr;
 }
 
-void RenderWidget::SetupWidgetInputHandler(
-    mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver,
-    mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) {
-  widget_input_handler_manager_->AddInterface(std::move(receiver),
-                                              std::move(host));
-}
-
-void RenderWidget::SetWidgetReceiver(
-    mojo::PendingReceiver<mojom::Widget> recevier) {
-  // Close the old receiver if there was one.
-  // A RenderWidgetHost should not need more than one channel.
-  widget_receiver_.reset();
-  widget_receiver_.Bind(std::move(recevier));
-}
-
 blink::mojom::WidgetInputHandlerHost* RenderWidget::GetInputHandlerHost() {
   return widget_input_handler_manager_->GetWidgetInputHandlerHost();
 }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h
index 570168ce..2f34276 100644
--- a/content/renderer/render_widget.h
+++ b/content/renderer/render_widget.h
@@ -34,7 +34,6 @@
 #include "content/common/content_export.h"
 #include "content/common/content_to_visible_time_reporter.h"
 #include "content/common/drag_event_source_info.h"
-#include "content/common/widget.mojom.h"
 #include "content/public/common/drop_data.h"
 #include "content/public/common/screen_info.h"
 #include "content/renderer/input/main_thread_event_queue.h"
@@ -135,15 +134,13 @@
     : public IPC::Listener,
       public IPC::Sender,
       public blink::WebPagePopupClient,  // Is-a WebWidgetClient also.
-      public mojom::Widget,
       public RenderWidgetScreenMetricsEmulatorDelegate,
       public MainThreadEventQueueClient {
  public:
   RenderWidget(int32_t widget_routing_id,
                CompositorDependencies* compositor_deps,
                bool hidden,
-               bool never_composited,
-               mojo::PendingReceiver<mojom::Widget> widget_receiver);
+               bool never_composited);
 
   ~RenderWidget() override;
 
@@ -160,12 +157,11 @@
 
   // Convenience type for creation method taken by InstallCreateForFrameHook().
   // The method signature matches the RenderWidget constructor.
-  using CreateRenderWidgetFunction = std::unique_ptr<RenderWidget> (*)(
-      int32_t routing_id,
-      CompositorDependencies*,
-      bool hidden,
-      bool never_composited,
-      mojo::PendingReceiver<mojom::Widget> widget_receiver);
+  using CreateRenderWidgetFunction =
+      std::unique_ptr<RenderWidget> (*)(int32_t routing_id,
+                                        CompositorDependencies*,
+                                        bool hidden,
+                                        bool never_composited);
   // Overrides the implementation of CreateForFrame() function below. Used by
   // web tests to return a partial fake of RenderWidget.
   static void InstallCreateForFrameHook(
@@ -184,12 +180,10 @@
   // A RenderWidget popup is owned by the browser process. The object will be
   // destroyed by the WidgetMsg_Close message. The object can request its own
   // destruction via ClosePopupWidgetSoon().
-  static RenderWidget* CreateForPopup(
-      int32_t widget_routing_id,
-      CompositorDependencies* compositor_deps,
-      bool hidden,
-      bool never_composited,
-      mojo::PendingReceiver<mojom::Widget> widget_receiver);
+  static RenderWidget* CreateForPopup(int32_t widget_routing_id,
+                                      CompositorDependencies* compositor_deps,
+                                      bool hidden,
+                                      bool never_composited);
 
   // Initialize a new RenderWidget for a popup. The |show_callback| is called
   // when RenderWidget::Show() happens. The |opener_widget| is the local root
@@ -365,6 +359,12 @@
   bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override;
   void QueueSyntheticEvent(
       std::unique_ptr<blink::WebCoalescedInputEvent>) override;
+  void GetWidgetInputHandler(
+      blink::CrossVariantMojoReceiver<
+          blink::mojom::WidgetInputHandlerInterfaceBase> widget_input_receiver,
+      blink::CrossVariantMojoRemote<
+          blink::mojom::WidgetInputHandlerHostInterfaceBase>
+          widget_input_host_remote) override;
 
   // Returns the scale being applied to the document in blink by the device
   // emulator. Returns 1 if there is no emulation active. Use this to position
@@ -472,11 +472,6 @@
   viz::FrameSinkId GetFrameSinkIdAtPoint(const gfx::PointF& point,
                                          gfx::PointF* local_point);
 
-  // Widget mojom overrides.
-  void SetupWidgetInputHandler(
-      mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver,
-      mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) override;
-
   blink::mojom::WidgetInputHandlerHost* GetInputHandlerHost();
 
   scoped_refptr<MainThreadEventQueue> GetInputEventQueue();
@@ -510,7 +505,6 @@
   // composition info (when in monitor mode).
   void OnRequestCompositionUpdates(bool immediate_request,
                                    bool monitor_updates);
-  void SetWidgetReceiver(mojo::PendingReceiver<mojom::Widget> receiver);
 
   void SetMouseCapture(bool capture);
 
@@ -540,6 +534,18 @@
 
   base::WeakPtr<RenderWidget> AsWeakPtr();
 
+  // This method returns the WebLocalFrame which is currently focused and
+  // belongs to the frame tree associated with this RenderWidget.
+  blink::WebLocalFrame* GetFocusedWebLocalFrameInWidget() const;
+
+  bool handling_select_range() const { return handling_select_range_; }
+
+  bool is_pasting() const { return is_pasting_; }
+
+  void set_is_pasting(bool value) { is_pasting_ = value; }
+
+  void set_handling_select_range(bool value) { handling_select_range_ = value; }
+
  protected:
   // Notify subclasses that we handled OnUpdateVisualProperties.
   virtual void AfterUpdateVisualProperties() {}
@@ -631,8 +637,6 @@
                             const gfx::PointF& screen_pt,
                             blink::WebDragOperationsMask operations_allowed,
                             int key_modifiers);
-  void OnDragTargetDragLeave(const gfx::PointF& client_point,
-                             const gfx::PointF& screen_point);
   void OnDragTargetDrop(const DropData& drop_data,
                         const gfx::PointF& client_pt,
                         const gfx::PointF& screen_pt,
@@ -720,10 +724,6 @@
   PepperPluginInstanceImpl* GetFocusedPepperPluginInsideWidget();
 #endif
 
-  // This method returns the WebLocalFrame which is currently focused and
-  // belongs to the frame tree associated with this RenderWidget.
-  blink::WebLocalFrame* GetFocusedWebLocalFrameInWidget() const;
-
   // Whether this widget is for a frame. This excludes widgets that are not for
   // a frame (eg popups, pepper), but includes both the main frame
   // (via delegate_) and subframes (via for_child_local_root_frame_).
@@ -971,13 +971,17 @@
   bool is_pinch_gesture_active_from_mainframe_ = false;
 
   scoped_refptr<MainThreadEventQueue> input_event_queue_;
-
-  mojo::Receiver<mojom::Widget> widget_receiver_;
-
   gfx::Rect compositor_visible_rect_;
 
   uint32_t last_capture_sequence_number_ = 0u;
 
+  // Used to inform didChangeSelection() when it is called in the context
+  // of handling a FrameInputHandler::SelectRange IPC.
+  bool handling_select_range_ = false;
+
+  // Whether or not this RenderWidget is currently pasting.
+  bool is_pasting_ = false;
+
   std::unique_ptr<blink::scheduler::WebWidgetScheduler> widget_scheduler_;
 
   base::WeakPtrFactory<RenderWidget> weak_ptr_factory_{this};
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc
index 1d0f570d..5cc8e9b 100644
--- a/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -162,6 +162,16 @@
     widget_->DidInitiatePaint();
   }
 
+  void GetWidgetInputHandler(
+      blink::CrossVariantMojoReceiver<
+          blink::mojom::WidgetInputHandlerInterfaceBase> widget_input_receiver,
+      blink::CrossVariantMojoRemote<
+          blink::mojom::WidgetInputHandlerHostInterfaceBase>
+          widget_input_host_remote) override {
+    widget_->GetWidgetInputHandler(std::move(widget_input_receiver),
+                                   std::move(widget_input_host_remote));
+  }
+
  private:
   RenderWidgetFullscreenPepper* widget_;
 };
@@ -174,16 +184,14 @@
     const ScreenInfo& screen_info,
     PepperPluginInstanceImpl* plugin,
     const blink::WebURL& local_main_frame_url,
-    mojo::PendingReceiver<mojom::Widget> widget_receiver,
     mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget) {
   DCHECK_NE(MSG_ROUTING_NONE, routing_id);
   DCHECK(show_callback);
   RenderWidgetFullscreenPepper* render_widget =
       new RenderWidgetFullscreenPepper(
-          routing_id, compositor_deps, plugin, std::move(widget_receiver),
-          std::move(blink_widget_host), std::move(blink_widget),
-          local_main_frame_url);
+          routing_id, compositor_deps, plugin, std::move(blink_widget_host),
+          std::move(blink_widget), local_main_frame_url);
   render_widget->InitForPepperFullscreen(std::move(show_callback),
                                          render_widget->blink_widget_.get(),
                                          screen_info);
@@ -194,15 +202,13 @@
     int32_t routing_id,
     CompositorDependencies* compositor_deps,
     PepperPluginInstanceImpl* plugin,
-    mojo::PendingReceiver<mojom::Widget> widget_receiver,
     mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> mojo_widget_host,
     mojo::PendingAssociatedReceiver<blink::mojom::Widget> mojo_widget,
     blink::WebURL main_frame_url)
     : RenderWidget(routing_id,
                    compositor_deps,
                    /*hidden=*/false,
-                   /*never_composited=*/false,
-                   std::move(widget_receiver)),
+                   /*never_composited=*/false),
       plugin_(plugin),
       mouse_lock_dispatcher_(
           std::make_unique<FullscreenMouseLockDispatcher>(this)),
diff --git a/content/renderer/render_widget_fullscreen_pepper.h b/content/renderer/render_widget_fullscreen_pepper.h
index 8c5f31d..f9039222 100644
--- a/content/renderer/render_widget_fullscreen_pepper.h
+++ b/content/renderer/render_widget_fullscreen_pepper.h
@@ -43,7 +43,6 @@
       const ScreenInfo& screen_info,
       PepperPluginInstanceImpl* plugin,
       const blink::WebURL& local_main_frame_url,
-      mojo::PendingReceiver<mojom::Widget> widget_receiver,
       mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host,
       mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget);
 
@@ -64,7 +63,6 @@
       int32_t routing_id,
       CompositorDependencies* compositor_deps,
       PepperPluginInstanceImpl* plugin,
-      mojo::PendingReceiver<mojom::Widget> widget_receiver,
       mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host,
       mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget,
       blink::WebURL main_frame_url);
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index 6cb2d13..a996af0 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -204,8 +204,7 @@
       : RenderWidget(++next_routing_id_,
                      compositor_deps,
                      /*is_hidden=*/false,
-                     /*never_composited=*/false,
-                     mojo::NullReceiver()) {}
+                     /*never_composited=*/false) {}
 
   void Init(blink::WebWidget* widget, const ScreenInfo& screen_info) {
     Initialize(base::NullCallback(), widget, screen_info);
diff --git a/content/services/isolated_xr_device/xr_runtime_provider.cc b/content/services/isolated_xr_device/xr_runtime_provider.cc
index 0eeed975..e6c72ba1 100644
--- a/content/services/isolated_xr_device/xr_runtime_provider.cc
+++ b/content/services/isolated_xr_device/xr_runtime_provider.cc
@@ -41,15 +41,21 @@
     base::TimeDelta::FromSecondsD(5);
 
 template <typename VrDeviceT>
+std::unique_ptr<VrDeviceT> CreateDevice() {
+  return std::make_unique<VrDeviceT>();
+}
+
+template <typename VrDeviceT>
 std::unique_ptr<VrDeviceT> EnableRuntime(
-    device::mojom::IsolatedXRRuntimeProviderClient* client) {
-  auto device = std::make_unique<VrDeviceT>();
+    device::mojom::IsolatedXRRuntimeProviderClient* client,
+    base::OnceCallback<std::unique_ptr<VrDeviceT>()> create_device) {
+  auto device = std::move(create_device).Run();
   TRACE_EVENT_INSTANT1("xr", "HardwareAdded", TRACE_EVENT_SCOPE_THREAD, "id",
                        static_cast<int>(device->GetId()));
   // "Device" here refers to a runtime + hardware pair, not necessarily
   // a physical device.
   client->OnDeviceAdded(device->BindXRRuntime(), device->BindCompositorHost(),
-                        device->GetId());
+                        device->GetDeviceData(), device->GetId());
   return device;
 }
 
@@ -64,12 +70,14 @@
 }
 
 template <typename VrHardwareT>
-void SetRuntimeStatus(device::mojom::IsolatedXRRuntimeProviderClient* client,
-                      IsolatedXRRuntimeProvider::RuntimeStatus status,
-                      std::unique_ptr<VrHardwareT>* out_device) {
+void SetRuntimeStatus(
+    device::mojom::IsolatedXRRuntimeProviderClient* client,
+    IsolatedXRRuntimeProvider::RuntimeStatus status,
+    base::OnceCallback<std::unique_ptr<VrHardwareT>()> create_device,
+    std::unique_ptr<VrHardwareT>* out_device) {
   if (status == IsolatedXRRuntimeProvider::RuntimeStatus::kEnable &&
       !*out_device) {
-    *out_device = EnableRuntime<VrHardwareT>(client);
+    *out_device = EnableRuntime<VrHardwareT>(client, std::move(create_device));
   } else if (status == IsolatedXRRuntimeProvider::RuntimeStatus::kDisable &&
              *out_device) {
     DisableRuntime(client, std::move(*out_device));
@@ -211,7 +219,9 @@
 }
 
 void IsolatedXRRuntimeProvider::SetOculusVrRuntimeStatus(RuntimeStatus status) {
-  SetRuntimeStatus(client_.get(), status, &oculus_device_);
+  SetRuntimeStatus(client_.get(), status,
+                   base::BindOnce(&CreateDevice<device::OculusDevice>),
+                   &oculus_device_);
 }
 #endif  // BUILDFLAG(ENABLE_OCULUS_VR)
 
@@ -223,7 +233,9 @@
 }
 
 void IsolatedXRRuntimeProvider::SetOpenVrRuntimeStatus(RuntimeStatus status) {
-  SetRuntimeStatus(client_.get(), status, &openvr_device_);
+  SetRuntimeStatus(client_.get(), status,
+                   base::BindOnce(&CreateDevice<device::OpenVRDevice>),
+                   &openvr_device_);
 }
 #endif  // BUILDFLAG(ENABLE_OPENVR)
 
@@ -233,7 +245,9 @@
 }
 
 void IsolatedXRRuntimeProvider::SetWMRRuntimeStatus(RuntimeStatus status) {
-  SetRuntimeStatus(client_.get(), status, &wmr_device_);
+  SetRuntimeStatus(client_.get(), status,
+                   base::BindOnce(&CreateDevice<device::MixedRealityDevice>),
+                   &wmr_device_);
 }
 #endif  // BUILDFLAG(ENABLE_WINDOWS_MR)
 
@@ -243,7 +257,17 @@
 }
 
 void IsolatedXRRuntimeProvider::SetOpenXrRuntimeStatus(RuntimeStatus status) {
-  SetRuntimeStatus(client_.get(), status, &openxr_device_);
+  SetRuntimeStatus(
+      client_.get(), status,
+      base::BindOnce(
+          [](device::OpenXrStatics* openxr_statics) {
+            // This does not give any ownership of the OpenXrStatics object to
+            // OpenXrDevice. The OpenXrStatics is only used in the constructor
+            // and a reference is not kept.
+            return std::make_unique<device::OpenXrDevice>(openxr_statics);
+          },
+          openxr_statics_.get()),
+      &openxr_device_);
 }
 #endif  // BUILDFLAG(ENABLE_OPENXR)
 
diff --git a/content/shell/browser/shell_platform_delegate_views.cc b/content/shell/browser/shell_platform_delegate_views.cc
index 215cd23..a5cd3583b 100644
--- a/content/shell/browser/shell_platform_delegate_views.cc
+++ b/content/shell/browser/shell_platform_delegate_views.cc
@@ -79,6 +79,7 @@
   enum UIControl { BACK_BUTTON, FORWARD_BUTTON, STOP_BUTTON };
 
   explicit ShellWindowDelegateView(Shell* shell) : shell_(shell) {
+    SetHasWindowSizeControls(true);
     InitShellWindow();
   }
 
@@ -268,9 +269,6 @@
   }
 
   // Overridden from WidgetDelegateView
-  bool CanResize() const override { return true; }
-  bool CanMaximize() const override { return true; }
-  bool CanMinimize() const override { return true; }
   base::string16 GetWindowTitle() const override { return title_; }
 
   // Overridden from View
diff --git a/content/shell/browser/web_test/web_test_content_browser_client.cc b/content/shell/browser/web_test/web_test_content_browser_client.cc
index c69a7f4..021b0687 100644
--- a/content/shell/browser/web_test/web_test_content_browser_client.cc
+++ b/content/shell/browser/web_test/web_test_content_browser_client.cc
@@ -116,7 +116,7 @@
     size_ = natural_size;
   }
   void SetPlaybackState(PlaybackState playback_state) override {}
-  void SetAlwaysHidePlayPauseButton(bool is_visible) override {}
+  void SetPlayPauseButtonVisibility(bool is_visible) override {}
   void SetSkipAdButtonVisibility(bool is_visible) override {}
   void SetNextTrackButtonVisibility(bool is_visible) override {}
   void SetPreviousTrackButtonVisibility(bool is_visible) override {}
diff --git a/content/shell/renderer/web_test/web_test_content_renderer_client.cc b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
index 13ea701..2f8536f 100644
--- a/content/shell/renderer/web_test/web_test_content_renderer_client.cc
+++ b/content/shell/renderer/web_test/web_test_content_renderer_client.cc
@@ -61,11 +61,10 @@
     int32_t routing_id,
     CompositorDependencies* compositor_deps,
     bool hidden,
-    bool never_composited,
-    mojo::PendingReceiver<mojom::Widget> widget_receiver) {
+    bool never_composited) {
   return std::make_unique<WebWidgetTestProxy>(routing_id, compositor_deps,
-                                              /*hidden=*/true, never_composited,
-                                              std::move(widget_receiver));
+                                              /*hidden=*/true,
+                                              never_composited);
 }
 
 RenderFrameImpl* CreateWebFrameTestProxy(RenderFrameImpl::CreateParams params) {
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index a05a1e03..b18ce78 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -289,8 +289,6 @@
     "mock_render_widget_host_delegate.h",
     "mock_ssl_host_state_delegate.cc",
     "mock_ssl_host_state_delegate.h",
-    "mock_widget_impl.cc",
-    "mock_widget_impl.h",
     "mock_widget_input_handler.cc",
     "mock_widget_input_handler.h",
     "navigation_simulator_impl.cc",
@@ -1927,6 +1925,7 @@
     "../browser/tracing/background_tracing_config_unittest.cc",
     "../browser/tracing/tracing_ui_unittest.cc",
     "../browser/web_contents/aura/gesture_nav_simple_unittest.cc",
+    "../browser/web_contents/color_chooser_unittest.cc",
     "../browser/web_contents/web_contents_delegate_unittest.cc",
     "../browser/web_contents/web_contents_impl_unittest.cc",
     "../browser/web_contents/web_contents_user_data_unittest.cc",
diff --git a/content/test/data/media/canplaytype_test.html b/content/test/data/media/canplaytype_test.html
new file mode 100644
index 0000000..c5567112
--- /dev/null
+++ b/content/test/data/media/canplaytype_test.html
@@ -0,0 +1,8 @@
+<!--
+Copyright 2020 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<video></video>
+<script src="canplaytype_test.js"></script>
diff --git a/content/test/data/media/canplaytype_test.js b/content/test/data/media/canplaytype_test.js
new file mode 100644
index 0000000..3fab6107
--- /dev/null
+++ b/content/test/data/media/canplaytype_test.js
@@ -0,0 +1,1499 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// List of unsupported MPEG codec types.
+const BAD_MPEG_CODEC_LIST = [
+  // AVC codecs must be followed by valid 6-digit hexadecimal number.
+  'avc1.12345',
+  'avc3.12345',
+  'avc1.1234567',
+  'avc3.1234567',
+  'avc1.number',
+  'avc3.number',
+  'avc1.12345.',
+  'avc3.12345.',
+  'avc1.123456.',
+  'avc3.123456.',
+  'avc1.123456.7',
+  'avc3.123456.7',
+  'avc1.x23456',
+  'avc1.1x3456',
+  'avc1.12x456',
+  'avc1.123x56',
+  'avc1.1234x6',
+  'avc1.12345x',
+
+  // Old-style avc1 codecs must be followed by two dot-separated decimal
+  // numbers (H.264 profile and level)
+  // Invalid formats
+  'avc1..',
+  'avc1.66.',
+  'avc1.66.30.',
+  'avc1.x66.30',
+  'avc1.66x.30',
+  'avc1.66.x30',
+  'avc1.66.30x',
+
+  // Invalid level values
+  'avc1.66.300',
+  'avc1.66.-1',
+  'avc1.66.x',
+
+  // Invalid profile values
+  'avc1.0.30',
+  'avc1.65.30',
+  'avc1.67.30',
+  'avc1.76.30',
+  'avc1.78.30',
+  'avc1.99.30',
+  'avc1.101.30',
+  'avc1.300.30',
+  'avc1.-1.30',
+  'avc1.x.30',
+
+  // Old-style codec ids are not supported for avc3 codec strings.
+  'avc3.66.13',
+  'avc3.77.30',
+  'avc3.100.40',
+
+  // AAC codecs must be followed by one or two valid hexadecimal numbers.
+  'mp4a.no',
+  'mp4a.0k',
+  'mp4a.0k.0k',
+  'mp4a.4.',
+  'mp4a.40.0k',
+  'mp4a.40.',
+  'mp4a.40k',
+  'mp4a.40.2k',
+  'mp4a.40.2k',
+  'mp4a.40.2.',
+  'mp4a.40.2.0',
+
+  // Unlike just "avc1", just "mp4a" is not supported.
+  'mp4a',
+  'mp4a.',
+
+  // Other names for the codecs are not supported.
+  'h264',
+  'h.264',
+  'H264',
+  'H.264',
+  'aac',
+  'AAC',
+
+  // Codecs must not end with a dot.
+  'avc1.',
+  'avc3.',
+  'mp4a.',
+  'mp4a.40.',
+
+  // A simple substring match is not sufficient.
+  'lavc1337',
+  ';mp4a+',
+  ';mp4a.40+',
+
+  // Codecs not belonging to MPEG container.
+  '1',
+  'avc1, 1',
+  'avc3, 1',
+  'avc1.4D401E, 1',
+  'avc3.64001F, 1',
+  'vorbis',
+  'avc1, vorbis',
+  'avc3, vorbis',
+  'avc1.4D401E, vorbis',
+  'avc3.64001F, vorbis',
+  'vp8',
+  'vp9',
+  'vp8.0',
+  'vp9.0',
+  'vp08',
+  'vp09',
+  'vp08.00.01.08.02.01.01.00',
+  'vp8, mp4a.40',
+  'vp9, mp4a.40',
+  'vp8, mp4a.40.2',
+  'vp9, mp4a.40.2',
+  'vp8, mp4a.40.02',
+  'vp9, mp4a.40.02',
+  'theora',
+  'theora, mp4a',
+  'theora, mp4a.40.2',
+  'theora, mp4a.40.02',
+
+  // Codecs are case sensitive.
+  'AVC1',
+  'AVC1.4d401e',
+  'AVC3',
+  'AVC3.64001f',
+  'MP4A',
+  'MP4A.40.2',
+  'MP4A.40.02',
+  'AVC1, MP4',
+  'AVC3, MP4',
+  ', AVC1.4D401E, MP4.40.2',
+  ', AVC3.64001F, MP4.40.2',
+  ', AVC1.4D401E, MP4.40.02',
+  ', AVC3.64001F, MP4.40.02',
+
+  // Unknown codecs.
+  'avc2',
+  'avc4',
+  'avc1x',
+  'avc3x',
+  'mp4ax',
+  'ac',
+  'ec',
+  'ac-',
+  'ec-',
+  'ac-2',
+  'ec-2',
+  'ac3',
+  'ec3',
+  'ac-4',
+  'ec-4',
+  'mp4a.a4',
+  'mp4a.a7',
+  'mp4a.a5.',
+  'mp4a.a6.',
+  'mp4a.a5.1',
+  'mp4a.a6.1',
+
+  'unknown',
+
+  // Don't allow incomplete/ambiguous codec ids for HEVC.
+  // Codec string must have info about codec level/profile, as described in
+  // ISO/IEC FDIS 14496-15 section E.3, for example "hev1.1.6.L93.B0"
+  'hev1',
+  'hvc1',
+
+  // Invalid codecs that look like something similar to HEVC/H.265
+  'hev1x',
+  'hvc1x',
+
+  // First component of codec id must be "hev1" or "hvc1" (case-sensitive)
+  'hevc.1.6.L93.B0',
+  'hev0.1.6.L93.B0',
+  'hvc0.1.6.L93.B0',
+  'hev2.1.6.L93.B0',
+  'hvc2.1.6.L93.B0',
+  'HEVC.1.6.L93.B0',
+  'HEV0.1.6.L93.B0',
+  'HVC0.1.6.L93.B0',
+  'HEV2.1.6.L93.B0',
+  'HVC2.1.6.L93.B0',
+
+  // Trailing dot is not allowed.
+  'hev1.1.6.L93.B0.',
+  'hvc1.1.6.L93.B0.',
+
+  // Invalid general_profile_space/general_profile_idc
+  'hev1.x.6.L93.B0',
+  'hvc1.x.6.L93.B0',
+  'hev1.d1.6.L93.B0',
+  'hvc1.d1.6.L93.B0',
+
+  // Invalid general_profile_compatibility_flags
+  'hev1.1.x.L93.B0',
+  'hvc1.1.x.L93.B0',
+
+  // Invalid general_tier_flag
+  'hev1.1.6.x.B0',
+  'hvc1.1.6.x.B0',
+  'hev1.1.6.Lx.B0',
+  'hvc1.1.6.Lx.B0',
+  'hev1.1.6.Hx.B0',
+  'hvc1.1.6.Hx.B0',
+
+  // Invalid constraint flags
+  'hev1.1.6.L93.x',
+  'hvc1.1.6.L93.x',
+];
+
+// Codecs not belonging to OGG container.
+const BAD_OGG_CODEC_LIST = [
+  '1',
+  'theora, 1',
+  'vp08',
+  'vp08.00.01.08.02.01.01.00',
+  'vp9',
+  'vp9.0',
+  'vp9, opus',
+  'vp9, vorbis',
+  'vp09',
+  'vp09.00.10.08',
+  'avc1',
+  'avc3',
+  'avc1.4D401E',
+  'avc3.64001F',
+  'avc1.66.30',
+  'avc1, vorbis',
+  'avc3, vorbis',
+  'avc1, opus',
+  'avc3, opus',
+  'hev1.1.6.L93.B0',
+  'hvc1.1.6.L93.B0',
+  'hev1.1.6.L93.B0,opus',
+  'hvc1.1.6.L93.B0,opus',
+  'mp3',
+  'mp4a.66',
+  'mp4a.67',
+  'mp4a.68',
+  'mp4a.69',
+  'mp4a.6B',
+  'mp4a.40',
+  'mp4a.40.2',
+  'mp4a.40.02',
+  'theora, mp4a.40.2',
+  'theora, mp4a.40.02',
+  'ac-3',
+  'ec-3',
+  'mp4a.A5',
+  'mp4a.A6',
+  'mp4a.a5',
+  'mp4a.a6',
+
+  // Codecs are case sensitive.
+  'Theora',
+  'Opus',
+  'Vorbis',
+  'Theora, Opus',
+  'Theora, Vorbis',
+
+  // Unknown codecs.
+  'unknown',
+];
+
+// Codecs not belonging to WEBM container.
+const BAD_WEBM_CODEC_LIST = [
+  '1',
+  'vp8, 1',
+  'vp9, 1',
+  'vp8.0, 1',
+  'vp9.0, 1',
+  'vp08',
+  'vp09',
+  'theora',
+  'theora, vorbis',
+  'theora, opus',
+  'avc1',
+  'avc3',
+  'avc1.4D401E',
+  'avc3.64001F',
+  'avc1.66.30',
+  'avc1, vorbis',
+  'avc3, vorbis',
+  'avc1, opus',
+  'avc3, opus',
+  'hev1.1.6.L93.B0',
+  'hvc1.1.6.L93.B0',
+  'hev1.1.6.L93.B0,opus',
+  'hvc1.1.6.L93.B0,opus',
+  'flac',
+  'mp3',
+  'mp4a.66',
+  'mp4a.67',
+  'mp4a.68',
+  'mp4a.69',
+  'mp4a.6B',
+  'mp4a.40',
+  'mp4a.40.2',
+  'mp4a.40.02',
+  'vp8, mp4a.40',
+  'vp9, mp4a.40',
+  'vp8.0, mp4a.40',
+  'vp9.0, mp4a.40',
+  'ac-3',
+  'ec-3',
+  'mp4a.A5',
+  'mp4a.A6',
+  'mp4a.a5',
+  'mp4a.a6',
+
+  // Codecs are case sensitive.
+  'VP8, Vorbis',
+  'VP8.0, Opus',
+  'VP9, Vorbis',
+  'VP9.0, Opus',
+
+  // Unknown codec.
+  'unknown',
+];
+
+// Codecs not belonging to WAV container.
+const BAD_WAV_CODEC_LIST = [
+  'vp8',
+  'vp9',
+  'vp8.0, 1',
+  'vp9.0, 1',
+  'vp08',
+  'vp09',
+  'vp09.00.10.08',
+  'vorbis',
+  'opus',
+  'theora',
+  'theora, 1',
+  'avc1',
+  'avc3',
+  'avc1.4D401E',
+  'avc3.64001F',
+  'avc1.66.30',
+  'avc1, 1',
+  'avc3, 1',
+  'hev1.1.6.L93.B0',
+  'hvc1.1.6.L93.B0',
+  'hev1.1.6.L93.B0,opus',
+  'hvc1.1.6.L93.B0,opus',
+  'flac',
+  'mp3',
+  'mp4a.66',
+  'mp4a.67',
+  'mp4a.68',
+  'mp4a.69',
+  'mp4a.6B',
+  'mp4a.40',
+  'mp4a.40.2',
+  'mp4a.40.02',
+  'ac-3',
+  'ec-3',
+  'mp4a.A5',
+  'mp4a.A6',
+  'mp4a.a5',
+  'mp4a.a6',
+
+  // Unknown codec.
+  'unknown',
+];
+
+const HLS_CODEC_MAP = {
+  'probably': [
+    'avc1.42E01E',
+    'avc1.42101E',
+    'avc1.42701E',
+    'avc1.42F01E',
+    'avc3.42E01E',
+    'avc3.42801E',
+    'avc3.42C01E',
+    'mp4a.69',
+    'mp4a.6B',
+    'mp4a.40.2',
+    'mp4a.40.02',
+    'avc1.42E01E, mp4a.40.2',
+    'avc1.42E01E, mp4a.40.02',
+    'avc3.42E01E, mp4a.40.5',
+    'avc3.42E01E, mp4a.40.05',
+    'avc3.42E01E, mp4a.40.29',
+
+    // This result is incorrect. See https://crbug.com/592889.
+    'mp3',
+  ],
+
+  'maybe': [
+    '',
+    'avc1',
+    'avc3',
+    'mp4a.40',
+    'avc1, mp4a.40',
+    'avc3, mp4a.40',
+
+    'avc1, mp4a.40.2',
+    'avc1, mp4a.40.02',
+    'avc3, mp4a.40.2',
+    'avc3, mp4a.40.02',
+    'avc1.42E01E, mp4a.40',
+    'avc3.42E01E, mp4a.40',
+  ],
+
+  'not': [
+    // Android, is the only platform that supports these types, and its HLS
+    // implementations uses platform codecs, which do not include MPEG-2 AAC.
+    // See https://crbug.com/544268.
+    'mp4a.66',
+    'mp4a.67',
+    'mp4a.68',
+    'hev1.1.6.L93.B0',
+    'hvc1.1.6.L93.B0',
+    'hev1.1.6.L93.B0,mp4a.40.5',
+    'hvc1.1.6.L93.B0,mp4a.40.5',
+    'vp09.00.10.08',
+    'flac',
+    'ac-3',
+    'ec-3',
+    'mp4a.A5',
+    'mp4a.A6',
+    'mp4a.a5',
+    'mp4a.a6',
+  ]
+};
+
+const video = document.querySelector('video');
+
+function testMimeCodec(mime_codec, expected_value) {
+  let result = video.canPlayType(mime_codec);
+  if (expected_value === result)
+    return true;
+  console.log(
+      `Expected "${expected_value}" got "${result}" for ` +
+      `canPlayType('${mime_codec}')`);
+  return false;
+}
+
+function testCodecList(mime, codec_list, expected_value) {
+  for (var i = 0; i < codec_list.length; ++i) {
+    let codec = codec_list[i];
+    if (!testMimeCodec(`${mime}; codecs="${codec}"`, expected_value))
+      return false;
+  }
+
+  return true;
+}
+
+function testMimeCodecList(mime_codec_list, expected_value) {
+  let video = document.querySelector('video');
+  for (var i = 0; i < mime_codec_list.length; ++i) {
+    let mime_and_codec = mime_codec_list[i];
+    if (!testMimeCodec(mime_and_codec, expected_value))
+      return false;
+  }
+  return true;
+}
+
+function testMimeCodecMap(mime_codec_map, expect_not) {
+  let probably_list = mime_codec_map['probably'];
+  if (!testMimeCodecList(probably_list, expect_not ? '' : 'probably'))
+    return false;
+
+  // Not all codecs have a maybe value.
+  if ('maybe' in mime_codec_map) {
+    let maybe_list = mime_codec_map['maybe'];
+    if (!testMimeCodecList(maybe_list, expect_not ? '' : 'maybe'))
+      return false;
+  }
+
+  if ('not' in mime_codec_map)
+    return testMimeCodecList(mime_codec_map['not'], '');
+
+  return true;
+}
+
+function testBadMpegVariants(mime) {
+  let codecs_to_test = [...BAD_MPEG_CODEC_LIST];
+
+  // Old-style avc1 codec ids are supported only for video/mp2t container.
+  if (mime != 'video/mp2t') {
+    codecs_to_test.push('avc1.66.13');
+    codecs_to_test.push('avc1.77.30');
+    codecs_to_test.push('avc1.100.40');
+  }
+
+  // Remove all but "audio/mpeg" when https://crbug.com/592889 is fixed.
+  if (mime != 'audio/mpeg' && mime != 'audio/mp4' && mime != 'video/mp4' &&
+      mime != 'video/mp2t' && !mime.endsWith('mpegurl')) {
+    codecs_to_test.push('mp3')
+  }
+
+  if (mime != 'audio/mp4' && mime != 'video/mp4') {
+    codecs_to_test.push('opus');
+    codecs_to_test.push('avc1, opus');
+    codecs_to_test.push('avc3, opus');
+    codecs_to_test.push('avc1.4D401E, opus');
+    codecs_to_test.push('avc3.64001F, opus');
+  }
+
+  return testCodecList(mime, codecs_to_test, '');
+}
+
+function testBadOggVariants(mime) {
+  return testCodecList(mime, BAD_OGG_CODEC_LIST, '');
+}
+
+function testBadWebmVariants(mime) {
+  return testCodecList(mime, BAD_WEBM_CODEC_LIST, '');
+}
+
+function testBadWavVariants(mime) {
+  return testCodecList(mime, BAD_WAV_CODEC_LIST, '');
+}
+
+function testHlsVariants(mime, has_hls_support) {
+  let probably_list = HLS_CODEC_MAP['probably'];
+  if (!testCodecList(mime, probably_list, has_hls_support ? 'probably' : ''))
+    return false;
+
+  let maybe_list = HLS_CODEC_MAP['maybe'];
+  if (!testCodecList(mime, maybe_list, has_hls_support ? 'maybe' : ''))
+    return false;
+
+  if (!testBadMpegVariants(mime))
+    return false;
+
+  return testCodecList(mime, HLS_CODEC_MAP['not'], '');
+}
+
+function testAv1Variants(has_av1_support) {
+  const AV1_CODEC_MAP = {
+    'probably': [
+      // Fully qualified codec strings are required. These tests are not
+      // exhaustive since codec string parsing is exhaustively tested elsewhere.
+      'video/webm; codecs="av01.0.04M.08"',
+      'video/mp4; codecs="av01.0.04M.08"',
+    ],
+    'not': [
+      'video/webm; codecs="av1"',
+      'video/mp4; codecs="av1"',
+    ],
+  }
+
+  return testMimeCodecMap(AV1_CODEC_MAP, !has_av1_support);
+}
+
+function testWavVariants() {
+  const WAV_CODEC_MAP = {
+    'probably': [
+      'audio/wav; codecs="1"',
+      'audio/x-wav; codecs="1"',
+    ],
+    'maybe': [
+      'audio/wav',
+      'audio/x-wav',
+    ],
+  };
+
+  return testBadWavVariants('audio/wav') && testBadWavVariants('audio/x-wav') &&
+      testMimeCodecMap(WAV_CODEC_MAP, false);
+}
+
+function testWebmVariants() {
+  const WEBM_CODEC_MAP = {
+    'probably': [
+      'video/webm; codecs="vp8"',
+      'video/webm; codecs="vp8.0"',
+      'video/webm; codecs="vp8, vorbis"',
+      'video/webm; codecs="vp8.0, vorbis"',
+      'video/webm; codecs="vp8, opus"',
+      'video/webm; codecs="vp8.0, opus"',
+      'video/webm; codecs="vp9"',
+      'video/webm; codecs="vp9.0"',
+      'video/webm; codecs="vp9, vorbis"',
+      'video/webm; codecs="vp9.0, vorbis"',
+      'video/webm; codecs="vp9, opus"',
+      'video/webm; codecs="vp9.0, opus"',
+      'video/webm; codecs="vp8, vp9"',
+      'video/webm; codecs="vp8.0, vp9.0"',
+      'audio/webm; codecs="vorbis"',
+      'audio/webm; codecs="opus"',
+      'audio/webm; codecs="opus, vorbis"',
+    ],
+    'maybe': [
+      'video/webm',
+      'audio/webm',
+    ],
+    'not': [
+      'audio/webm; codecs="vp8"',
+      'audio/webm; codecs="vp8.0"',
+      'audio/webm; codecs="vp8, vorbis"',
+      'audio/webm; codecs="vp8.0, vorbis"',
+      'audio/webm; codecs="vp8, opus"',
+      'audio/webm; codecs="vp8.0, opus"',
+      'audio/webm; codecs="vp9"',
+      'audio/webm; codecs="vp9.0"',
+      'audio/webm; codecs="vp9, vorbis"',
+      'audio/webm; codecs="vp9.0, vorbis"',
+      'audio/webm; codecs="vp9, opus"',
+      'audio/webm; codecs="vp9.0, opus"',
+    ],
+  };
+
+  return testBadWebmVariants('video/webm') &&
+      testBadWebmVariants('audio/webm') &&
+      testMimeCodecMap(WEBM_CODEC_MAP, false);
+}
+
+function testOggVariants(has_theora_support) {
+  const OGG_THEORA_MAP = {
+    'probably': [
+      'video/ogg; codecs="theora"',
+      'video/ogg; codecs="theora, flac"',
+      'video/ogg; codecs="theora, opus"',
+      'video/ogg; codecs="theora, vorbis"',
+      'application/ogg; codecs="theora"',
+      'application/ogg; codecs="theora, flac"',
+      'application/ogg; codecs="theora, opus"',
+      'application/ogg; codecs="theora, vorbis"',
+    ],
+    'not': [
+      'audio/ogg; codecs="theora"',
+      'audio/ogg; codecs="theora, flac"',
+      'audio/ogg; codecs="theora, opus"',
+      'audio/ogg; codecs="theora, vorbis"',
+    ],
+  };
+
+  const OGG_CODEC_MAP = {
+    'probably': [
+      'video/ogg; codecs="flac, opus, vorbis"',
+      'video/ogg; codecs="vp8"',
+      'video/ogg; codecs="vp8.0"',
+      'video/ogg; codecs="vp8, opus"',
+      'video/ogg; codecs="vp8, vorbis"',
+      'audio/ogg; codecs="flac"',
+      'audio/ogg; codecs="opus"',
+      'audio/ogg; codecs="vorbis"',
+      'audio/ogg; codecs="flac, vorbis, opus"',
+      'application/ogg; codecs="flac"',
+      'application/ogg; codecs="opus"',
+      'application/ogg; codecs="vorbis"',
+      'application/ogg; codecs="flac, opus, vorbis"',
+    ],
+    'maybe': [
+      'application/ogg',
+      'video/ogg',
+      'audio/ogg',
+    ]
+  };
+  return testBadOggVariants('video/ogg') && testBadOggVariants('audio/ogg') &&
+      testBadOggVariants('application/ogg') &&
+      testMimeCodecMap(OGG_THEORA_MAP, !has_theora_support) &&
+      testMimeCodecMap(OGG_CODEC_MAP, false);
+}
+
+function testFlacVariants() {
+  const FLAC_CODEC_MAP = {
+    'probably': [
+      'audio/flac',
+      'audio/ogg; codecs="flac"',
+
+      // See CodecSupportTest_mp4 for more flac Variants.
+      'audio/mp4; codecs="flac"',
+      'video/mp4; codecs="flac"',
+    ],
+    'not': [
+      'video/flac',
+      'video/x-flac',
+      'audio/x-flac',
+      'application/x-flac',
+      'audio/flac; codecs="flac"',
+      'video/webm; codecs="flac"',
+      'audio/webm; codecs="flac"',
+      'audio/flac; codecs="avc1"',
+      'audio/flac; codecs="avc3"',
+      'audio/flac; codecs="avc1.4D401E"',
+      'audio/flac; codecs="avc3.64001F"',
+      'audio/flac; codecs="mp4a.66"',
+      'audio/flac; codecs="mp4a.67"',
+      'audio/flac; codecs="mp4a.68"',
+      'audio/flac; codecs="mp4a.40.2"',
+      'audio/flac; codecs="mp4a.40.02"',
+    ],
+  };
+
+  return testMimeCodecMap(FLAC_CODEC_MAP, false);
+}
+
+function testMp3Variants() {
+  const MP3_CODEC_MAP = {
+    'probably': [
+      // audio/mpeg without a codecs parameter (RFC 3003 compliant)
+      'audio/mpeg',
+
+      // audio/mpeg with mp3 in codecs parameter. (Not RFC compliant, but
+      // very common in the wild so it is a defacto standard).
+      'audio/mpeg; codecs="mp3"',
+      // The next two results are wrong due to https://crbug.com/592889.
+      'audio/mpeg; codecs="mp4a.69"',
+      'audio/mpeg; codecs="mp4a.6B"',
+
+      // audio/mp3 does not allow any codecs parameter
+      'audio/mp3',
+
+      // audio/x-mp3 does not allow any codecs parameter
+      'audio/x-mp3',
+    ],
+    'not': [
+      'video/mp3',
+      'video/mpeg',
+      'video/x-mp3',
+      'audio/mp3; codecs="mp3"',
+      'audio/x-mp3; codecs="mp3"',
+    ],
+  };
+
+  const MP3_BAD_CODEC_LIST = [
+    'avc1',
+    'avc3',
+    'avc1.4D401E',
+    'avc3.64001F',
+    'mp4a.66',
+    'mp4a.67',
+    'mp4a.68',
+    'mp4a.40.2',
+    'mp4a.40.02',
+    'flac',
+  ];
+
+  return testCodecList('audio/mp3', MP3_BAD_CODEC_LIST, '') &&
+      testCodecList('audio/mpeg', MP3_BAD_CODEC_LIST, '') &&
+      testCodecList('audio/x-mp3', MP3_BAD_CODEC_LIST, '') &&
+      testBadMpegVariants('audio/mp3') && testBadMpegVariants('audio/mpeg') &&
+      testBadMpegVariants('audio/x-mp3') &&
+      testMimeCodecMap(MP3_CODEC_MAP, false);
+}
+
+function testMp4Variants(has_proprietary_codecs) {
+  const MP4_CODEC_MAP = {
+    'probably': [
+      'audio/mp4; codecs="flac"',
+      'audio/mp4; codecs="mp4a.69"',
+      'audio/mp4; codecs="mp4a.6B"',
+      'audio/mp4; codecs="opus"',
+      'video/mp4; codecs="flac"',
+      'video/mp4; codecs="mp4a.69"',
+      'video/mp4; codecs="mp4a.6B"',
+      'video/mp4; codecs="opus"',
+      'video/mp4; codecs="vp09.00.10.08"',
+
+      // These results are incorrect. See https://crbug.com/592889.
+      'video/mp4; codecs="mp3"',
+      'audio/mp4; codecs="mp3"',
+    ],
+    'maybe': [
+      'audio/mp4',
+      'video/mp4',
+    ],
+    'not': [
+      'video/x-m4a; codecs="flac"',
+      'video/x-m4a; codecs="opus"',
+      'video/x-m4a; codecs="mp4a.69"',
+      'video/x-m4a; codecs="mp4a.6B"',
+      'video/x-m4v; codecs="ac-3"',
+      'video/x-m4v; codecs="avc1.640028,ac-3"',
+      'video/x-m4v; codecs="avc1.640028,ec-3"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.A5"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.A6"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.a5"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.a6"',
+      'video/x-m4v; codecs="ec-3"',
+      'video/x-m4v; codecs="flac"',
+      'video/x-m4v; codecs="mp4a.69"',
+      'video/x-m4v; codecs="mp4a.6B"',
+      'video/x-m4v; codecs="mp4a.A5"',
+      'video/x-m4v; codecs="mp4a.A6"',
+      'video/x-m4v; codecs="mp4a.a5"',
+      'video/x-m4v; codecs="mp4a.a6"',
+      'video/x-m4v; codecs="opus"',
+      'video/x-m4v; codecs="vp09.00.10.08"',
+      'video/x-m4v; codecs="hev1.1.6.L93.B0, mp4a.40.5"',
+      'video/x-m4v; codecs="hev1.1.6.L93.B0"',
+      'video/x-m4v; codecs="hvc1.1.6.L93.B0, mp4a.40.5"',
+      'video/x-m4v; codecs="hvc1.1.6.L93.B0"',
+      'video/mp4; codecs="hev1.1.6.L93.B0, mp4a.40.5"',
+      'video/mp4; codecs="hev1.1.6.L93.B0"',
+      'video/mp4; codecs="hvc1.1.6.L93.B0, mp4a.40.5"',
+      'video/mp4; codecs="hvc1.1.6.L93.B0"',
+
+      // AC3 and EAC3 (aka Dolby Digital Plus, DD+) audio codecs. These are not
+      // supported by Chrome by default. TODO(servolk): Strictly speaking only
+      // mp4a.A5 and mp4a.A6 codec ids are valid according to RFC 6381 section
+      // 3.3, 3.4. Lower-case oti (mp4a.a5 and mp4a.a6) should be rejected. But
+      // we used to allow those in older versions of Chromecast firmware and
+      // some apps (notably MPL) depend on those codec types being supported, so
+      // they should be allowed for now (crbug.com/564960)
+      'video/mp4; codecs="ac-3"',
+      'video/mp4; codecs="mp4a.a5"',
+      'video/mp4; codecs="mp4a.A5"',
+      'video/mp4; codecs="ec-3"',
+      'video/mp4; codecs="mp4a.a6"',
+      'video/mp4; codecs="mp4a.A6"',
+      'video/mp4; codecs="avc1.640028,ac-3"',
+      'video/mp4; codecs="avc1.640028,mp4a.a5"',
+      'video/mp4; codecs="avc1.640028,mp4a.A5"',
+      'video/mp4; codecs="avc1.640028,ec-3"',
+      'video/mp4; codecs="avc1.640028,mp4a.a6"',
+      'video/mp4; codecs="avc1.640028,mp4a.A6"',
+    ],
+  };
+
+  const MP4A_BAD_CODEC_LIST = [
+    'ac-3',
+    'avc1, mp4a.40',
+    'avc1, mp4a',
+    'avc1.4D401E',
+    'avc1',
+    'avc3, mp4a.40',
+    'avc3, mp4a',
+    'avc3.64001F',
+    'avc3',
+    'ec-3',
+    'hev1.1.6.L93.B0,mp4a.40.5',
+    'hev1.1.6.L93.B0',
+    'hvc1.1.6.L93.B0,mp4a.40.5',
+    'hvc1.1.6.L93.B0',
+    'mp4a.A5',
+    'mp4a.A6',
+    'mp4a.a5',
+    'mp4a.a6',
+    'vp09.00.10.08',
+  ];
+
+  const MP4_PROP_CODEC_MAP = {
+    'probably': [
+      'audio/mp4; codecs="mp4a.40.02"',
+      'audio/mp4; codecs="mp4a.40.05"',
+      'audio/mp4; codecs="mp4a.40.29"',
+      'audio/mp4; codecs="mp4a.40.2"',
+      'audio/mp4; codecs="mp4a.40.5"',
+      'audio/mp4; codecs="mp4a.66"',
+      'audio/mp4; codecs="mp4a.67"',
+      'audio/mp4; codecs="mp4a.68"',
+      'audio/x-m4a; codecs="mp4a.40.02"',
+      'audio/x-m4a; codecs="mp4a.40.05"',
+      'audio/x-m4a; codecs="mp4a.40.29"',
+      'audio/x-m4a; codecs="mp4a.40.2"',
+      'audio/x-m4a; codecs="mp4a.40.5"',
+      'audio/x-m4a; codecs="mp4a.66"',
+      'audio/x-m4a; codecs="mp4a.67"',
+      'audio/x-m4a; codecs="mp4a.68"',
+      'video/mp4; codecs="avc1.42101E"',
+      'video/mp4; codecs="avc1.42701E"',
+      'video/mp4; codecs="avc1.42E01E, mp4a.40.02"',
+      'video/mp4; codecs="avc1.42E01E, mp4a.40.2"',
+      'video/mp4; codecs="avc1.42E01E"',
+      'video/mp4; codecs="avc1.42F01E"',
+      'video/mp4; codecs="avc1.4D401E, flac"',
+      'video/mp4; codecs="avc1.4D401E, opus"',
+      'video/mp4; codecs="avc3.42801E"',
+      'video/mp4; codecs="avc3.42C01E"',
+      'video/mp4; codecs="avc3.42E01E, mp4a.40.05"',
+      'video/mp4; codecs="avc3.42E01E, mp4a.40.29"',
+      'video/mp4; codecs="avc3.42E01E, mp4a.40.5"',
+      'video/mp4; codecs="avc3.42E01E"',
+      'video/mp4; codecs="avc3.64001F, flac"',
+      'video/mp4; codecs="avc3.64001F, opus"',
+      'video/mp4; codecs="mp4a.40.02"',
+      'video/mp4; codecs="mp4a.40.2"',
+      'video/mp4; codecs="mp4a.66"',
+      'video/mp4; codecs="mp4a.67"',
+      'video/mp4; codecs="mp4a.68"',
+      'video/x-m4v; codecs="avc1.42101E"',
+      'video/x-m4v; codecs="avc1.42701E"',
+      'video/x-m4v; codecs="avc1.42E01E, mp4a.40.02"',
+      'video/x-m4v; codecs="avc1.42E01E, mp4a.40.2"',
+      'video/x-m4v; codecs="avc1.42E01E"',
+      'video/x-m4v; codecs="avc1.42F01E"',
+      'video/x-m4v; codecs="avc3.42801E"',
+      'video/x-m4v; codecs="avc3.42C01E"',
+      'video/x-m4v; codecs="avc3.42E01E, mp4a.40.05"',
+      'video/x-m4v; codecs="avc3.42E01E, mp4a.40.29"',
+      'video/x-m4v; codecs="avc3.42E01E, mp4a.40.5"',
+      'video/x-m4v; codecs="avc3.42E01E"',
+      'video/x-m4v; codecs="mp4a.40.02"',
+      'video/x-m4v; codecs="mp4a.40.2"',
+      'video/x-m4v; codecs="mp4a.66"',
+      'video/x-m4v; codecs="mp4a.67"',
+      'video/x-m4v; codecs="mp4a.68"',
+    ],
+    'maybe': [
+      'audio/mp4; codecs="mp4a.40"',
+      'audio/x-m4a',
+      'audio/x-m4a; codecs="mp4a.40"',
+      'video/mp4; codecs="avc1, avc3"',
+      'video/mp4; codecs="avc1, flac"',
+      'video/mp4; codecs="avc1, mp4a.40.02"',
+      'video/mp4; codecs="avc1, mp4a.40.2"',
+      'video/mp4; codecs="avc1, mp4a.40"',
+      'video/mp4; codecs="avc1, opus"',
+      'video/mp4; codecs="avc1.42E01E, mp4a.40"',
+      'video/mp4; codecs="avc1"',
+      'video/mp4; codecs="avc3, flac"',
+      'video/mp4; codecs="avc3, mp4a.40.02"',
+      'video/mp4; codecs="avc3, mp4a.40.2"',
+      'video/mp4; codecs="avc3, mp4a.40"',
+      'video/mp4; codecs="avc3, opus"',
+      'video/mp4; codecs="avc3.42E01E, mp4a.40"',
+      'video/mp4; codecs="avc3"',
+      'video/mp4; codecs="mp4a.40"',
+      'video/x-m4v',
+      'video/x-m4v; codecs="avc1, avc3"',
+      'video/x-m4v; codecs="avc1, mp4a.40.02"',
+      'video/x-m4v; codecs="avc1, mp4a.40.2"',
+      'video/x-m4v; codecs="avc1, mp4a.40"',
+      'video/x-m4v; codecs="avc1.42E01E, mp4a.40"',
+      'video/x-m4v; codecs="avc1"',
+      'video/x-m4v; codecs="avc3, mp4a.40.02"',
+      'video/x-m4v; codecs="avc3, mp4a.40.2"',
+      'video/x-m4v; codecs="avc3, mp4a.40"',
+      'video/x-m4v; codecs="avc3.42E01E, mp4a.40"',
+      'video/x-m4v; codecs="avc3"',
+      'video/x-m4v; codecs="mp4a.40"',
+    ],
+    'not': [
+      'video/x-m4a; codecs="flac"',
+      'video/x-m4a; codecs="opus"',
+      'video/x-m4a; codecs="mp4a.69"',
+      'video/x-m4a; codecs="mp4a.6B"',
+      'video/x-m4v; codecs="ac-3"',
+      'video/x-m4v; codecs="avc1.640028,ac-3"',
+      'video/x-m4v; codecs="avc1.640028,ec-3"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.A5"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.A6"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.a5"',
+      'video/x-m4v; codecs="avc1.640028,mp4a.a6"',
+      'video/x-m4v; codecs="ec-3"',
+      'video/x-m4v; codecs="flac"',
+      'video/x-m4v; codecs="mp4a.69"',
+      'video/x-m4v; codecs="mp4a.6B"',
+      'video/x-m4v; codecs="mp4a.A5"',
+      'video/x-m4v; codecs="mp4a.A6"',
+      'video/x-m4v; codecs="mp4a.a5"',
+      'video/x-m4v; codecs="mp4a.a6"',
+      'video/x-m4v; codecs="opus"',
+      'video/x-m4v; codecs="vp09.00.10.08"',
+    ],
+  };
+
+  return testCodecList('audio/mp4', MP4A_BAD_CODEC_LIST, '') &&
+      testCodecList('audio/x-m4a', MP4A_BAD_CODEC_LIST, '') &&
+      testMimeCodecMap(MP4_CODEC_MAP, false) &&
+      testMimeCodecMap(MP4_PROP_CODEC_MAP, !has_proprietary_codecs) &&
+      testBadMpegVariants('video/mp4') && testBadMpegVariants('video/x-m4v') &&
+      testBadMpegVariants('audio/mp4') && testBadMpegVariants('audio/x-m4a');
+}
+
+function testAvcVariantsInternal(
+    has_proprietary_codecs, has_software_avc, avc) {
+  let P_MAYBE = has_proprietary_codecs ? 'maybe' : '';
+  let P_PROBABLY = has_proprietary_codecs ? 'probably' : '';
+
+  // avc1 without extensions results in "maybe" for compatibility.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '"', P_MAYBE))
+    return false;
+
+  // A valid-looking 6-digit hexadecimal number will result in at least "maybe".
+  // But the first hex byte after the dot must be a valid profile_idc and the
+  // lower two bits of the second byte/4th digit must be zero.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42AC23"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42ACDF"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42acdf"', P_MAYBE))
+    return false;
+
+  // Invalid profile 0x12.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.123456"', ''))
+    return false;
+  // Valid profile/level, but reserved bits are set to 1 (4th digit after dot).
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42011E"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42021E"', ''))
+    return false;
+
+  // Both upper and lower case hexadecimal digits are accepted.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42E01E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42e01e"', P_PROBABLY))
+    return false;
+
+  // From a YouTube DASH MSE test manifest.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4d401f"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4d401e"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4d4015"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.640028"', P_PROBABLY))
+    return false;
+
+  //
+  // Baseline Profile (66 == 0x42).
+  //  The first two digits after the dot must be 42. The third and fourth digits
+  //  contain constraint_set_flags and must be valid hex. The last two digits
+  //  should be any valid H.264 level. If the level value is invalid the result
+  //  will be kMaybe.
+  //
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42001E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42401E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42801E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42E00A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42G01E"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42000G"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.42E0FF"', P_MAYBE))
+    return false;
+
+  //
+  // Main Profile (77 == 0x4D).
+  //  The first two digits after the dot must be 4D. The third and fourth digits
+  //  contain constraint_set_flags and must be valid hex. The last two digits
+  //  should be any valid H.264 level. If the level value is invalid the result
+  //  will be kMaybe.
+  //
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4D001E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4D400A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4D800A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4DE00A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4DG01E"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4D000G"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.4DE0FF"', P_MAYBE))
+    return false;
+
+  //
+  // High Profile (100 == 0x64).
+  //  The first two digits after the dot must be 64. The third and fourth digits
+  //  contain constraint_set_flags and must be valid hex. The last two digits
+  //  should be any valid H.264 level. If the level value is invalid the result
+  //  will be kMaybe.
+  //
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.64001E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.64400A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.64800A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.64E00A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.64G01E"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.64000G"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.64E0FF"', P_MAYBE))
+    return false;
+
+  //
+  // High 10-bit Profile (110 == 0x6E).
+  //  The first two digits after the dot must be 6E. The third and fourth digits
+  //  contain constraint_set_flags and must be valid hex. The last two digits
+  //  should be any valid H.264 level. If the level value is invalid the result
+  //  will be kMaybe.
+  //
+  let HI10P_PROBABLY =
+      has_software_avc ? 'probably' : (has_proprietary_codecs ? 'maybe' : '');
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.6E001E"', HI10P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.6E400A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.6E800A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.6EE00A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.6EG01E"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.6E000G"', ''))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.6EE0FF"', P_MAYBE))
+    return false;
+
+  //
+  //  Other profiles are not known to be supported.
+  //
+
+  // Extended Profile (88 == 0x58).
+  //   Without any constraint flags.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.58001E"', P_MAYBE))
+    return false;
+  //   With constraint_set0_flag==1 indicating compatibility with baseline
+  //   profile.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.58801E"', P_PROBABLY))
+    return false;
+  //   With constraint_set1_flag==1 indicating compatibility with main profile.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.58401E"', P_PROBABLY))
+    return false;
+  //   With constraint_set2_flag==1 indicating compatibility with extended
+  //   profile, the result is 'maybe' the same as for straight extended profile.
+  if (!testMimeCodec('video/mp4; codecs="' + avc + '.58201E"', P_MAYBE))
+    return false;
+
+  return true;
+}
+
+function testAvcVariants(has_proprietary_codecs, has_software_avc) {
+  return testAvcVariantsInternal(
+             has_proprietary_codecs, has_software_avc, 'avc1') &&
+      testAvcVariantsInternal(has_proprietary_codecs, has_software_avc, 'avc3');
+}
+
+// Tests AVC levels using |avc|.
+// Other supported values for the first four hexadecimal digits should behave
+// the same way but are not tested.
+// For each full level, the following are tested:
+// * The hexadecimal value before it is not supported.
+// * The hexadecimal value for the main level and all sub-levels are supported.
+// * The hexadecimal value after the last sub-level it is not supported.
+// * Decimal representations of the levels are not supported.
+function testAvcLevelsInternal(has_proprietary_codecs, avc) {
+  let P_MAYBE = has_proprietary_codecs ? 'maybe' : '';
+  let P_PROBABLY = has_proprietary_codecs ? 'probably' : '';
+
+  // Level 0 is not supported.
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E000"', P_MAYBE))
+    return false;
+
+  // Levels 1 (0x0A), 1.1 (0x0B), 1.2 (0x0C), 1.3 (0x0D).
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E009"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E00A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E00B"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E00C"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E00D"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E00E"', P_MAYBE))
+    return false;
+  // Verify that decimal representations of levels are not supported.
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E001"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E010"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E011"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E012"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E013"', P_MAYBE))
+    return false;
+
+  // Levels 2 (0x14), 2.1 (0x15), 2.2 (0x16)
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E013"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E014"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E015"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E016"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E017"', P_MAYBE))
+    return false;
+  // Verify that decimal representations of levels are not supported.
+  // However, 20 is level 3.2.
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E002"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E020"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E021"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E022"', P_MAYBE))
+    return false;
+
+  // Levels 3 (0x1e), 3.1 (0x1F), 3.2 (0x20)
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E01D"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E01E"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E01F"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E020"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E021"', P_MAYBE))
+    return false;
+  // Verify that decimal representations of levels are not supported.
+  // However, 32 is level 5.
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E003"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E030"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E031"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E032"', P_PROBABLY))
+    return false;
+
+  // Levels 4 (0x28), 4.1 (0x29), 4.2 (0x2A)
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E027"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E028"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E029"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E02A"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E02B"', P_MAYBE))
+    return false;
+  // Verify that decimal representations of levels are not supported.
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E004"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E040"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E041"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E042"', P_MAYBE))
+    return false;
+
+  // Levels 5 (0x32), 5.1 (0x33), 5.2 (0x34).
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E031"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E032"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E033"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E034"', P_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E035"', P_MAYBE))
+    return false;
+  // Verify that decimal representations of levels are not supported.
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E005"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E050"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E051"', P_MAYBE))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="avc1.42E052"', P_MAYBE))
+    return false;
+
+  return true;
+}
+
+function testAvcLevels(has_proprietary_codecs) {
+  return testAvcLevelsInternal(has_proprietary_codecs, 'avc1') &&
+      testAvcLevelsInternal(has_proprietary_codecs, 'avc3');
+}
+
+// All values that return positive results are tested. There are also
+// negative tests for values around or that could potentially be confused with
+// (e.g. case, truncation, hex <-> decimal conversion) those values that return
+// positive results.
+function testMp4aVariants(has_proprietary_codecs, has_xhe_aac_support) {
+  const MP3_CODEC_LIST = ['mp4a.6B', 'mp4a.69'];
+  const MP4A_BAD_CODEC_LIST = [
+    'mp4a',
+    'mp4a.',
+    'mp4a.6',
+    'mp4a.60',
+    'mp4a.61',
+    'mp4a.62',
+    'mp4a.63',
+    'mp4a.65',
+    'mp4a.65',
+    'mp4a.6A',
+    'mp4a.6b',
+    'mp4a.6C',
+    'mp4a.6D',
+    'mp4a.6E',
+    'mp4a.6F',
+    'mp4a.76',
+    'mp4a.4',
+    'mp4a.39',
+    'mp4a.40.',
+    'mp4a.40.0',
+    'mp4a.40.1',
+    'mp4a.40.3',
+    'mp4a.40.4',
+    'mp4a.40.6',
+    'mp4a.40.7',
+    'mp4a.40.8',
+    'mp4a.40.9',
+    'mp4a.40.10',
+    'mp4a.40.20',
+    'mp4a.40.30',
+    'mp4a.40.40',
+    'mp4a.40.50',
+    'mp4a.40.290',
+
+    // Check conversions of decimal 29 to hex and hex 29 to decimal.
+    'mp4a.40.1d',
+    'mp4a.40.1D',
+    'mp4a.40.41',
+
+    // Allow leading zeros in aud-oti for specific MPEG4 AAC strings.
+    // See http://crbug.com/440607.
+    'mp4a.40.00',
+    'mp4a.40.01',
+    'mp4a.40.03',
+    'mp4a.40.04',
+    'mp4a.40.029',
+    'mp4a.41',
+    'mp4a.41.2',
+    'mp4a.4.2',
+    'mp4a.400.2',
+    'mp4a.040.2',
+    'mp4a.4.5',
+    'mp4a.400.5',
+    'mp4a.040.5',
+  ];
+
+  const MP4A_GOOD_CODEC_LIST = [
+    // MPEG2 AAC Main, LC, and SSR are supported.
+    'mp4a.66',
+    'mp4a.67',
+    'mp4a.68',
+
+    // MPEG4 AAC SBR PS v2.
+    'mp4a.40.29',
+
+    // MPEG4 AAC SBR v1.
+    'mp4a.40.05',
+
+    // MPEG4 AAC LC.
+    'mp4a.40.2',
+
+    // MPEG4 AAC SBR v1.
+    'mp4a.40.5',
+
+    // MPEG4 AAC LC.
+    'mp4a.40.02',
+  ];
+
+  let P_MAYBE = has_proprietary_codecs ? 'maybe' : '';
+  let P_PROBABLY = has_proprietary_codecs ? 'probably' : '';
+
+  // mp4a.40 without further extension is ambiguous and results in "maybe".
+  if (!testMimeCodec('audio/mp4; codecs="mp4a.40"', P_MAYBE))
+    return false;
+
+  let XHE_PROBABLY = has_xhe_aac_support ? 'probably' : '';
+  if (!testMimeCodec('audio/mp4; codecs="mp4a.40.42"', XHE_PROBABLY))
+    return false;
+  if (!testMimeCodec('video/mp4; codecs="mp4a.40.42"', XHE_PROBABLY))
+    return false;
+
+  return testCodecList('audio/mp4', MP3_CODEC_LIST, 'probably') &&
+      testCodecList('audio/mp4', MP4A_BAD_CODEC_LIST, '') &&
+      testCodecList('audio/mp4', MP4A_GOOD_CODEC_LIST, P_PROBABLY);
+}
+
+function testHls(has_hls_support) {
+  return testHlsVariants('application/vnd.apple.mpegurl', has_hls_support) &&
+      testHlsVariants('application/x-mpegurl', has_hls_support) &&
+      testHlsVariants('audio/mpegurl', has_hls_support) &&
+      testHlsVariants('audio/x-mpegurl', has_hls_support);
+}
+
+function testAacAdts(has_proprietary_codecs) {
+  let P_PROBABLY = has_proprietary_codecs ? 'probably' : '';
+  if (!testMimeCodec('audio/aac', P_PROBABLY))
+    return false;
+
+  // audio/aac doesn't support the codecs parameter.
+  const ADTS_BAD_CODEC_LIST = ['1', 'aac', 'mp4a.40.2'];
+  return testCodecList('audio/aac', ADTS_BAD_CODEC_LIST, '');
+}
+
+function testMp2tsVariants(has_mp2ts_support) {
+  const MP2T_CODEC_MAP = {
+    'probably': [
+      // video/mp2t must support standard RFC 6381 compliant H.264 / AAC codec
+      // ids. H.264 baseline, main, high profiles
+      'video/mp2t; codecs="avc1.42E01E"',
+      'video/mp2t; codecs="avc1.4D401E"',
+      'video/mp2t; codecs="avc1.640028"',
+      'video/mp2t; codecs="mp4a.66"',
+      'video/mp2t; codecs="mp4a.67"',
+      'video/mp2t; codecs="mp4a.68"',
+      'video/mp2t; codecs="mp4a.69"',
+      'video/mp2t; codecs="mp4a.6B"',
+
+      // AAC LC audio
+      'video/mp2t; codecs="mp4a.40.2"',
+
+      // H.264 + AAC audio Variants
+      'video/mp2t; codecs="avc1.42E01E,mp4a.40.2"',
+      'video/mp2t; codecs="avc1.4D401E,mp4a.40.2"',
+      'video/mp2t; codecs="avc1.640028,mp4a.40.2"',
+
+      // This result is incorrect. See https://crbug.com/592889.
+      'video/mp2t; codecs="mp3"',
+
+      // Old-style avc1/H.264 codec ids that are still being used by some HLS
+      // streaming apps for backward compatibility.
+      // H.264 baseline profile
+      'video/mp2t; codecs="avc1.66.10"',
+      'video/mp2t; codecs="avc1.66.13"',
+      'video/mp2t; codecs="avc1.66.20"',
+      'video/mp2t; codecs="avc1.66.22"',
+      'video/mp2t; codecs="avc1.66.30"',
+      'video/mp2t; codecs="avc1.66.32"',
+      'video/mp2t; codecs="avc1.66.40"',
+      'video/mp2t; codecs="avc1.66.42"',
+
+      // H.264 main profile
+      'video/mp2t; codecs="avc1.77.10"',
+      'video/mp2t; codecs="avc1.77.13"',
+      'video/mp2t; codecs="avc1.77.20"',
+      'video/mp2t; codecs="avc1.77.22"',
+      'video/mp2t; codecs="avc1.77.30"',
+      'video/mp2t; codecs="avc1.77.32"',
+      'video/mp2t; codecs="avc1.77.40"',
+      'video/mp2t; codecs="avc1.77.42"',
+
+      // H.264 high profile
+      'video/mp2t; codecs="avc1.100.10"',
+      'video/mp2t; codecs="avc1.100.13"',
+      'video/mp2t; codecs="avc1.100.20"',
+      'video/mp2t; codecs="avc1.100.22"',
+      'video/mp2t; codecs="avc1.100.30"',
+      'video/mp2t; codecs="avc1.100.32"',
+      'video/mp2t; codecs="avc1.100.40"',
+      'video/mp2t; codecs="avc1.100.42"',
+
+      // H.264 + AAC audio Variants
+      'video/mp2t; codecs="avc1.66.10,mp4a.40.2"',
+      'video/mp2t; codecs="avc1.66.30,mp4a.40.2"',
+      'video/mp2t; codecs="avc1.77.10,mp4a.40.2"',
+      'video/mp2t; codecs="avc1.77.30,mp4a.40.2"',
+      'video/mp2t; codecs="avc1.100.40,mp4a.40.2"',
+    ],
+    'maybe': [
+      'video/mp2t',
+    ],
+    'not': [
+      // audio/mp2t is currently not supported (see also crbug.com/556837).
+      'audio/mp2t; codecs="mp4a.40.2"',
+
+      // H.264 + AC3/EAC3 audio Variants
+      'video/mp2t; codecs="avc1.640028,ac-3"',
+      'video/mp2t; codecs="avc1.640028,ec-3"',
+      'video/mp2t; codecs="avc1.640028,mp4a.A5"',
+      'video/mp2t; codecs="avc1.640028,mp4a.A6"',
+      'video/mp2t; codecs="avc1.640028,mp4a.a5"',
+      'video/mp2t; codecs="avc1.640028,mp4a.a6"',
+    ],
+  };
+
+  return testBadMpegVariants('video/mp2t') &&
+      testMimeCodecMap(MP2T_CODEC_MAP, !has_mp2ts_support)
+}
+
+function testNewVp9Variants(has_profile_2_3_support) {
+  // Malformed codecs string never allowed.
+  const VP9_BAD_CODEC_LIST = ['vp09.00.-1.08'];
+
+  // Test a few valid strings.
+  const VP9_GOOD_CODEC_LIST = [
+    'vp09.00.10.08',
+    'vp09.00.10.08.00.01.01.01.00',
+    'vp09.00.10.08.01.02.02.02.00',
+    'vp09.01.10.08',
+  ];
+
+  // Profiles 0 and 1 are always supported supported. Profiles 2 and 3 are
+  // only supported on certain architectures.
+  const VP9_2_3_CODEC_LIST = [
+    'vp09.02.10.08',
+    'vp09.03.10.08',
+  ];
+
+  let PROBABLY_23 = has_profile_2_3_support ? 'probably' : '';
+
+  const MIME_TYPES = ['video/webm', 'video/mp4'];
+  for (var i = 0; i < MIME_TYPES.length; ++i) {
+    let mime = MIME_TYPES[i];
+    if (!testCodecList(mime, VP9_BAD_CODEC_LIST, ''))
+      return false;
+    if (!testCodecList(mime, VP9_GOOD_CODEC_LIST, 'probably'))
+      return false;
+    if (!testCodecList(mime, VP9_2_3_CODEC_LIST, PROBABLY_23))
+      return false;
+  }
+
+  return true;
+}
diff --git a/content/test/gpu/gpu_tests/maps_integration_test.py b/content/test/gpu/gpu_tests/maps_integration_test.py
index ef1c85e..ecdf99e 100644
--- a/content/test/gpu/gpu_tests/maps_integration_test.py
+++ b/content/test/gpu/gpu_tests/maps_integration_test.py
@@ -95,12 +95,14 @@
     print 'Maps\' devicePixelRatio is ' + str(dpr)
 
     page = _GetMapsPageForUrl(url)
-    if page.test_rect:
+    # The bottom corners of Mac screenshots have black triangles due to the rounded corners of Mac
+    # windows. So, crop the bottom few rows off now to get rid of those. The triangles appear to be
+    # 5 pixels wide and tall regardless of DPI, so 10 pixels should be sufficient.
+    if self.browser.platform.GetOSName() == 'mac':
       img_height, img_width = screenshot.shape[:2]
-      screenshot = image_util.Crop(screenshot, int(page.test_rect[0] * dpr),
-                                   int(page.test_rect[1] * dpr),
-                                   min(int(page.test_rect[2] * dpr), img_width),
-                                   min(int(page.test_rect[3] * dpr), img_height))
+      screenshot = image_util.Crop(screenshot, 0, 0, img_width, img_height - 10)
+    x1, y1, x2, y2 = _GetCropBoundaries(screenshot)
+    screenshot = image_util.Crop(screenshot, x1, y1, x2 - x1, y2 - y1)
 
     self._UploadTestResultToSkiaGold(_TEST_NAME, screenshot, page,
                                      self._GetBuildIdArgs())
@@ -126,6 +128,60 @@
   return page
 
 
+def _GetCropBoundaries(screenshot):
+  """Returns the boundaries to crop the screenshot to.
+
+  Specifically, we look for the boundaries where the white background
+  transitions into the (non-white) content we care about.
+
+  Args:
+    screenshot: A screenshot returned by Tab.Screenshot() (numpy ndarray?)
+
+  Returns:
+    A 4-tuple (x1, y1, x2, y2) denoting the top left and bottom right
+    coordinates to crop to.
+  """
+  img_height, img_width = screenshot.shape[:2]
+
+  def RowIsWhite(row):
+    for col in xrange(img_width):
+      pixel = image_util.GetPixelColor(screenshot, col, row)
+      if pixel.r != 255 or pixel.g != 255 or pixel.b != 255:
+        return False
+    return True
+
+  def ColumnIsWhite(column):
+    for row in xrange(img_height):
+      pixel = image_util.GetPixelColor(screenshot, column, row)
+      if pixel.r != 255 or pixel.g != 255 or pixel.b != 255:
+        return False
+    return True
+
+  x1 = y1 = 0
+  x2 = img_width
+  y2 = img_height
+  for column in xrange(img_width):
+    if not ColumnIsWhite(column):
+      x1 = column
+      break
+
+  for row in xrange(img_height):
+    if not RowIsWhite(row):
+      y1 = row
+      break
+
+  for column in xrange(x1 + 1, img_width):
+    if ColumnIsWhite(column):
+      x2 = column
+      break
+
+  for row in xrange(y1 + 1, img_height):
+    if RowIsWhite(row):
+      y2 = row
+      break
+  return x1, y1, x2, y2
+
+
 def load_tests(loader, tests, pattern):
   del loader, tests, pattern  # Unused.
   return gpu_integration_test.LoadAllTestsInModule(sys.modules[__name__])
diff --git a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
index e9afcda..bdae88d 100644
--- a/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/info_collection_expectations.txt
@@ -1,6 +1,10 @@
 # tags: [ win ]
-# tags: [ intel-0x3e92 ]
+# tags: [ intel-0x3e92 intel-0x5912 ]
 # results: [ Failure ]
 
 # Incorrectly reporting SCALING instead of DIRECT on Win10 w/ UHD 630 GPUs.
 crbug.com/1079393 [ win intel-0x3e92 ] InfoCollection_direct_composition [ Failure ]
+
+# Incorrectly reporting SOFTWARE instead of SCALING for nv12_overlay_support on
+# Win10 w/ HD 630 GPUs and driver 26.20.100.8141
+crbug.com/1079393 [ win intel-0x5912 ] InfoCollection_direct_composition [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index b69c9f95..757be8d 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -77,3 +77,20 @@
 crbug.com/1079393 [ win10 intel-0x3e92 ] VideoPathTraceTest_DirectComposition_Underlay_Fullsize [ Failure ]
 crbug.com/1079393 [ win10 intel-0x3e92 ] VideoPathTraceTest_DirectComposition_Video_MP4_Fullsize [ Failure ]
 crbug.com/1079393 [ win10 intel-0x3e92 ] VideoPathTraceTest_DirectComposition_Video_MP4_YUY2 [ Failure ]
+
+# Using YUY2 instead of NV12 on Windows 10 HD 630 GPUs due to NV12 support
+# showing up as SOFTWARE.
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_ComplexOverlays [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Nonroot [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Underlay [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Underlay_DXVA [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Underlay_Fullsize [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4 [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4_DXVA [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4_FourColors_Aspect_4x3 [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4_FourColors_Rot_180 [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4_FourColors_Rot_270 [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4_FourColors_Rot_90 [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_MP4_Fullsize [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_VP9 [ Failure ]
+crbug.com/1079393 [ win10 intel-0x5912 ] VideoPathTraceTest_DirectComposition_Video_VP9_DXVA [ Failure ]
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
index ba8134c..e000b9f 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl2_conformance_expectations.txt
@@ -297,13 +297,14 @@
 crbug.com/965648 [ opengl linux passthrough nvidia ] deqp/functional/gles3/shaderstruct.html [ RetryOnFailure ]
 
 # Flaky on Windows 10 1909 Intel HD 630/UHD 630 GPUs w/ 26.20.100.8141
-crbug.com/1085222 [ win10 intel-0x3e92 d3d11 ] deqp/functional/gles3/shaderoperator/binary_operator_* [ Skip ]
-crbug.com/1085222 [ win10 intel-0x3e92 d3d11 ] deqp/functional/gles3/shaderoperator/unary_operator_01.html [ Skip ]
-crbug.com/1085222 [ win10 intel-0x3e92 d3d11 ] deqp/functional/gles3/shaderoperator/unary_operator_02.html [ Skip ]
-crbug.com/1085222 [ win10 intel-0x5912 d3d11 ] deqp/functional/gles3/shaderoperator/binary_operator_00.html [ RetryOnFailure ]
-crbug.com/1085222 [ win10 intel-0x5912 d3d11 ] deqp/functional/gles3/shaderoperator/binary_operator_01.html [ RetryOnFailure ]
-crbug.com/1085222 [ win10 intel-0x5912 d3d11 ] deqp/functional/gles3/shaderoperator/unary_operator_01.html [ RetryOnFailure ]
-crbug.com/1085222 [ win10 intel-0x5912 d3d11 ] deqp/functional/gles3/shaderoperator/unary_operator_02.html [ RetryOnFailure ]
+crbug.com/1085222 [ win10 intel-0x3e92 ] deqp/functional/gles3/shaderoperator/binary_operator_* [ Skip ]
+crbug.com/1085222 [ win10 intel-0x3e92 ] deqp/functional/gles3/shaderoperator/unary_operator_01.html [ Skip ]
+crbug.com/1085222 [ win10 intel-0x3e92 ] deqp/functional/gles3/shaderoperator/unary_operator_02.html [ Skip ]
+crbug.com/1085222 [ win10 intel-0x5912 ] deqp/functional/gles3/shaderoperator/binary_operator_* [ Skip ]
+crbug.com/1085222 [ win10 intel-0x5912 ] deqp/functional/gles3/shaderoperator/unary_operator_01.html [ Skip ]
+crbug.com/1085222 [ win10 intel-0x5912 ] deqp/functional/gles3/shaderoperator/unary_operator_02.html [ Skip ]
+
+# Flaky direct composition failure on Windows 10 1909 Intel UHD 630 GPUs w/ 26.20.100.8141
 crbug.com/1087993 [ win10 intel-0x5912 d3d11 ] conformance2/textures/image_data/tex-2d-rgb8ui-rgb_integer-unsigned_byte.html [ RetryOnFailure ]
 crbug.com/1087993 [ win10 intel-0x5912 d3d11 ] conformance2/textures/image_data/tex-2d-srgb8_alpha8-rgba-unsigned_byte.html [ RetryOnFailure ]
 
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 fccf3569..3acb9c69 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
@@ -332,6 +332,7 @@
 crbug.com/886970 [ mac intel-0xa2e ] conformance/rendering/canvas-alpha-bug.html [ Failure ]
 crbug.com/782317 [ mac intel ] conformance/rendering/rendering-stencil-large-viewport.html [ Failure ]
 crbug.com/1018028 [ mac intel ] conformance/rendering/bind-framebuffer-flush-bug.html [ Failure ]
+crbug.com/1092734 [ mac passthrough intel ] conformance/textures/webgl_canvas/tex-2d-rgba-rgba* [ Failure ]
 
 # Mac Retina NVidia failures
 crbug.com/635081 [ mac nvidia-0xfe9 ] conformance/attribs/gl-disabled-vertex-attrib.html [ Failure ]
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
index 56cb42c..5219e9c 100644
--- a/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
+++ b/content/test/gpu/gpu_tests/webgl_conformance_revision.txt
@@ -1,3 +1,3 @@
 # AUTOGENERATED FILE - DO NOT EDIT
 # SEE roll_webgl_conformance.py
-Current webgl revision 204abd22436837ddbe93816ec2ac52b7440daa6e
+Current webgl revision 1b5de6a99a004ea1de500f7324a89dd4d3818cc5
diff --git a/content/test/mock_widget_impl.cc b/content/test/mock_widget_impl.cc
deleted file mode 100644
index 976e16ac..0000000
--- a/content/test/mock_widget_impl.cc
+++ /dev/null
@@ -1,21 +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.
-
-#include "content/test/mock_widget_impl.h"
-
-namespace content {
-
-MockWidgetImpl::MockWidgetImpl(mojo::PendingReceiver<mojom::Widget> request)
-    : receiver_(this, std::move(request)) {}
-
-MockWidgetImpl::~MockWidgetImpl() {}
-
-void MockWidgetImpl::SetupWidgetInputHandler(
-    mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver,
-    mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) {
-  input_handler_ = std::make_unique<MockWidgetInputHandler>(std::move(receiver),
-                                                            std::move(host));
-}
-
-}  // namespace content
diff --git a/content/test/mock_widget_impl.h b/content/test/mock_widget_impl.h
deleted file mode 100644
index 496046f..0000000
--- a/content/test/mock_widget_impl.h
+++ /dev/null
@@ -1,35 +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 CONTENT_TEST_MOCK_WIDGET_IMPL_H_
-#define CONTENT_TEST_MOCK_WIDGET_IMPL_H_
-
-#include "content/common/widget.mojom.h"
-#include "content/test/mock_widget_input_handler.h"
-#include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-
-namespace content {
-
-class MockWidgetImpl : public mojom::Widget {
- public:
-  explicit MockWidgetImpl(mojo::PendingReceiver<mojom::Widget> receiver);
-  ~MockWidgetImpl() override;
-
-  void SetupWidgetInputHandler(
-      mojo::PendingReceiver<blink::mojom::WidgetInputHandler> receiver,
-      mojo::PendingRemote<blink::mojom::WidgetInputHandlerHost> host) override;
-
-  MockWidgetInputHandler* input_handler() { return input_handler_.get(); }
-
- private:
-  mojo::Receiver<mojom::Widget> receiver_;
-  std::unique_ptr<MockWidgetInputHandler> input_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockWidgetImpl);
-};
-
-}  // namespace content
-
-#endif  // CONTENT_TEST_MOCK_WIDGET_IMPL_H_
diff --git a/content/test/mock_widget_input_handler.cc b/content/test/mock_widget_input_handler.cc
index 2eb72d36..280e152 100644
--- a/content/test/mock_widget_input_handler.cc
+++ b/content/test/mock_widget_input_handler.cc
@@ -75,7 +75,8 @@
   dispatched_messages_.emplace_back(std::make_unique<DispatchedIMEMessage>(
       "CommitText", text, ime_text_spans, range, relative_cursor_position,
       relative_cursor_position));
-  std::move(callback).Run();
+  if (callback)
+    std::move(callback).Run();
 }
 
 void MockWidgetInputHandler::ImeFinishComposingText(bool keep_selection) {
@@ -127,6 +128,10 @@
     mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor>
         compositor_request) {}
 
+void MockWidgetInputHandler::GetFrameWidgetInputHandler(
+    mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler>
+        interface_request) {}
+
 MockWidgetInputHandler::DispatchedMessage::DispatchedMessage(
     const std::string& name)
     : name_(name) {}
diff --git a/content/test/mock_widget_input_handler.h b/content/test/mock_widget_input_handler.h
index 62b51bb..c138433 100644
--- a/content/test/mock_widget_input_handler.h
+++ b/content/test/mock_widget_input_handler.h
@@ -226,6 +226,9 @@
           host,
       mojo::PendingAssociatedReceiver<blink::mojom::SynchronousCompositor>
           compositor_request) override;
+  void GetFrameWidgetInputHandler(
+      mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetInputHandler>
+          interface_request) override;
 
   using MessageVector = std::vector<std::unique_ptr<DispatchedMessage>>;
   MessageVector GetAndResetDispatchedMessages();
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index 0011b45..0c929e1 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -135,7 +135,6 @@
   }
 
   bool CreateNewWidget(
-      mojo::PendingRemote<::content::mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
@@ -147,7 +146,6 @@
   }
 
   void CreateNewWidget(
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
@@ -156,7 +154,6 @@
   }
 
   void CreateNewFullscreenWidget(
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
@@ -324,34 +321,6 @@
   OnUnload(proxy_routing_id, is_loading, replicated_frame_state, frame_token);
 }
 
-void TestRenderFrame::SetEditableSelectionOffsets(int start, int end) {
-  GetFrameInputHandler()->SetEditableSelectionOffsets(start, end);
-}
-
-void TestRenderFrame::ExtendSelectionAndDelete(int before, int after) {
-  GetFrameInputHandler()->ExtendSelectionAndDelete(before, after);
-}
-
-void TestRenderFrame::DeleteSurroundingText(int before, int after) {
-  GetFrameInputHandler()->DeleteSurroundingText(before, after);
-}
-
-void TestRenderFrame::DeleteSurroundingTextInCodePoints(int before, int after) {
-  GetFrameInputHandler()->DeleteSurroundingTextInCodePoints(before, after);
-}
-
-void TestRenderFrame::CollapseSelection() {
-  GetFrameInputHandler()->CollapseSelection();
-}
-
-void TestRenderFrame::SetCompositionFromExistingText(
-    int start,
-    int end,
-    const std::vector<ui::ImeTextSpan>& ime_text_spans) {
-  GetFrameInputHandler()->SetCompositionFromExistingText(start, end,
-                                                         ime_text_spans);
-}
-
 void TestRenderFrame::BeginNavigation(
     std::unique_ptr<blink::WebNavigationInfo> info) {
   if (next_navigation_html_override_.has_value()) {
@@ -453,15 +422,4 @@
   return mock_frame_host_.get();
 }
 
-blink::mojom::FrameInputHandler* TestRenderFrame::GetFrameInputHandler() {
-  if (!frame_input_handler_) {
-    mojo::PendingReceiver<blink::mojom::FrameInputHandler>
-        frame_input_handler_receiver =
-            frame_input_handler_.BindNewPipeAndPassReceiver();
-    FrameInputHandlerImpl::CreateMojoService(
-        weak_factory_.GetWeakPtr(), std::move(frame_input_handler_receiver));
-  }
-  return frame_input_handler_.get();
-}
-
 }  // namespace content
diff --git a/content/test/test_render_frame.h b/content/test/test_render_frame.h
index fe5a2fcb..5ab1936 100644
--- a/content/test/test_render_frame.h
+++ b/content/test/test_render_frame.h
@@ -60,16 +60,6 @@
               bool is_loading,
               const FrameReplicationState& replicated_frame_state,
               const base::UnguessableToken& frame_token);
-  void SetEditableSelectionOffsets(int start, int end);
-  void ExtendSelectionAndDelete(int before, int after);
-  void DeleteSurroundingText(int before, int after);
-  void DeleteSurroundingTextInCodePoints(int before, int after);
-  void CollapseSelection();
-  void SetCompositionFromExistingText(
-      int start,
-      int end,
-      const std::vector<ui::ImeTextSpan>& ime_text_spans);
-
   void BeginNavigation(std::unique_ptr<blink::WebNavigationInfo> info) override;
 
   std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
@@ -98,11 +88,8 @@
  private:
   mojom::FrameHost* GetFrameHost() override;
 
-  blink::mojom::FrameInputHandler* GetFrameInputHandler();
-
   std::unique_ptr<MockFrameHost> mock_frame_host_;
   base::Optional<std::string> next_navigation_html_override_;
-  mojo::Remote<blink::mojom::FrameInputHandler> frame_input_handler_;
 
   mojo::AssociatedRemote<mojom::NavigationClient> mock_navigation_client_;
 
diff --git a/content/test/test_render_widget_host.cc b/content/test/test_render_widget_host.cc
index bafaa66..7f834c6 100644
--- a/content/test/test_render_widget_host.cc
+++ b/content/test/test_render_widget_host.cc
@@ -16,28 +16,19 @@
     RenderProcessHost* process,
     int32_t routing_id,
     bool hidden) {
-  mojo::PendingRemote<mojom::Widget> widget;
-  std::unique_ptr<MockWidgetImpl> widget_impl =
-      std::make_unique<MockWidgetImpl>(widget.InitWithNewPipeAndPassReceiver());
-  return base::WrapUnique(new TestRenderWidgetHost(
-      delegate, process, routing_id, std::move(widget_impl), std::move(widget),
-      hidden));
+  return base::WrapUnique(
+      new TestRenderWidgetHost(delegate, process, routing_id, hidden));
 }
 
-TestRenderWidgetHost::TestRenderWidgetHost(
-    RenderWidgetHostDelegate* delegate,
-    RenderProcessHost* process,
-    int32_t routing_id,
-    std::unique_ptr<MockWidgetImpl> widget_impl,
-    mojo::PendingRemote<mojom::Widget> widget,
-    bool hidden)
+TestRenderWidgetHost::TestRenderWidgetHost(RenderWidgetHostDelegate* delegate,
+                                           RenderProcessHost* process,
+                                           int32_t routing_id,
+                                           bool hidden)
     : RenderWidgetHostImpl(delegate,
                            process,
                            routing_id,
-                           std::move(widget),
                            hidden,
-                           std::make_unique<FrameTokenMessageQueue>()),
-      widget_impl_(std::move(widget_impl)) {
+                           std::make_unique<FrameTokenMessageQueue>()) {
   mojo::AssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
   mojo::AssociatedRemote<blink::mojom::Widget> blink_widget;
   auto blink_widget_receiver =
@@ -50,11 +41,11 @@
 TestRenderWidgetHost::~TestRenderWidgetHost() {}
 blink::mojom::WidgetInputHandler*
 TestRenderWidgetHost::GetWidgetInputHandler() {
-  return widget_impl_->input_handler();
+  return &input_handler_;
 }
 
 MockWidgetInputHandler* TestRenderWidgetHost::GetMockWidgetInputHandler() {
-  return widget_impl_->input_handler();
+  return &input_handler_;
 }
 
 }  // namespace content
diff --git a/content/test/test_render_widget_host.h b/content/test/test_render_widget_host.h
index 54e8418..13fbe11 100644
--- a/content/test/test_render_widget_host.h
+++ b/content/test/test_render_widget_host.h
@@ -6,7 +6,6 @@
 #define CONTENT_TEST_TEST_RENDER_WIDGET_HOST_H_
 
 #include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/test/mock_widget_impl.h"
 #include "content/test/mock_widget_input_handler.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
@@ -33,11 +32,8 @@
   TestRenderWidgetHost(RenderWidgetHostDelegate* delegate,
                        RenderProcessHost* process,
                        int32_t routing_id,
-                       std::unique_ptr<MockWidgetImpl> widget_impl,
-                       mojo::PendingRemote<mojom::Widget> widget,
                        bool hidden);
-
-  std::unique_ptr<MockWidgetImpl> widget_impl_;
+  MockWidgetInputHandler input_handler_;
 };
 
 }  // namespace content
diff --git a/content/test/test_render_widget_host_factory.cc b/content/test/test_render_widget_host_factory.cc
index d8864fb..71106e4b 100644
--- a/content/test/test_render_widget_host_factory.cc
+++ b/content/test/test_render_widget_host_factory.cc
@@ -21,7 +21,6 @@
     RenderWidgetHostDelegate* delegate,
     RenderProcessHost* process,
     int32_t routing_id,
-    mojo::PendingRemote<mojom::Widget> widget_interface,
     bool hidden) {
   return TestRenderWidgetHost::Create(delegate, process, routing_id, hidden);
 }
diff --git a/content/test/test_render_widget_host_factory.h b/content/test/test_render_widget_host_factory.h
index b4cae01..bf49da9 100644
--- a/content/test/test_render_widget_host_factory.h
+++ b/content/test/test_render_widget_host_factory.h
@@ -27,7 +27,6 @@
       RenderWidgetHostDelegate* delegate,
       RenderProcessHost* process,
       int32_t routing_id,
-      mojo::PendingRemote<mojom::Widget> widget_interface,
       bool hidden) override;
 
  private:
diff --git a/content/test/test_web_contents.cc b/content/test/test_web_contents.cc
index 5401bec..b7cee4c1 100644
--- a/content/test/test_web_contents.cc
+++ b/content/test/test_web_contents.cc
@@ -386,14 +386,12 @@
 void TestWebContents::CreateNewWidget(
     int32_t render_process_id,
     int32_t route_id,
-    mojo::PendingRemote<mojom::Widget> widget,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {}
 
 void TestWebContents::CreateNewFullscreenWidget(
     int32_t render_process_id,
     int32_t route_id,
-    mojo::PendingRemote<mojom::Widget> widget,
     mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
     mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {}
 
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 30c834c..ab03a197 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -178,7 +178,6 @@
       SessionStorageNamespace* session_storage_namespace) override;
   void CreateNewWidget(int32_t render_process_id,
                        int32_t route_id,
-                       mojo::PendingRemote<mojom::Widget> widget,
                        mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
                            blink_widget_host,
                        mojo::PendingAssociatedRemote<blink::mojom::Widget>
@@ -186,7 +185,6 @@
   void CreateNewFullscreenWidget(
       int32_t render_process_id,
       int32_t route_id,
-      mojo::PendingRemote<mojom::Widget> widget,
       mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
           blink_widget_host,
       mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget)
diff --git a/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc b/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
index da081df..b59f4ace 100644
--- a/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
+++ b/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
@@ -97,7 +97,7 @@
 class BluetoothGattBlueZTest : public testing::Test {
  public:
   BluetoothGattBlueZTest()
-      : fake_bluetooth_gatt_service_client_(NULL),
+      : fake_bluetooth_gatt_service_client_(nullptr),
         success_callback_count_(0),
         error_callback_count_(0) {}
 
diff --git a/device/fido/attested_credential_data.cc b/device/fido/attested_credential_data.cc
index 6830cb24..1365828 100644
--- a/device/fido/attested_credential_data.cc
+++ b/device/fido/attested_credential_data.cc
@@ -229,7 +229,7 @@
   fido_parsing_utils::Append(&attestation_data, aaguid_);
   fido_parsing_utils::Append(&attestation_data, credential_id_length_);
   fido_parsing_utils::Append(&attestation_data, credential_id_);
-  fido_parsing_utils::Append(&attestation_data, public_key_->cose_key_bytes());
+  fido_parsing_utils::Append(&attestation_data, public_key_->cose_key_bytes);
   return attestation_data;
 }
 
diff --git a/device/fido/attested_credential_data.h b/device/fido/attested_credential_data.h
index 1999430a..a78c334 100644
--- a/device/fido/attested_credential_data.h
+++ b/device/fido/attested_credential_data.h
@@ -18,7 +18,7 @@
 
 namespace device {
 
-class PublicKey;
+struct PublicKey;
 
 // https://www.w3.org/TR/2017/WD-webauthn-20170505/#sec-attestation-data
 class COMPONENT_EXPORT(DEVICE_FIDO) AttestedCredentialData {
diff --git a/device/fido/ctap_response_unittest.cc b/device/fido/ctap_response_unittest.cc
index 1a20bec1..93e1371 100644
--- a/device/fido/ctap_response_unittest.cc
+++ b/device/fido/ctap_response_unittest.cc
@@ -429,7 +429,7 @@
       static_cast<int32_t>(CoseAlgorithmIdentifier::kCoseEs256),
       test_data::kTestU2fRegisterResponse);
   ASSERT_TRUE(public_key);
-  EXPECT_THAT(public_key->cose_key_bytes(),
+  EXPECT_THAT(public_key->cose_key_bytes,
               ::testing::ElementsAreArray(test_data::kTestECPublicKeyCOSE));
 }
 
diff --git a/device/fido/p256_public_key.h b/device/fido/p256_public_key.h
index 4eeccb70..f9d5bec 100644
--- a/device/fido/p256_public_key.h
+++ b/device/fido/p256_public_key.h
@@ -15,7 +15,7 @@
 
 namespace device {
 
-class PublicKey;
+struct PublicKey;
 
 struct COMPONENT_EXPORT(DEVICE_FIDO) P256PublicKey {
   static std::unique_ptr<PublicKey> ExtractFromU2fRegistrationResponse(
diff --git a/device/fido/public_key.cc b/device/fido/public_key.cc
index 39c6397..88c6f58 100644
--- a/device/fido/public_key.cc
+++ b/device/fido/public_key.cc
@@ -11,25 +11,13 @@
 
 namespace device {
 
+PublicKey::PublicKey(int32_t in_algorithm,
+                     base::span<const uint8_t> in_cose_key_bytes,
+                     base::Optional<std::vector<uint8_t>> in_der_bytes)
+    : algorithm(in_algorithm),
+      cose_key_bytes(fido_parsing_utils::Materialize(in_cose_key_bytes)),
+      der_bytes(std::move(in_der_bytes)) {}
+
 PublicKey::~PublicKey() = default;
 
-PublicKey::PublicKey(int32_t algorithm,
-                     base::span<const uint8_t> cbor_bytes,
-                     base::Optional<std::vector<uint8_t>> der_bytes)
-    : algorithm_(algorithm),
-      cbor_bytes_(fido_parsing_utils::Materialize(cbor_bytes)),
-      der_bytes_(std::move(der_bytes)) {}
-
-int32_t PublicKey::algorithm() const {
-  return algorithm_;
-}
-
-const std::vector<uint8_t>& PublicKey::cose_key_bytes() const {
-  return cbor_bytes_;
-}
-
-const base::Optional<std::vector<uint8_t>>& PublicKey::der_bytes() const {
-  return der_bytes_;
-}
-
 }  // namespace device
diff --git a/device/fido/public_key.h b/device/fido/public_key.h
index c3e51ab7..f9e9701 100644
--- a/device/fido/public_key.h
+++ b/device/fido/public_key.h
@@ -6,41 +6,36 @@
 #define DEVICE_FIDO_PUBLIC_KEY_H_
 
 #include <stdint.h>
-#include <string>
 #include <vector>
 
 #include "base/component_export.h"
 #include "base/containers/span.h"
 #include "base/macros.h"
+#include "base/optional.h"
 
 namespace device {
 
 // https://www.w3.org/TR/webauthn/#credentialpublickey
-class COMPONENT_EXPORT(DEVICE_FIDO) PublicKey {
- public:
+struct COMPONENT_EXPORT(DEVICE_FIDO) PublicKey {
   PublicKey(int32_t algorithm,
             base::span<const uint8_t> cbor_bytes,
             base::Optional<std::vector<uint8_t>> der_bytes);
-  virtual ~PublicKey();
+  ~PublicKey();
 
-  // algorithm returns the COSE algorithm identifier for this public key.
-  int32_t algorithm() const;
+  // algorithm contains the COSE algorithm identifier for this public key.
+  const int32_t algorithm;
 
-  // The credential public key as a COSE_Key map as defined in Section 7
-  // of https://tools.ietf.org/html/rfc8152.
-  const std::vector<uint8_t>& cose_key_bytes() const;
+  // cose_key_bytes contains the credential public key as a COSE_Key map as
+  // defined in Section 7 of https://tools.ietf.org/html/rfc8152.
+  const std::vector<uint8_t> cose_key_bytes;
 
-  // der_bytes returns an ASN.1, DER, SubjectPublicKeyInfo describing this
+  // der_bytes contains an ASN.1, DER, SubjectPublicKeyInfo describing this
   // public key, if possible. (WebAuthn can negotiate the use of unknown
   // public-key algorithms so not all public keys can be transformed into SPKI
   // form.)
-  const base::Optional<std::vector<uint8_t>>& der_bytes() const;
+  const base::Optional<std::vector<uint8_t>> der_bytes;
 
  private:
-  const int32_t algorithm_;
-  std::vector<uint8_t> cbor_bytes_;
-  base::Optional<std::vector<uint8_t>> der_bytes_;
-
   DISALLOW_COPY_AND_ASSIGN(PublicKey);
 };
 
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc
index af61196..94917d2 100644
--- a/device/fido/virtual_ctap2_device.cc
+++ b/device/fido/virtual_ctap2_device.cc
@@ -842,7 +842,7 @@
   }
 
   // Our key handles are simple hashes of the public key.
-  const auto key_handle = crypto::SHA256Hash(public_key->cose_key_bytes());
+  const auto key_handle = crypto::SHA256Hash(public_key->cose_key_bytes);
 
   base::Optional<cbor::Value> extensions;
   cbor::Value::MapValue extensions_map;
@@ -1934,7 +1934,7 @@
                                              registration.first)));
 
     base::Optional<cbor::Value> cose_key = cbor::Reader::Read(
-        registration.second.private_key->GetPublicKey()->cose_key_bytes());
+        registration.second.private_key->GetPublicKey()->cose_key_bytes);
     response_map.emplace(
         static_cast<int>(CredentialManagementResponseKey::kPublicKey),
         cose_key->GetMap());
diff --git a/device/fido/virtual_fido_device.h b/device/fido/virtual_fido_device.h
index d027832b..e396771 100644
--- a/device/fido/virtual_fido_device.h
+++ b/device/fido/virtual_fido_device.h
@@ -32,7 +32,7 @@
 
 namespace device {
 
-class PublicKey;
+struct PublicKey;
 
 constexpr size_t kMaxPinRetries = 8;
 
diff --git a/device/vr/android/gvr/gvr_device_provider.cc b/device/vr/android/gvr/gvr_device_provider.cc
index 7e967c1..b5fd986 100644
--- a/device/vr/android/gvr/gvr_device_provider.cc
+++ b/device/vr/android/gvr/gvr_device_provider.cc
@@ -17,6 +17,7 @@
 void GvrDeviceProvider::Initialize(
     base::RepeatingCallback<void(mojom::XRDeviceId,
                                  mojom::VRDisplayInfoPtr,
+                                 mojom::XRDeviceDataPtr,
                                  mojo::PendingRemote<mojom::XRRuntime>)>
         add_device_callback,
     base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
@@ -32,6 +33,7 @@
   }
   if (vr_device_) {
     add_device_callback.Run(vr_device_->GetId(), vr_device_->GetVRDisplayInfo(),
+                            vr_device_->GetDeviceData(),
                             vr_device_->BindXRRuntime());
   }
   initialized_ = true;
diff --git a/device/vr/android/gvr/gvr_device_provider.h b/device/vr/android/gvr/gvr_device_provider.h
index dcf579f6..aed9b3ab 100644
--- a/device/vr/android/gvr/gvr_device_provider.h
+++ b/device/vr/android/gvr/gvr_device_provider.h
@@ -24,6 +24,7 @@
   void Initialize(
       base::RepeatingCallback<void(mojom::XRDeviceId,
                                    mojom::VRDisplayInfoPtr,
+                                   mojom::XRDeviceDataPtr,
                                    mojo::PendingRemote<mojom::XRRuntime>)>
           add_device_callback,
       base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
diff --git a/device/vr/openxr/openxr_device.cc b/device/vr/openxr/openxr_device.cc
index 2b7a8cf0..7e2c2cc 100644
--- a/device/vr/openxr/openxr_device.cc
+++ b/device/vr/openxr/openxr_device.cc
@@ -7,8 +7,10 @@
 #include <string>
 
 #include "base/bind_helpers.h"
+#include "build/build_config.h"
 #include "device/vr/openxr/openxr_api_wrapper.h"
 #include "device/vr/openxr/openxr_render_loop.h"
+#include "device/vr/openxr/openxr_statics.h"
 #include "device/vr/util/transform_utils.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 
@@ -53,10 +55,17 @@
 
 }  // namespace
 
-OpenXrDevice::OpenXrDevice()
+// OpenXrDevice must not take ownership of the OpenXrStatics passed in.
+// The OpenXrStatics object is owned by IsolatedXRRuntimeProvider.
+OpenXrDevice::OpenXrDevice(OpenXrStatics* openxr_statics)
     : VRDeviceBase(device::mojom::XRDeviceId::OPENXR_DEVICE_ID),
       weak_ptr_factory_(this) {
-  SetVRDisplayInfo(CreateFakeVRDisplayInfo(GetId()));
+  mojom::VRDisplayInfoPtr display_info = CreateFakeVRDisplayInfo(GetId());
+  SetVRDisplayInfo(std::move(display_info));
+
+#if defined(OS_WIN)
+  SetLuid(openxr_statics->GetLuid());
+#endif
 }
 
 OpenXrDevice::~OpenXrDevice() {
diff --git a/device/vr/openxr/openxr_device.h b/device/vr/openxr/openxr_device.h
index 5b1d1dc..237223a 100644
--- a/device/vr/openxr/openxr_device.h
+++ b/device/vr/openxr/openxr_device.h
@@ -18,13 +18,14 @@
 namespace device {
 
 class OpenXrRenderLoop;
+class OpenXrStatics;
 
 class DEVICE_VR_EXPORT OpenXrDevice
     : public VRDeviceBase,
       public mojom::XRSessionController,
       public mojom::XRCompositorHost {
  public:
-  OpenXrDevice();
+  OpenXrDevice(OpenXrStatics* openxr_statics);
   ~OpenXrDevice() override;
 
   // VRDeviceBase
diff --git a/device/vr/openxr/openxr_statics.cc b/device/vr/openxr/openxr_statics.cc
index 4b6096f..c10611cb 100644
--- a/device/vr/openxr/openxr_statics.cc
+++ b/device/vr/openxr/openxr_statics.cc
@@ -31,4 +31,25 @@
          XR_SUCCEEDED(CreateInstance(&instance_));
 }
 
-}  // namespace device
\ No newline at end of file
+#if defined(OS_WIN)
+// Returns the LUID of the adapter the OpenXR runtime is on. Returns {0, 0} if
+// the LUID could not be determined.
+LUID OpenXrStatics::GetLuid() {
+  if (!IsApiAvailable())
+    return {0, 0};
+
+  XrSystemId system;
+  if (XR_FAILED(GetSystem(instance_, &system)))
+    return {0, 0};
+
+  XrGraphicsRequirementsD3D11KHR graphics_requirements = {
+      XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
+  if (XR_FAILED(xrGetD3D11GraphicsRequirementsKHR(instance_, system,
+                                                  &graphics_requirements)))
+    return {0, 0};
+
+  return graphics_requirements.adapterLuid;
+}
+#endif
+
+}  // namespace device
diff --git a/device/vr/openxr/openxr_statics.h b/device/vr/openxr/openxr_statics.h
index 0b41f576..4663b8a 100644
--- a/device/vr/openxr/openxr_statics.h
+++ b/device/vr/openxr/openxr_statics.h
@@ -8,6 +8,7 @@
 #include <d3d11.h>
 #include <memory>
 
+#include "build/build_config.h"
 #include "device/vr/vr_export.h"
 #include "third_party/openxr/src/include/openxr/openxr.h"
 #include "third_party/openxr/src/include/openxr/openxr_platform.h"
@@ -22,10 +23,14 @@
   bool IsHardwareAvailable();
   bool IsApiAvailable();
 
+#if defined(OS_WIN)
+  LUID GetLuid();
+#endif
+
  private:
   XrInstance instance_;
 };
 
 }  // namespace device
 
-#endif  // DEVICE_VR_WINDOWS_MIXED_REALITY_MIXED_REALITY_STATICS_H_
\ No newline at end of file
+#endif  // DEVICE_VR_WINDOWS_MIXED_REALITY_MIXED_REALITY_STATICS_H_
diff --git a/device/vr/orientation/orientation_device_provider.cc b/device/vr/orientation/orientation_device_provider.cc
index 7745bc51..785f4328 100644
--- a/device/vr/orientation/orientation_device_provider.cc
+++ b/device/vr/orientation/orientation_device_provider.cc
@@ -22,13 +22,14 @@
 void VROrientationDeviceProvider::Initialize(
     base::RepeatingCallback<void(mojom::XRDeviceId,
                                  mojom::VRDisplayInfoPtr,
+                                 mojom::XRDeviceDataPtr,
                                  mojo::PendingRemote<mojom::XRRuntime>)>
         add_device_callback,
     base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
     base::OnceClosure initialization_complete) {
   if (device_ && device_->IsAvailable()) {
     add_device_callback.Run(device_->GetId(), device_->GetVRDisplayInfo(),
-                            device_->BindXRRuntime());
+                            device_->GetDeviceData(), device_->BindXRRuntime());
     return;
   }
 
@@ -55,6 +56,7 @@
   // If the device successfully connected to the orientation APIs, provide it.
   if (device_->IsAvailable()) {
     add_device_callback_.Run(device_->GetId(), device_->GetVRDisplayInfo(),
+                             device_->GetDeviceData(),
                              device_->BindXRRuntime());
   }
 
diff --git a/device/vr/orientation/orientation_device_provider.h b/device/vr/orientation/orientation_device_provider.h
index 1d6e814..6d988f1c 100644
--- a/device/vr/orientation/orientation_device_provider.h
+++ b/device/vr/orientation/orientation_device_provider.h
@@ -28,6 +28,7 @@
   void Initialize(
       base::RepeatingCallback<void(mojom::XRDeviceId,
                                    mojom::VRDisplayInfoPtr,
+                                   mojom::XRDeviceDataPtr,
                                    mojo::PendingRemote<mojom::XRRuntime>)>
           add_device_callback,
       base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
@@ -46,6 +47,7 @@
 
   base::RepeatingCallback<void(mojom::XRDeviceId,
                                mojom::VRDisplayInfoPtr,
+                               mojom::XRDeviceDataPtr,
                                mojo::PendingRemote<mojom::XRRuntime>)>
       add_device_callback_;
   base::OnceClosure initialized_callback_;
diff --git a/device/vr/orientation/orientation_device_provider_unittest.cc b/device/vr/orientation/orientation_device_provider_unittest.cc
index 7f257ce..f40c5f35 100644
--- a/device/vr/orientation/orientation_device_provider_unittest.cc
+++ b/device/vr/orientation/orientation_device_provider_unittest.cc
@@ -84,10 +84,12 @@
 
   base::RepeatingCallback<void(device::mojom::XRDeviceId,
                                mojom::VRDisplayInfoPtr,
+                               mojom::XRDeviceDataPtr,
                                mojo::PendingRemote<mojom::XRRuntime> device)>
   DeviceAndIdCallbackFailIfCalled() {
     return base::BindRepeating(
         [](device::mojom::XRDeviceId id, mojom::VRDisplayInfoPtr,
+           mojom::XRDeviceDataPtr,
            mojo::PendingRemote<mojom::XRRuntime> device) { FAIL(); });
   }
 
@@ -98,14 +100,16 @@
 
   base::RepeatingCallback<void(device::mojom::XRDeviceId,
                                mojom::VRDisplayInfoPtr,
+                               mojom::XRDeviceDataPtr,
                                mojo::PendingRemote<mojom::XRRuntime> device)>
   DeviceAndIdCallbackMustBeCalled(base::RunLoop* loop) {
     return base::BindRepeating(
         [](base::OnceClosure quit_closure, device::mojom::XRDeviceId id,
-           mojom::VRDisplayInfoPtr info,
+           mojom::VRDisplayInfoPtr info, mojom::XRDeviceDataPtr data,
            mojo::PendingRemote<mojom::XRRuntime> device) {
           ASSERT_TRUE(device);
           ASSERT_TRUE(info);
+          ASSERT_TRUE(data);
           std::move(quit_closure).Run();
         },
         loop->QuitClosure());
diff --git a/device/vr/public/cpp/vr_device_provider.h b/device/vr/public/cpp/vr_device_provider.h
index 10c3460..f3ecf6a 100644
--- a/device/vr/public/cpp/vr_device_provider.h
+++ b/device/vr/public/cpp/vr_device_provider.h
@@ -23,6 +23,7 @@
   virtual void Initialize(
       base::RepeatingCallback<void(mojom::XRDeviceId id,
                                    mojom::VRDisplayInfoPtr,
+                                   mojom::XRDeviceDataPtr,
                                    mojo::PendingRemote<mojom::XRRuntime>)>
           add_device_callback,
       base::RepeatingCallback<void(mojom::XRDeviceId id)>
diff --git a/device/vr/public/mojom/isolated_xr_service.mojom b/device/vr/public/mojom/isolated_xr_service.mojom
index 787636c9..12235c2 100644
--- a/device/vr/public/mojom/isolated_xr_service.mojom
+++ b/device/vr/public/mojom/isolated_xr_service.mojom
@@ -6,6 +6,8 @@
 
 import "device/vr/public/mojom/browser_test_interfaces.mojom";
 import "device/vr/public/mojom/vr_service.mojom";
+[EnableIf=is_win]
+import "gpu/ipc/common/luid.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 
@@ -110,6 +112,15 @@
   CreateImmersiveOverlay(pending_receiver<ImmersiveOverlay> overlay);
 };
 
+// Information about a particular XR device that is available. All information
+// about an available XR device should be wrapped in this struct.
+// TODO(crbug.com/1090029): Wrap XRDeviceId + VRDisplayInfo in this struct
+struct XRDeviceData {
+  [EnableIf=is_win]
+  // The LUID of the GPU that the device is plugged into.
+  gpu.mojom.Luid? luid;
+};
+
 // Notify the browser process about a set of runtimes.  The browser process
 // implements this interface to be notified about runtime changes from the XR
 // device service.
@@ -118,6 +129,7 @@
   // attached and become available.
   OnDeviceAdded(pending_remote<XRRuntime> runtime,
       pending_remote<XRCompositorHost> compositor_host,
+      XRDeviceData device_data,
       device.mojom.XRDeviceId device_id);
 
   // Called when runtimes become unavailable - for example if the hardware is
diff --git a/device/vr/test/fake_vr_device_provider.cc b/device/vr/test/fake_vr_device_provider.cc
index ee7da86..93fafdf 100644
--- a/device/vr/test/fake_vr_device_provider.cc
+++ b/device/vr/test/fake_vr_device_provider.cc
@@ -17,9 +17,9 @@
   VRDeviceBase* device_base = static_cast<VRDeviceBase*>(device.get());
   devices_.push_back(std::move(device));
   if (initialized_)
-    add_device_callback_.Run(device_base->GetId(),
-                             device_base->GetVRDisplayInfo(),
-                             device_base->BindXRRuntime());
+    add_device_callback_.Run(
+        device_base->GetId(), device_base->GetVRDisplayInfo(),
+        device_base->GetDeviceData(), device_base->BindXRRuntime());
 }
 
 void FakeVRDeviceProvider::RemoveDevice(mojom::XRDeviceId device_id) {
@@ -36,6 +36,7 @@
 void FakeVRDeviceProvider::Initialize(
     base::RepeatingCallback<void(mojom::XRDeviceId,
                                  mojom::VRDisplayInfoPtr,
+                                 mojom::XRDeviceDataPtr,
                                  mojo::PendingRemote<mojom::XRRuntime>)>
         add_device_callback,
     base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
@@ -45,9 +46,9 @@
 
   for (std::unique_ptr<VRDeviceBase>& device : devices_) {
     auto* device_base = static_cast<VRDeviceBase*>(device.get());
-    add_device_callback_.Run(device_base->GetId(),
-                             device_base->GetVRDisplayInfo(),
-                             device_base->BindXRRuntime());
+    add_device_callback_.Run(
+        device_base->GetId(), device_base->GetVRDisplayInfo(),
+        device_base->GetDeviceData(), device_base->BindXRRuntime());
   }
   initialized_ = true;
   std::move(initialization_complete).Run();
diff --git a/device/vr/test/fake_vr_device_provider.h b/device/vr/test/fake_vr_device_provider.h
index 08887a2..e1b3a9e 100644
--- a/device/vr/test/fake_vr_device_provider.h
+++ b/device/vr/test/fake_vr_device_provider.h
@@ -28,6 +28,7 @@
   void Initialize(
       base::RepeatingCallback<void(mojom::XRDeviceId,
                                    mojom::VRDisplayInfoPtr,
+                                   mojom::XRDeviceDataPtr,
                                    mojo::PendingRemote<mojom::XRRuntime>)>
           add_device_callback,
       base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback,
@@ -39,6 +40,7 @@
   bool initialized_;
   base::RepeatingCallback<void(mojom::XRDeviceId,
                                mojom::VRDisplayInfoPtr,
+                               mojom::XRDeviceDataPtr,
                                mojo::PendingRemote<mojom::XRRuntime>)>
       add_device_callback_;
   base::RepeatingCallback<void(mojom::XRDeviceId)> remove_device_callback_;
diff --git a/device/vr/vr_device_base.cc b/device/vr/vr_device_base.cc
index 61a64046..9d113bb6 100644
--- a/device/vr/vr_device_base.cc
+++ b/device/vr/vr_device_base.cc
@@ -19,6 +19,10 @@
   return id_;
 }
 
+mojom::XRDeviceDataPtr VRDeviceBase::GetDeviceData() const {
+  return device_data_.Clone();
+}
+
 void VRDeviceBase::PauseTracking() {}
 
 void VRDeviceBase::ResumeTracking() {}
@@ -75,6 +79,15 @@
     listener_->OnVisibilityStateChanged(visibility_state);
 }
 
+#if defined(OS_WIN)
+void VRDeviceBase::SetLuid(const LUID& luid) {
+  if (luid.HighPart != 0 || luid.LowPart != 0) {
+    // Only set the LUID if it exists and is nonzero.
+    device_data_.luid = base::make_optional<LUID>(luid);
+  }
+}
+#endif
+
 mojo::PendingRemote<mojom::XRRuntime> VRDeviceBase::BindXRRuntime() {
   DVLOG(2) << __func__;
   return runtime_receiver_.BindNewPipeAndPassRemote();
diff --git a/device/vr/vr_device_base.h b/device/vr/vr_device_base.h
index 7a33f90..c16a63c 100644
--- a/device/vr/vr_device_base.h
+++ b/device/vr/vr_device_base.h
@@ -11,6 +11,7 @@
 #include "base/callback.h"
 #include "base/component_export.h"
 #include "base/macros.h"
+#include "build/build_config.h"
 #include "device/vr/public/mojom/vr_service.mojom.h"
 #include "device/vr/vr_device.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
@@ -35,6 +36,7 @@
   void ShutdownSession(mojom::XRRuntime::ShutdownSessionCallback) override;
 
   device::mojom::XRDeviceId GetId() const;
+  device::mojom::XRDeviceDataPtr GetDeviceData() const;
 
   bool HasExclusiveSession();
 
@@ -61,6 +63,9 @@
   bool IsPresenting() { return presenting_; }  // Exposed for test.
   void SetVRDisplayInfo(mojom::VRDisplayInfoPtr display_info);
   void OnVisibilityStateChanged(mojom::XRVisibilityState visibility_state);
+#if defined(OS_WIN)
+  void SetLuid(const LUID& luid);
+#endif
 
   mojom::VRDisplayInfoPtr display_info_;
 
@@ -73,6 +78,8 @@
 
   device::mojom::XRDeviceId id_;
 
+  device::mojom::XRDeviceData device_data_;
+
   mojo::Receiver<mojom::XRRuntime> runtime_receiver_{this};
 
   DISALLOW_COPY_AND_ASSIGN(VRDeviceBase);
diff --git a/docs/gpu/gpu_testing.md b/docs/gpu/gpu_testing.md
index a2d9b204..2d6b0f2 100644
--- a/docs/gpu/gpu_testing.md
+++ b/docs/gpu/gpu_testing.md
@@ -628,6 +628,9 @@
 *   A change to Blink's memory purging primitive which caused intermittent
     timeouts of WebGL conformance tests on all platforms ([Issue
     840988](http://crbug.com/840988)).
+*   Screen DPI being inconsistent across seemingly identical Linux machines,
+    causing the Maps pixel test to flakily produce incorrectly sized images
+    ([Issue 1091410](https://crbug.com/1091410)).
 
 If you notice flaky test failures either on the GPU waterfalls or try servers,
 please file bugs right away with the component Internals>GPU>Testing and
diff --git a/docs/webui_explainer.md b/docs/webui_explainer.md
index 75d46bf..e3dc1a0 100644
--- a/docs/webui_explainer.md
+++ b/docs/webui_explainer.md
@@ -583,7 +583,7 @@
 
 Older WebUI code exposed public methods for event notification, similar to how
 responses to [chrome.send()](#chrome_send) used to work. They both
-resulted in global namespace polution, but it was additionally hard to stop
+resulted in global namespace pollution, but it was additionally hard to stop
 listening for events in some cases. **cr.addWebUIListener** is preferred in new
 code.
 
diff --git a/extensions/browser/api/declarative/rules_registry_service.cc b/extensions/browser/api/declarative/rules_registry_service.cc
index 9e76ebf..19f4de0 100644
--- a/extensions/browser/api/declarative/rules_registry_service.cc
+++ b/extensions/browser/api/declarative/rules_registry_service.cc
@@ -42,7 +42,7 @@
 
 RulesRegistryService::RulesRegistryService(content::BrowserContext* context)
     : current_rules_registry_id_(kDefaultRulesRegistryID),
-      content_rules_registry_(NULL),
+      content_rules_registry_(nullptr),
       browser_context_(context) {
   if (browser_context_) {
     extension_registry_observer_.Add(ExtensionRegistry::Get(browser_context_));
diff --git a/extensions/browser/api/networking_private/networking_private_linux.cc b/extensions/browser/api/networking_private/networking_private_linux.cc
index 8eaa75db..0a0bcd94 100644
--- a/extensions/browser/api/networking_private/networking_private_linux.cc
+++ b/extensions/browser/api/networking_private/networking_private_linux.cc
@@ -135,7 +135,7 @@
 }  // namespace
 
 NetworkingPrivateLinux::NetworkingPrivateLinux()
-    : dbus_thread_("Networking Private DBus"), network_manager_proxy_(NULL) {
+    : dbus_thread_("Networking Private DBus"), network_manager_proxy_(nullptr) {
   base::Thread::Options thread_options(base::MessagePumpType::IO, 0);
 
   dbus_thread_.StartWithOptions(thread_options);
diff --git a/extensions/browser/api/system_storage/system_storage_eject_apitest.cc b/extensions/browser/api/system_storage/system_storage_eject_apitest.cc
index 5fb7179..d87a81a 100644
--- a/extensions/browser/api/system_storage/system_storage_eject_apitest.cc
+++ b/extensions/browser/api/system_storage/system_storage_eject_apitest.cc
@@ -34,7 +34,7 @@
 
 class SystemStorageEjectApiTest : public extensions::ShellApiTest {
  public:
-  SystemStorageEjectApiTest() : monitor_(NULL) {}
+  SystemStorageEjectApiTest() : monitor_(nullptr) {}
   ~SystemStorageEjectApiTest() override {}
 
  protected:
diff --git a/extensions/browser/api/test/test_api.cc b/extensions/browser/api/test/test_api.cc
index 01e9d167..8458efa2f 100644
--- a/extensions/browser/api/test/test_api.cc
+++ b/extensions/browser/api/test/test_api.cc
@@ -129,7 +129,7 @@
 }
 
 TestGetConfigFunction::TestConfigState::TestConfigState()
-    : config_state_(NULL) {}
+    : config_state_(nullptr) {}
 
 // static
 TestGetConfigFunction::TestConfigState*
diff --git a/extensions/browser/updater/extension_downloader.cc b/extensions/browser/updater/extension_downloader.cc
index 0f15ce5..6d86382 100644
--- a/extensions/browser/updater/extension_downloader.cc
+++ b/extensions/browser/updater/extension_downloader.cc
@@ -1300,8 +1300,6 @@
       RETRY_HISTOGRAM("CrxFetchFailure",
                       extensions_queue_.active_request_failure_count(),
                       url);
-      // net_error is 0 (net::OK) or negative. (See net/base/net_errors.h)
-      base::UmaHistogramSparse("Extensions.CrxFetchError", -net_error);
       delegate_->OnExtensionDownloadStageChanged(
           id, ExtensionDownloaderDelegate::Stage::FINISHED);
       ExtensionDownloaderDelegate::FailureData failure_data(
diff --git a/extensions/browser/updater/update_data_provider.cc b/extensions/browser/updater/update_data_provider.cc
index 1759d68..d2617101 100644
--- a/extensions/browser/updater/update_data_provider.cc
+++ b/extensions/browser/updater/update_data_provider.cc
@@ -26,6 +26,7 @@
 #include "extensions/browser/install/crx_install_error.h"
 #include "extensions/browser/updater/manifest_fetch_data.h"
 #include "extensions/common/extension.h"
+#include "extensions/common/extension_urls.h"
 #include "extensions/common/verifier_formats.h"
 
 namespace extensions {
@@ -108,9 +109,11 @@
       crx_component->fingerprint = extension->DifferentialFingerprint();
     }
     crx_component->allows_background_download = false;
-    crx_component->requires_network_encryption = true;
+    bool allow_dev = extension_urls::GetWebstoreUpdateUrl() !=
+                     extension_urls::GetDefaultWebstoreUpdateUrl();
+    crx_component->requires_network_encryption = !allow_dev;
     crx_component->crx_format_requirement =
-        extension->from_webstore() ? GetWebstoreVerifierFormat(false)
+        extension->from_webstore() ? GetWebstoreVerifierFormat(allow_dev)
                                    : GetPolicyVerifierFormat();
     crx_component->installer = base::MakeRefCounted<ExtensionInstaller>(
         id, extension->path(), install_immediately,
diff --git a/extensions/browser/updater/update_service.cc b/extensions/browser/updater/update_service.cc
index e0dca18..2c57317a 100644
--- a/extensions/browser/updater/update_service.cc
+++ b/extensions/browser/updater/update_service.cc
@@ -87,26 +87,19 @@
 }
 
 bool UpdateService::CanUpdate(const std::string& extension_id) const {
-  // It's possible to change Webstore update URL from command line (through
-  // apps-gallery-update-url command line switch). When Webstore update URL is
-  // different the default Webstore update URL, we won't support updating
-  // extensions through UpdateService.
-  if (extension_urls::GetDefaultWebstoreUpdateUrl() !=
-      extension_urls::GetWebstoreUpdateUrl())
-    return false;
-
   // Won't update extensions with empty IDs.
   if (extension_id.empty())
     return false;
 
   // We can only update extensions that have been installed on the system.
-  // Furthermore, we can only update extensions that were installed from the
-  // webstore or extensions with empty update URLs not converted from user
-  // scripts.
   const ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
   const Extension* extension = registry->GetInstalledExtension(extension_id);
   if (extension == nullptr)
     return false;
+
+  // Furthermore, we can only update extensions that were installed from the
+  // default webstore or extensions with empty update URLs not converted from
+  // user scripts.
   const GURL& update_url = ManifestURL::GetUpdateURL(extension);
   if (update_url.is_empty())
     return !extension->converted_from_user_script();
diff --git a/extensions/browser/updater/update_service_unittest.cc b/extensions/browser/updater/update_service_unittest.cc
index f6719ed5..8b17ff6a 100644
--- a/extensions/browser/updater/update_service_unittest.cc
+++ b/extensions/browser/updater/update_service_unittest.cc
@@ -745,7 +745,7 @@
     auto* command_line = base::CommandLine::ForCurrentProcess();
     // Note: |offstore_extension_|'s update url is the same.
     command_line->AppendSwitchASCII("apps-gallery-update-url",
-                                    "http://localhost/test/updates.xml");
+                                    "http://localhost/test2/updates.xml");
     ExtensionsClient::Get()->InitializeWebStoreUrls(
         base::CommandLine::ForCurrentProcess());
   }
@@ -756,7 +756,7 @@
   EXPECT_TRUE(update_service()->CanUpdate(store_extension_->id()));
   // ... and extensions with empty update URL.
   EXPECT_TRUE(update_service()->CanUpdate(emptyurl_extension_->id()));
-  // It can't update off-store extrensions.
+  // It can't update off-store extensions.
   EXPECT_FALSE(update_service()->CanUpdate(offstore_extension_->id()));
   // ... or extensions with empty update URL converted from user script.
   EXPECT_FALSE(update_service()->CanUpdate(userscript_extension_->id()));
@@ -768,10 +768,10 @@
 
 TEST_F(UpdateServiceCanUpdateFeatureEnabledNonDefaultUpdateUrl,
        UpdateService_CanUpdate) {
-  // Update service cannot update extensions when the default webstore update
-  // url is changed.
+  // Update service can update extensions when the default webstore update url
+  // is changed.
   EXPECT_FALSE(update_service()->CanUpdate(store_extension_->id()));
-  EXPECT_FALSE(update_service()->CanUpdate(emptyurl_extension_->id()));
+  EXPECT_TRUE(update_service()->CanUpdate(emptyurl_extension_->id()));
   EXPECT_FALSE(update_service()->CanUpdate(offstore_extension_->id()));
   EXPECT_FALSE(update_service()->CanUpdate(userscript_extension_->id()));
   EXPECT_FALSE(update_service()->CanUpdate(std::string(32, 'a')));
diff --git a/extensions/browser/url_loader_factory_manager.cc b/extensions/browser/url_loader_factory_manager.cc
index 83f51da..0f2bfc2 100644
--- a/extensions/browser/url_loader_factory_manager.cc
+++ b/extensions/browser/url_loader_factory_manager.cc
@@ -179,7 +179,6 @@
     "999BD8D1929F9ABB817E9368480D93BAB2A0983D",
     "99E06C364BBB2D1F82A9D20BC1645BF21E478259",
     "9C6A186F8D3C5FD0CC8DCF49682FA726BD8A7705",
-    "A04F08A772F1C83B7A14ED29788ACA4F000BBE05",
     "A059797AECB77D24DEB248C3413D99B0D3BF9A8C",
     "A07DA0EDB967D027E3B220208AD085FDC44C3231",
     "A3660FA31A0DBF07C9F80D5342FF215DBC962719",
diff --git a/extensions/test/result_catcher.cc b/extensions/test/result_catcher.cc
index 666208d8..6c690c7d 100644
--- a/extensions/test/result_catcher.cc
+++ b/extensions/test/result_catcher.cc
@@ -11,8 +11,7 @@
 
 namespace extensions {
 
-ResultCatcher::ResultCatcher()
-    : browser_context_restriction_(NULL) {
+ResultCatcher::ResultCatcher() : browser_context_restriction_(nullptr) {
   registrar_.Add(this,
                  extensions::NOTIFICATION_EXTENSION_TEST_PASSED,
                  content::NotificationService::AllSources());
diff --git a/fuchsia/engine/browser/cookie_manager_impl.cc b/fuchsia/engine/browser/cookie_manager_impl.cc
index e7362ae5..d5c05f4 100644
--- a/fuchsia/engine/browser/cookie_manager_impl.cc
+++ b/fuchsia/engine/browser/cookie_manager_impl.cc
@@ -67,12 +67,13 @@
   }
   // Same as above except it takes CookieStatusList instead of just CookieList.
   CookiesIteratorImpl(
-      const std::vector<net::CookieWithStatus>& cookies_with_statuses,
+      const std::vector<net::CookieWithAccessResult>&
+          cookies_with_access_results,
       fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator)
       : CookiesIteratorImpl(std::move(iterator)) {
-    for (const auto& cookie_with_status : cookies_with_statuses) {
-      queued_cookies_[cookie_with_status.cookie.UniqueKey()] =
-          ConvertCanonicalCookie(cookie_with_status.cookie,
+    for (const auto& cookie_with_access_result : cookies_with_access_results) {
+      queued_cookies_[cookie_with_access_result.cookie.UniqueKey()] =
+          ConvertCanonicalCookie(cookie_with_access_result.cookie,
                                  net::CookieChangeCause::INSERTED);
     }
   }
@@ -159,12 +160,12 @@
 
 void OnCookiesAndExcludedReceived(
     fidl::InterfaceRequest<fuchsia::web::CookiesIterator> iterator,
-    const std::vector<net::CookieWithStatus>& cookies_with_statuses,
-    const std::vector<net::CookieWithStatus>& excluded_cookies) {
+    const std::vector<net::CookieWithAccessResult>& cookies_with_access_results,
+    const std::vector<net::CookieWithAccessResult>& excluded_cookies) {
   // Since CookieOptions::set_return_excluded_cookies() is not used when calling
   // the Mojo GetCookieList() API, |excluded_cookies| should be empty.
   DCHECK(excluded_cookies.empty());
-  new CookiesIteratorImpl(cookies_with_statuses, std::move(iterator));
+  new CookiesIteratorImpl(cookies_with_access_results, std::move(iterator));
 }
 
 }  // namespace
diff --git a/gin/array_buffer.cc b/gin/array_buffer.cc
index 891a2e3..124c2f7 100644
--- a/gin/array_buffer.cc
+++ b/gin/array_buffer.cc
@@ -151,10 +151,7 @@
 
 // ArrayBuffer ----------------------------------------------------------------
 
-ArrayBuffer::ArrayBuffer()
-    : bytes_(0),
-      num_bytes_(0) {
-}
+ArrayBuffer::ArrayBuffer() : bytes_(nullptr), num_bytes_(0) {}
 
 ArrayBuffer::ArrayBuffer(v8::Isolate* isolate,
                          v8::Local<v8::ArrayBuffer> array) {
diff --git a/gin/handle.h b/gin/handle.h
index 938e00f8..8a27f91 100644
--- a/gin/handle.h
+++ b/gin/handle.h
@@ -16,7 +16,7 @@
 template<typename T>
 class Handle {
  public:
-  Handle() : object_(NULL) {}
+  Handle() : object_(nullptr) {}
 
   Handle(v8::Local<v8::Value> wrapper, T* object)
     : wrapper_(wrapper),
diff --git a/gin/per_context_data.cc b/gin/per_context_data.cc
index c4e83e5..6c6eda5 100644
--- a/gin/per_context_data.cc
+++ b/gin/per_context_data.cc
@@ -11,8 +11,7 @@
 
 PerContextData::PerContextData(ContextHolder* context_holder,
                                v8::Local<v8::Context> context)
-    : context_holder_(context_holder),
-      runner_(NULL) {
+    : context_holder_(context_holder), runner_(nullptr) {
   context->SetAlignedPointerInEmbedderData(
       kPerContextDataStartIndex + kEmbedderNativeGin, this);
 }
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index a694140..16cb606 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -227,6 +227,7 @@
     "shared_image_backing_factory.h",
     "shared_image_backing_factory_gl_texture.cc",
     "shared_image_backing_factory_gl_texture.h",
+    "shared_image_backing_factory_gl_texture_internal.h",
     "shared_image_factory.cc",
     "shared_image_factory.h",
     "shared_image_manager.cc",
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index a64ed1d..cedc3ac6 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -856,21 +856,15 @@
           shared_context_state_->vk_context_provider(), &flush_info);
       auto result = sk_surface_->flush(
           SkSurface::BackendSurfaceAccess::kPresent, flush_info);
-      DCHECK(gr_context());
-      gr_context()->submit();
       DCHECK(result == GrSemaphoresSubmitted::kYes || end_semaphores_.empty());
       end_semaphores_.clear();
       sk_surface_ = nullptr;
-      if (shared_image_) {
-        scoped_shared_image_write_.reset();
-        shared_image_.reset();
-      } else {
-        sk_surface_for_testing_.reset();
-      }
     }
-    if (gr_context()) {
+    if (gr_context())
       gr_context()->flushAndSubmit();
-    }
+    scoped_shared_image_write_.reset();
+    shared_image_.reset();
+    sk_surface_for_testing_.reset();
   }
 
   copy_tex_image_blit_.reset();
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc
index 4432b92..bd7c709 100644
--- a/gpu/command_buffer/service/service_utils.cc
+++ b/gpu/command_buffer/service/service_utils.cc
@@ -165,8 +165,7 @@
   gpu_preferences.enable_dawn_backend_validation =
       command_line->HasSwitch(switches::kEnableDawnBackendValidation);
   gpu_preferences.gr_context_type = ParseGrContextType();
-  gpu_preferences.use_vulkan = ParseVulkanImplementationName(
-      command_line, gpu_preferences.gr_context_type);
+  gpu_preferences.use_vulkan = ParseVulkanImplementationName(command_line);
   gpu_preferences.disable_vulkan_surface =
       command_line->HasSwitch(switches::kDisableVulkanSurface);
 
@@ -192,8 +191,7 @@
 }
 
 VulkanImplementationName ParseVulkanImplementationName(
-    const base::CommandLine* command_line,
-    GrContextType gr_context_type) {
+    const base::CommandLine* command_line) {
   if (command_line->HasSwitch(switches::kUseVulkan)) {
     auto value = command_line->GetSwitchValueASCII(switches::kUseVulkan);
     if (value.empty() || value == switches::kVulkanImplementationNameNative) {
@@ -202,11 +200,17 @@
       return VulkanImplementationName::kSwiftshader;
     }
   }
-  // If the vulkan implementation is not set from --use-vulkan, the native
-  // vulkan implementation will be used by default.
-  return gr_context_type == GrContextType::kVulkan
-             ? VulkanImplementationName::kNative
-             : VulkanImplementationName::kNone;
+
+  // GrContext is not going to use Vulkan.
+  if (!base::FeatureList::IsEnabled(features::kVulkan))
+    return VulkanImplementationName::kNone;
+
+  // If the vulkan feature is enabled from command line, we will force to use
+  // vulkan even if it is blacklisted.
+  return base::FeatureList::GetInstance()->IsFeatureOverriddenFromCommandLine(
+             features::kVulkan.name, base::FeatureList::OVERRIDE_ENABLE_FEATURE)
+             ? VulkanImplementationName::kForcedNative
+             : VulkanImplementationName::kNative;
 }
 
 }  // namespace gles2
diff --git a/gpu/command_buffer/service/service_utils.h b/gpu/command_buffer/service/service_utils.h
index 76a802e4..e10ff73 100644
--- a/gpu/command_buffer/service/service_utils.h
+++ b/gpu/command_buffer/service/service_utils.h
@@ -40,10 +40,10 @@
 GPU_GLES2_EXPORT GrContextType ParseGrContextType();
 
 // Parse the value of --use-vulkan from the command line. If unspecified and
-// a Vulkan GrContext is going to be used, default to the native implementation.
+// features::kVulkan is enabled (GrContext is going to use vulkan), default to
+// the native implementation.
 GPU_GLES2_EXPORT VulkanImplementationName
-ParseVulkanImplementationName(const base::CommandLine* command_line,
-                              GrContextType gr_context_type);
+ParseVulkanImplementationName(const base::CommandLine* command_line);
 
 }  // namespace gles2
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
index 420d0faf..ea5cd968 100644
--- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
+++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
@@ -25,6 +25,7 @@
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
 #include "gpu/command_buffer/service/shared_image_backing.h"
+#include "gpu/command_buffer/service/shared_image_backing_factory_gl_texture_internal.h"
 #include "gpu/command_buffer/service/shared_image_factory.h"
 #include "gpu/command_buffer/service/shared_image_representation.h"
 #include "gpu/command_buffer/service/skia_utils.h"
@@ -303,516 +304,504 @@
 
 }  // anonymous namespace
 
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageRepresentationGLTextureImpl
+
 // Representation of a SharedImageBackingGLTexture as a GL Texture.
-class SharedImageRepresentationGLTextureImpl
-    : public SharedImageRepresentationGLTexture {
- public:
-  SharedImageRepresentationGLTextureImpl(SharedImageManager* manager,
-                                         SharedImageBacking* backing,
-                                         MemoryTypeTracker* tracker,
-                                         gles2::Texture* texture)
-      : SharedImageRepresentationGLTexture(manager, backing, tracker),
-        texture_(texture) {}
+SharedImageRepresentationGLTextureImpl::SharedImageRepresentationGLTextureImpl(
+    SharedImageManager* manager,
+    SharedImageBacking* backing,
+    MemoryTypeTracker* tracker,
+    gles2::Texture* texture)
+    : SharedImageRepresentationGLTexture(manager, backing, tracker),
+      texture_(texture) {}
 
-  gles2::Texture* GetTexture() override { return texture_; }
+gles2::Texture* SharedImageRepresentationGLTextureImpl::GetTexture() {
+  return texture_;
+}
 
- private:
-  gles2::Texture* texture_;
-};
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageRepresentationGLTexturePassthroughImpl
 
-// Representation of a SharedImageBackingGLTexturePassthrough as a GL
-// TexturePassthrough.
-class SharedImageRepresentationGLTexturePassthroughImpl
-    : public SharedImageRepresentationGLTexturePassthrough {
- public:
-  SharedImageRepresentationGLTexturePassthroughImpl(
-      SharedImageManager* manager,
-      SharedImageBacking* backing,
-      MemoryTypeTracker* tracker,
-      scoped_refptr<gles2::TexturePassthrough> texture_passthrough)
-      : SharedImageRepresentationGLTexturePassthrough(manager,
-                                                      backing,
-                                                      tracker),
-        texture_passthrough_(std::move(texture_passthrough)) {}
+SharedImageRepresentationGLTexturePassthroughImpl::
+    SharedImageRepresentationGLTexturePassthroughImpl(
+        SharedImageManager* manager,
+        SharedImageBacking* backing,
+        MemoryTypeTracker* tracker,
+        scoped_refptr<gles2::TexturePassthrough> texture_passthrough)
+    : SharedImageRepresentationGLTexturePassthrough(manager, backing, tracker),
+      texture_passthrough_(std::move(texture_passthrough)) {}
 
-  const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
-      override {
-    return texture_passthrough_;
+SharedImageRepresentationGLTexturePassthroughImpl::
+    ~SharedImageRepresentationGLTexturePassthroughImpl() = default;
+
+const scoped_refptr<gles2::TexturePassthrough>&
+SharedImageRepresentationGLTexturePassthroughImpl::GetTexturePassthrough() {
+  return texture_passthrough_;
+}
+
+void SharedImageRepresentationGLTexturePassthroughImpl::EndAccess() {
+  GLenum target = texture_passthrough_->target();
+  gl::GLImage* image = texture_passthrough_->GetLevelImage(target, 0);
+  if (!image)
+    return;
+  if (image->ShouldBindOrCopy() == gl::GLImage::BIND) {
+    gl::ScopedTextureBinder binder(target, texture_passthrough_->service_id());
+    image->ReleaseTexImage(target);
+    image->BindTexImage(target);
   }
+}
 
-  void EndAccess() override {
-    GLenum target = texture_passthrough_->target();
-    gl::GLImage* image = texture_passthrough_->GetLevelImage(target, 0);
-    if (!image)
-      return;
-    if (image->ShouldBindOrCopy() == gl::GLImage::BIND) {
-      gl::ScopedTextureBinder binder(target,
-                                     texture_passthrough_->service_id());
-      image->ReleaseTexImage(target);
-      image->BindTexImage(target);
-    }
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageBackingWithReadAccess
+
+SharedImageBackingWithReadAccess::SharedImageBackingWithReadAccess(
+    const Mailbox& mailbox,
+    viz::ResourceFormat format,
+    const gfx::Size& size,
+    const gfx::ColorSpace& color_space,
+    uint32_t usage,
+    size_t estimated_size,
+    bool is_thread_safe)
+    : SharedImageBacking(mailbox,
+                         format,
+                         size,
+                         color_space,
+                         usage,
+                         estimated_size,
+                         is_thread_safe) {}
+
+SharedImageBackingWithReadAccess::~SharedImageBackingWithReadAccess() = default;
+
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageRepresentationSkiaImpl
+
+SharedImageRepresentationSkiaImpl::SharedImageRepresentationSkiaImpl(
+    SharedImageManager* manager,
+    SharedImageBackingWithReadAccess* backing,
+    scoped_refptr<SharedContextState> context_state,
+    sk_sp<SkPromiseImageTexture> cached_promise_texture,
+    MemoryTypeTracker* tracker,
+    GLenum target,
+    GLuint service_id)
+    : SharedImageRepresentationSkia(manager, backing, tracker),
+      context_state_(std::move(context_state)),
+      promise_texture_(cached_promise_texture) {
+  if (!promise_texture_) {
+    GrBackendTexture backend_texture;
+    GetGrBackendTexture(context_state_->feature_info(), target, size(),
+                        service_id, format(), &backend_texture);
+    promise_texture_ = SkPromiseImageTexture::Make(backend_texture);
   }
-
- private:
-  scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
-};
-
-class SharedImageBackingWithReadAccess : public SharedImageBacking {
- public:
-  SharedImageBackingWithReadAccess(const Mailbox& mailbox,
-                                   viz::ResourceFormat format,
-                                   const gfx::Size& size,
-                                   const gfx::ColorSpace& color_space,
-                                   uint32_t usage,
-                                   size_t estimated_size,
-                                   bool is_thread_safe)
-      : SharedImageBacking(mailbox,
-                           format,
-                           size,
-                           color_space,
-                           usage,
-                           estimated_size,
-                           is_thread_safe) {}
-  ~SharedImageBackingWithReadAccess() override = default;
-
-  virtual void BeginReadAccess() = 0;
-};
-
-class SharedImageRepresentationSkiaImpl : public SharedImageRepresentationSkia {
- public:
-  SharedImageRepresentationSkiaImpl(
-      SharedImageManager* manager,
-      SharedImageBackingWithReadAccess* backing,
-      scoped_refptr<SharedContextState> context_state,
-      sk_sp<SkPromiseImageTexture> cached_promise_texture,
-      MemoryTypeTracker* tracker,
-      GLenum target,
-      GLuint service_id)
-      : SharedImageRepresentationSkia(manager, backing, tracker),
-        context_state_(std::move(context_state)),
-        promise_texture_(cached_promise_texture) {
-    if (!promise_texture_) {
-      GrBackendTexture backend_texture;
-      GetGrBackendTexture(context_state_->feature_info(), target, size(),
-                          service_id, format(), &backend_texture);
-      promise_texture_ = SkPromiseImageTexture::Make(backend_texture);
-    }
 #if DCHECK_IS_ON()
     context_ = gl::GLContext::GetCurrent();
 #endif
+}
+
+SharedImageRepresentationSkiaImpl::~SharedImageRepresentationSkiaImpl() {
+  if (write_surface_) {
+    DLOG(ERROR) << "SharedImageRepresentationSkia was destroyed while still "
+                << "open for write access.";
   }
+}
 
-  ~SharedImageRepresentationSkiaImpl() override {
-    if (write_surface_) {
-      DLOG(ERROR) << "SharedImageRepresentationSkia was destroyed while still "
-                  << "open for write access.";
-    }
+sk_sp<SkSurface> SharedImageRepresentationSkiaImpl::BeginWriteAccess(
+    int final_msaa_count,
+    const SkSurfaceProps& surface_props,
+    std::vector<GrBackendSemaphore>* begin_semaphores,
+    std::vector<GrBackendSemaphore>* end_semaphores) {
+  CheckContext();
+  if (write_surface_)
+    return nullptr;
+
+  if (!promise_texture_) {
+    return nullptr;
   }
+  SkColorType sk_color_type = viz::ResourceFormatToClosestSkColorType(
+      /*gpu_compositing=*/true, format());
+  auto surface = SkSurface::MakeFromBackendTexture(
+      context_state_->gr_context(), promise_texture_->backendTexture(),
+      kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type,
+      backing()->color_space().ToSkColorSpace(), &surface_props);
+  write_surface_ = surface.get();
+  return surface;
+}
 
-  sk_sp<SkSurface> BeginWriteAccess(
-      int final_msaa_count,
-      const SkSurfaceProps& surface_props,
-      std::vector<GrBackendSemaphore>* begin_semaphores,
-      std::vector<GrBackendSemaphore>* end_semaphores) override {
-    CheckContext();
-    if (write_surface_)
-      return nullptr;
+void SharedImageRepresentationSkiaImpl::EndWriteAccess(
+    sk_sp<SkSurface> surface) {
+  DCHECK_EQ(surface.get(), write_surface_);
+  DCHECK(surface->unique());
+  CheckContext();
+  // TODO(ericrk): Keep the surface around for re-use.
+  write_surface_ = nullptr;
+}
 
-    if (!promise_texture_) {
-      return nullptr;
-    }
-    SkColorType sk_color_type = viz::ResourceFormatToClosestSkColorType(
-        /*gpu_compositing=*/true, format());
-    auto surface = SkSurface::MakeFromBackendTexture(
-        context_state_->gr_context(), promise_texture_->backendTexture(),
-        kTopLeft_GrSurfaceOrigin, final_msaa_count, sk_color_type,
-        backing()->color_space().ToSkColorSpace(), &surface_props);
-    write_surface_ = surface.get();
-    return surface;
-  }
+sk_sp<SkPromiseImageTexture> SharedImageRepresentationSkiaImpl::BeginReadAccess(
+    std::vector<GrBackendSemaphore>* begin_semaphores,
+    std::vector<GrBackendSemaphore>* end_semaphores) {
+  CheckContext();
+  static_cast<SharedImageBackingWithReadAccess*>(backing())->BeginReadAccess();
+  return promise_texture_;
+}
 
-  void EndWriteAccess(sk_sp<SkSurface> surface) override {
-    DCHECK_EQ(surface.get(), write_surface_);
-    DCHECK(surface->unique());
-    CheckContext();
-    // TODO(ericrk): Keep the surface around for re-use.
-    write_surface_ = nullptr;
-  }
+void SharedImageRepresentationSkiaImpl::EndReadAccess() {
+  // TODO(ericrk): Handle begin/end correctness checks.
+}
 
-  sk_sp<SkPromiseImageTexture> BeginReadAccess(
-      std::vector<GrBackendSemaphore>* begin_semaphores,
-      std::vector<GrBackendSemaphore>* end_semaphores) override {
-    CheckContext();
-    static_cast<SharedImageBackingWithReadAccess*>(backing())
-        ->BeginReadAccess();
-    return promise_texture_;
-  }
+bool SharedImageRepresentationSkiaImpl::SupportsMultipleConcurrentReadAccess() {
+  return true;
+}
 
-  void EndReadAccess() override {
-    // TODO(ericrk): Handle begin/end correctness checks.
-  }
+sk_sp<SkPromiseImageTexture>
+SharedImageRepresentationSkiaImpl::promise_texture() {
+  return promise_texture_;
+}
 
-  bool SupportsMultipleConcurrentReadAccess() override { return true; }
-
-  sk_sp<SkPromiseImageTexture> promise_texture() { return promise_texture_; }
-
- private:
-  void CheckContext() {
+void SharedImageRepresentationSkiaImpl::CheckContext() {
 #if DCHECK_IS_ON()
     DCHECK(gl::GLContext::GetCurrent() == context_);
 #endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageBackingGLTexture
+
+SharedImageBackingGLTexture::SharedImageBackingGLTexture(
+    const Mailbox& mailbox,
+    viz::ResourceFormat format,
+    const gfx::Size& size,
+    const gfx::ColorSpace& color_space,
+    uint32_t usage,
+    gles2::Texture* texture,
+    const UnpackStateAttribs& attribs)
+    : SharedImageBackingWithReadAccess(mailbox,
+                                       format,
+                                       size,
+                                       color_space,
+                                       usage,
+                                       texture->estimated_size(),
+                                       false /* is_thread_safe */),
+      texture_(texture),
+      attribs_(attribs) {
+  DCHECK(texture_);
+  gl::GLImage* image = texture_->GetLevelImage(texture_->target(), 0, nullptr);
+  if (image)
+    native_pixmap_ = image->GetNativePixmap();
+}
+
+SharedImageBackingGLTexture::~SharedImageBackingGLTexture() {
+  DCHECK(texture_);
+  texture_->RemoveLightweightRef(have_context());
+  texture_ = nullptr;
+
+  if (rgb_emulation_texture_) {
+    rgb_emulation_texture_->RemoveLightweightRef(have_context());
+    rgb_emulation_texture_ = nullptr;
   }
+}
 
-  scoped_refptr<SharedContextState> context_state_;
-  sk_sp<SkPromiseImageTexture> promise_texture_;
+gfx::Rect SharedImageBackingGLTexture::ClearedRect() const {
+  return texture_->GetLevelClearedRect(texture_->target(), 0);
+}
 
-  SkSurface* write_surface_ = nullptr;
-#if DCHECK_IS_ON()
-  gl::GLContext* context_;
-#endif
-};
+void SharedImageBackingGLTexture::SetClearedRect(
+    const gfx::Rect& cleared_rect) {
+  texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
+}
 
-// Implementation of SharedImageBacking that creates a GL Texture and stores it
-// as a gles2::Texture. Can be used with the legacy mailbox implementation.
-class SharedImageBackingGLTexture : public SharedImageBackingWithReadAccess {
- public:
-  SharedImageBackingGLTexture(const Mailbox& mailbox,
-                              viz::ResourceFormat format,
-                              const gfx::Size& size,
-                              const gfx::ColorSpace& color_space,
-                              uint32_t usage,
-                              gles2::Texture* texture,
-                              const UnpackStateAttribs& attribs)
-      : SharedImageBackingWithReadAccess(mailbox,
-                                         format,
-                                         size,
-                                         color_space,
-                                         usage,
-                                         texture->estimated_size(),
-                                         false /* is_thread_safe */),
-        texture_(texture),
-        attribs_(attribs) {
-    DCHECK(texture_);
-    gl::GLImage* image =
-        texture_->GetLevelImage(texture_->target(), 0, nullptr);
-    if (image)
-      native_pixmap_ = image->GetNativePixmap();
+void SharedImageBackingGLTexture::Update(
+    std::unique_ptr<gfx::GpuFence> in_fence) {
+  GLenum target = texture_->target();
+  gl::GLApi* api = gl::g_current_gl_context;
+  ScopedRestoreTexture scoped_restore(api, target);
+  api->glBindTextureFn(target, texture_->service_id());
+
+  gles2::Texture::ImageState old_state = gles2::Texture::UNBOUND;
+  gl::GLImage* image = texture_->GetLevelImage(target, 0, &old_state);
+  if (!image)
+    return;
+  if (old_state == gles2::Texture::BOUND)
+    image->ReleaseTexImage(target);
+
+  if (in_fence) {
+    // TODO(dcastagna): Don't wait for the fence if the SharedImage is going
+    // to be scanned out as an HW overlay. Currently we don't know that at
+    // this point and we always bind the image, therefore we need to wait for
+    // the fence.
+    std::unique_ptr<gl::GLFence> egl_fence =
+        gl::GLFence::CreateFromGpuFence(*in_fence.get());
+    egl_fence->ServerWait();
   }
-
-  ~SharedImageBackingGLTexture() override {
-    DCHECK(texture_);
-    texture_->RemoveLightweightRef(have_context());
-    texture_ = nullptr;
-
-    if (rgb_emulation_texture_) {
-      rgb_emulation_texture_->RemoveLightweightRef(have_context());
-      rgb_emulation_texture_ = nullptr;
-    }
+  gles2::Texture::ImageState new_state = gles2::Texture::UNBOUND;
+  if (image->ShouldBindOrCopy() == gl::GLImage::BIND &&
+      image->BindTexImage(target)) {
+    new_state = gles2::Texture::BOUND;
   }
+  if (old_state != new_state)
+    texture_->SetLevelImage(target, 0, image, new_state);
+}
 
-  gfx::Rect ClearedRect() const override {
-    return texture_->GetLevelClearedRect(texture_->target(), 0);
-  }
+bool SharedImageBackingGLTexture::ProduceLegacyMailbox(
+    MailboxManager* mailbox_manager) {
+  DCHECK(texture_);
+  mailbox_manager->ProduceTexture(mailbox(), texture_);
+  return true;
+}
 
-  void SetClearedRect(const gfx::Rect& cleared_rect) override {
-    texture_->SetLevelClearedRect(texture_->target(), 0, cleared_rect);
-  }
+void SharedImageBackingGLTexture::OnMemoryDump(
+    const std::string& dump_name,
+    base::trace_event::MemoryAllocatorDump* dump,
+    base::trace_event::ProcessMemoryDump* pmd,
+    uint64_t client_tracing_id) {
+  // Add a |service_guid| which expresses shared ownership between the
+  // various GPU dumps.
+  auto client_guid = GetSharedImageGUIDForTracing(mailbox());
+  auto service_guid =
+      gl::GetGLTextureServiceGUIDForTracing(texture_->service_id());
+  pmd->CreateSharedGlobalAllocatorDump(service_guid);
+  // TODO(piman): coalesce constant with TextureManager::DumpTextureRef.
+  int importance = 2;  // This client always owns the ref.
 
-  void Update(std::unique_ptr<gfx::GpuFence> in_fence) override {
-    GLenum target = texture_->target();
+  pmd->AddOwnershipEdge(client_guid, service_guid, importance);
+
+  // Dump all sub-levels held by the texture. They will appear below the
+  // main gl/textures/client_X/mailbox_Y dump.
+  texture_->DumpLevelMemory(pmd, client_tracing_id, dump_name);
+}
+
+void SharedImageBackingGLTexture::BeginReadAccess() {
+  GLenum target = texture_->target();
+  gles2::Texture::ImageState old_state = gles2::Texture::UNBOUND;
+  gl::GLImage* image = texture_->GetLevelImage(target, 0, &old_state);
+  if (image && old_state == gpu::gles2::Texture::UNBOUND) {
     gl::GLApi* api = gl::g_current_gl_context;
     ScopedRestoreTexture scoped_restore(api, target);
     api->glBindTextureFn(target, texture_->service_id());
-
-    gles2::Texture::ImageState old_state = gles2::Texture::UNBOUND;
-    gl::GLImage* image = texture_->GetLevelImage(target, 0, &old_state);
-    if (!image)
-      return;
-    if (old_state == gles2::Texture::BOUND)
-      image->ReleaseTexImage(target);
-
-    if (in_fence) {
-      // TODO(dcastagna): Don't wait for the fence if the SharedImage is going
-      // to be scanned out as an HW overlay. Currently we don't know that at
-      // this point and we always bind the image, therefore we need to wait for
-      // the fence.
-      std::unique_ptr<gl::GLFence> egl_fence =
-          gl::GLFence::CreateFromGpuFence(*in_fence.get());
-      egl_fence->ServerWait();
-    }
     gles2::Texture::ImageState new_state = gles2::Texture::UNBOUND;
-    if (image->ShouldBindOrCopy() == gl::GLImage::BIND &&
-        image->BindTexImage(target)) {
-      new_state = gles2::Texture::BOUND;
+    if (image->ShouldBindOrCopy() == gl::GLImage::BIND) {
+      if (image->BindTexImage(target))
+        new_state = gles2::Texture::BOUND;
+    } else {
+      ScopedResetAndRestoreUnpackState scoped_unpack_state(api, attribs_,
+                                                           /*upload=*/true);
+      if (image->CopyTexImage(target))
+        new_state = gles2::Texture::COPIED;
     }
     if (old_state != new_state)
       texture_->SetLevelImage(target, 0, image, new_state);
   }
+}
 
-  bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override {
-    DCHECK(texture_);
-    mailbox_manager->ProduceTexture(mailbox(), texture_);
-    return true;
-  }
+scoped_refptr<gfx::NativePixmap>
+SharedImageBackingGLTexture::GetNativePixmap() {
+  return native_pixmap_;
+}
 
-  void OnMemoryDump(const std::string& dump_name,
-                    base::trace_event::MemoryAllocatorDump* dump,
-                    base::trace_event::ProcessMemoryDump* pmd,
-                    uint64_t client_tracing_id) override {
-    // Add a |service_guid| which expresses shared ownership between the
-    // various GPU dumps.
-    auto client_guid = GetSharedImageGUIDForTracing(mailbox());
-    auto service_guid =
-        gl::GetGLTextureServiceGUIDForTracing(texture_->service_id());
-    pmd->CreateSharedGlobalAllocatorDump(service_guid);
-    // TODO(piman): coalesce constant with TextureManager::DumpTextureRef.
-    int importance = 2;  // This client always owns the ref.
+std::unique_ptr<SharedImageRepresentationGLTexture>
+SharedImageBackingGLTexture::ProduceGLTexture(SharedImageManager* manager,
+                                              MemoryTypeTracker* tracker) {
+  return std::make_unique<SharedImageRepresentationGLTextureImpl>(
+      manager, this, tracker, texture_);
+}
 
-    pmd->AddOwnershipEdge(client_guid, service_guid, importance);
-
-    // Dump all sub-levels held by the texture. They will appear below the
-    // main gl/textures/client_X/mailbox_Y dump.
-    texture_->DumpLevelMemory(pmd, client_tracing_id, dump_name);
-  }
-
-  void BeginReadAccess() override {
+std::unique_ptr<SharedImageRepresentationGLTexture>
+SharedImageBackingGLTexture::ProduceRGBEmulationGLTexture(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
+  if (!rgb_emulation_texture_) {
     GLenum target = texture_->target();
-    gles2::Texture::ImageState old_state = gles2::Texture::UNBOUND;
-    gl::GLImage* image = texture_->GetLevelImage(target, 0, &old_state);
-    if (image && old_state == gpu::gles2::Texture::UNBOUND) {
-      gl::GLApi* api = gl::g_current_gl_context;
-      ScopedRestoreTexture scoped_restore(api, target);
-      api->glBindTextureFn(target, texture_->service_id());
-      gles2::Texture::ImageState new_state = gles2::Texture::UNBOUND;
-      if (image->ShouldBindOrCopy() == gl::GLImage::BIND) {
-        if (image->BindTexImage(target))
-          new_state = gles2::Texture::BOUND;
-      } else {
-        ScopedResetAndRestoreUnpackState scoped_unpack_state(api, attribs_,
-                                                             /*upload=*/true);
-        if (image->CopyTexImage(target))
-          new_state = gles2::Texture::COPIED;
-      }
-      if (old_state != new_state)
-        texture_->SetLevelImage(target, 0, image, new_state);
-    }
-  }
-
-  scoped_refptr<gfx::NativePixmap> GetNativePixmap() override {
-    return native_pixmap_;
-  }
-
- protected:
-  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
-      SharedImageManager* manager,
-      MemoryTypeTracker* tracker) override {
-    return std::make_unique<SharedImageRepresentationGLTextureImpl>(
-        manager, this, tracker, texture_);
-  }
-
-  std::unique_ptr<SharedImageRepresentationGLTexture>
-  ProduceRGBEmulationGLTexture(SharedImageManager* manager,
-                               MemoryTypeTracker* tracker) override {
-    if (!rgb_emulation_texture_) {
-      GLenum target = texture_->target();
-      gl::GLApi* api = gl::g_current_gl_context;
-      ScopedRestoreTexture scoped_restore(api, target);
-
-      // Set to false as this code path is only used on Mac.
-      bool framebuffer_attachment_angle = false;
-      GLuint service_id = MakeTextureAndSetParameters(
-          api, target, framebuffer_attachment_angle);
-
-      gles2::Texture::ImageState image_state = gles2::Texture::BOUND;
-      gl::GLImage* image = texture_->GetLevelImage(target, 0, &image_state);
-      if (!image) {
-        LOG(ERROR) << "Texture is not bound to an image.";
-        return nullptr;
-      }
-
-      DCHECK(image->ShouldBindOrCopy() == gl::GLImage::BIND);
-      const GLenum internal_format = GL_RGB;
-      if (!image->BindTexImageWithInternalformat(target, internal_format)) {
-        LOG(ERROR) << "Failed to bind image to rgb texture.";
-        api->glDeleteTexturesFn(1, &service_id);
-        return nullptr;
-      }
-
-      rgb_emulation_texture_ = new gles2::Texture(service_id);
-      rgb_emulation_texture_->SetLightweightRef();
-      rgb_emulation_texture_->SetTarget(target, 1);
-      rgb_emulation_texture_->sampler_state_.min_filter = GL_LINEAR;
-      rgb_emulation_texture_->sampler_state_.mag_filter = GL_LINEAR;
-      rgb_emulation_texture_->sampler_state_.wrap_s = GL_CLAMP_TO_EDGE;
-      rgb_emulation_texture_->sampler_state_.wrap_t = GL_CLAMP_TO_EDGE;
-
-      GLenum format = gles2::TextureManager::ExtractFormatFromStorageFormat(
-          internal_format);
-      GLenum type =
-          gles2::TextureManager::ExtractTypeFromStorageFormat(internal_format);
-
-      const gles2::Texture::LevelInfo* info = texture_->GetLevelInfo(target, 0);
-      rgb_emulation_texture_->SetLevelInfo(target, 0, internal_format,
-                                           info->width, info->height, 1, 0,
-                                           format, type, info->cleared_rect);
-
-      rgb_emulation_texture_->SetLevelImage(target, 0, image, image_state);
-      rgb_emulation_texture_->SetImmutable(true, false);
-    }
-
-    return std::make_unique<SharedImageRepresentationGLTextureImpl>(
-        manager, this, tracker, rgb_emulation_texture_);
-  }
-
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
-      SharedImageManager* manager,
-      MemoryTypeTracker* tracker,
-      scoped_refptr<SharedContextState> context_state) override {
-    auto result = std::make_unique<SharedImageRepresentationSkiaImpl>(
-        manager, this, std::move(context_state), cached_promise_texture_,
-        tracker, texture_->target(), texture_->service_id());
-    cached_promise_texture_ = result->promise_texture();
-    return result;
-  }
-
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
-      SharedImageManager* manager,
-      MemoryTypeTracker* tracker,
-      WGPUDevice device) override {
-    if (!factory()) {
-      DLOG(ERROR) << "No SharedImageFactory to create a dawn representation.";
-      return nullptr;
-    }
-
-    return ProduceDawnCommon(factory(), manager, tracker, device, this, false);
-  }
-
- private:
-  gles2::Texture* texture_ = nullptr;
-  gles2::Texture* rgb_emulation_texture_ = nullptr;
-  sk_sp<SkPromiseImageTexture> cached_promise_texture_;
-  const UnpackStateAttribs attribs_;
-  scoped_refptr<gfx::NativePixmap> native_pixmap_;
-};
-
-// Implementation of SharedImageBacking that creates a GL Texture and stores it
-// as a gles2::TexturePassthrough. Can be used with the legacy mailbox
-// implementation.
-class SharedImageBackingPassthroughGLTexture
-    : public SharedImageBackingWithReadAccess {
- public:
-  SharedImageBackingPassthroughGLTexture(
-      const Mailbox& mailbox,
-      viz::ResourceFormat format,
-      const gfx::Size& size,
-      const gfx::ColorSpace& color_space,
-      uint32_t usage,
-      scoped_refptr<gles2::TexturePassthrough> passthrough_texture)
-      : SharedImageBackingWithReadAccess(mailbox,
-                                         format,
-                                         size,
-                                         color_space,
-                                         usage,
-                                         passthrough_texture->estimated_size(),
-                                         false /* is_thread_safe */),
-        texture_passthrough_(std::move(passthrough_texture)) {
-    DCHECK(texture_passthrough_);
-  }
-
-  ~SharedImageBackingPassthroughGLTexture() override {
-    DCHECK(texture_passthrough_);
-    if (!have_context())
-      texture_passthrough_->MarkContextLost();
-    texture_passthrough_.reset();
-  }
-
-  gfx::Rect ClearedRect() const override {
-    // This backing is used exclusively with ANGLE which handles clear tracking
-    // internally. Act as though the texture is always cleared.
-    return gfx::Rect(size());
-  }
-
-  void SetClearedRect(const gfx::Rect& cleared_rect) override {}
-
-  void Update(std::unique_ptr<gfx::GpuFence> in_fence) override {
-    GLenum target = texture_passthrough_->target();
     gl::GLApi* api = gl::g_current_gl_context;
     ScopedRestoreTexture scoped_restore(api, target);
-    api->glBindTextureFn(target, texture_passthrough_->service_id());
 
-    gl::GLImage* image = texture_passthrough_->GetLevelImage(target, 0);
-    if (!image)
-      return;
-    image->ReleaseTexImage(target);
-    if (image->ShouldBindOrCopy() == gl::GLImage::BIND)
-      image->BindTexImage(target);
-    else
-      image->CopyTexImage(target);
-  }
+    // Set to false as this code path is only used on Mac.
+    bool framebuffer_attachment_angle = false;
+    GLuint service_id =
+        MakeTextureAndSetParameters(api, target, framebuffer_attachment_angle);
 
-  bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override {
-    DCHECK(texture_passthrough_);
-    mailbox_manager->ProduceTexture(mailbox(), texture_passthrough_.get());
-    return true;
-  }
-
-  void OnMemoryDump(const std::string& dump_name,
-                    base::trace_event::MemoryAllocatorDump* dump,
-                    base::trace_event::ProcessMemoryDump* pmd,
-                    uint64_t client_tracing_id) override {
-    // Add a |service_guid| which expresses shared ownership between the
-    // various GPU dumps.
-    auto client_guid = GetSharedImageGUIDForTracing(mailbox());
-    auto service_guid = gl::GetGLTextureServiceGUIDForTracing(
-        texture_passthrough_->service_id());
-    pmd->CreateSharedGlobalAllocatorDump(service_guid);
-
-    int importance = 2;  // This client always owns the ref.
-    pmd->AddOwnershipEdge(client_guid, service_guid, importance);
-
-    auto* gl_image = texture_passthrough_->GetLevelImage(
-        texture_passthrough_->target(), /*level=*/0);
-    if (gl_image)
-      gl_image->OnMemoryDump(pmd, client_tracing_id, dump_name);
-  }
-
-  void BeginReadAccess() override {}
-
- protected:
-  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
-  ProduceGLTexturePassthrough(SharedImageManager* manager,
-                              MemoryTypeTracker* tracker) override {
-    return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>(
-        manager, this, tracker, texture_passthrough_);
-  }
-  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
-      SharedImageManager* manager,
-      MemoryTypeTracker* tracker,
-      scoped_refptr<SharedContextState> context_state) override {
-    auto result = std::make_unique<SharedImageRepresentationSkiaImpl>(
-        manager, this, std::move(context_state), cached_promise_texture_,
-        tracker, texture_passthrough_->target(),
-        texture_passthrough_->service_id());
-    cached_promise_texture_ = result->promise_texture();
-    return result;
-  }
-
-  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
-      SharedImageManager* manager,
-      MemoryTypeTracker* tracker,
-      WGPUDevice device) override {
-    if (!factory()) {
-      DLOG(ERROR) << "No SharedImageFactory to create a dawn representation.";
+    gles2::Texture::ImageState image_state = gles2::Texture::BOUND;
+    gl::GLImage* image = texture_->GetLevelImage(target, 0, &image_state);
+    if (!image) {
+      LOG(ERROR) << "Texture is not bound to an image.";
       return nullptr;
     }
 
-    return ProduceDawnCommon(factory(), manager, tracker, device, this, true);
+    DCHECK(image->ShouldBindOrCopy() == gl::GLImage::BIND);
+    const GLenum internal_format = GL_RGB;
+    if (!image->BindTexImageWithInternalformat(target, internal_format)) {
+      LOG(ERROR) << "Failed to bind image to rgb texture.";
+      api->glDeleteTexturesFn(1, &service_id);
+      return nullptr;
+    }
+
+    rgb_emulation_texture_ = new gles2::Texture(service_id);
+    rgb_emulation_texture_->SetLightweightRef();
+    rgb_emulation_texture_->SetTarget(target, 1);
+    rgb_emulation_texture_->sampler_state_.min_filter = GL_LINEAR;
+    rgb_emulation_texture_->sampler_state_.mag_filter = GL_LINEAR;
+    rgb_emulation_texture_->sampler_state_.wrap_s = GL_CLAMP_TO_EDGE;
+    rgb_emulation_texture_->sampler_state_.wrap_t = GL_CLAMP_TO_EDGE;
+
+    GLenum format =
+        gles2::TextureManager::ExtractFormatFromStorageFormat(internal_format);
+    GLenum type =
+        gles2::TextureManager::ExtractTypeFromStorageFormat(internal_format);
+
+    const gles2::Texture::LevelInfo* info = texture_->GetLevelInfo(target, 0);
+    rgb_emulation_texture_->SetLevelInfo(target, 0, internal_format,
+                                         info->width, info->height, 1, 0,
+                                         format, type, info->cleared_rect);
+
+    rgb_emulation_texture_->SetLevelImage(target, 0, image, image_state);
+    rgb_emulation_texture_->SetImmutable(true, false);
   }
 
- private:
-  scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
-  sk_sp<SkPromiseImageTexture> cached_promise_texture_;
-};
+  return std::make_unique<SharedImageRepresentationGLTextureImpl>(
+      manager, this, tracker, rgb_emulation_texture_);
+}
+
+std::unique_ptr<SharedImageRepresentationSkia>
+SharedImageBackingGLTexture::ProduceSkia(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    scoped_refptr<SharedContextState> context_state) {
+  auto result = std::make_unique<SharedImageRepresentationSkiaImpl>(
+      manager, this, std::move(context_state), cached_promise_texture_, tracker,
+      texture_->target(), texture_->service_id());
+  cached_promise_texture_ = result->promise_texture();
+  return result;
+}
+
+std::unique_ptr<SharedImageRepresentationDawn>
+SharedImageBackingGLTexture::ProduceDawn(SharedImageManager* manager,
+                                         MemoryTypeTracker* tracker,
+                                         WGPUDevice device) {
+  if (!factory()) {
+    DLOG(ERROR) << "No SharedImageFactory to create a dawn representation.";
+    return nullptr;
+  }
+
+  return ProduceDawnCommon(factory(), manager, tracker, device, this, false);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageBackingPassthroughGLTexture
+
+SharedImageBackingPassthroughGLTexture::SharedImageBackingPassthroughGLTexture(
+    const Mailbox& mailbox,
+    viz::ResourceFormat format,
+    const gfx::Size& size,
+    const gfx::ColorSpace& color_space,
+    uint32_t usage,
+    scoped_refptr<gles2::TexturePassthrough> passthrough_texture)
+    : SharedImageBackingWithReadAccess(mailbox,
+                                       format,
+                                       size,
+                                       color_space,
+                                       usage,
+                                       passthrough_texture->estimated_size(),
+                                       false /* is_thread_safe */),
+      texture_passthrough_(std::move(passthrough_texture)) {
+  DCHECK(texture_passthrough_);
+}
+
+SharedImageBackingPassthroughGLTexture::
+    ~SharedImageBackingPassthroughGLTexture() {
+  DCHECK(texture_passthrough_);
+  if (!have_context())
+    texture_passthrough_->MarkContextLost();
+  texture_passthrough_.reset();
+}
+
+gfx::Rect SharedImageBackingPassthroughGLTexture::ClearedRect() const {
+  // This backing is used exclusively with ANGLE which handles clear tracking
+  // internally. Act as though the texture is always cleared.
+  return gfx::Rect(size());
+}
+
+void SharedImageBackingPassthroughGLTexture::SetClearedRect(
+    const gfx::Rect& cleared_rect) {}
+
+void SharedImageBackingPassthroughGLTexture::Update(
+    std::unique_ptr<gfx::GpuFence> in_fence) {
+  GLenum target = texture_passthrough_->target();
+  gl::GLApi* api = gl::g_current_gl_context;
+  ScopedRestoreTexture scoped_restore(api, target);
+  api->glBindTextureFn(target, texture_passthrough_->service_id());
+
+  gl::GLImage* image = texture_passthrough_->GetLevelImage(target, 0);
+  if (!image)
+    return;
+  image->ReleaseTexImage(target);
+  if (image->ShouldBindOrCopy() == gl::GLImage::BIND)
+    image->BindTexImage(target);
+  else
+    image->CopyTexImage(target);
+}
+
+bool SharedImageBackingPassthroughGLTexture::ProduceLegacyMailbox(
+    MailboxManager* mailbox_manager) {
+  DCHECK(texture_passthrough_);
+  mailbox_manager->ProduceTexture(mailbox(), texture_passthrough_.get());
+  return true;
+}
+
+void SharedImageBackingPassthroughGLTexture::OnMemoryDump(
+    const std::string& dump_name,
+    base::trace_event::MemoryAllocatorDump* dump,
+    base::trace_event::ProcessMemoryDump* pmd,
+    uint64_t client_tracing_id) {
+  // Add a |service_guid| which expresses shared ownership between the
+  // various GPU dumps.
+  auto client_guid = GetSharedImageGUIDForTracing(mailbox());
+  auto service_guid =
+      gl::GetGLTextureServiceGUIDForTracing(texture_passthrough_->service_id());
+  pmd->CreateSharedGlobalAllocatorDump(service_guid);
+
+  int importance = 2;  // This client always owns the ref.
+  pmd->AddOwnershipEdge(client_guid, service_guid, importance);
+
+  auto* gl_image = texture_passthrough_->GetLevelImage(
+      texture_passthrough_->target(), /*level=*/0);
+  if (gl_image)
+    gl_image->OnMemoryDump(pmd, client_tracing_id, dump_name);
+}
+
+void SharedImageBackingPassthroughGLTexture::BeginReadAccess() {}
+
+std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+SharedImageBackingPassthroughGLTexture::ProduceGLTexturePassthrough(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker) {
+  return std::make_unique<SharedImageRepresentationGLTexturePassthroughImpl>(
+      manager, this, tracker, texture_passthrough_);
+}
+
+std::unique_ptr<SharedImageRepresentationSkia>
+SharedImageBackingPassthroughGLTexture::ProduceSkia(
+    SharedImageManager* manager,
+    MemoryTypeTracker* tracker,
+    scoped_refptr<SharedContextState> context_state) {
+  auto result = std::make_unique<SharedImageRepresentationSkiaImpl>(
+      manager, this, std::move(context_state), cached_promise_texture_, tracker,
+      texture_passthrough_->target(), texture_passthrough_->service_id());
+  cached_promise_texture_ = result->promise_texture();
+  return result;
+}
+
+std::unique_ptr<SharedImageRepresentationDawn>
+SharedImageBackingPassthroughGLTexture::ProduceDawn(SharedImageManager* manager,
+                                                    MemoryTypeTracker* tracker,
+                                                    WGPUDevice device) {
+  if (!factory()) {
+    DLOG(ERROR) << "No SharedImageFactory to create a dawn representation.";
+    return nullptr;
+  }
+
+  return ProduceDawnCommon(factory(), manager, tracker, device, this, true);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageBackingFactoryGLTexture
 
 SharedImageBackingFactoryGLTexture::SharedImageBackingFactoryGLTexture(
     const GpuPreferences& gpu_preferences,
@@ -1371,6 +1360,9 @@
       size, color_space, usage, attribs);
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// SharedImageBackingFactoryGLTexture::FormatInfo
+
 SharedImageBackingFactoryGLTexture::FormatInfo::FormatInfo() = default;
 SharedImageBackingFactoryGLTexture::FormatInfo::~FormatInfo() = default;
 
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_internal.h b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_internal.h
new file mode 100644
index 0000000..b645d3c
--- /dev/null
+++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_internal.h
@@ -0,0 +1,207 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_BACKING_FACTORY_GL_TEXTURE_INTERNAL_H_
+#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_BACKING_FACTORY_GL_TEXTURE_INTERNAL_H_
+
+#include "gpu/command_buffer/service/shared_image_backing.h"
+#include "gpu/command_buffer/service/shared_image_backing_factory_gl_texture.h"
+#include "gpu/command_buffer/service/shared_image_representation.h"
+
+namespace gpu {
+
+// Representation of a SharedImageBackingGLTexture as a GL Texture.
+class SharedImageRepresentationGLTextureImpl
+    : public SharedImageRepresentationGLTexture {
+ public:
+  SharedImageRepresentationGLTextureImpl(SharedImageManager* manager,
+                                         SharedImageBacking* backing,
+                                         MemoryTypeTracker* tracker,
+                                         gles2::Texture* texture);
+
+ private:
+  // SharedImageRepresentationGLTexturePassthrough:
+  gles2::Texture* GetTexture() override;
+
+  gles2::Texture* texture_;
+};
+
+// Representation of a SharedImageBackingGLTexturePassthrough as a GL
+// TexturePassthrough.
+class SharedImageRepresentationGLTexturePassthroughImpl
+    : public SharedImageRepresentationGLTexturePassthrough {
+ public:
+  SharedImageRepresentationGLTexturePassthroughImpl(
+      SharedImageManager* manager,
+      SharedImageBacking* backing,
+      MemoryTypeTracker* tracker,
+      scoped_refptr<gles2::TexturePassthrough> texture_passthrough);
+  ~SharedImageRepresentationGLTexturePassthroughImpl() override;
+
+ private:
+  // SharedImageRepresentationGLTexturePassthrough:
+  const scoped_refptr<gles2::TexturePassthrough>& GetTexturePassthrough()
+      override;
+  void EndAccess() override;
+
+  scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
+};
+
+// Common superclass for SharedImageBackingGLTexture,
+// SharedImageBackingPassthroughGLTexture, and
+// SharedImageRepresentationSkiaImpl.
+class SharedImageBackingWithReadAccess : public SharedImageBacking {
+ public:
+  SharedImageBackingWithReadAccess(const Mailbox& mailbox,
+                                   viz::ResourceFormat format,
+                                   const gfx::Size& size,
+                                   const gfx::ColorSpace& color_space,
+                                   uint32_t usage,
+                                   size_t estimated_size,
+                                   bool is_thread_safe);
+  ~SharedImageBackingWithReadAccess() override;
+
+  virtual void BeginReadAccess() = 0;
+};
+
+// Skia representation for both SharedImageBackingGLTexture and
+// SharedImageBackingGLTexturePassthrough.
+class SharedImageRepresentationSkiaImpl : public SharedImageRepresentationSkia {
+ public:
+  SharedImageRepresentationSkiaImpl(
+      SharedImageManager* manager,
+      SharedImageBackingWithReadAccess* backing,
+      scoped_refptr<SharedContextState> context_state,
+      sk_sp<SkPromiseImageTexture> cached_promise_texture,
+      MemoryTypeTracker* tracker,
+      GLenum target,
+      GLuint service_id);
+  ~SharedImageRepresentationSkiaImpl() override;
+
+  sk_sp<SkPromiseImageTexture> promise_texture();
+
+ private:
+  // SharedImageRepresentationSkia:
+  sk_sp<SkSurface> BeginWriteAccess(
+      int final_msaa_count,
+      const SkSurfaceProps& surface_props,
+      std::vector<GrBackendSemaphore>* begin_semaphores,
+      std::vector<GrBackendSemaphore>* end_semaphores) override;
+  void EndWriteAccess(sk_sp<SkSurface> surface) override;
+  sk_sp<SkPromiseImageTexture> BeginReadAccess(
+      std::vector<GrBackendSemaphore>* begin_semaphores,
+      std::vector<GrBackendSemaphore>* end_semaphores) override;
+  bool SupportsMultipleConcurrentReadAccess() override;
+
+  // SharedImageBackingWithReadAccess:
+  void EndReadAccess() override;
+
+  void CheckContext();
+
+  scoped_refptr<SharedContextState> context_state_;
+  sk_sp<SkPromiseImageTexture> promise_texture_;
+
+  SkSurface* write_surface_ = nullptr;
+#if DCHECK_IS_ON()
+  gl::GLContext* context_ = nullptr;
+#endif
+};
+
+// Implementation of SharedImageBacking that creates a GL Texture and stores it
+// as a gles2::Texture. Can be used with the legacy mailbox implementation.
+class SharedImageBackingGLTexture : public SharedImageBackingWithReadAccess {
+ public:
+  SharedImageBackingGLTexture(
+      const Mailbox& mailbox,
+      viz::ResourceFormat format,
+      const gfx::Size& size,
+      const gfx::ColorSpace& color_space,
+      uint32_t usage,
+      gles2::Texture* texture,
+      const SharedImageBackingFactoryGLTexture::UnpackStateAttribs& attribs);
+  ~SharedImageBackingGLTexture() override;
+
+ private:
+  // SharedImageBacking:
+  gfx::Rect ClearedRect() const override;
+  void SetClearedRect(const gfx::Rect& cleared_rect) override;
+  void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
+  bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
+  void OnMemoryDump(const std::string& dump_name,
+                    base::trace_event::MemoryAllocatorDump* dump,
+                    base::trace_event::ProcessMemoryDump* pmd,
+                    uint64_t client_tracing_id) override;
+  scoped_refptr<gfx::NativePixmap> GetNativePixmap() override;
+  std::unique_ptr<SharedImageRepresentationGLTexture> ProduceGLTexture(
+      SharedImageManager* manager,
+      MemoryTypeTracker* tracker) override;
+  std::unique_ptr<SharedImageRepresentationGLTexture>
+  ProduceRGBEmulationGLTexture(SharedImageManager* manager,
+                               MemoryTypeTracker* tracker) override;
+  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+      SharedImageManager* manager,
+      MemoryTypeTracker* tracker,
+      scoped_refptr<SharedContextState> context_state) override;
+  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+      SharedImageManager* manager,
+      MemoryTypeTracker* tracker,
+      WGPUDevice device) override;
+
+  // SharedImageBackingPassthroughGLTexture:
+  void BeginReadAccess() override;
+
+  gles2::Texture* texture_ = nullptr;
+  gles2::Texture* rgb_emulation_texture_ = nullptr;
+  sk_sp<SkPromiseImageTexture> cached_promise_texture_;
+  const SharedImageBackingFactoryGLTexture::UnpackStateAttribs attribs_;
+  scoped_refptr<gfx::NativePixmap> native_pixmap_;
+};
+
+// Implementation of SharedImageBacking that creates a GL Texture and stores it
+// as a gles2::TexturePassthrough. Can be used with the legacy mailbox
+// implementation.
+class SharedImageBackingPassthroughGLTexture
+    : public SharedImageBackingWithReadAccess {
+ public:
+  SharedImageBackingPassthroughGLTexture(
+      const Mailbox& mailbox,
+      viz::ResourceFormat format,
+      const gfx::Size& size,
+      const gfx::ColorSpace& color_space,
+      uint32_t usage,
+      scoped_refptr<gles2::TexturePassthrough> passthrough_texture);
+  ~SharedImageBackingPassthroughGLTexture() override;
+
+ private:
+  // SharedImageBacking:
+  gfx::Rect ClearedRect() const override;
+  void SetClearedRect(const gfx::Rect& cleared_rect) override;
+  void Update(std::unique_ptr<gfx::GpuFence> in_fence) override;
+  bool ProduceLegacyMailbox(MailboxManager* mailbox_manager) override;
+  void OnMemoryDump(const std::string& dump_name,
+                    base::trace_event::MemoryAllocatorDump* dump,
+                    base::trace_event::ProcessMemoryDump* pmd,
+                    uint64_t client_tracing_id) override;
+  std::unique_ptr<SharedImageRepresentationGLTexturePassthrough>
+  ProduceGLTexturePassthrough(SharedImageManager* manager,
+                              MemoryTypeTracker* tracker) override;
+  std::unique_ptr<SharedImageRepresentationSkia> ProduceSkia(
+      SharedImageManager* manager,
+      MemoryTypeTracker* tracker,
+      scoped_refptr<SharedContextState> context_state) override;
+  std::unique_ptr<SharedImageRepresentationDawn> ProduceDawn(
+      SharedImageManager* manager,
+      MemoryTypeTracker* tracker,
+      WGPUDevice device) override;
+
+  // SharedImageBackingPassthroughGLTexture:
+  void BeginReadAccess() override;
+
+  scoped_refptr<gles2::TexturePassthrough> texture_passthrough_;
+  sk_sp<SkPromiseImageTexture> cached_promise_texture_;
+};
+
+}  // namespace gpu
+
+#endif  // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_BACKING_FACTORY_GL_TEXTURE_INTERNAL_H_
diff --git a/gpu/ipc/common/BUILD.gn b/gpu/ipc/common/BUILD.gn
index 8c04e9f..47c730f 100644
--- a/gpu/ipc/common/BUILD.gn
+++ b/gpu/ipc/common/BUILD.gn
@@ -214,6 +214,10 @@
     "vulkan_ycbcr_info.mojom",
   ]
 
+  if (is_win) {
+    sources += [ "luid.mojom" ]
+  }
+
   public_deps = [
     ":gpu_preferences_interface",
     "//mojo/public/mojom/base",
@@ -269,6 +273,24 @@
     },
   ]
 
+  if (is_win) {
+    shared_cpp_typemaps += [
+      {
+        types = [
+          {
+            mojom = "gpu.mojom.Luid"
+            cpp = "::LUID"
+          },
+        ]
+        traits_headers = [ "luid_mojom_traits.h" ]
+        traits_public_deps = [
+          ":mojom_traits",
+          "//gpu/config",
+        ]
+      },
+    ]
+  }
+
   cpp_typemaps = shared_cpp_typemaps
   blink_cpp_typemaps = shared_cpp_typemaps
 
@@ -399,10 +421,6 @@
           mojom = "gpu.mojom.ImageDecodeAcceleratorSupportedProfile"
           cpp = "::gpu::ImageDecodeAcceleratorSupportedProfile"
         },
-        {
-          mojom = "gpu.mojom.Luid"
-          cpp = "::LUID"
-        },
       ]
       traits_sources = [ "gpu_info_mojom_traits.cc" ]
       traits_headers = [ "gpu_info_mojom_traits.h" ]
@@ -584,6 +602,9 @@
   if (is_android) {
     sources += [ "vulkan_ycbcr_info_mojom_traits.h" ]
   }
+  if (is_win) {
+    sources += [ "luid_mojom_traits.h" ]
+  }
   if (enable_vulkan) {
     deps += [ ":vulkan_types_mojom_traits" ]
   }
diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom
index 4bef7ee..b83f01b3 100644
--- a/gpu/ipc/common/gpu_info.mojom
+++ b/gpu/ipc/common/gpu_info.mojom
@@ -6,19 +6,14 @@
 module gpu.mojom;
 
 import "gpu/ipc/common/dx_diag_node.mojom";
+[EnableIf=is_win]
+import "gpu/ipc/common/luid.mojom";
 import "mojo/public/mojom/base/time.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 
 [EnableIf=supports_vulkan]
 import "gpu/ipc/common/vulkan_info.mojom";
 
-// Corresponds to LUID in dxgi.h
-[EnableIf=is_win]
-struct Luid {
-  int32 high;
-  uint32 low;
-};
-
 // gpu::GPUInfo::GPUDevice
 struct GpuDevice {
   uint32 vendor_id;
diff --git a/gpu/ipc/common/gpu_info_mojom_traits.cc b/gpu/ipc/common/gpu_info_mojom_traits.cc
index 44e127d..50c0f85 100644
--- a/gpu/ipc/common/gpu_info_mojom_traits.cc
+++ b/gpu/ipc/common/gpu_info_mojom_traits.cc
@@ -378,15 +378,6 @@
   return data.ReadYuy2OverlaySupport(&out->yuy2_overlay_support) &&
          data.ReadNv12OverlaySupport(&out->nv12_overlay_support);
 }
-
-// static
-bool StructTraits<gpu::mojom::LuidDataView, LUID>::Read(
-    gpu::mojom::LuidDataView data,
-    LUID* out) {
-  out->HighPart = data.high();
-  out->LowPart = data.low();
-  return true;
-}
 #endif
 
 bool StructTraits<gpu::mojom::GpuInfoDataView, gpu::GPUInfo>::Read(
diff --git a/gpu/ipc/common/gpu_info_mojom_traits.h b/gpu/ipc/common/gpu_info_mojom_traits.h
index 39ed48d..e2e559e1 100644
--- a/gpu/ipc/common/gpu_info_mojom_traits.h
+++ b/gpu/ipc/common/gpu_info_mojom_traits.h
@@ -257,15 +257,6 @@
   }
 };
 
-template <>
-struct StructTraits<gpu::mojom::LuidDataView, LUID> {
-  static bool Read(gpu::mojom::LuidDataView data, LUID* out);
-
-  static int32_t high(const LUID& input) { return input.HighPart; }
-
-  static uint32_t low(const LUID& input) { return input.LowPart; }
-};
-
 #endif
 
 template <>
diff --git a/gpu/ipc/common/luid.mojom b/gpu/ipc/common/luid.mojom
new file mode 100644
index 0000000..68da5dbda
--- /dev/null
+++ b/gpu/ipc/common/luid.mojom
@@ -0,0 +1,12 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module gpu.mojom;
+
+// Corresponds to LUID in dxgi.h
+[EnableIf=is_win]
+struct Luid {
+  int32 high;
+  uint32 low;
+};
diff --git a/gpu/ipc/common/luid_mojom_traits.h b/gpu/ipc/common/luid_mojom_traits.h
new file mode 100644
index 0000000..e736c53c
--- /dev/null
+++ b/gpu/ipc/common/luid_mojom_traits.h
@@ -0,0 +1,27 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GPU_IPC_COMMON_LUID_MOJOM_TRAITS_H_
+#define GPU_IPC_COMMON_LUID_MOJOM_TRAITS_H_
+
+#include "gpu/ipc/common/luid.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<gpu::mojom::LuidDataView, LUID> {
+  static bool Read(gpu::mojom::LuidDataView data, LUID* out) {
+    out->HighPart = data.high();
+    out->LowPart = data.low();
+    return true;
+  }
+
+  static int32_t high(const LUID& input) { return input.HighPart; }
+
+  static uint32_t low(const LUID& input) { return input.LowPart; }
+};
+
+}  // namespace mojo
+
+#endif  // GPU_IPC_COMMON_LUID_MOJOM_TRAITS_H_
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index da3cadec..6443a323 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -67,7 +67,7 @@
   base::TimeTicks before_collect_context_graphics_info = base::TimeTicks::Now();
   bool success = CollectContextGraphicsInfo(gpu_info);
   if (!success)
-    LOG(ERROR) << "gpu::CollectGraphicsInfo failed.";
+    LOG(ERROR) << "CollectGraphicsInfo failed.";
 
   if (success) {
     base::TimeDelta collect_context_time =
@@ -113,17 +113,18 @@
       watchdog_ptr_->OnInitComplete();
   }
 
-  void SetGpuWatchdogPtr(gpu::GpuWatchdogThread* ptr) { watchdog_ptr_ = ptr; }
+  void SetGpuWatchdogPtr(GpuWatchdogThread* ptr) { watchdog_ptr_ = ptr; }
 
  private:
-  gpu::GpuWatchdogThread* watchdog_ptr_ = nullptr;
+  GpuWatchdogThread* watchdog_ptr_ = nullptr;
 };
+
 }  // namespace
 
 GpuInit::GpuInit() = default;
 
 GpuInit::~GpuInit() {
-  gpu::StopForceDiscreteGPU();
+  StopForceDiscreteGPU();
 }
 
 bool GpuInit::InitializeAndStartSandbox(base::CommandLine* command_line,
@@ -146,7 +147,7 @@
 
   // Set keys for crash logging based on preliminary gpu info, in case we
   // crash during feature collection.
-  gpu::SetKeysForCrashLogging(gpu_info_);
+  SetKeysForCrashLogging(gpu_info_);
 #if defined(SUBPIXEL_FONT_RENDERING_DISABLED)
   gpu_info_.subpixel_font_rendering = false;
 #else
@@ -168,31 +169,31 @@
   if (!PopGpuFeatureInfoCache(&gpu_feature_info_)) {
     // Compute blacklist and driver bug workaround decisions based on basic GPU
     // info.
-    gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
-        gpu_info_, gpu_preferences_, command_line, &needs_more_info);
+    gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
+                                              command_line, &needs_more_info);
   }
 #endif  // !OS_ANDROID && !BUILDFLAG(IS_CHROMECAST)
 
   gpu_info_.in_process_gpu = false;
-  bool use_swiftshader = false;
+  gl_use_swiftshader_ = false;
 
   // GL bindings may have already been initialized, specifically on MacOSX.
   bool gl_initialized = gl::GetGLImplementation() != gl::kGLImplementationNone;
   if (!gl_initialized) {
     // If GL has already been initialized, then it's too late to select GPU.
-    if (gpu::SwitchableGPUsSupported(gpu_info_, *command_line)) {
-      gpu::InitializeSwitchableGPUs(
+    if (SwitchableGPUsSupported(gpu_info_, *command_line)) {
+      InitializeSwitchableGPUs(
           gpu_feature_info_.enabled_gpu_driver_bug_workarounds);
     }
   } else if (gl::GetGLImplementation() == gl::kGLImplementationSwiftShaderGL &&
              command_line->GetSwitchValueASCII(switches::kUseGL) !=
                  gl::kGLImplementationSwiftShaderName) {
-    use_swiftshader = true;
+    gl_use_swiftshader_ = true;
   }
 
   bool enable_watchdog = !gpu_preferences_.disable_gpu_watchdog &&
                          !command_line->HasSwitch(switches::kHeadless) &&
-                         !use_swiftshader;
+                         !gl_use_swiftshader_;
 
   // Disable the watchdog in debug builds because they tend to only be run by
   // developers who will not appreciate the watchdog killing the GPU process.
@@ -233,11 +234,11 @@
   // consuming has completed, otherwise the process is liable to be aborted.
   if (enable_watchdog && !delayed_watchdog_enable) {
     if (base::FeatureList::IsEnabled(features::kGpuWatchdogV2)) {
-      watchdog_thread_ = gpu::GpuWatchdogThreadImplV2::Create(
+      watchdog_thread_ = GpuWatchdogThreadImplV2::Create(
           gpu_preferences_.watchdog_starts_backgrounded);
       watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
     } else {
-      watchdog_thread_ = gpu::GpuWatchdogThreadImplV1::Create(
+      watchdog_thread_ = GpuWatchdogThreadImplV1::Create(
           gpu_preferences_.watchdog_starts_backgrounded);
     }
 
@@ -282,12 +283,12 @@
           ->GetSupportedFormatsForTexturing();
 #endif
 
-  if (!use_swiftshader) {
-    use_swiftshader = EnableSwiftShaderIfNeeded(
+  if (!gl_use_swiftshader_) {
+    gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
         command_line, gpu_feature_info_,
         gpu_preferences_.disable_software_rasterizer, needs_more_info);
   }
-  if (gl_initialized && use_swiftshader &&
+  if (gl_initialized && gl_use_swiftshader_ &&
       gl::GetGLImplementation() != gl::kGLImplementationSwiftShaderGL) {
 #if defined(OS_LINUX)
     VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
@@ -324,7 +325,7 @@
 
 #if defined(OS_LINUX)
   // The ContentSandboxHelper is currently the only one implementation of
-  // gpu::GpuSandboxHelper and it has no dependency. Except on Linux where
+  // GpuSandboxHelper and it has no dependency. Except on Linux where
   // VaapiWrapper checks the GL implementation to determine which display
   // to use. So call PreSandboxStartup after GL initialization. But make
   // sure the watchdog is paused as loadLibrary may take a long time and
@@ -350,7 +351,7 @@
 #if defined(OS_MACOSX)
   if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE &&
       gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader) {
-    gpu::SetMacOSSpecificTextureTarget(GL_TEXTURE_2D);
+    SetMacOSSpecificTextureTarget(GL_TEXTURE_2D);
   }
 #endif  // defined(OS_MACOSX)
 
@@ -363,16 +364,17 @@
 
   // We need to collect GL strings (VENDOR, RENDERER) for blacklisting purposes.
   if (!gl_disabled) {
-    if (!use_swiftshader) {
+    if (!gl_use_swiftshader_) {
       if (!CollectGraphicsInfo(&gpu_info_))
         return false;
-      gpu::SetKeysForCrashLogging(gpu_info_);
-      gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(
-          gpu_info_, gpu_preferences_, command_line, nullptr);
-      use_swiftshader = EnableSwiftShaderIfNeeded(
+
+      SetKeysForCrashLogging(gpu_info_);
+      gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
+                                                command_line, nullptr);
+      gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
           command_line, gpu_feature_info_,
           gpu_preferences_.disable_software_rasterizer, false);
-      if (use_swiftshader) {
+      if (gl_use_swiftshader_) {
 #if defined(OS_LINUX)
         VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
                 << "on Linux";
@@ -389,34 +391,48 @@
         }
 #endif  // OS_LINUX
       }
-    } else {  // use_swiftshader == true
+    } else {  // gl_use_swiftshader_ == true
       switch (gpu_preferences_.use_vulkan) {
-        case gpu::VulkanImplementationName::kNative: {
+        case VulkanImplementationName::kNative: {
           // Collect GPU info, so we can use blacklist to disable vulkan if it
           // is needed.
-          gpu::GPUInfo gpu_info;
+          GPUInfo gpu_info;
           if (!CollectGraphicsInfo(&gpu_info))
             return false;
-          auto gpu_feature_info = gpu::ComputeGpuFeatureInfo(
+          auto gpu_feature_info = ComputeGpuFeatureInfo(
               gpu_info, gpu_preferences_, command_line, nullptr);
-          gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
-              gpu_feature_info.status_values[gpu::GPU_FEATURE_TYPE_VULKAN];
+          gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
+              gpu_feature_info.status_values[GPU_FEATURE_TYPE_VULKAN];
           break;
         }
-        case gpu::VulkanImplementationName::kForcedNative:
-        case gpu::VulkanImplementationName::kSwiftshader:
-          gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
-              gpu::kGpuFeatureStatusEnabled;
+        case VulkanImplementationName::kForcedNative:
+        case VulkanImplementationName::kSwiftshader:
+          gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
+              kGpuFeatureStatusEnabled;
           break;
-        case gpu::VulkanImplementationName::kNone:
-          gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
-              gpu::kGpuFeatureStatusDisabled;
+        case VulkanImplementationName::kNone:
+          gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
+              kGpuFeatureStatusDisabled;
           break;
       }
     }
   }
 
-  InitializeVulkan();
+  if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] !=
+          kGpuFeatureStatusEnabled ||
+      !InitializeVulkan()) {
+    gpu_preferences_.use_vulkan = VulkanImplementationName::kNone;
+    gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
+        kGpuFeatureStatusDisabled;
+    if (gpu_preferences_.gr_context_type == GrContextType::kVulkan) {
+#if defined(OS_FUCHSIA)
+      // Fuchsia uses ANGLE for GL which requires Vulkan, so don't fall
+      // back to GL if Vulkan init fails.
+      LOG(FATAL) << "Vulkan initialization failed";
+#endif
+      gpu_preferences_.gr_context_type = GrContextType::kGL;
+    }
+  }
 
   // Collect GPU process info
   if (!gl_disabled) {
@@ -447,16 +463,16 @@
   // Driver may create a compatibility profile context when collect graphics
   // information on Linux platform. Try to collect graphics information
   // based on core profile context after disabling platform extensions.
-  if (!gl_disabled && !use_swiftshader) {
+  if (!gl_disabled && !gl_use_swiftshader_) {
     if (!CollectGraphicsInfo(&gpu_info_))
       return false;
-    gpu::SetKeysForCrashLogging(gpu_info_);
-    gpu_feature_info_ = gpu::ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
-                                                   command_line, nullptr);
-    use_swiftshader = EnableSwiftShaderIfNeeded(
+    SetKeysForCrashLogging(gpu_info_);
+    gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
+                                              command_line, nullptr);
+    gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
         command_line, gpu_feature_info_,
         gpu_preferences_.disable_software_rasterizer, false);
-    if (use_swiftshader) {
+    if (gl_use_swiftshader_) {
       VLOG(1) << "Quit GPU process launch to fallback to SwiftShader cleanly "
               << "on Linux";
       return false;
@@ -464,7 +480,7 @@
   }
 #endif  // defined(OS_LINUX)
 
-  if (use_swiftshader) {
+  if (gl_use_swiftshader_) {
     AdjustInfoToSwiftShader();
   }
 
@@ -482,14 +498,14 @@
   // Software GL is expected to run slowly, so disable the watchdog
   // in that case.
   // In SwiftShader case, the implementation is actually EGLGLES2.
-  if (!use_swiftshader && command_line->HasSwitch(switches::kUseGL)) {
+  if (!gl_use_swiftshader_ && command_line->HasSwitch(switches::kUseGL)) {
     std::string use_gl = command_line->GetSwitchValueASCII(switches::kUseGL);
     if (use_gl == gl::kGLImplementationSwiftShaderName ||
         use_gl == gl::kGLImplementationSwiftShaderForWebGLName) {
-      use_swiftshader = true;
+      gl_use_swiftshader_ = true;
     }
   }
-  if (use_swiftshader ||
+  if (gl_use_swiftshader_ ||
       gl::GetGLImplementation() == gl::GetSoftwareGLImplementation()) {
     gpu_info_.software_rendering = true;
     watchdog_thread_ = nullptr;
@@ -499,11 +515,11 @@
     watchdog_init.SetGpuWatchdogPtr(nullptr);
   } else if (enable_watchdog && delayed_watchdog_enable) {
     if (base::FeatureList::IsEnabled(features::kGpuWatchdogV2)) {
-      watchdog_thread_ = gpu::GpuWatchdogThreadImplV2::Create(
+      watchdog_thread_ = GpuWatchdogThreadImplV2::Create(
           gpu_preferences_.watchdog_starts_backgrounded);
       watchdog_init.SetGpuWatchdogPtr(watchdog_thread_.get());
     } else {
-      watchdog_thread_ = gpu::GpuWatchdogThreadImplV1::Create(
+      watchdog_thread_ = GpuWatchdogThreadImplV1::Create(
           gpu_preferences_.watchdog_starts_backgrounded);
     }
   }
@@ -544,7 +560,16 @@
 
   InitializeGLThreadSafe(command_line, gpu_preferences_, &gpu_info_,
                          &gpu_feature_info_);
-  InitializeVulkan();
+
+  if (gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] !=
+          kGpuFeatureStatusEnabled ||
+      !InitializeVulkan()) {
+    gpu_preferences_.use_vulkan = VulkanImplementationName::kNone;
+    gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN] =
+        kGpuFeatureStatusDisabled;
+    if (gpu_preferences_.gr_context_type == GrContextType::kVulkan)
+      gpu_preferences_.gr_context_type = GrContextType::kGL;
+  }
 
   default_offscreen_surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
 
@@ -585,7 +610,7 @@
   }
 #endif  // !BUILDFLAG(IS_CHROMECAST)
 
-  bool use_swiftshader = EnableSwiftShaderIfNeeded(
+  gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
       command_line, gpu_feature_info_,
       gpu_preferences_.disable_software_rasterizer, needs_more_info);
   if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
@@ -594,14 +619,14 @@
   }
   bool gl_disabled = gl::GetGLImplementation() == gl::kGLImplementationDisabled;
 
-  if (!gl_disabled && !use_swiftshader) {
+  if (!gl_disabled && !gl_use_swiftshader_) {
     CollectContextGraphicsInfo(&gpu_info_);
     gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
                                               command_line, nullptr);
-    use_swiftshader = EnableSwiftShaderIfNeeded(
+    gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
         command_line, gpu_feature_info_,
         gpu_preferences_.disable_software_rasterizer, false);
-    if (use_swiftshader) {
+    if (gl_use_swiftshader_) {
       gl::init::ShutdownGL(true);
       if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
@@ -632,14 +657,14 @@
   // Driver may create a compatibility profile context when collect graphics
   // information on Linux platform. Try to collect graphics information
   // based on core profile context after disabling platform extensions.
-  if (!gl_disabled && !use_swiftshader) {
+  if (!gl_disabled && !gl_use_swiftshader_) {
     CollectContextGraphicsInfo(&gpu_info_);
     gpu_feature_info_ = ComputeGpuFeatureInfo(gpu_info_, gpu_preferences_,
                                               command_line, nullptr);
-    use_swiftshader = EnableSwiftShaderIfNeeded(
+    gl_use_swiftshader_ = EnableSwiftShaderIfNeeded(
         command_line, gpu_feature_info_,
         gpu_preferences_.disable_software_rasterizer, false);
-    if (use_swiftshader) {
+    if (gl_use_swiftshader_) {
       gl::init::ShutdownGL(true);
       if (!gl::init::InitializeGLNoExtensionsOneOff(/*init_bindings*/ true)) {
         VLOG(1) << "gl::init::InitializeGLNoExtensionsOneOff failed "
@@ -650,7 +675,7 @@
   }
 #endif  // defined(OS_LINUX)
 
-  if (use_swiftshader) {
+  if (gl_use_swiftshader_) {
     AdjustInfoToSwiftShader();
   }
 
@@ -675,63 +700,76 @@
   return std::move(default_offscreen_surface_);
 }
 
-void GpuInit::InitializeVulkan() {
 #if BUILDFLAG(ENABLE_VULKAN)
-  if (gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] ==
-      gpu::kGpuFeatureStatusEnabled) {
-    DCHECK_NE(gpu_preferences_.use_vulkan,
-              gpu::VulkanImplementationName::kNone);
-    bool vulkan_use_swiftshader = gpu_preferences_.use_vulkan ==
-                                  gpu::VulkanImplementationName::kSwiftshader;
-    const bool enforce_protected_memory =
-        gpu_preferences_.enforce_vulkan_protected_memory;
-    vulkan_implementation_ = gpu::CreateVulkanImplementation(
-        vulkan_use_swiftshader,
-        enforce_protected_memory ? true : false /* allow_protected_memory */,
-        enforce_protected_memory);
-    if (!vulkan_implementation_ ||
-        !vulkan_implementation_->InitializeVulkanInstance(
-            !gpu_preferences_.disable_vulkan_surface)) {
-      DLOG(ERROR) << "Failed to create and initialize Vulkan implementation.";
-      vulkan_implementation_ = nullptr;
-      CHECK(!gpu_preferences_.disable_vulkan_fallback_to_gl_for_testing);
-    }
-    // TODO(penghuang): Remove GPU.SupportsVulkan and GPU.VulkanVersion from
-    // //gpu/config/gpu_info_collector_win.cc when we are finch vulkan on
-    // Windows.
-    if (!vulkan_use_swiftshader) {
-      const bool supports_vulkan = !!vulkan_implementation_;
-      UMA_HISTOGRAM_BOOLEAN("GPU.SupportsVulkan", supports_vulkan);
-      uint32_t vulkan_version = 0;
-      if (supports_vulkan) {
-        const auto& vulkan_info =
-            vulkan_implementation_->GetVulkanInstance()->vulkan_info();
-        vulkan_version = vulkan_info.used_api_version;
-      }
-      UMA_HISTOGRAM_ENUMERATION(
-          "GPU.VulkanVersion", ConvertToHistogramVulkanVersion(vulkan_version));
-    }
-  }
-  if (!vulkan_implementation_) {
-    if (gpu_preferences_.gr_context_type == gpu::GrContextType::kVulkan) {
-#if defined(OS_FUCHSIA)
-      // Fuchsia uses ANGLE for GL which requires Vulkan, so don't fall
-      // back to GL if Vulkan init fails.
-      LOG(FATAL) << "Vulkan initialization failed";
-#endif
-      gpu_preferences_.gr_context_type = gpu::GrContextType::kGL;
-    }
-    gpu_preferences_.use_vulkan = gpu::VulkanImplementationName::kNone;
-    gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
-        gpu::kGpuFeatureStatusDisabled;
-  } else {
-    gpu_info_.vulkan_info =
-        vulkan_implementation_->GetVulkanInstance()->vulkan_info();
-  }
+bool GpuInit::InitializeVulkan() {
+  DCHECK_EQ(gpu_feature_info_.status_values[GPU_FEATURE_TYPE_VULKAN],
+            kGpuFeatureStatusEnabled);
+  DCHECK_NE(gpu_preferences_.use_vulkan, VulkanImplementationName::kNone);
+  bool vulkan_use_swiftshader =
+      gpu_preferences_.use_vulkan == VulkanImplementationName::kSwiftshader;
+  bool forced_native =
+      gpu_preferences_.use_vulkan == VulkanImplementationName::kForcedNative;
+  bool use_swiftshader = gl_use_swiftshader_ || vulkan_use_swiftshader;
+  if (!use_swiftshader && !forced_native) {
+#if defined(OS_WIN)
+    constexpr char kMemoryObjectExtension[] = "GL_EXT_memory_object_win32";
+    constexpr char kSemaphoreExtension[] = "GL_EXT_semaphore_win32";
+#elif defined(OS_FUCHSIA)
+    constexpr char kMemoryObjectExtension[] = "GL_ANGLE_memory_object_fuchsia";
+    constexpr char kSemaphoreExtension[] = "GL_ANGLE_semaphore_fuchsia";
 #else
-  gpu_preferences_.use_vulkan = gpu::VulkanImplementationName::kNone;
-  gpu_feature_info_.status_values[gpu::GPU_FEATURE_TYPE_VULKAN] =
-      gpu::kGpuFeatureStatusDisabled;
-#endif  // BUILDFLAG(ENABLE_VULKAN)
+    constexpr char kMemoryObjectExtension[] = "GL_EXT_memory_object_fd";
+    constexpr char kSemaphoreExtension[] = "GL_EXT_semaphore_fd";
+#endif
+    // If both Vulkan and GL are using native GPU (non swiftshader), check
+    // necessary extensions for GL and Vulkan interop.
+    const auto extensions = gfx::MakeExtensionSet(gpu_info_.gl_extensions);
+    if (!gfx::HasExtension(extensions, kMemoryObjectExtension) ||
+        !gfx::HasExtension(extensions, kSemaphoreExtension)) {
+      DLOG(ERROR) << kMemoryObjectExtension << " or " << kSemaphoreExtension
+                  << " is not supported.";
+      return false;
+    }
+  }
+
+  const bool enforce_protected_memory =
+      gpu_preferences_.enforce_vulkan_protected_memory;
+  vulkan_implementation_ = CreateVulkanImplementation(
+      vulkan_use_swiftshader,
+      enforce_protected_memory ? true : false /* allow_protected_memory */,
+      enforce_protected_memory);
+  if (!vulkan_implementation_ ||
+      !vulkan_implementation_->InitializeVulkanInstance(
+          !gpu_preferences_.disable_vulkan_surface)) {
+    DLOG(ERROR) << "Failed to create and initialize Vulkan implementation.";
+    vulkan_implementation_ = nullptr;
+    CHECK(!gpu_preferences_.disable_vulkan_fallback_to_gl_for_testing);
+  }
+  // TODO(penghuang): Remove GPU.SupportsVulkan and GPU.VulkanVersion from
+  // //gpu/config/gpu_info_collector_win.cc when we are finch vulkan on
+  // Windows.
+  if (!vulkan_use_swiftshader) {
+    const bool supports_vulkan = !!vulkan_implementation_;
+    UMA_HISTOGRAM_BOOLEAN("GPU.SupportsVulkan", supports_vulkan);
+    uint32_t vulkan_version = 0;
+    if (supports_vulkan) {
+      const auto& vulkan_info =
+          vulkan_implementation_->GetVulkanInstance()->vulkan_info();
+      vulkan_version = vulkan_info.used_api_version;
+    }
+    UMA_HISTOGRAM_ENUMERATION("GPU.VulkanVersion",
+                              ConvertToHistogramVulkanVersion(vulkan_version));
+  }
+  if (!vulkan_implementation_)
+    return false;
+  gpu_info_.vulkan_info =
+      vulkan_implementation_->GetVulkanInstance()->vulkan_info();
+  return true;
 }
+#else   // BUILDFLAG(ENABLE_VULKAN)
+bool GpuInit::InitializeVulkan() {
+  return false;
+}
+#endif  // !BUILDFLAG(ENABLE_VULKAN)
+
 }  // namespace gpu
diff --git a/gpu/ipc/service/gpu_init.h b/gpu/ipc/service/gpu_init.h
index 5f1d6fc..3c236db 100644
--- a/gpu/ipc/service/gpu_init.h
+++ b/gpu/ipc/service/gpu_init.h
@@ -83,9 +83,10 @@
 #endif
 
  private:
-  void InitializeVulkan();
+  bool InitializeVulkan();
 
   GpuSandboxHelper* sandbox_helper_ = nullptr;
+  bool gl_use_swiftshader_ = false;
   std::unique_ptr<GpuWatchdogThread> watchdog_thread_;
   GPUInfo gpu_info_;
   GpuFeatureInfo gpu_feature_info_;
diff --git a/gpu/ipc/service/gpu_watchdog_thread.cc b/gpu/ipc/service/gpu_watchdog_thread.cc
index cc5d8a9..f84571e5 100644
--- a/gpu/ipc/service/gpu_watchdog_thread.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread.cc
@@ -53,17 +53,6 @@
 const int kNewGpuTimeout = 15000;
 #endif
 
-// Histogram parameters for GPU.WatchdogThread.V1.ExtraThreadTime and
-// GPU.WatchdogThread.V1.WaitTime
-constexpr base::TimeDelta kMin = base::TimeDelta::FromSeconds(1);
-constexpr base::TimeDelta kMax = base::TimeDelta::FromSeconds(150);
-constexpr int kBuckets = 50;
-
-// Histogram recorded in OnWatchdogTimeout()
-void GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent timeout_event) {
-  base::UmaHistogramEnumeration("GPU.WatchdogThread.V1.Timeout", timeout_event);
-}
-
 #if defined(USE_X11)
 const base::FilePath::CharType kTtyFilePath[] =
     FILE_PATH_LITERAL("/sys/class/tty/tty0/active");
@@ -150,11 +139,6 @@
                      base::Unretained(this)));
 }
 
-void GpuWatchdogThreadImplV1::GpuWatchdogHistogram(
-    GpuWatchdogThreadEvent thread_event) {
-  base::UmaHistogramEnumeration("GPU.WatchdogThread.Event", thread_event);
-}
-
 bool GpuWatchdogThreadImplV1::IsGpuHangDetectedForTesting() {
   return false;
 }
@@ -166,7 +150,6 @@
 
 void GpuWatchdogThreadImplV1::CleanUp() {
   weak_factory_.InvalidateWeakPtrs();
-  more_gpu_thread_time_allowed_ = false;
   armed_ = false;
 }
 
@@ -258,24 +241,11 @@
 #endif
 
   base::MessageLoopCurrent::Get()->RemoveTaskObserver(&task_observer_);
-  GpuWatchdogHistogram(GpuWatchdogThreadEvent::kGpuWatchdogEnd);
 }
 
 void GpuWatchdogThreadImplV1::OnAcknowledge() {
   CHECK(base::PlatformThread::CurrentId() == GetThreadId());
 
-  // For metrics only
-  if (more_gpu_thread_time_allowed_) {
-    base::TimeDelta wait_time =
-        base::TimeTicks::Now() - last_timeout_timeticks_;
-    base::UmaHistogramCustomTimes("GPU.WatchdogThread.V1.ExtraThreadTime",
-                                  wait_time, kMin, kMax, kBuckets);
-    GpuWatchdogTimeoutHistogram(
-        GpuWatchdogTimeoutEvent::kProgressAfterMoreThreadTime);
-
-    more_gpu_thread_time_allowed_ = false;
-  }
-
   // The check has already been acknowledged and another has already been
   // scheduled by a previous call to OnAcknowledge. It is normal for a
   // watched thread to see armed_ being true multiple times before
@@ -372,25 +342,11 @@
   // Should not get here while the system is suspended.
   DCHECK(!suspension_counter_.HasRefs());
 
-  base::TimeTicks function_start = base::TimeTicks::Now();
-  GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent::kTimeout);
-
-  // If this metric is added too early (eg. watchdog creation time), it cannot
-  // be persistent. The histogram data will be lost after crash or browser exit.
-  // Delay the recording of kGpuWatchdogStart until the first OnCheckTimeout().
-  if (!is_watchdog_start_histogram_recorded) {
-    is_watchdog_start_histogram_recorded = true;
-    GpuWatchdogHistogram(GpuWatchdogThreadEvent::kGpuWatchdogStart);
-  }
-
   // If the watchdog woke up significantly behind schedule, disarm and reset
   // the watchdog check. This is to prevent the watchdog thread from terminating
   // when a machine wakes up from sleep or hibernation, which would otherwise
   // appear to be a hang.
   if (base::Time::Now() > suspension_timeout_) {
-    // Reset the timeticks after resume for metrics.
-    last_timeout_timeticks_ = function_start;
-
     OnAcknowledge();
     return;
   }
@@ -406,12 +362,6 @@
   base::ThreadTicks current_cpu_time = GetWatchedThreadTime();
   base::TimeDelta time_since_arm = current_cpu_time - arm_cpu_time_;
   if (use_thread_cpu_time_ && (time_since_arm < timeout_)) {
-    // For metrics
-    if (!more_gpu_thread_time_allowed_) {
-      more_gpu_thread_time_allowed_ = true;
-      last_timeout_timeticks_ = function_start;
-      GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent::kMoreThreadTime);
-    }
 
     task_runner()->PostDelayedTask(
         FROM_HERE,
@@ -421,7 +371,6 @@
     return;
   }
 #endif
-  GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent::kTimeoutWait);
 
   // For minimal developer annoyance, don't keep terminating. You need to skip
   // the call to base::Process::Terminate below in a debugger for this to be
@@ -439,11 +388,6 @@
   // Don't crash if we're not on the TTY of our host X11 server.
   UpdateActiveTTY();
   if (host_tty_ != -1 && active_tty_ != -1 && host_tty_ != active_tty_) {
-    // Only record for the time there is a change on TTY
-    if (last_active_tty_ != active_tty_) {
-      GpuWatchdogTimeoutHistogram(
-          GpuWatchdogTimeoutEvent::kContinueOnNonHostServerTty);
-    }
     OnAcknowledge();
     return;
   }
@@ -504,23 +448,9 @@
 
   // Check it one last time before crashing.
   if (!base::subtle::NoBarrier_Load(&awaiting_acknowledge_)) {
-    {  // For metrics only
-      base::TimeDelta wait_time;
-      if (more_gpu_thread_time_allowed_) {
-        more_gpu_thread_time_allowed_ = false;
-        wait_time = base::TimeTicks::Now() - last_timeout_timeticks_;
-      } else {
-        wait_time = base::TimeTicks::Now() - function_start;
-      }
-      base::UmaHistogramCustomTimes("GPU.WatchdogThread.V1.WaitTime", wait_time,
-                                    kMin, kMax, kBuckets);
-      GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent::kProgressAfterWait);
-    }
     OnAcknowledge();
     return;
   }
-  GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent::kKill);
-  GpuWatchdogHistogram(GpuWatchdogThreadEvent::kGpuWatchdogKill);
 
   // Deliberately crash the process to create a crash dump.
   *((volatile int*)0) = 0x1337;
diff --git a/gpu/ipc/service/gpu_watchdog_thread.h b/gpu/ipc/service/gpu_watchdog_thread.h
index b39ae227..ad265659 100644
--- a/gpu/ipc/service/gpu_watchdog_thread.h
+++ b/gpu/ipc/service/gpu_watchdog_thread.h
@@ -100,8 +100,6 @@
   // Continue the watchdog after a pause.
   virtual void ResumeWatchdog() = 0;
 
-  virtual void GpuWatchdogHistogram(GpuWatchdogThreadEvent thread_event) = 0;
-
   // For gpu testing only. Return status for the watchdog tests
   virtual bool IsGpuHangDetectedForTesting() = 0;
 
@@ -130,7 +128,6 @@
   void OnGpuProcessTearDown() override {}
   void ResumeWatchdog() override {}
   void PauseWatchdog() override {}
-  void GpuWatchdogHistogram(GpuWatchdogThreadEvent thread_event) override;
   bool IsGpuHangDetectedForTesting() override;
 
   // gl::ProgressReporter implementation:
@@ -264,16 +261,6 @@
   base::Time check_time_;
   base::TimeTicks check_timeticks_;
 
-  // The time in the last OnCheckTimeout()
-  base::TimeTicks last_timeout_timeticks_;
-
-  // After GPU hang detected, whether the GPU thread is allowed to continue due
-  // to not spending enough thread time.
-  bool more_gpu_thread_time_allowed_ = false;
-
-  // whether GpuWatchdogThreadEvent::kGpuWatchdogStart has been recorded.
-  bool is_watchdog_start_histogram_recorded = false;
-
 #if defined(USE_X11)
   FILE* tty_file_;
   int host_tty_;
diff --git a/gpu/ipc/service/gpu_watchdog_thread_v2.cc b/gpu/ipc/service/gpu_watchdog_thread_v2.cc
index 68bd765..6df85496 100644
--- a/gpu/ipc/service/gpu_watchdog_thread_v2.cc
+++ b/gpu/ipc/service/gpu_watchdog_thread_v2.cc
@@ -661,7 +661,6 @@
 
 void GpuWatchdogThreadImplV2::GpuWatchdogHistogram(
     GpuWatchdogThreadEvent thread_event) {
-  base::UmaHistogramEnumeration("GPU.WatchdogThread.Event.V2", thread_event);
   base::UmaHistogramEnumeration("GPU.WatchdogThread.Event", thread_event);
 }
 
diff --git a/gpu/ipc/service/gpu_watchdog_thread_v2.h b/gpu/ipc/service/gpu_watchdog_thread_v2.h
index c9b7182..4c79e53 100644
--- a/gpu/ipc/service/gpu_watchdog_thread_v2.h
+++ b/gpu/ipc/service/gpu_watchdog_thread_v2.h
@@ -40,8 +40,6 @@
   void OnGpuProcessTearDown() override;
   void ResumeWatchdog() override;
   void PauseWatchdog() override;
-  // Records "GPU.WatchdogThread.Event.V2" and "GPU.WatchdogThread.Event".
-  void GpuWatchdogHistogram(GpuWatchdogThreadEvent thread_event) override;
   bool IsGpuHangDetectedForTesting() override;
   void WaitForPowerObserverAddedForTesting() override;
 
@@ -91,6 +89,9 @@
   // Do not change the function name. It is used for [GPU HANG] carsh reports.
   void DeliberatelyTerminateToRecoverFromHang();
 
+  // Records "GPU.WatchdogThread.Event".
+  void GpuWatchdogHistogram(GpuWatchdogThreadEvent thread_event);
+
   // Histogram recorded in OnWatchdogTimeout()
   // Records "GPU.WatchdogThread.Timeout"
   void GpuWatchdogTimeoutHistogram(GpuWatchdogTimeoutEvent timeout_event);
diff --git a/headless/lib/DEPS b/headless/lib/DEPS
index 4eabc9c..ca360954 100644
--- a/headless/lib/DEPS
+++ b/headless/lib/DEPS
@@ -9,6 +9,7 @@
     "+cc/base/switches.h",
     "+components/viz/common/switches.h",
     "+gpu/config/gpu_switches.h",
+    "+third_party/blink/public/common/switches.h",
   ],
   "headless_web_contents_browsertest.cc": [
     "+cc/base/switches.h",
diff --git a/headless/lib/browser/headless_focus_client.cc b/headless/lib/browser/headless_focus_client.cc
index c406c70..661c3a2e 100644
--- a/headless/lib/browser/headless_focus_client.cc
+++ b/headless/lib/browser/headless_focus_client.cc
@@ -10,7 +10,7 @@
 namespace headless {
 
 HeadlessFocusClient::HeadlessFocusClient()
-    : focused_window_(NULL), observer_manager_(this) {}
+    : focused_window_(nullptr), observer_manager_(this) {}
 
 HeadlessFocusClient::~HeadlessFocusClient() = default;
 
diff --git a/headless/lib/headless_content_main_delegate.cc b/headless/lib/headless_content_main_delegate.cc
index 6cce5d6..2ddeec83 100644
--- a/headless/lib/headless_content_main_delegate.cc
+++ b/headless/lib/headless_content_main_delegate.cc
@@ -36,6 +36,7 @@
 #include "headless/lib/utility/headless_content_utility_client.h"
 #include "services/service_manager/embedder/switches.h"
 #include "services/service_manager/sandbox/switches.h"
+#include "third_party/blink/public/common/switches.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/ui_base_switches.h"
@@ -228,7 +229,7 @@
 
   // When running headless there is no need to suppress input until content
   // is ready for display (because it isn't displayed to users).
-  command_line->AppendSwitch(::switches::kAllowPreCommitInput);
+  command_line->AppendSwitch(::blink::switches::kAllowPreCommitInput);
 
 #if defined(OS_WIN)
   command_line->AppendSwitch(
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index e94bee2c..60eb207 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -10466,12 +10466,12 @@
         properties_j: "$build/goma:{\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"}"
         properties_j: "$kitchen:{\"devshell\":true,\"git_auth\":true}"
         properties_j: "mastername:\"chromium.fyi\""
-        properties_j: "xcode_build_version:\"11n605cwk\""
+        properties_j: "xcode_build_version:\"11e608cwk\""
       >
       execution_timeout_secs: 36000
       caches: <
-        name: "xcode_ios_11n605cwk"
-        path: "xcode_ios_11n605cwk.app"
+        name: "xcode_ios_11e608cwk"
+        path: "xcode_ios_11e608cwk.app"
       >
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star
index f870f02..5bcfeee 100644
--- a/infra/config/lib/builders.star
+++ b/infra/config/lib/builders.star
@@ -133,11 +133,11 @@
 xcode_cache = struct(
    x10e1001 = xcode_enum('xcode_ios_10e1001', 'xcode_ios_10e1001.app'),
    x11a1027 = xcode_enum('xcode_ios_11a1027', 'xcode_ios_11a1027.app'),
-   x11c505wk = xcode_enum('xcode_ios_11c505wk', 'xcode_ios_11c505wk.app'),
    x11c29 = xcode_enum('xcode_ios_11c29', 'xcode_ios_11c29.app'),
    x11m382q = xcode_enum('xcode_ios_11m382q', 'xcode_ios_11m382q.app'),
    x11e146 = xcode_enum('xcode_ios_11e146', 'xcode_ios_11e146.app'),
-   x11n605cwk = xcode_enum('xcode_ios_11n605cwk', 'xcode_ios_11n605cwk.app'),
+   x11e608c = xcode_enum('xcode_ios_11e608c', 'xcode_ios_11e608c.app'),
+   x11e608cwk = xcode_enum('xcode_ios_11e608cwk', 'xcode_ios_11e608cwk.app'),
 )
 
 
diff --git a/infra/config/subprojects/chromium/master-only/ci.star b/infra/config/subprojects/chromium/master-only/ci.star
index 47c9ee4..7e1c3a4 100644
--- a/infra/config/subprojects/chromium/master-only/ci.star
+++ b/infra/config/subprojects/chromium/master-only/ci.star
@@ -1721,14 +1721,14 @@
 
 ci.fyi_ios_builder(
     name = 'ios-webkit-tot',
-    caches = [xcode_cache.x11n605cwk],
+    caches = [xcode_cache.x11e608cwk],
     console_view_entry = ci.console_view_entry(
         category = 'iOS',
         short_name = 'wk',
     ),
     executable = 'recipe:chromium',
     properties = {
-        'xcode_build_version': '11n605cwk'
+        'xcode_build_version': '11e608cwk'
     },
     schedule = '0 1-23/6 * * *',
     triggered_by = [],
diff --git a/ios/chrome/browser/application_context_impl.cc b/ios/chrome/browser/application_context_impl.cc
index a5fe46b..003e5de 100644
--- a/ios/chrome/browser/application_context_impl.cc
+++ b/ios/chrome/browser/application_context_impl.cc
@@ -40,6 +40,7 @@
 #include "components/update_client/configurator.h"
 #include "components/update_client/update_query_params.h"
 #include "components/variations/service/variations_service.h"
+#include "components/version_info/channel.h"
 #include "ios/chrome/app/tests_hook.h"
 #include "ios/chrome/browser/application_context.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
@@ -422,8 +423,11 @@
       // BrowserPolicyConnector::OnResourceBundleCreated() will need to be added
       // later in the startup sequence, after the ResourceBundle is initialized.
       DCHECK(ui::ResourceBundle::HasSharedInstance());
+      version_info::Channel channel = ::GetChannel();
       browser_policy_connector_ = std::make_unique<BrowserPolicyConnectorIOS>(
-          base::Bind(&BuildPolicyHandlerList));
+          base::Bind(&BuildPolicyHandlerList,
+                     channel != version_info::Channel::STABLE &&
+                         channel != version_info::Channel::BETA));
 
       // Install a mock platform policy provider, if running under EG2 and one
       // is supplied.
diff --git a/ios/chrome/browser/drag_and_drop/drag_and_drop_flag.mm b/ios/chrome/browser/drag_and_drop/drag_and_drop_flag.mm
index d5a58a7..79dc8de 100644
--- a/ios/chrome/browser/drag_and_drop/drag_and_drop_flag.mm
+++ b/ios/chrome/browser/drag_and_drop/drag_and_drop_flag.mm
@@ -9,7 +9,7 @@
 #endif
 
 const base::Feature kDragAndDrop{"DragAndDrop",
-                                 base::FEATURE_ENABLED_BY_DEFAULT};
+                                 base::FEATURE_DISABLED_BY_DEFAULT};
 
 bool DragAndDropIsEnabled() {
   return base::FeatureList::IsEnabled(kDragAndDrop);
diff --git a/ios/chrome/browser/infobars/overlays/OWNERS b/ios/chrome/browser/infobars/overlays/OWNERS
index 12c5223a..2580b2a 100644
--- a/ios/chrome/browser/infobars/overlays/OWNERS
+++ b/ios/chrome/browser/infobars/overlays/OWNERS
@@ -1,4 +1,3 @@
-kkhorimoto@chromium.org
 sczs@chromium.org
 thegreenfrog@chromium.org
 
diff --git a/ios/chrome/browser/main/BUILD.gn b/ios/chrome/browser/main/BUILD.gn
index b3388ff..7aeb8b5c 100644
--- a/ios/chrome/browser/main/BUILD.gn
+++ b/ios/chrome/browser/main/BUILD.gn
@@ -79,7 +79,6 @@
     "//base",
     "//ios/chrome/browser/browser_state",
     "//ios/chrome/browser/browser_state:test_support",
-    "//ios/chrome/browser/tabs",
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/browser/web_state_list:test_support",
diff --git a/ios/chrome/browser/main/browser_impl.h b/ios/chrome/browser/main/browser_impl.h
index 96ef3ee..c0455af 100644
--- a/ios/chrome/browser/main/browser_impl.h
+++ b/ios/chrome/browser/main/browser_impl.h
@@ -41,10 +41,9 @@
   void RemoveObserver(BrowserObserver* observer) override;
 
  private:
-  // Exposed to allow unittests to inject a TabModel and WebStateList
+  // Exposed to allow unittests to inject a WebStateList
   FRIEND_TEST_ALL_PREFIXES(BrowserImplTest, TestAccessors);
   BrowserImpl(ChromeBrowserState* browser_state,
-              TabModel* tab_model,
               std::unique_ptr<WebStateList> web_state_list);
 
   ChromeBrowserState* browser_state_;
diff --git a/ios/chrome/browser/main/browser_impl.mm b/ios/chrome/browser/main/browser_impl.mm
index eceac9f..cd38991 100644
--- a/ios/chrome/browser/main/browser_impl.mm
+++ b/ios/chrome/browser/main/browser_impl.mm
@@ -35,13 +35,10 @@
 }
 
 BrowserImpl::BrowserImpl(ChromeBrowserState* browser_state,
-                         TabModel* tab_model,
                          std::unique_ptr<WebStateList> web_state_list)
     : browser_state_(browser_state),
-      tab_model_(tab_model),
       web_state_list_(std::move(web_state_list)) {
   DCHECK(browser_state_);
-  DCHECK(tab_model.webStateList == web_state_list_.get());
 }
 
 BrowserImpl::~BrowserImpl() {
diff --git a/ios/chrome/browser/main/browser_impl_unittest.mm b/ios/chrome/browser/main/browser_impl_unittest.mm
index a2dc35ea..3e1f9d5a 100644
--- a/ios/chrome/browser/main/browser_impl_unittest.mm
+++ b/ios/chrome/browser/main/browser_impl_unittest.mm
@@ -24,9 +24,6 @@
             std::make_unique<WebStateList>(&web_state_list_delegate_)) {
     TestChromeBrowserState::Builder test_cbs_builder;
     chrome_browser_state_ = test_cbs_builder.Build();
-
-    tab_model_ = [OCMockObject mockForClass:[TabModel class]];
-    OCMStub([tab_model_ webStateList]).andReturn(web_state_list_.get());
   }
 
   web::WebTaskEnvironment task_environment_;
@@ -35,17 +32,14 @@
   FakeWebStateListDelegate web_state_list_delegate_;
   // Unique ptr to the web_state_list_ to transfer into new Browser instances.
   std::unique_ptr<WebStateList> web_state_list_;
-  id tab_model_;
 };
 
 // Tests that the accessors return the expected values.
 TEST_F(BrowserImplTest, TestAccessors) {
   WebStateList* web_state_list_weak_reference = web_state_list_.get();
-  BrowserImpl browser(chrome_browser_state_.get(), tab_model_,
-                      std::move(web_state_list_));
+  BrowserImpl browser(chrome_browser_state_.get(), std::move(web_state_list_));
 
   EXPECT_EQ(chrome_browser_state_.get(), browser.GetBrowserState());
-  EXPECT_EQ(tab_model_, browser.GetTabModel());
   EXPECT_EQ(web_state_list_weak_reference, browser.GetWebStateList());
 }
 
diff --git a/ios/chrome/browser/main/test_browser.h b/ios/chrome/browser/main/test_browser.h
index aa80fe3..53575f5 100644
--- a/ios/chrome/browser/main/test_browser.h
+++ b/ios/chrome/browser/main/test_browser.h
@@ -13,13 +13,7 @@
 
 class TestBrowser : public Browser {
  public:
-  // Constructor that takes a TabModel.  TestBrowsers created using this
-  // constructor will return return the |tab_model|'s WebStateList for
-  // GetWebStateList().  DEPRECATED: Use this constructor only to test legacy
-  // code that has not been updated to use WebStateList.
-  TestBrowser(ChromeBrowserState* browser_state, TabModel* tab_model);
-  // Constructor that takes a WebStateList.  TestBrowsers created using this
-  // constructor will return nil for GetTabModel().
+  // Constructor that takes a WebStateList.
   TestBrowser(ChromeBrowserState* browser_state, WebStateList* web_state_list);
 
   // Constructor that takes only a BrowserState; an empty web state list will be
diff --git a/ios/chrome/browser/main/test_browser.mm b/ios/chrome/browser/main/test_browser.mm
index b621fd7..c67057b 100644
--- a/ios/chrome/browser/main/test_browser.mm
+++ b/ios/chrome/browser/main/test_browser.mm
@@ -7,7 +7,6 @@
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/main/browser_observer.h"
-#import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #include "ios/chrome/browser/web_state_list/web_state_list.h"
 
@@ -15,12 +14,6 @@
 #error "This file requires ARC support."
 #endif
 
-TestBrowser::TestBrowser(ChromeBrowserState* browser_state, TabModel* tab_model)
-    : command_dispatcher_([[CommandDispatcher alloc] init]),
-      browser_state_(browser_state),
-      tab_model_(tab_model),
-      web_state_list_(tab_model_.webStateList) {}
-
 TestBrowser::TestBrowser(ChromeBrowserState* browser_state,
                          WebStateList* web_state_list)
     : command_dispatcher_([[CommandDispatcher alloc] init]),
diff --git a/ios/chrome/browser/metrics/ukm_egtest.mm b/ios/chrome/browser/metrics/ukm_egtest.mm
index fb6a67fe..cd18254 100644
--- a/ios/chrome/browser/metrics/ukm_egtest.mm
+++ b/ios/chrome/browser/metrics/ukm_egtest.mm
@@ -4,14 +4,10 @@
 
 #include "base/ios/ios_util.h"
 #include "base/macros.h"
-#include "base/stl_util.h"
-#import "base/test/ios/wait_util.h"
-#include "components/strings/grit/components_strings.h"
 #import "ios/chrome/browser/metrics/metrics_app_interface.h"
 #import "ios/chrome/browser/ui/authentication/signin_earl_grey_ui.h"
 #import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils.h"
 #import "ios/chrome/browser/ui/authentication/signin_earlgrey_utils_app_interface.h"
-#include "ios/chrome/grit/ios_strings.h"
 #import "ios/chrome/test/earl_grey/chrome_actions.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
 #import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
@@ -19,24 +15,13 @@
 #import "ios/chrome/test/earl_grey/chrome_test_case.h"
 #import "ios/public/provider/chrome/browser/signin/fake_chrome_identity.h"
 #import "ios/testing/earl_grey/earl_grey_test.h"
-#include "ui/base/l10n/l10n_util.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-using chrome_test_util::AccountsSyncButton;
-using chrome_test_util::ButtonWithAccessibilityLabel;
-using chrome_test_util::ButtonWithAccessibilityLabelId;
-using chrome_test_util::ClearBrowsingDataButton;
-using chrome_test_util::ClearBrowsingDataCell;
-using chrome_test_util::ConfirmClearBrowsingDataButton;
 using chrome_test_util::GoogleServicesSettingsButton;
-using chrome_test_util::SettingsAccountButton;
 using chrome_test_util::SettingsDoneButton;
-using chrome_test_util::SettingsMenuPrivacyButton;
-using chrome_test_util::SyncSwitchCell;
-using chrome_test_util::TurnSyncSwitchOn;
 
 @interface UKMTestCase : ChromeTestCase
 
@@ -160,23 +145,6 @@
   [ChromeEarlGrey waitForMainTabCount:(tabCount + 1)];
 }
 
-// Waits for browsing data to be cleared.
-- (void)clearBrowsingData {
-  [ChromeEarlGreyUI openSettingsMenu];
-  [ChromeEarlGreyUI tapSettingsMenuButton:SettingsMenuPrivacyButton()];
-  [ChromeEarlGreyUI tapPrivacyMenuButton:ClearBrowsingDataCell()];
-  [ChromeEarlGreyUI tapClearBrowsingDataMenuButton:ClearBrowsingDataButton()];
-  [[EarlGrey selectElementWithMatcher:ConfirmClearBrowsingDataButton()]
-      performAction:grey_tap()];
-
-  // Wait until activity indicator modal is cleared, meaning clearing browsing
-  // data has been finished.
-  [[GREYUIThreadExecutor sharedInstance] drainUntilIdle];
-
-  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
-      performAction:grey_tap()];
-}
-
 #pragma mark - Tests
 
 // The tests in this file should correspond to the tests in //chrome/browser/
@@ -394,8 +362,8 @@
 //
 // Corresponds to HistoryDeleteCheck in //chrome/browser/metrics/
 // ukm_browsertest.cc.
-// TODO(crbug.com/866598): Re-enable this test.
-- (void)DISABLED_testHistoryDelete {
+#if defined(CHROME_EARL_GREY_2)
+- (void)testHistoryDelete {
   const uint64_t originalClientID = [MetricsAppInterface UKMClientID];
 
   const uint64_t kDummySourceId = 0x54321;
@@ -403,9 +371,11 @@
   GREYAssert([MetricsAppInterface UKMHasDummySource:kDummySourceId],
              @"Dummy source failed to record.");
 
-  [self clearBrowsingData];
+  [ChromeEarlGrey clearBrowsingHistory];
+  GREYAssertEqual([ChromeEarlGrey getBrowsingHistoryEntryCount], 0,
+                  @"History was unexpectedly non-empty");
 
-  // Other sources may already have been recorded since the data was cleared,
+  // Other sources may have already been recorded since the data was cleared,
   // but the dummy source should be gone.
   GREYAssert(![MetricsAppInterface UKMHasDummySource:kDummySourceId],
              @"Dummy source was not purged.");
@@ -414,5 +384,6 @@
   GREYAssert([MetricsAppInterface checkUKMRecordingEnabled:YES],
              @"Failed to assert that UKM was enabled.");
 }
+#endif  // defined(CHROME_EARL_GREY_2)
 
 @end
diff --git a/ios/chrome/browser/overlays/OWNERS b/ios/chrome/browser/overlays/OWNERS
index 51f8831..9b85e75 100644
--- a/ios/chrome/browser/overlays/OWNERS
+++ b/ios/chrome/browser/overlays/OWNERS
@@ -1,3 +1,2 @@
-kkhorimoto@chromium.org
 michaeldo@chromium.org
-thegreenfrog@chromium.org
\ No newline at end of file
+thegreenfrog@chromium.org
diff --git a/ios/chrome/browser/policy/configuration_policy_handler_list_factory.h b/ios/chrome/browser/policy/configuration_policy_handler_list_factory.h
index 1c57406..64cb3e9 100644
--- a/ios/chrome/browser/policy/configuration_policy_handler_list_factory.h
+++ b/ios/chrome/browser/policy/configuration_policy_handler_list_factory.h
@@ -13,7 +13,10 @@
 }  // namespace policy
 
 // Builds a policy handler list.
+// All un-released policies will be ignored by default unless
+// |allow_future_policies| is True.
 std::unique_ptr<policy::ConfigurationPolicyHandlerList> BuildPolicyHandlerList(
+    bool allow_future_policies,
     const policy::Schema& chrome_schema);
 
 #endif  // IOS_CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_HANDLER_LIST_FACTORY_H_
diff --git a/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm b/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm
index 4e84a82..f612006 100644
--- a/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm
+++ b/ios/chrome/browser/policy/configuration_policy_handler_list_factory.mm
@@ -77,12 +77,13 @@
 }  // namespace
 
 std::unique_ptr<policy::ConfigurationPolicyHandlerList> BuildPolicyHandlerList(
+    bool allow_future_policies,
     const policy::Schema& chrome_schema) {
   DCHECK(IsEnterprisePolicyEnabled());
   std::unique_ptr<policy::ConfigurationPolicyHandlerList> handlers =
       std::make_unique<policy::ConfigurationPolicyHandlerList>(
           base::Bind(&PopulatePolicyHandlerParameters),
-          base::Bind(&policy::GetChromePolicyDetails));
+          base::Bind(&policy::GetChromePolicyDetails), allow_future_policies);
 
   // Check the feature flag before adding handlers to the list.
   if (!ShouldInstallEnterprisePolicyHandlers()) {
diff --git a/ios/chrome/browser/policy/enterprise_policy_test_helper.cc b/ios/chrome/browser/policy/enterprise_policy_test_helper.cc
index fd7170f..ad40b46 100644
--- a/ios/chrome/browser/policy/enterprise_policy_test_helper.cc
+++ b/ios/chrome/browser/policy/enterprise_policy_test_helper.cc
@@ -21,7 +21,7 @@
   // Create a BrowserPolicyConnectorIOS, install the mock policy
   // provider, and hook up Local State.
   browser_policy_connector_ = std::make_unique<BrowserPolicyConnectorIOS>(
-      base::Bind(&BuildPolicyHandlerList));
+      base::Bind(&BuildPolicyHandlerList, /* allow_future_policies= */ true));
   browser_policy_connector_->SetPolicyProviderForTesting(&policy_provider_);
 
   scoped_refptr<PrefRegistrySimple> local_state_registry(
diff --git a/ios/chrome/browser/safe_browsing/OWNERS b/ios/chrome/browser/safe_browsing/OWNERS
index d936253f..29a6a0b 100644
--- a/ios/chrome/browser/safe_browsing/OWNERS
+++ b/ios/chrome/browser/safe_browsing/OWNERS
@@ -1,5 +1,4 @@
 ajuma@chromium.org
-kkhorimoto@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h
index 1f9bb67..a096a99 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.h
@@ -42,8 +42,8 @@
 
   // Starts the NSURLRequest with the cookie list.
   void FetchPendingRequestWithCookies(
-      const net::CookieStatusList& cookies,
-      const net::CookieStatusList& excluded_cookies);
+      const net::CookieAccessResultList& cookies_with_access_results,
+      const net::CookieAccessResultList& excluded_cookies);
   // Creates a NSURLSession, and sets its delegate.
   virtual NSURLSession* CreateNSURLSession(
       id<NSURLSessionTaskDelegate> url_session_delegate);
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm
index 87dba03..7d6f1b6 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm
@@ -128,8 +128,8 @@
 }
 
 void GaiaAuthFetcherIOSNSURLSessionBridge::FetchPendingRequestWithCookies(
-    const net::CookieStatusList& cookies_with_statuses,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies_with_access_results,
+    const net::CookieAccessResultList& excluded_cookies) {
   DCHECK(!url_session_);
   url_session_ = CreateNSURLSession(url_session_delegate_);
   url_session_delegate_.requestSession = url_session_;
@@ -143,11 +143,11 @@
                                                       response:response
                                                          error:error];
                       }];
-  NSMutableArray* http_cookies =
-      [[NSMutableArray alloc] initWithCapacity:cookies_with_statuses.size()];
-  for (const auto& cookie_with_status : cookies_with_statuses) {
+  NSMutableArray* http_cookies = [[NSMutableArray alloc]
+      initWithCapacity:cookies_with_access_results.size()];
+  for (const auto& cookie_with_access_result : cookies_with_access_results) {
     [http_cookies addObject:net::SystemCookieFromCanonicalCookie(
-                                cookie_with_status.cookie)];
+                                cookie_with_access_result.cookie)];
   }
   [url_session_.configuration.HTTPCookieStorage
       storeCookies:http_cookies
diff --git a/ios/chrome/browser/ui/activity_services/activities/BUILD.gn b/ios/chrome/browser/ui/activity_services/activities/BUILD.gn
index a510936..22bde5f 100644
--- a/ios/chrome/browser/ui/activity_services/activities/BUILD.gn
+++ b/ios/chrome/browser/ui/activity_services/activities/BUILD.gn
@@ -44,7 +44,6 @@
     "//ios/chrome/browser/ui/activity_services/data",
     "//ios/chrome/browser/ui/activity_services/requirements",
     "//ios/chrome/browser/ui/commands",
-    "//ios/chrome/browser/ui/context_menu",
     "//ios/chrome/browser/ui/util",
     "//ios/web/common:user_agent",
     "//ios/web/public",
diff --git a/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.mm b/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.mm
index 95103cdd..eb9fd14 100644
--- a/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.mm
+++ b/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.mm
@@ -4,6 +4,8 @@
 
 #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
 
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/strings/grit/ui_strings.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
@@ -74,6 +76,19 @@
   return self;
 }
 
+#pragma mark - ChromeCoordinator
+
+- (void)start {
+  if (!self.cancelButtonAdded) {
+    [self addItemWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL)
+                    action:nil
+                     style:UIAlertActionStyleCancel];
+  }
+  [super start];
+}
+
+#pragma mark - AlertCoordinator
+
 - (UIAlertController*)alertControllerWithTitle:(NSString*)title
                                        message:(NSString*)message {
   UIAlertController* alert =
@@ -96,6 +111,8 @@
   return alert;
 }
 
+#pragma mark - Public Methods
+
 - (void)updateAttributedText {
   // Use setValue to access unexposed attributed strings for title and message.
   if (self.attributedTitle) {
diff --git a/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator_unittest.mm b/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator_unittest.mm
index c9488f8..83aba96 100644
--- a/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator_unittest.mm
+++ b/ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator_unittest.mm
@@ -10,45 +10,70 @@
 #import "base/test/task_environment.h"
 #import "ios/chrome/browser/main/test_browser.h"
 #import "ios/chrome/test/scoped_key_window.h"
+#import "testing/gtest_mac.h"
 #include "testing/platform_test.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/strings/grit/ui_strings.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-using ActionSheetCoordinatorTest = PlatformTest;
+class ActionSheetCoordinatorTest : public PlatformTest {
+ protected:
+  ActionSheetCoordinatorTest() : browser_(std::make_unique<TestBrowser>()) {}
+
+  void SetUp() override {
+    base_view_controller_ = [[UIViewController alloc] init];
+    [scoped_key_window_.Get() setRootViewController:base_view_controller_];
+
+    test_view_ =
+        [[UIView alloc] initWithFrame:base_view_controller_.view.bounds];
+    [base_view_controller_.view addSubview:test_view_];
+  }
+
+  ActionSheetCoordinator* CreateCoordinator() {
+    return [[ActionSheetCoordinator alloc]
+        initWithBaseViewController:base_view_controller_
+                           browser:browser_.get()
+                             title:@"Some Title"
+                           message:nil
+                              rect:CGRectMake(124, 432, 126, 63)
+                              view:test_view_];
+  }
+
+  UIAlertController* GetAlertController() {
+    EXPECT_TRUE([base_view_controller_.presentedViewController
+        isKindOfClass:[UIAlertController class]]);
+    return base::mac::ObjCCastStrict<UIAlertController>(
+        base_view_controller_.presentedViewController);
+  }
+
+  base::test::TaskEnvironment task_environment_;
+
+  ScopedKeyWindow scoped_key_window_;
+  std::unique_ptr<TestBrowser> browser_;
+  UIViewController* base_view_controller_;
+  UIView* test_view_;
+};
 
 // Tests that if there is a popover, it uses the CGRect passed in init.
 TEST_F(ActionSheetCoordinatorTest, CGRectUsage) {
-  base::test::TaskEnvironment task_environment_;
-
-  ScopedKeyWindow scoped_key_window;
-  UIViewController* viewController = [[UIViewController alloc] init];
-  std::unique_ptr<Browser> browser_ = std::make_unique<TestBrowser>();
-  [scoped_key_window.Get() setRootViewController:viewController];
-
-  UIView* view = [[UIView alloc] initWithFrame:viewController.view.bounds];
-
-  [viewController.view addSubview:view];
   CGRect rect = CGRectMake(124, 432, 126, 63);
-  AlertCoordinator* alertCoordinator =
-      [[ActionSheetCoordinator alloc] initWithBaseViewController:viewController
-                                                         browser:browser_.get()
-                                                           title:@"title"
-                                                         message:nil
-                                                            rect:rect
-                                                            view:view];
+  AlertCoordinator* alertCoordinator = [[ActionSheetCoordinator alloc]
+      initWithBaseViewController:base_view_controller_
+                         browser:browser_.get()
+                           title:@"title"
+                         message:nil
+                            rect:rect
+                            view:test_view_];
 
   // Action.
   [alertCoordinator start];
 
   // Test.
   // Get the alert.
-  EXPECT_TRUE([viewController.presentedViewController
-      isKindOfClass:[UIAlertController class]]);
-  UIAlertController* alertController =
-      base::mac::ObjCCastStrict<UIAlertController>(
-          viewController.presentedViewController);
+  UIAlertController* alertController = GetAlertController();
 
   // Test the results.
   EXPECT_EQ(UIAlertControllerStyleActionSheet, alertController.preferredStyle);
@@ -57,8 +82,97 @@
     UIPopoverPresentationController* popover =
         alertController.popoverPresentationController;
     EXPECT_TRUE(CGRectEqualToRect(rect, popover.sourceRect));
-    EXPECT_EQ(view, popover.sourceView);
+    EXPECT_EQ(test_view_, popover.sourceView);
   }
 
   [alertCoordinator stop];
 }
+
+// Tests that initializing with a location properly sets the popover sourceRect.
+TEST_F(ActionSheetCoordinatorTest, Location_CGRectUsage) {
+  CGRect rect = CGRectMake(12, 13, 1.0, 1.0);
+
+  AlertCoordinator* alertCoordinator = [[ActionSheetCoordinator alloc]
+      initWithBaseViewController:base_view_controller_
+                         browser:browser_.get()
+                           title:@"title"
+                         message:nil
+                            rect:rect
+                            view:test_view_];
+
+  // Action.
+  [alertCoordinator start];
+
+  // Test.
+  // Get the alert.
+  UIAlertController* alertController = GetAlertController();
+
+  // Test the results.
+  EXPECT_EQ(UIAlertControllerStyleActionSheet, alertController.preferredStyle);
+
+  if (alertController.popoverPresentationController) {
+    UIPopoverPresentationController* popover =
+        alertController.popoverPresentationController;
+    EXPECT_TRUE(CGRectEqualToRect(rect, popover.sourceRect));
+    EXPECT_EQ(test_view_, popover.sourceView);
+  }
+
+  [alertCoordinator stop];
+}
+
+// Tests that a Cancel action is added by default upon starting.
+TEST_F(ActionSheetCoordinatorTest, Start_AddCancel) {
+  ActionSheetCoordinator* coordinator = CreateCoordinator();
+
+  // Add a basic, non-cancel, action.
+  NSString* addActionTitle = @"Add";
+  [coordinator addItemWithTitle:addActionTitle
+                         action:nil
+                          style:UIAlertActionStyleDefault];
+
+  EXPECT_FALSE(coordinator.cancelButtonAdded);
+
+  [coordinator start];
+
+  EXPECT_TRUE(coordinator.cancelButtonAdded);
+
+  // Verify that there are two actions total.
+  UIAlertController* alertController = GetAlertController();
+  EXPECT_EQ(2U, [alertController.actions count]);
+
+  UIAlertAction* addAction = alertController.actions[0];
+  EXPECT_EQ(addActionTitle, addAction.title);
+  EXPECT_EQ(UIAlertActionStyleDefault, addAction.style);
+
+  UIAlertAction* cancelAction = alertController.actions[1];
+  EXPECT_NSEQ(l10n_util::GetNSString(IDS_APP_CANCEL), cancelAction.title);
+  EXPECT_EQ(UIAlertActionStyleCancel, cancelAction.style);
+}
+
+// Tests that a Cancel action is not added upon starting when another Cancel
+// action was already added.
+TEST_F(ActionSheetCoordinatorTest, Start_SkipCancel_IfAdded) {
+  ActionSheetCoordinator* coordinator = CreateCoordinator();
+
+  EXPECT_FALSE(coordinator.cancelButtonAdded);
+
+  // Add a cancel action.
+  NSString* cancelActionTitle = @"Some Cancel Text";
+  [coordinator addItemWithTitle:cancelActionTitle
+                         action:nil
+                          style:UIAlertActionStyleCancel];
+
+  EXPECT_TRUE(coordinator.cancelButtonAdded);
+
+  [coordinator start];
+
+  EXPECT_TRUE(coordinator.cancelButtonAdded);
+
+  // Verify that there is only one action in total.
+  UIAlertController* alertController = GetAlertController();
+  EXPECT_EQ(1U, [alertController.actions count]);
+
+  UIAlertAction* cancelAction = alertController.actions[0];
+  EXPECT_EQ(cancelActionTitle, cancelAction.title);
+  EXPECT_EQ(UIAlertActionStyleCancel, cancelAction.style);
+}
diff --git a/ios/chrome/browser/ui/alert_view/OWNERS b/ios/chrome/browser/ui/alert_view/OWNERS
deleted file mode 100644
index bd85dcf2..0000000
--- a/ios/chrome/browser/ui/alert_view/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-kkhorimoto@chromium.org
-
-# TEAM: ios-directory-owners@chromium.org
-# OS: iOS
diff --git a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
index 02565101..0d69ca5 100644
--- a/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/user_signin/user_signin_coordinator.mm
@@ -102,9 +102,6 @@
 - (void)start {
   [super start];
   self.viewController = [[UserSigninViewController alloc] init];
-  if (@available(iOS 13, *)) {
-    self.viewController.presentationController.delegate = self;
-  }
   self.viewController.delegate = self;
   self.viewController.useFirstRunSkipButton =
       self.signinIntent == UserSigninIntentFirstRun;
@@ -396,7 +393,12 @@
 // controller. First run requires an additional transitional fade animation when
 // presenting this view.
 - (void)presentUserSigninViewController {
+  // Always set the -UIViewController.modalPresentationStyle before accessing
+  // -UIViewController.presentationController.
   self.viewController.modalPresentationStyle = UIModalPresentationFormSheet;
+  if (@available(iOS 13, *)) {
+    self.viewController.presentationController.delegate = self;
+  }
   switch (self.signinIntent) {
     case UserSigninIntentFirstRun: {
       // Displays the sign-in screen with transitions specific to first-run.
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 c0fc6a4..a4fbe8d 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -1643,10 +1643,6 @@
                            [weakSelf moveNodes:nodes];
                          }
                           style:UIAlertActionStyleDefault];
-
-  [coordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                         action:nil
-                          style:UIAlertActionStyleCancel];
 }
 
 - (void)configureCoordinator:(AlertCoordinator*)coordinator
@@ -1696,10 +1692,6 @@
                   [weakSelf setTableViewEditing:NO];
                 }
                  style:UIAlertActionStyleDefault];
-
-  [coordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                         action:nil
-                          style:UIAlertActionStyleCancel];
 }
 
 - (void)configureCoordinator:(AlertCoordinator*)coordinator
@@ -1731,10 +1723,6 @@
     coordinator.alertController.actions[0].enabled = NO;
     coordinator.alertController.actions[1].enabled = NO;
   }
-
-  [coordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                         action:nil
-                          style:UIAlertActionStyleCancel];
 }
 
 - (void)configureCoordinator:(AlertCoordinator*)coordinator
@@ -1750,10 +1738,6 @@
                            [weakSelf moveNodes:nodes];
                          }
                           style:UIAlertActionStyleDefault];
-
-  [coordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                         action:nil
-                          style:UIAlertActionStyleCancel];
 }
 
 #pragma mark - UIGestureRecognizerDelegate and gesture handling
diff --git a/ios/chrome/browser/ui/browser_container/OWNERS b/ios/chrome/browser/ui/browser_container/OWNERS
deleted file mode 100644
index a8416a4..0000000
--- a/ios/chrome/browser/ui/browser_container/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-eugenebut@chromium.org
-kkhorimoto@chromium.org
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn
index 423a1bd..9d1fbdf 100644
--- a/ios/chrome/browser/ui/browser_view/BUILD.gn
+++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -89,7 +89,6 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/content_suggestions",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant",
-    "//ios/chrome/browser/ui/context_menu",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/dialogs:dialogs_internal",
     "//ios/chrome/browser/ui/download",
diff --git a/ios/chrome/browser/ui/browser_view/OWNERS b/ios/chrome/browser/ui/browser_view/OWNERS
index 39e8096..bf4adb1 100644
--- a/ios/chrome/browser/ui/browser_view/OWNERS
+++ b/ios/chrome/browser/ui/browser_view/OWNERS
@@ -6,7 +6,6 @@
 # BVC OWNERS for small changes. Please refer larger changes to one
 # of the above OWNERs.
 per-file browser_view_controller*=edchin@chromium.org
-per-file browser_view_controller*=kkhorimoto@chromium.org
 per-file browser_view_controller*=gambard@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
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 ac809b9..a9660894 100644
--- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -62,6 +62,7 @@
 #import "ios/chrome/browser/ssl/captive_portal_detector_tab_helper_delegate.h"
 #import "ios/chrome/browser/translate/chrome_ios_translate_client.h"
 #import "ios/chrome/browser/ui/activity_services/requirements/activity_service_positioner.h"
+#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
 #import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/re_signin_infobar_delegate.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmark_interaction_controller.h"
@@ -77,7 +78,6 @@
 #import "ios/chrome/browser/ui/commands/show_signin_command.h"
 #import "ios/chrome/browser/ui/commands/text_zoom_commands.h"
 #import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
-#import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
 #import "ios/chrome/browser/ui/download/download_manager_coordinator.h"
 #import "ios/chrome/browser/ui/elements/activity_overlay_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/first_run_util.h"
@@ -360,8 +360,8 @@
   // Controller for edge swipe gestures for page and tab navigation.
   SideSwipeController* _sideSwipeController;
 
-  // Handles displaying the context menu for all form factors.
-  ContextMenuCoordinator* _contextMenuCoordinator;
+  // Handles displaying the action sheet for all form factors.
+  ActionSheetCoordinator* _contextMenuCoordinator;
 
   // Handles presentation of JavaScript dialogs.
   std::unique_ptr<web::JavaScriptDialogPresenter> _javaScriptDialogPresenter;
@@ -2936,12 +2936,14 @@
 
   DCHECK(self.browserState);
 
-  _contextMenuCoordinator = [[ContextMenuCoordinator alloc]
+  _contextMenuCoordinator = [[ActionSheetCoordinator alloc]
       initWithBaseViewController:self
                          browser:self.browser
                            title:params.menu_title
-                          inView:params.view
-                      atLocation:params.location];
+                         message:nil
+                            rect:CGRectMake(params.location.x,
+                                            params.location.y, 1.0, 1.0)
+                            view:params.view];
 
   NSString* title = nil;
   ProceduralBlock action = nil;
@@ -2966,7 +2968,9 @@
         Record(ACTION_OPEN_JAVASCRIPT, isImage, isLink);
         [weakSelf openJavascript:base::SysUTF8ToNSString(link.GetContent())];
       };
-      [_contextMenuCoordinator addItemWithTitle:title action:action];
+      [_contextMenuCoordinator addItemWithTitle:title
+                                         action:action
+                                          style:UIAlertActionStyleDefault];
     }
 
     if (web::UrlHasWebScheme(link)) {
@@ -2994,7 +2998,9 @@
         params.origin_point = originPoint;
         UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params);
       };
-      [_contextMenuCoordinator addItemWithTitle:title action:action];
+      [_contextMenuCoordinator addItemWithTitle:title
+                                         action:action
+                                          style:UIAlertActionStyleDefault];
 
       if (IsMultiwindowSupported()) {
         // Open in New Window.
@@ -3016,7 +3022,9 @@
                                 strongSelf.isOffTheRecord);
           [strongSelf.dispatcher openNewWindowWithActivity:loadURLActivity];
         };
-        [_contextMenuCoordinator addItemWithTitle:title action:action];
+        [_contextMenuCoordinator addItemWithTitle:title
+                                           action:action
+                                            style:UIAlertActionStyleDefault];
       }
       if (!_isOffTheRecord) {
         // Open in Incognito Tab.
@@ -3037,7 +3045,9 @@
           params.append_to = kCurrentTab;
           UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params);
         };
-        [_contextMenuCoordinator addItemWithTitle:title action:action];
+        [_contextMenuCoordinator addItemWithTitle:title
+                                           action:action
+                                            style:UIAlertActionStyleDefault];
       }
     }
     if (link.SchemeIsHTTPOrHTTPS()) {
@@ -3052,7 +3062,9 @@
           Record(ACTION_READ_LATER, isImage, isLink);
           [weakSelf addToReadingListURL:link title:innerText];
         };
-        [_contextMenuCoordinator addItemWithTitle:title action:action];
+        [_contextMenuCoordinator addItemWithTitle:title
+                                           action:action
+                                            style:UIAlertActionStyleDefault];
       }
     }
     // Copy Link.
@@ -3063,7 +3075,9 @@
       Record(ACTION_COPY_LINK_ADDRESS, isImage, isLink);
       StoreURLInPasteboard(link);
     };
-    [_contextMenuCoordinator addItemWithTitle:title action:action];
+    [_contextMenuCoordinator addItemWithTitle:title
+                                       action:action
+                                        style:UIAlertActionStyleDefault];
   }
   if (isImage) {
     base::RecordAction(
@@ -3079,7 +3093,9 @@
                                  referrer:referrer
                                  webState:weakSelf.currentWebState];
     };
-    [_contextMenuCoordinator addItemWithTitle:title action:action];
+    [_contextMenuCoordinator addItemWithTitle:title
+                                       action:action
+                                        style:UIAlertActionStyleDefault];
     // Copy Image.
     title = l10n_util::GetNSStringWithFixup(IDS_IOS_CONTENT_CONTEXT_COPYIMAGE);
     action = ^{
@@ -3091,7 +3107,9 @@
                                   referrer:referrer
                                   webState:weakSelf.currentWebState];
     };
-    [_contextMenuCoordinator addItemWithTitle:title action:action];
+    [_contextMenuCoordinator addItemWithTitle:title
+                                       action:action
+                                        style:UIAlertActionStyleDefault];
     // Open Image.
     title = l10n_util::GetNSStringWithFixup(IDS_IOS_CONTENT_CONTEXT_OPENIMAGE);
     action = ^{
@@ -3105,7 +3123,9 @@
       UrlLoadingBrowserAgent::FromBrowser(self.browser)
           ->Load(UrlLoadParams::InCurrentTab(imageUrl));
     };
-    [_contextMenuCoordinator addItemWithTitle:title action:action];
+    [_contextMenuCoordinator addItemWithTitle:title
+                                       action:action
+                                        style:UIAlertActionStyleDefault];
     // Open Image In New Tab.
     title = l10n_util::GetNSStringWithFixup(
         IDS_IOS_CONTENT_CONTEXT_OPENIMAGENEWTAB);
@@ -3125,7 +3145,9 @@
       params.origin_point = originPoint;
       UrlLoadingBrowserAgent::FromBrowser(self.browser)->Load(params);
     };
-    [_contextMenuCoordinator addItemWithTitle:title action:action];
+    [_contextMenuCoordinator addItemWithTitle:title
+                                       action:action
+                                        style:UIAlertActionStyleDefault];
 
     TemplateURLService* service =
         ios::TemplateURLServiceFactory::GetForBrowserState(self.browserState);
@@ -3144,7 +3166,9 @@
           [weakSelf searchByImageData:data atURL:imageUrl];
         });
       };
-      [_contextMenuCoordinator addItemWithTitle:title action:action];
+      [_contextMenuCoordinator addItemWithTitle:title
+                                         action:action
+                                          style:UIAlertActionStyleDefault];
     }
   }
 
@@ -3414,14 +3438,17 @@
                    didTriggerAction:(OverscrollAction)action {
   switch (action) {
     case OverscrollAction::NEW_TAB:
+      base::RecordAction(base::UserMetricsAction("MobilePullGestureNewTab"));
       [self.dispatcher
           openURLInNewTab:[OpenNewTabCommand
                               commandWithIncognito:self.isOffTheRecord]];
       break;
     case OverscrollAction::CLOSE_TAB:
+      base::RecordAction(base::UserMetricsAction("MobilePullGestureCloseTab"));
       [self.dispatcher closeCurrentTab];
       break;
     case OverscrollAction::REFRESH:
+      base::RecordAction(base::UserMetricsAction("MobilePullGestureReload"));
       // Instruct the SnapshotTabHelper to ignore the next load event.
       // Attempting to snapshot while the overscroll "bounce back" animation is
       // occurring will cut the animation short.
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.mm
index fb2a3fa..9450ca0f 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.mm
@@ -93,11 +93,6 @@
                                 }
                               }
                                style:UIAlertActionStyleDestructive];
-
-  [alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL)
-                              action:^{
-                              }
-                               style:UIAlertActionStyleCancel];
   return alertCoordinator;
 }
 
diff --git a/ios/chrome/browser/ui/context_menu/BUILD.gn b/ios/chrome/browser/ui/context_menu/BUILD.gn
deleted file mode 100644
index d02973ff..0000000
--- a/ios/chrome/browser/ui/context_menu/BUILD.gn
+++ /dev/null
@@ -1,32 +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.
-
-source_set("context_menu") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "context_menu_coordinator.h",
-    "context_menu_coordinator.mm",
-  ]
-  deps = [
-    "//base",
-    "//ios/chrome/browser",
-    "//ios/chrome/browser/ui/alert_coordinator",
-    "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
-    "//ui/base",
-    "//ui/strings",
-  ]
-}
-
-source_set("unit_tests") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  testonly = true
-  sources = [ "context_menu_coordinator_unittest.mm" ]
-  deps = [
-    ":context_menu",
-    "//base",
-    "//base/test:test_support",
-    "//ios/chrome/browser/main:test_support",
-    "//testing/gtest",
-  ]
-}
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.h b/ios/chrome/browser/ui/context_menu/context_menu_coordinator.h
deleted file mode 100644
index 0123167..0000000
--- a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.h
+++ /dev/null
@@ -1,42 +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 IOS_CHROME_BROWSER_UI_CONTEXT_MENU_CONTEXT_MENU_COORDINATOR_H_
-#define IOS_CHROME_BROWSER_UI_CONTEXT_MENU_CONTEXT_MENU_COORDINATOR_H_
-
-#import <UIKit/UIKit.h>
-
-#include "base/ios/block_types.h"
-#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
-
-// Abstracts displaying context menus for all device form factors. Will show a
-// sheet on the phone and use a popover on a tablet.
-// Once this coordinator is stopped, the underlying alert and any menu items
-// which have been added are deleted.
-@interface ContextMenuCoordinator : ChromeCoordinator
-
-// Whether the context menu is visible. This will be true after |-start| is
-// called until a subsequent |-stop|.
-@property(nonatomic, readonly, getter=isVisible) BOOL visible;
-
-// Initializes context menu with |title| which may be nil if context menu does
-// not need a title. For iPad where context menu may be presented at a specific
-// location, the context menu will originate from |location| in |view|.
-// Context menu will be presented from |viewController|.
-- (instancetype)initWithBaseViewController:(UIViewController*)viewController
-                                   browser:(Browser*)browser
-                                     title:(NSString*)title
-                                    inView:(UIView*)view
-                                atLocation:(CGPoint)location
-    NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)initWithBaseViewController:(UIViewController*)viewController
-                                   browser:(Browser*)browser NS_UNAVAILABLE;
-
-// Adds an item at the end of the menu if |visible| is false.
-- (void)addItemWithTitle:(NSString*)title action:(ProceduralBlock)action;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_CONTEXT_MENU_CONTEXT_MENU_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.mm b/ios/chrome/browser/ui/context_menu/context_menu_coordinator.mm
deleted file mode 100644
index bfe4f10e..0000000
--- a/ios/chrome/browser/ui/context_menu/context_menu_coordinator.mm
+++ /dev/null
@@ -1,68 +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.
-
-#import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
-
-#import <UIKit/UIKit.h>
-
-#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
-#include "ui/base/l10n/l10n_util.h"
-#include "ui/strings/grit/ui_strings.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface ContextMenuCoordinator () {
-  // Coordinator handling the alert.
-  ActionSheetCoordinator* _alertCoordinator;
-}
-@end
-
-@implementation ContextMenuCoordinator
-
-- (instancetype)initWithBaseViewController:(UIViewController*)viewController
-                                   browser:(Browser*)browser
-                                     title:(NSString*)title
-                                    inView:(UIView*)view
-                                atLocation:(CGPoint)location {
-  self = [super initWithBaseViewController:viewController browser:browser];
-  if (self) {
-    _alertCoordinator = [[ActionSheetCoordinator alloc]
-        initWithBaseViewController:viewController
-                           browser:browser
-                             title:title
-                           message:nil
-                              rect:CGRectMake(location.x, location.y, 1.0, 1.0)
-                              view:view];
-  }
-  return self;
-}
-
-#pragma mark - Public Methods
-
-- (void)addItemWithTitle:(NSString*)title action:(ProceduralBlock)actionBlock {
-  [_alertCoordinator addItemWithTitle:title
-                               action:actionBlock
-                                style:UIAlertActionStyleDefault];
-}
-
-- (void)start {
-  [_alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL)
-                               action:nil
-                                style:UIAlertActionStyleCancel];
-  [_alertCoordinator start];
-}
-
-- (void)stop {
-  [_alertCoordinator stop];
-}
-
-#pragma mark - Property Implementation
-
-- (BOOL)isVisible {
-  return [_alertCoordinator isVisible];
-}
-
-@end
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_coordinator_unittest.mm b/ios/chrome/browser/ui/context_menu/context_menu_coordinator_unittest.mm
deleted file mode 100644
index 4cc2fc1..0000000
--- a/ios/chrome/browser/ui/context_menu/context_menu_coordinator_unittest.mm
+++ /dev/null
@@ -1,155 +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.
-
-#import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
-
-#import <UIKit/UIKit.h>
-
-#import "base/mac/foundation_util.h"
-#import "base/test/task_environment.h"
-#import "ios/chrome/browser/main/test_browser.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-// Fixture to test ContextMenuCoordinator.
-class ContextMenuCoordinatorTest : public PlatformTest {
- public:
-  ContextMenuCoordinatorTest() {
-    // Save the current key window and restore it after the test.
-    previous_key_window_ = [[UIApplication sharedApplication] keyWindow];
-    window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
-    [window_ makeKeyAndVisible];
-    view_controller_ = [[UIViewController alloc] init];
-    [window_ setRootViewController:view_controller_];
-    browser_ = std::make_unique<TestBrowser>();
-  }
-
-  ~ContextMenuCoordinatorTest() override {
-    [previous_key_window_ makeKeyAndVisible];
-  }
-
- protected:
-  base::test::TaskEnvironment task_environment_;
-
-  UIWindow* previous_key_window_;
-  ContextMenuCoordinator* menu_coordinator_;
-  UIWindow* window_;
-  UIViewController* view_controller_;
-  std::unique_ptr<Browser> browser_;
-};
-
-// Tests the context menu reports as visible after presenting.
-TEST_F(ContextMenuCoordinatorTest, ValidateIsVisible) {
-  menu_coordinator_ = [[ContextMenuCoordinator alloc]
-      initWithBaseViewController:view_controller_
-                         browser:browser_.get()
-                           title:@"Context Menu"
-                          inView:view_controller_.view
-                      atLocation:CGPointZero];
-  [menu_coordinator_ start];
-  EXPECT_TRUE([menu_coordinator_ isVisible]);
-}
-
-// Tests the context menu dismissal.
-TEST_F(ContextMenuCoordinatorTest, ValidateDismissalOnStop) {
-  menu_coordinator_ = [[ContextMenuCoordinator alloc]
-      initWithBaseViewController:view_controller_
-                         browser:browser_.get()
-                           title:nil
-                          inView:view_controller_.view
-                      atLocation:CGPointZero];
-  [menu_coordinator_ start];
-  [menu_coordinator_ stop];
-  EXPECT_FALSE([menu_coordinator_ isVisible]);
-}
-
-// Tests that only the expected actions are present on the context menu.
-TEST_F(ContextMenuCoordinatorTest, ValidateActions) {
-  menu_coordinator_ = [[ContextMenuCoordinator alloc]
-      initWithBaseViewController:view_controller_
-                         browser:browser_.get()
-                           title:nil
-                          inView:view_controller_.view
-                      atLocation:CGPointZero];
-
-  NSArray* menu_titles = @[ @"foo", @"bar" ];
-  for (NSString* title in menu_titles) {
-    [menu_coordinator_ addItemWithTitle:title
-                                 action:^{
-                                 }];
-  }
-
-  [menu_coordinator_ start];
-
-  EXPECT_TRUE([[view_controller_ presentedViewController]
-      isKindOfClass:[UIAlertController class]]);
-  UIAlertController* alert_controller =
-      base::mac::ObjCCastStrict<UIAlertController>(
-          [view_controller_ presentedViewController]);
-
-  NSMutableArray* remaining_titles = [menu_titles mutableCopy];
-  for (UIAlertAction* action in alert_controller.actions) {
-    if (action.style != UIAlertActionStyleCancel) {
-      EXPECT_TRUE([remaining_titles containsObject:action.title]);
-      [remaining_titles removeObject:action.title];
-    }
-  }
-
-  EXPECT_EQ(0LU, [remaining_titles count]);
-}
-
-// Validates that the cancel action is present on the context menu.
-TEST_F(ContextMenuCoordinatorTest, CancelButtonExists) {
-  menu_coordinator_ = [[ContextMenuCoordinator alloc]
-      initWithBaseViewController:view_controller_
-                         browser:browser_.get()
-                           title:nil
-                          inView:view_controller_.view
-                      atLocation:CGPointZero];
-
-  [menu_coordinator_ start];
-
-  EXPECT_TRUE([[view_controller_ presentedViewController]
-      isKindOfClass:[UIAlertController class]]);
-  UIAlertController* alert_controller =
-      base::mac::ObjCCastStrict<UIAlertController>(
-          [view_controller_ presentedViewController]);
-
-  EXPECT_EQ(1LU, alert_controller.actions.count);
-  EXPECT_EQ(UIAlertActionStyleCancel,
-            [alert_controller.actions.firstObject style]);
-}
-
-// Tests that the ContextMenuParams are used to display context menu.
-TEST_F(ContextMenuCoordinatorTest, ValidateContextMenuParams) {
-  CGPoint location = CGPointMake(100.0, 125.0);
-  NSString* title = @"Context Menu Title";
-  menu_coordinator_ = [[ContextMenuCoordinator alloc]
-      initWithBaseViewController:view_controller_
-                         browser:browser_.get()
-                           title:title
-                          inView:view_controller_.view
-                      atLocation:location];
-  [menu_coordinator_ start];
-
-  EXPECT_TRUE([[view_controller_ presentedViewController]
-      isKindOfClass:[UIAlertController class]]);
-  UIAlertController* alert_controller =
-      base::mac::ObjCCastStrict<UIAlertController>(
-          [view_controller_ presentedViewController]);
-
-  EXPECT_EQ(title, alert_controller.title);
-
-  // Only validate the popover location if it is displayed in a popover.
-  if (alert_controller.popoverPresentationController) {
-    CGPoint presentedLocation =
-        alert_controller.popoverPresentationController.sourceRect.origin;
-    EXPECT_EQ(location.x, presentedLocation.x);
-    EXPECT_EQ(location.y, presentedLocation.y);
-  }
-}
diff --git a/ios/chrome/browser/ui/coordinators/OWNERS b/ios/chrome/browser/ui/coordinators/OWNERS
index 1f7a7b8..f49ed38 100644
--- a/ios/chrome/browser/ui/coordinators/OWNERS
+++ b/ios/chrome/browser/ui/coordinators/OWNERS
@@ -1,2 +1 @@
-kkhorimoto@chromium.org
 marq@chromium.org
diff --git a/ios/chrome/browser/ui/dialogs/OWNERS b/ios/chrome/browser/ui/dialogs/OWNERS
index bd85dcf2..f58cd95 100644
--- a/ios/chrome/browser/ui/dialogs/OWNERS
+++ b/ios/chrome/browser/ui/dialogs/OWNERS
@@ -1,4 +1,4 @@
-kkhorimoto@chromium.org
+thegreenfrog@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator.h b/ios/chrome/browser/ui/download/download_manager_mediator.h
index 08a9f85..dd44a124 100644
--- a/ios/chrome/browser/ui/download/download_manager_mediator.h
+++ b/ios/chrome/browser/ui/download/download_manager_mediator.h
@@ -57,6 +57,10 @@
   // Updates consumer from web::DownloadTask.
   void UpdateConsumer();
 
+  // Moves the downloaded file to user's Documents if it exists.
+  void MoveToUserDocumentsIfFileExists(base::FilePath download_path_,
+                                       bool file_exists);
+
   // Restores the download path once the downloaded file has been moved to
   // user's Documents.
   void RestoreDownloadPath(base::FilePath user_download_path,
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator.mm b/ios/chrome/browser/ui/download/download_manager_mediator.mm
index 3ce11779..ed87ffca 100644
--- a/ios/chrome/browser/ui/download/download_manager_mediator.mm
+++ b/ios/chrome/browser/ui/download/download_manager_mediator.mm
@@ -127,17 +127,12 @@
 
     if (base::FeatureList::IsEnabled(
             web::features::kEnablePersistentDownloads)) {
-      base::FilePath user_download_path;
-      GetDownloadsDirectory(&user_download_path);
-      user_download_path = user_download_path.Append(
-          base::UTF16ToUTF8(task_->GetSuggestedFilename()));
-
       base::ThreadPool::PostTaskAndReplyWithResult(
           FROM_HERE,
           {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
-          base::Bind(&base::Move, download_path_, user_download_path),
-          base::Bind(&DownloadManagerMediator::RestoreDownloadPath,
-                     weak_ptr_factory_.GetWeakPtr(), user_download_path));
+          base::Bind(base::PathExists, download_path_),
+          base::Bind(&DownloadManagerMediator::MoveToUserDocumentsIfFileExists,
+                     weak_ptr_factory_.GetWeakPtr(), download_path_));
     }
   }
 
@@ -158,6 +153,25 @@
   }
 }
 
+void DownloadManagerMediator::MoveToUserDocumentsIfFileExists(
+    base::FilePath download_path_,
+    bool file_exists) {
+  if (!file_exists)
+    return;
+
+  base::FilePath user_download_path;
+  GetDownloadsDirectory(&user_download_path);
+  user_download_path = user_download_path.Append(
+      base::UTF16ToUTF8(task_->GetSuggestedFilename()));
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE,
+      {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
+      base::Bind(&base::Move, download_path_, user_download_path),
+      base::Bind(&DownloadManagerMediator::RestoreDownloadPath,
+                 weak_ptr_factory_.GetWeakPtr(), user_download_path));
+}
+
 void DownloadManagerMediator::RestoreDownloadPath(
     base::FilePath user_download_path,
     bool moveCompleted) {
diff --git a/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm b/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm
index 3edaef0..d1a7b80 100644
--- a/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/download/download_manager_mediator_unittest.mm
@@ -131,6 +131,9 @@
         base::RunLoop().RunUntilIdle();
         return download_dir.IsParent(mediator_.GetDownloadPath());
       }));
+
+  // Updates the consumer once the file has been moved.
+  mediator_.SetDownloadTask(task());
 }
 
 // Tests starting and failing the download. Simulates download failure from
diff --git a/ios/chrome/browser/ui/first_run/OWNERS b/ios/chrome/browser/ui/first_run/OWNERS
deleted file mode 100644
index 468c5fa9..0000000
--- a/ios/chrome/browser/ui/first_run/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-file://components/signin/ios/OWNERS
-
-kkhorimoto@chromium.org
-
-# TEAM: ios-directory-owners@chromium.org
-# OS: iOS
diff --git a/ios/chrome/browser/ui/history/BUILD.gn b/ios/chrome/browser/ui/history/BUILD.gn
index f13380b..d3668c6c6 100644
--- a/ios/chrome/browser/ui/history/BUILD.gn
+++ b/ios/chrome/browser/ui/history/BUILD.gn
@@ -25,7 +25,7 @@
     "//ios/chrome/browser/history",
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/sync",
-    "//ios/chrome/browser/ui/context_menu",
+    "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/chrome/browser/ui/coordinators:chrome_coordinators",
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view:feature_flags",
@@ -84,9 +84,9 @@
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/metrics:metrics_internal",
     "//ios/chrome/browser/sync",
+    "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/chrome/browser/ui/collection_view/cells",
     "//ios/chrome/browser/ui/commands",
-    "//ios/chrome/browser/ui/context_menu",
     "//ios/chrome/browser/ui/list_model",
     "//ios/chrome/browser/ui/table_view",
     "//ios/chrome/browser/ui/table_view:presentation",
diff --git a/ios/chrome/browser/ui/history/history_coordinator.mm b/ios/chrome/browser/ui/history/history_coordinator.mm
index c5ca7a0..1c71719 100644
--- a/ios/chrome/browser/ui/history/history_coordinator.mm
+++ b/ios/chrome/browser/ui/history/history_coordinator.mm
@@ -10,7 +10,7 @@
 #include "ios/chrome/browser/history/history_service_factory.h"
 #import "ios/chrome/browser/main/browser.h"
 #include "ios/chrome/browser/sync/profile_sync_service_factory.h"
-#import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
+#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
 #import "ios/chrome/browser/ui/history/history_clear_browsing_data_coordinator.h"
 #import "ios/chrome/browser/ui/history/history_mediator.h"
 #include "ios/chrome/browser/ui/history/history_table_view_controller.h"
diff --git a/ios/chrome/browser/ui/history/history_table_view_controller.h b/ios/chrome/browser/ui/history/history_table_view_controller.h
index 965014d9..bfc3251 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.h
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.h
@@ -12,7 +12,7 @@
 class Browser;
 enum class UrlLoadStrategy;
 
-@class ContextMenuCoordinator;
+@class ActionSheetCoordinator;
 @protocol TableViewFaviconDataSource;
 @protocol HistoryUIDelegate;
 @protocol HistoryPresentationDelegate;
@@ -34,8 +34,8 @@
 @property(nonatomic, weak) id<HistoryPresentationDelegate> presentationDelegate;
 // Data source for favicon images.
 @property(nonatomic, weak) id<TableViewFaviconDataSource> imageDataSource;
-// Coordinator for displaying context menus for history entries.
-@property(nonatomic, strong) ContextMenuCoordinator* contextMenuCoordinator;
+// Coordinator for displaying a context menu for history entries.
+@property(nonatomic, strong) ActionSheetCoordinator* contextMenuCoordinator;
 
 // Initializers.
 - (instancetype)init NS_DESIGNATED_INITIALIZER;
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 39c026a..b1d58f7 100644
--- a/ios/chrome/browser/ui/history/history_table_view_controller.mm
+++ b/ios/chrome/browser/ui/history/history_table_view_controller.mm
@@ -17,7 +17,7 @@
 #import "ios/chrome/browser/metrics/new_tab_page_uma.h"
 #include "ios/chrome/browser/sync/sync_setup_service.h"
 #include "ios/chrome/browser/sync/sync_setup_service_factory.h"
-#import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
+#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
 #include "ios/chrome/browser/ui/history/history_entries_status_item.h"
 #import "ios/chrome/browser/ui/history/history_entries_status_item_delegate.h"
 #include "ios/chrome/browser/ui/history/history_entry_inserter.h"
@@ -168,11 +168,12 @@
   // history content.
   self.tableView.tableFooterView = [[UIView alloc] init];
 
-  // ContextMenu gesture recognizer.
-  UILongPressGestureRecognizer* longPressRecognizer = [
-      [UILongPressGestureRecognizer alloc]
-      initWithTarget:self
-              action:@selector(displayContextMenuInvokedByGestureRecognizer:)];
+  // Long-press gesture recognizer.
+  UILongPressGestureRecognizer* longPressRecognizer =
+      [[UILongPressGestureRecognizer alloc]
+          initWithTarget:self
+                  action:@selector
+                  (displayContextMenuInvokedByGestureRecognizer:)];
   [self.tableView addGestureRecognizer:longPressRecognizer];
 
   // NavigationController configuration.
@@ -972,7 +973,7 @@
 
 #pragma mark Context Menu
 
-// Displays context menu on cell pressed with gestureRecognizer.
+// Displays a context menu on the cell pressed with gestureRecognizer.
 - (void)displayContextMenuInvokedByGestureRecognizer:
     (UILongPressGestureRecognizer*)gestureRecognizer {
   if (gestureRecognizer.numberOfTouches != 1 || self.editing ||
@@ -1001,12 +1002,14 @@
   __weak HistoryTableViewController* weakSelf = self;
   NSString* menuTitle =
       base::SysUTF16ToNSString(url_formatter::FormatUrl(entry.URL));
-  self.contextMenuCoordinator = [[ContextMenuCoordinator alloc]
+  self.contextMenuCoordinator = [[ActionSheetCoordinator alloc]
       initWithBaseViewController:self.navigationController
                          browser:_browser
                            title:menuTitle
-                          inView:self.tableView
-                      atLocation:touchLocation];
+                         message:nil
+                            rect:CGRectMake(touchLocation.x, touchLocation.y,
+                                            1.0, 1.0)
+                            view:self.tableView];
 
   // Add "Open in New Tab" option.
   NSString* openInNewTabTitle =
@@ -1015,7 +1018,8 @@
     [weakSelf openURLInNewTab:entry.URL];
   };
   [self.contextMenuCoordinator addItemWithTitle:openInNewTabTitle
-                                         action:openInNewTabAction];
+                                         action:openInNewTabAction
+                                          style:UIAlertActionStyleDefault];
 
   // Add "Open in New Incognito Tab" option.
   NSString* openInNewIncognitoTabTitle = l10n_util::GetNSStringWithFixup(
@@ -1024,7 +1028,8 @@
     [weakSelf openURLInNewIncognitoTab:entry.URL];
   };
   [self.contextMenuCoordinator addItemWithTitle:openInNewIncognitoTabTitle
-                                         action:openInNewIncognitoTabAction];
+                                         action:openInNewIncognitoTabAction
+                                          style:UIAlertActionStyleDefault];
 
   // Add "Copy URL" option.
   NSString* copyURLTitle =
@@ -1033,7 +1038,8 @@
     StoreURLInPasteboard(entry.URL);
   };
   [self.contextMenuCoordinator addItemWithTitle:copyURLTitle
-                                         action:copyURLAction];
+                                         action:copyURLAction
+                                          style:UIAlertActionStyleDefault];
   [self.contextMenuCoordinator start];
 }
 
diff --git a/ios/chrome/browser/ui/main/browser_interface_provider.h b/ios/chrome/browser/ui/main/browser_interface_provider.h
index d6289c7c..7368e9d 100644
--- a/ios/chrome/browser/ui/main/browser_interface_provider.h
+++ b/ios/chrome/browser/ui/main/browser_interface_provider.h
@@ -13,7 +13,6 @@
 @class BrowserCoordinator;
 @class BrowserViewController;
 class ChromeBrowserState;
-@class TabModel;
 
 // A BrowserInterface is an abstraction that exposes an interface to the Chrome
 // user interface (and related model objects) to the application layer. Each
@@ -33,8 +32,6 @@
 // The BrowserViewController showing the current tab. The API surface this
 // property exposes will be refactored so that the BVC class isn't exposed.
 @property(nonatomic, readonly) BrowserViewController* bvc;
-// The tab model to which the current tab belongs.
-@property(nonatomic, readonly) TabModel* tabModel;
 // The active browser. This can never be nullptr.
 @property(nonatomic, readonly) Browser* browser;
 // The browser state for this interface. This can never be nullptr.
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler.mm b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
index 33daf41..52962ef 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler.mm
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler.mm
@@ -15,7 +15,6 @@
 #import "ios/chrome/browser/main/browser_list.h"
 #import "ios/chrome/browser/main/browser_list_factory.h"
 #import "ios/chrome/browser/sessions/session_restoration_browser_agent.h"
-
 #import "ios/chrome/browser/tabs/tab_model.h"
 #import "ios/chrome/browser/ui/browser_view/browser_coordinator.h"
 #import "ios/chrome/browser/ui/browser_view/browser_view_controller.h"
@@ -24,6 +23,7 @@
 #import "ios/chrome/browser/ui/commands/browsing_data_commands.h"
 #import "ios/chrome/browser/ui/commands/command_dispatcher.h"
 #import "ios/chrome/browser/ui/util/multi_window_support.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."
@@ -57,10 +57,6 @@
   return self.coordinator.viewController;
 }
 
-- (TabModel*)tabModel {
-  return self.browser->GetTabModel();
-}
-
 - (Browser*)browser {
   return self.coordinator.browser;
 }
@@ -109,8 +105,6 @@
 // Backing objects.
 @property(nonatomic) BrowserCoordinator* mainBrowserCoordinator;
 @property(nonatomic) BrowserCoordinator* incognitoBrowserCoordinator;
-//@property(nonatomic, readonly) TabModel* mainTabModel;
-//@property(nonatomic, readonly) TabModel* otrTabModel;
 @property(nonatomic, readonly) Browser* mainBrowser;
 @property(nonatomic, readonly) Browser* otrBrowser;
 
@@ -233,11 +227,10 @@
 
 - (void)setMainBrowser:(std::unique_ptr<Browser>)mainBrowser {
   if (_mainBrowser.get()) {
-    TabModel* tabModel = self.mainBrowser->GetTabModel();
     WebStateList* webStateList = self.mainBrowser->GetWebStateList();
     breakpad::StopMonitoringTabStateForWebStateList(webStateList);
     breakpad::StopMonitoringURLsForWebStateList(webStateList);
-    [tabModel disconnect];
+    [self.mainBrowser->GetTabModel() disconnect];
   }
 
   _mainBrowser = std::move(mainBrowser);
@@ -245,10 +238,9 @@
 
 - (void)setOtrBrowser:(std::unique_ptr<Browser>)otrBrowser {
   if (_otrBrowser.get()) {
-    TabModel* tabModel = self.otrBrowser->GetTabModel();
     WebStateList* webStateList = self.otrBrowser->GetWebStateList();
     breakpad::StopMonitoringTabStateForWebStateList(webStateList);
-    [tabModel disconnect];
+    [self.otrBrowser->GetTabModel() disconnect];
   }
 
   _otrBrowser = std::move(otrBrowser);
@@ -278,10 +270,10 @@
 #pragma mark - Other public methods
 
 - (void)willDestroyIncognitoBrowserState {
-  // It is theoretically possible that a Tab has been added to |_otrTabModel|
+  // It is theoretically possible that a Tab has been added to the webStateList
   // since the deletion has been scheduled. It is unlikely to happen for real
   // because it would require superhuman speed.
-  DCHECK(![self.otrBrowser->GetTabModel() count]);
+  DCHECK(self.otrBrowser->GetWebStateList()->empty());
   DCHECK(_browserState);
 
   // Remove the OTR browser from the browser list. The browser itself is
@@ -317,12 +309,12 @@
   DCHECK(_browserState);
   DCHECK(_browserState->HasOffTheRecordChromeBrowserState());
 
-  // An empty _otrTabModel must be created at this point, because it is then
+  // An empty _otrBrowser must be created at this point, because it is then
   // possible to prevent the tabChanged notification being sent. Otherwise,
   // when it is created, a notification with no tabs will be sent, and it will
   // be immediately deleted.
   [self setOtrBrowser:[self buildOtrBrowser:NO]];
-  DCHECK(![self.otrBrowser->GetTabModel() count]);
+  DCHECK(self.otrBrowser->GetWebStateList()->empty());
 
   if (_currentInterface == nil) {
     self.currentInterface = self.incognitoInterface;
diff --git a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
index 945cdb6..4e97578 100644
--- a/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
+++ b/ios/chrome/browser/ui/main/browser_view_wrangler_unittest.mm
@@ -56,8 +56,6 @@
     // Test that the OTR objects are (a) OTR and (b) not the same as the non-OTR
     // objects.
     EXPECT_NE(bvc, wrangler.incognitoInterface.viewController);
-    EXPECT_NE(wrangler.mainInterface.tabModel,
-              wrangler.incognitoInterface.tabModel);
     EXPECT_TRUE(wrangler.incognitoInterface.browserState->IsOffTheRecord());
 
     [wrangler shutdown];
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index dcfda2d..7a398ae 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -120,6 +120,10 @@
 // Constants for deferred promo display.
 const NSTimeInterval kDisplayPromoDelay = 0.1;
 
+// Key of the UMA IOS.MultiWindow.OpenInNewWindow histogram.
+const char kMultiWindowOpenInNewWindowHistogram[] =
+    "IOS.MultiWindow.OpenInNewWindow";
+
 }  // namespace
 
 @interface SceneController () <AppStateObserver,
@@ -396,8 +400,10 @@
   if (sceneState.currentOrigin != WindowActivityRestoredOrigin) {
     if (IsMultiwindowSupported()) {
       if (@available(iOS 13, *)) {
-        // TODO(crbug.com/1084905): log metrics for open in window.
-        LOG(WARNING) << "New scene origin: " << (int)sceneState.currentOrigin;
+        // int origin =
+        //    static_cast<int>(sceneState.currentOrigin);
+        base::UmaHistogramEnumeration(kMultiWindowOpenInNewWindowHistogram,
+                                      sceneState.currentOrigin);
       }
     }
   }
@@ -1994,11 +2000,13 @@
   // When opening with URLs for GetChromeIdentityService, it is expected that a
   // single URL is passed.
   DCHECK(URLsToOpen.count == URLContexts.count || URLContexts.count == 1);
+  BOOL active =
+      _sceneState.activationLevel >= SceneActivationLevelForegroundActive;
   for (URLOpenerParams* options : URLsToOpen) {
     [URLOpener openURL:options
-         applicationActive:YES
+         applicationActive:active
                  tabOpener:self
-        startupInformation:nil];
+        startupInformation:self.mainController];
   }
 }
 
diff --git a/ios/chrome/browser/ui/main/test/stub_browser_interface.h b/ios/chrome/browser/ui/main/test/stub_browser_interface.h
index 2e79b2f..22645e3 100644
--- a/ios/chrome/browser/ui/main/test/stub_browser_interface.h
+++ b/ios/chrome/browser/ui/main/test/stub_browser_interface.h
@@ -12,14 +12,12 @@
 class Browser;
 @class BrowserViewController;
 class ChromeBrowserState;
-@class TabModel;
 
 // Test double for BrowserInterface implementors. All properties are writable,
 // and have nil, nullptr, or NO as default values.
 @interface StubBrowserInterface : NSObject <BrowserInterface>
 @property(nonatomic, readwrite) UIViewController* viewController;
 @property(nonatomic, readwrite) BrowserViewController* bvc;
-@property(nonatomic, readwrite) TabModel* tabModel;
 @property(nonatomic, readwrite) Browser* browser;
 @property(nonatomic, readwrite) ChromeBrowserState* browserState;
 @property(nonatomic, readwrite) BOOL incognito;
diff --git a/ios/chrome/browser/ui/main_content/OWNERS b/ios/chrome/browser/ui/main_content/OWNERS
deleted file mode 100644
index 48efb49e..0000000
--- a/ios/chrome/browser/ui/main_content/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-kkhorimoto@chromium.org
diff --git a/ios/chrome/browser/ui/ntp/BUILD.gn b/ios/chrome/browser/ui/ntp/BUILD.gn
index 1aeaaefe..ff94d57 100644
--- a/ios/chrome/browser/ui/ntp/BUILD.gn
+++ b/ios/chrome/browser/ui/ntp/BUILD.gn
@@ -105,7 +105,6 @@
     "//ios/chrome/browser/ui/commands",
     "//ios/chrome/browser/ui/content_suggestions:content_suggestions_constant",
     "//ios/chrome/browser/ui/content_suggestions/cells",
-    "//ios/chrome/browser/ui/context_menu",
     "//ios/chrome/browser/ui/favicon",
     "//ios/chrome/browser/ui/overscroll_actions",
     "//ios/chrome/browser/ui/page_info:features",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_ios.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_ios.mm
index 9bda28f7..30d5344f 100644
--- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_ios.mm
@@ -114,7 +114,7 @@
 }
 
 void OmniboxPopupViewIOS::OnMatchHighlighted(size_t row) {
-  model_->SetSelectedLine(row, false, true);
+  model_->SetSelection(OmniboxPopupModel::Selection(row), false, true);
   if ([mediator_ isOpen]) {
     UpdateEditViewIcon();
   }
diff --git a/ios/chrome/browser/ui/overlays/OWNERS b/ios/chrome/browser/ui/overlays/OWNERS
index 85f767ff..65b249a 100644
--- a/ios/chrome/browser/ui/overlays/OWNERS
+++ b/ios/chrome/browser/ui/overlays/OWNERS
@@ -1,4 +1,3 @@
-kkhorimoto@chromium.org
 michaeldo@chromium.org
 thegreenfrog@chromium.org
 
diff --git a/ios/chrome/browser/ui/overscroll_actions/OWNERS b/ios/chrome/browser/ui/overscroll_actions/OWNERS
deleted file mode 100644
index bd85dcf2..0000000
--- a/ios/chrome/browser/ui/overscroll_actions/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-kkhorimoto@chromium.org
-
-# TEAM: ios-directory-owners@chromium.org
-# OS: iOS
diff --git a/ios/chrome/browser/ui/product_tour/OWNERS b/ios/chrome/browser/ui/product_tour/OWNERS
deleted file mode 100644
index bd85dcf2..0000000
--- a/ios/chrome/browser/ui/product_tour/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-kkhorimoto@chromium.org
-
-# TEAM: ios-directory-owners@chromium.org
-# OS: iOS
diff --git a/ios/chrome/browser/ui/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
index 6364cf4..1e0d256 100644
--- a/ios/chrome/browser/ui/recent_tabs/BUILD.gn
+++ b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
@@ -77,10 +77,10 @@
     "//ios/chrome/browser/sessions:serialisation",
     "//ios/chrome/browser/sync",
     "//ios/chrome/browser/ui:feature_flags",
+    "//ios/chrome/browser/ui/alert_coordinator",
     "//ios/chrome/browser/ui/authentication",
     "//ios/chrome/browser/ui/authentication/cells",
     "//ios/chrome/browser/ui/commands",
-    "//ios/chrome/browser/ui/context_menu",
     "//ios/chrome/browser/ui/settings/sync/utils",
     "//ios/chrome/browser/ui/signin_interaction/public",
     "//ios/chrome/browser/ui/table_view",
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
index 879ae6f67..423b51d 100644
--- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
+++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller.mm
@@ -22,6 +22,7 @@
 #include "ios/chrome/browser/sessions/live_tab_context_browser_agent.h"
 #include "ios/chrome/browser/sessions/session_util.h"
 #include "ios/chrome/browser/sync/session_sync_service_factory.h"
+#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h"
 #import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_consumer.h"
 #import "ios/chrome/browser/ui/authentication/cells/table_view_signin_promo_item.h"
@@ -29,7 +30,6 @@
 #include "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/open_new_tab_command.h"
 #import "ios/chrome/browser/ui/commands/show_signin_command.h"
-#import "ios/chrome/browser/ui/context_menu/context_menu_coordinator.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_constants.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_presentation_delegate.h"
 #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_table_view_controller_delegate.h"
@@ -115,7 +115,7 @@
 // The sync state.
 @property(nonatomic, assign) SessionsSyncUserState sessionState;
 // Handles displaying the context menu for all form factors.
-@property(nonatomic, strong) ContextMenuCoordinator* contextMenuCoordinator;
+@property(nonatomic, strong) ActionSheetCoordinator* contextMenuCoordinator;
 @property(nonatomic, strong) SigninPromoViewMediator* signinPromoViewMediator;
 // The browser state used for many operations, derived from the one provided by
 // |self.browser|.
@@ -1061,12 +1061,14 @@
   // Get view coordinates in local space.
   CGPoint viewCoordinate = [sender locationInView:self.tableView];
   // Present sheet/popover using controller that is added to view hierarchy.
-  self.contextMenuCoordinator = [[ContextMenuCoordinator alloc]
+  self.contextMenuCoordinator = [[ActionSheetCoordinator alloc]
       initWithBaseViewController:self
                          browser:self.browser
                            title:nil
-                          inView:self.tableView
-                      atLocation:viewCoordinate];
+                         message:nil
+                            rect:CGRectMake(viewCoordinate.x, viewCoordinate.y,
+                                            1.0, 1.0)
+                            view:self.tableView];
 
   // Fill the sheet/popover with buttons.
   __weak RecentTabsTableViewController* weakSelf = self;
@@ -1079,7 +1081,8 @@
                 action:^{
                   [weakSelf
                       openTabsFromSessionSectionIdentifier:sectionIdentifier];
-                }];
+                }
+                 style:UIAlertActionStyleDefault];
 
   // "Hide for now" button.
   NSString* hideButtonLabel =
@@ -1089,7 +1092,8 @@
                 action:^{
                   [weakSelf removeSessionAtSessionSectionIdentifier:
                                 sectionIdentifier];
-                }];
+                }
+                 style:UIAlertActionStyleDefault];
 
   [self.contextMenuCoordinator start];
 }
diff --git a/ios/chrome/browser/ui/sad_tab/OWNERS b/ios/chrome/browser/ui/sad_tab/OWNERS
deleted file mode 100644
index bd85dcf2..0000000
--- a/ios/chrome/browser/ui/sad_tab/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-kkhorimoto@chromium.org
-
-# TEAM: ios-directory-owners@chromium.org
-# OS: iOS
diff --git a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
index 68b65be..5e23b1e8 100644
--- a/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
+++ b/ios/chrome/browser/ui/settings/clear_browsing_data/clear_browsing_data_manager.mm
@@ -306,9 +306,6 @@
                   [weakSelf clearDataForDataTypes:dataTypeMaskToRemove];
                 }
                  style:UIAlertActionStyleDestructive];
-  [actionCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                               action:nil
-                                style:UIAlertActionStyleCancel];
   return actionCoordinator;
 }
 
diff --git a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
index 498f336..7fe25a2 100644
--- a/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/google_services/accounts_table_view_controller.mm
@@ -490,9 +490,6 @@
                   }
                    style:UIAlertActionStyleDestructive];
 
-    [_alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_CANCEL)
-                                 action:nil
-                                  style:UIAlertActionStyleCancel];
     [_alertCoordinator start];
   } else {
     _dimissAccountDetailsViewControllerBlock =
diff --git a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
index b64107a..169f116 100644
--- a/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
+++ b/ios/chrome/browser/ui/tabs/tab_strip_controller.mm
@@ -16,7 +16,6 @@
 #include "base/strings/sys_string_conversions.h"
 #include "components/favicon/ios/web_favicon_driver.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h"
 #import "ios/chrome/browser/drag_and_drop/drop_and_navigate_delegate.h"
 #import "ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction.h"
 #include "ios/chrome/browser/main/browser.h"
@@ -487,11 +486,9 @@
                       action:@selector(recordUserMetrics:)
             forControlEvents:UIControlEventTouchUpInside];
 
-    if (DragAndDropIsEnabled()) {
-      _buttonNewTabInteraction =
-          [[DropAndNavigateInteraction alloc] initWithDelegate:self];
-      [_buttonNewTab addInteraction:_buttonNewTabInteraction];
-    }
+    _buttonNewTabInteraction =
+        [[DropAndNavigateInteraction alloc] initWithDelegate:self];
+    [_buttonNewTab addInteraction:_buttonNewTabInteraction];
 
 #if defined(__IPHONE_13_4)
     if (@available(iOS 13.4, *)) {
diff --git a/ios/chrome/browser/ui/tabs/tab_view.mm b/ios/chrome/browser/ui/tabs/tab_view.mm
index 89638474..99b6292 100644
--- a/ios/chrome/browser/ui/tabs/tab_view.mm
+++ b/ios/chrome/browser/ui/tabs/tab_view.mm
@@ -10,7 +10,6 @@
 #include "base/feature_list.h"
 #include "base/ios/ios_util.h"
 #include "base/strings/sys_string_conversions.h"
-#include "ios/chrome/browser/drag_and_drop/drag_and_drop_flag.h"
 #include "ios/chrome/browser/drag_and_drop/drop_and_navigate_delegate.h"
 #include "ios/chrome/browser/drag_and_drop/drop_and_navigate_interaction.h"
 #include "ios/chrome/browser/system_flags.h"
@@ -138,11 +137,9 @@
                   action:@selector(tabWasTapped)
         forControlEvents:UIControlEventTouchUpInside];
 
-    if (DragAndDropIsEnabled()) {
-      _dropInteraction =
-          [[DropAndNavigateInteraction alloc] initWithDelegate:self];
-      [self addInteraction:_dropInteraction];
-    }
+    _dropInteraction =
+        [[DropAndNavigateInteraction alloc] initWithDelegate:self];
+    [self addInteraction:_dropInteraction];
   }
   return self;
 }
diff --git a/ios/chrome/browser/ui/toolbar_container/OWNERS b/ios/chrome/browser/ui/toolbar_container/OWNERS
index 309fe54..2d35f0a5 100644
--- a/ios/chrome/browser/ui/toolbar_container/OWNERS
+++ b/ios/chrome/browser/ui/toolbar_container/OWNERS
@@ -1,2 +1 @@
 gambard@chromium.org
-kkhorimoto@chromium.org
diff --git a/ios/chrome/browser/ui/util/OWNERS b/ios/chrome/browser/ui/util/OWNERS
index 37eb1aa3..01e8c98 100644
--- a/ios/chrome/browser/ui/util/OWNERS
+++ b/ios/chrome/browser/ui/util/OWNERS
@@ -1,4 +1,3 @@
-kkhorimoto@chromium.org
 marq@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
diff --git a/ios/chrome/browser/ui/voice/OWNERS b/ios/chrome/browser/ui/voice/OWNERS
deleted file mode 100644
index bd85dcf2..0000000
--- a/ios/chrome/browser/ui/voice/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-kkhorimoto@chromium.org
-
-# TEAM: ios-directory-owners@chromium.org
-# OS: iOS
diff --git a/ios/chrome/browser/voice/OWNERS b/ios/chrome/browser/voice/OWNERS
index 2f0d436..b127701 100644
--- a/ios/chrome/browser/voice/OWNERS
+++ b/ios/chrome/browser/voice/OWNERS
@@ -1,4 +1,3 @@
-kkhorimoto@chromium.org
 rohitrao@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
diff --git a/ios/chrome/browser/web/font_size_tab_helper.h b/ios/chrome/browser/web/font_size_tab_helper.h
index 65af123..7bb3c63 100644
--- a/ios/chrome/browser/web/font_size_tab_helper.h
+++ b/ios/chrome/browser/web/font_size_tab_helper.h
@@ -81,6 +81,9 @@
 
   PrefService* GetPrefService() const;
 
+  // Logs any events after zooming.
+  void LogZoomEvent(Zoom zoom) const;
+
   // Returns the new multiplier after zooming in the given direction. Returns
   // nullopt if it is impossible to zoom in the given direction;
   base::Optional<double> NewMultiplierAfterZoom(Zoom zoom) const;
diff --git a/ios/chrome/browser/web/font_size_tab_helper.mm b/ios/chrome/browser/web/font_size_tab_helper.mm
index e2121ab..42921be 100644
--- a/ios/chrome/browser/web/font_size_tab_helper.mm
+++ b/ios/chrome/browser/web/font_size_tab_helper.mm
@@ -7,6 +7,8 @@
 #import <UIKit/UIKit.h>
 
 #include "base/containers/adapters.h"
+#include "base/metrics/user_metrics.h"
+#include "base/metrics/user_metrics_action.h"
 #include "base/strings/stringprintf.h"
 #import "base/strings/sys_string_conversions.h"
 #import "base/values.h"
@@ -148,7 +150,13 @@
   double new_zoom_multiplier = NewMultiplierAfterZoom(zoom).value_or(1);
   StoreCurrentUserZoomMultiplier(new_zoom_multiplier);
 
-  // Track when the user zooms to see if there are certain websites that are
+  LogZoomEvent(zoom);
+
+  SetPageFontSize(GetFontSize());
+}
+
+void FontSizeTabHelper::LogZoomEvent(Zoom zoom) const {
+  // Log when the user zooms to see if there are certain websites that are
   // broken when zooming.
   IOSContentSizeCategory content_size_category =
       IOSContentSizeCategoryForCurrentUIContentSizeCategory();
@@ -160,7 +168,18 @@
       .SetOverallZoomLevel(GetFontSize())
       .Record(ukm_recorder);
 
-  SetPageFontSize(GetFontSize());
+  // Log a UserMetricsAction as well so the zoom events appear in breadcrumbs.
+  switch (zoom) {
+    case ZOOM_OUT:
+      base::RecordAction(base::UserMetricsAction("IOS.PageZoom.ZoomOut"));
+      break;
+    case ZOOM_IN:
+      base::RecordAction(base::UserMetricsAction("IOS.PageZoom.ZoomIn"));
+      break;
+    case ZOOM_RESET:
+      base::RecordAction(base::UserMetricsAction("IOS.PageZoom.ZoomReset"));
+      break;
+  }
 }
 
 base::Optional<double> FontSizeTabHelper::NewMultiplierAfterZoom(
diff --git a/ios/chrome/browser/window_activities/window_activity_helpers.h b/ios/chrome/browser/window_activities/window_activity_helpers.h
index c029b459..1268e40 100644
--- a/ios/chrome/browser/window_activities/window_activity_helpers.h
+++ b/ios/chrome/browser/window_activities/window_activity_helpers.h
@@ -30,6 +30,8 @@
   WindowActivityHistoryOrigin,
   // The command origin comes from tools.
   WindowActivityToolsOrigin,
+  // Size of enum.
+  kMaxValue = WindowActivityToolsOrigin
 };
 
 // Helper functions to create NSUserActivity instances that encode specific
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index 6b7ea4a..e0eb8d2 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -263,7 +263,6 @@
     "//ios/chrome/browser/ui/content_suggestions:unit_tests",
     "//ios/chrome/browser/ui/content_suggestions/cells:unit_tests",
     "//ios/chrome/browser/ui/content_suggestions/identifier:unit_tests",
-    "//ios/chrome/browser/ui/context_menu:unit_tests",
     "//ios/chrome/browser/ui/dialogs:unit_tests",
     "//ios/chrome/browser/ui/dialogs:unit_tests_internal",
     "//ios/chrome/browser/ui/download:unit_tests",
diff --git a/ios/components/security_interstitials/OWNERS b/ios/components/security_interstitials/OWNERS
index 7bd0f55..233a0ea 100644
--- a/ios/components/security_interstitials/OWNERS
+++ b/ios/components/security_interstitials/OWNERS
@@ -1,3 +1,2 @@
 ajuma@chromium.org
-kkhorimoto@chromium.org
 livvielin@chromium.org
diff --git a/ios/components/ui_util/OWNERS b/ios/components/ui_util/OWNERS
index 37eb1aa3..01e8c98 100644
--- a/ios/components/ui_util/OWNERS
+++ b/ios/components/ui_util/OWNERS
@@ -1,4 +1,3 @@
-kkhorimoto@chromium.org
 marq@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
diff --git a/ios/net/cookies/cookie_store_ios.h b/ios/net/cookies/cookie_store_ios.h
index f395222..1fc5db6b 100644
--- a/ios/net/cookies/cookie_store_ios.h
+++ b/ios/net/cookies/cookie_store_ios.h
@@ -238,8 +238,8 @@
   // UpdateCachesFromCookieMonster completes. Updates the cookie cache and runs
   // callbacks if the cache changed.
   void GotCookieListFor(const std::pair<GURL, std::string> key,
-                        const net::CookieStatusList& cookies,
-                        const net::CookieStatusList& excluded_cookies);
+                        const net::CookieAccessResultList& cookies,
+                        const net::CookieAccessResultList& excluded_cookies);
 
   // Fetches new values for all (url, name) pairs that have hooks registered,
   // asynchronously invoking callbacks if necessary.
@@ -273,12 +273,12 @@
   // creation date.
   net::CookieList CanonicalCookieListFromSystemCookies(NSArray* cookies);
 
-  // Takes an NSArray of NSHTTPCookies as returns a net::CookieStatusList.
+  // Takes an NSArray of NSHTTPCookies as returns a net::CookieAccessResultList.
   // A status of "INCLUDE" is assigned to each cookie.
   // The returned cookies are ordered by longest path, then earliest
   // creation date.
-  net::CookieStatusList CanonicalCookieWithStatusListFromSystemCookies(
-      NSArray* cookies);
+  net::CookieAccessResultList
+  CanonicalCookieWithAccessResultListFromSystemCookies(NSArray* cookies);
 
   // Runs |callback| on CanonicalCookie with status List converted from cookies.
   void RunGetCookieListCallbackOnSystemCookies(GetCookieListCallback callback,
diff --git a/ios/net/cookies/cookie_store_ios.mm b/ios/net/cookies/cookie_store_ios.mm
index dfa99a8..be2ad5bf2 100644
--- a/ios/net/cookies/cookie_store_ios.mm
+++ b/ios/net/cookies/cookie_store_ios.mm
@@ -115,12 +115,12 @@
 }
 
 // Adds cookies in |cookies| with name |name| to |filtered|.
-void OnlyCookiesWithName(const net::CookieStatusList& cookies,
+void OnlyCookiesWithName(const net::CookieAccessResultList& cookies,
                          const std::string& name,
                          net::CookieList* filtered) {
-  for (const auto& cookie_with_status : cookies) {
-    if (cookie_with_status.cookie.Name() == name)
-      filtered->push_back(cookie_with_status.cookie);
+  for (const auto& cookie_with_access_result : cookies) {
+    if (cookie_with_access_result.cookie.Name() == name)
+      filtered->push_back(cookie_with_access_result.cookie);
   }
 }
 
@@ -613,8 +613,8 @@
 
 void CookieStoreIOS::GotCookieListFor(
     const std::pair<GURL, std::string> key,
-    const net::CookieStatusList& cookies,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookies,
+    const net::CookieAccessResultList& excluded_cookies) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   net::CookieList filtered;
@@ -676,15 +676,15 @@
   return cookie_list;
 }
 
-net::CookieStatusList
-CookieStoreIOS::CanonicalCookieWithStatusListFromSystemCookies(
+net::CookieAccessResultList
+CookieStoreIOS::CanonicalCookieWithAccessResultListFromSystemCookies(
     NSArray* cookies) {
-  net::CookieStatusList cookie_list;
+  net::CookieAccessResultList cookie_list;
   cookie_list.reserve([cookies count]);
   for (NSHTTPCookie* cookie in cookies) {
     base::Time created = system_store_->GetCookieCreationTime(cookie);
     cookie_list.push_back({CanonicalCookieFromSystemCookie(cookie, created),
-                           net::CookieInclusionStatus()});
+                           net::CookieAccessResult()});
   }
   return cookie_list;
 }
@@ -693,9 +693,9 @@
     CookieStoreIOS::GetCookieListCallback callback,
     NSArray<NSHTTPCookie*>* cookies) {
   if (!callback.is_null()) {
-    net::CookieStatusList excluded_cookies;
+    net::CookieAccessResultList excluded_cookies;
     std::move(callback).Run(
-        CanonicalCookieWithStatusListFromSystemCookies(cookies),
+        CanonicalCookieWithAccessResultListFromSystemCookies(cookies),
         excluded_cookies);
   }
 }
diff --git a/ios/net/cookies/cookie_store_ios_unittest.mm b/ios/net/cookies/cookie_store_ios_unittest.mm
index bb6fe4f..124c833c 100644
--- a/ios/net/cookies/cookie_store_ios_unittest.mm
+++ b/ios/net/cookies/cookie_store_ios_unittest.mm
@@ -100,11 +100,12 @@
   // Returns the parameter of the callback.
   const net::CookieList& cookie_list() { return cookie_list_; }
 
-  void Run(const net::CookieStatusList& cookie_status_list,
-           const net::CookieStatusList& excluded_cookies) {
+  void Run(const net::CookieAccessResultList& cookie_with_access_result,
+           const net::CookieAccessResultList& excluded_cookies) {
     ASSERT_FALSE(did_run_);
     did_run_ = true;
-    cookie_list_ = net::cookie_util::StripStatuses(cookie_status_list);
+    cookie_list_ =
+        net::cookie_util::StripAccessResults(cookie_with_access_result);
   }
 
  private:
@@ -112,8 +113,8 @@
   net::CookieList cookie_list_;
 };
 
-void IgnoreList(const net::CookieStatusList& ignored,
-                const net::CookieStatusList& excluded_cookies) {}
+void IgnoreList(const net::CookieAccessResultList& ignored,
+                const net::CookieAccessResultList& excluded_cookies) {}
 
 }  // namespace
 
@@ -257,9 +258,9 @@
 
   // Cookie should still exist.
   base::RunLoop run_loop2;
-  GetCookies(
-      base::BindLambdaForTesting([&](const CookieStatusList& cookies,
-                                     const CookieStatusList& excluded_list) {
+  GetCookies(base::BindLambdaForTesting(
+      [&](const CookieAccessResultList& cookies,
+          const CookieAccessResultList& excluded_list) {
         ASSERT_EQ(1u, cookies.size());
         EXPECT_EQ("abc", cookies[0].cookie.Name());
         EXPECT_EQ("def", cookies[0].cookie.Value());
@@ -282,9 +283,9 @@
 
   // Cookie should no longer exist.
   base::RunLoop run_loop4;
-  GetCookies(
-      base::BindLambdaForTesting([&](const CookieStatusList& cookies,
-                                     const CookieStatusList& excluded_list) {
+  GetCookies(base::BindLambdaForTesting(
+      [&](const CookieAccessResultList& cookies,
+          const CookieAccessResultList& excluded_list) {
         EXPECT_EQ(0u, cookies.size());
         run_loop4.Quit();
       }));
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn
index fd44b92..fb9f0e7 100644
--- a/ios/third_party/material_components_ios/BUILD.gn
+++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -6,11 +6,10 @@
 import("//build/config/ios/rules.gni")
 import("//build/config/locales.gni")
 
-# This variable lists all public headers that are exported by MDC. It is
-# there to allow supporting build. It allows not repeating the list if
-# ios_third_party_material_components_built_as_framework is true/false.
-# TODO(crbug.com/1017165): remove once MaterialComponents is always built
-# as a framework
+# The three variables _mdc_public_headers, _mdc_include_dirs and _mdc_sources
+# are there to allow script to automatically keep the build rules up-to-date
+# when rolling material_components_ios. They should not be removed.
+
 _mdc_public_headers = [
   # List generated by the following commands:
   # $ cd src/ios/third_party/material_components_ios
@@ -334,6 +333,7 @@
   "src/components/Snackbar/src/FontThemer/MDCSnackbarFontThemer.h",
   "src/components/Snackbar/src/FontThemer/MaterialSnackbar+FontThemer.h",
   "src/components/Snackbar/src/MDCSnackbarAlignment.h",
+  "src/components/Snackbar/src/MDCSnackbarError.h",
   "src/components/Snackbar/src/MDCSnackbarManager.h",
   "src/components/Snackbar/src/MDCSnackbarManagerDelegate.h",
   "src/components/Snackbar/src/MDCSnackbarMessage.h",
@@ -722,6 +722,839 @@
   "src/components/schemes/Typography/src/Scheming",
 ]
 
+_mdc_sources = [
+  # List generated by the following commands:
+  # $ cd src/ios/third_party/material_components_ios
+  # $ find src -path 'src/components/*/src/*.[hm]' -a \! -path '*Test*'|\
+  #   sed -e 's:\(.*\):  "\1",:'|sort -u
+  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.h",
+  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.m",
+  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.h",
+  "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.m",
+  "src/components/ActionSheet/src/ActionSheetThemer/MaterialActionSheet+ActionSheetThemer.h",
+  "src/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.h",
+  "src/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.m",
+  "src/components/ActionSheet/src/ColorThemer/MaterialActionSheet+ColorThemer.h",
+  "src/components/ActionSheet/src/MDCActionSheetAction.h",
+  "src/components/ActionSheet/src/MDCActionSheetController.h",
+  "src/components/ActionSheet/src/MDCActionSheetController.m",
+  "src/components/ActionSheet/src/MDCActionSheetControllerDelegate.h",
+  "src/components/ActionSheet/src/MaterialActionSheet.h",
+  "src/components/ActionSheet/src/Theming/MDCActionSheetController+MaterialTheming.h",
+  "src/components/ActionSheet/src/Theming/MDCActionSheetController+MaterialTheming.m",
+  "src/components/ActionSheet/src/Theming/MaterialActionSheet+Theming.h",
+  "src/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.h",
+  "src/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.m",
+  "src/components/ActionSheet/src/TypographyThemer/MaterialActionSheet+TypographyThemer.h",
+  "src/components/ActionSheet/src/private/MDCActionSheetHeaderView.h",
+  "src/components/ActionSheet/src/private/MDCActionSheetHeaderView.m",
+  "src/components/ActionSheet/src/private/MDCActionSheetItemTableViewCell.h",
+  "src/components/ActionSheet/src/private/MDCActionSheetItemTableViewCell.m",
+  "src/components/ActivityIndicator/src/MDCActivityIndicator.h",
+  "src/components/ActivityIndicator/src/MDCActivityIndicator.m",
+  "src/components/ActivityIndicator/src/MDCActivityIndicatorDelegate.h",
+  "src/components/ActivityIndicator/src/MaterialActivityIndicator.h",
+  "src/components/ActivityIndicator/src/private/MDCActivityIndicator+Private.h",
+  "src/components/ActivityIndicator/src/private/MDCActivityIndicatorMotionSpec.h",
+  "src/components/ActivityIndicator/src/private/MDCActivityIndicatorMotionSpec.m",
+  "src/components/ActivityIndicator/src/private/MaterialActivityIndicatorStrings.h",
+  "src/components/ActivityIndicator/src/private/MaterialActivityIndicatorStrings_table.h",
+  "src/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h",
+  "src/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m",
+  "src/components/AnimationTiming/src/MaterialAnimationTiming.h",
+  "src/components/AnimationTiming/src/UIView+MDCTimingFunction.h",
+  "src/components/AnimationTiming/src/UIView+MDCTimingFunction.m",
+  "src/components/AppBar/src/ColorThemer/MDCAppBarColorThemer.h",
+  "src/components/AppBar/src/ColorThemer/MDCAppBarColorThemer.m",
+  "src/components/AppBar/src/ColorThemer/MaterialAppBar+ColorThemer.h",
+  "src/components/AppBar/src/MDCAppBar.h",
+  "src/components/AppBar/src/MDCAppBarContainerViewController.h",
+  "src/components/AppBar/src/MDCAppBarContainerViewController.m",
+  "src/components/AppBar/src/MDCAppBarNavigationController.h",
+  "src/components/AppBar/src/MDCAppBarNavigationController.m",
+  "src/components/AppBar/src/MDCAppBarNavigationControllerToBeDeprecatedDelegate.h",
+  "src/components/AppBar/src/MDCAppBarViewController.h",
+  "src/components/AppBar/src/MDCAppBarViewController.m",
+  "src/components/AppBar/src/MDCAppBarViewControllerAccessibilityPerformEscapeDelegate.h",
+  "src/components/AppBar/src/MaterialAppBar.h",
+  "src/components/AppBar/src/Theming/MDCAppBarViewController+MaterialTheming.h",
+  "src/components/AppBar/src/Theming/MDCAppBarViewController+MaterialTheming.m",
+  "src/components/AppBar/src/Theming/MaterialAppBar+Theming.h",
+  "src/components/AppBar/src/TypographyThemer/MDCAppBarTypographyThemer.h",
+  "src/components/AppBar/src/TypographyThemer/MDCAppBarTypographyThemer.m",
+  "src/components/AppBar/src/TypographyThemer/MaterialAppBar+TypographyThemer.h",
+  "src/components/AppBar/src/private/MaterialAppBarStrings.h",
+  "src/components/AppBar/src/private/MaterialAppBarStrings_table.h",
+  "src/components/Availability/src/MDCAvailability.h",
+  "src/components/Availability/src/MaterialAvailability.h",
+  "src/components/Banner/src/MDCBannerView.h",
+  "src/components/Banner/src/MDCBannerView.m",
+  "src/components/Banner/src/MaterialBanner.h",
+  "src/components/Banner/src/Theming/MDCBannerView+MaterialTheming.h",
+  "src/components/Banner/src/Theming/MDCBannerView+MaterialTheming.m",
+  "src/components/Banner/src/Theming/MaterialBanner+Theming.h",
+  "src/components/BottomAppBar/src/MDCBottomAppBarView.h",
+  "src/components/BottomAppBar/src/MDCBottomAppBarView.m",
+  "src/components/BottomAppBar/src/MaterialBottomAppBar.h",
+  "src/components/BottomAppBar/src/private/MDCBottomAppBarAttributes.h",
+  "src/components/BottomAppBar/src/private/MDCBottomAppBarLayer.h",
+  "src/components/BottomAppBar/src/private/MDCBottomAppBarLayer.m",
+  "src/components/BottomNavigation/src/MDCBottomNavigationBar.h",
+  "src/components/BottomNavigation/src/MDCBottomNavigationBar.m",
+  "src/components/BottomNavigation/src/MDCBottomNavigationBarController.h",
+  "src/components/BottomNavigation/src/MDCBottomNavigationBarController.m",
+  "src/components/BottomNavigation/src/MDCBottomNavigationBarControllerDelegate.h",
+  "src/components/BottomNavigation/src/MDCBottomNavigationBarDelegate.h",
+  "src/components/BottomNavigation/src/MaterialBottomNavigation.h",
+  "src/components/BottomNavigation/src/MaterialBottomNavigationBeta.h",
+  "src/components/BottomNavigation/src/Theming/MDCBottomNavigationBar+MaterialTheming.h",
+  "src/components/BottomNavigation/src/Theming/MDCBottomNavigationBar+MaterialTheming.m",
+  "src/components/BottomNavigation/src/Theming/MaterialBottomNavigation+Theming.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+Private.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationItemBadge.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationItemBadge.m",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.m",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationLargeItemDialogView.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationLargeItemDialogView.m",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationSystemDialogView.h",
+  "src/components/BottomNavigation/src/private/MDCBottomNavigationSystemDialogView.m",
+  "src/components/BottomNavigation/src/private/MaterialBottomNavigationStrings.h",
+  "src/components/BottomNavigation/src/private/MaterialBottomNavigationStrings_table.h",
+  "src/components/BottomSheet/src/MDCBottomSheetController.h",
+  "src/components/BottomSheet/src/MDCBottomSheetController.m",
+  "src/components/BottomSheet/src/MDCBottomSheetControllerDelegate.h",
+  "src/components/BottomSheet/src/MDCBottomSheetPresentationController.h",
+  "src/components/BottomSheet/src/MDCBottomSheetPresentationController.m",
+  "src/components/BottomSheet/src/MDCBottomSheetPresentationControllerDelegate.h",
+  "src/components/BottomSheet/src/MDCBottomSheetTransitionController.h",
+  "src/components/BottomSheet/src/MDCBottomSheetTransitionController.m",
+  "src/components/BottomSheet/src/MDCSheetState.h",
+  "src/components/BottomSheet/src/MaterialBottomSheet.h",
+  "src/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.h",
+  "src/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.m",
+  "src/components/BottomSheet/src/ShapeThemer/MaterialBottomSheet+ShapeThemer.h",
+  "src/components/BottomSheet/src/UIViewController+MaterialBottomSheet.h",
+  "src/components/BottomSheet/src/UIViewController+MaterialBottomSheet.m",
+  "src/components/BottomSheet/src/private/MDCDraggableView.h",
+  "src/components/BottomSheet/src/private/MDCDraggableView.m",
+  "src/components/BottomSheet/src/private/MDCDraggableViewDelegate.h",
+  "src/components/BottomSheet/src/private/MDCSheetBehavior.h",
+  "src/components/BottomSheet/src/private/MDCSheetBehavior.m",
+  "src/components/BottomSheet/src/private/MDCSheetContainerView.h",
+  "src/components/BottomSheet/src/private/MDCSheetContainerView.m",
+  "src/components/BottomSheet/src/private/MDCSheetContainerViewDelegate.h",
+  "src/components/ButtonBar/src/MDCButtonBar.h",
+  "src/components/ButtonBar/src/MDCButtonBar.m",
+  "src/components/ButtonBar/src/MDCButtonBarButton.h",
+  "src/components/ButtonBar/src/MDCButtonBarDelegate.h",
+  "src/components/ButtonBar/src/MaterialButtonBar.h",
+  "src/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h",
+  "src/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m",
+  "src/components/ButtonBar/src/private/MDCButtonBar+Private.h",
+  "src/components/ButtonBar/src/private/MDCButtonBarButton.m",
+  "src/components/Buttons/src/ButtonThemer/MDCButtonScheme.h",
+  "src/components/Buttons/src/ButtonThemer/MDCButtonScheme.m",
+  "src/components/Buttons/src/ButtonThemer/MDCContainedButtonThemer.h",
+  "src/components/Buttons/src/ButtonThemer/MDCContainedButtonThemer.m",
+  "src/components/Buttons/src/ButtonThemer/MDCTextButtonThemer.h",
+  "src/components/Buttons/src/ButtonThemer/MDCTextButtonThemer.m",
+  "src/components/Buttons/src/ButtonThemer/MaterialButtons+ButtonThemer.h",
+  "src/components/Buttons/src/ColorThemer/MDCButtonColorThemer.h",
+  "src/components/Buttons/src/ColorThemer/MDCButtonColorThemer.m",
+  "src/components/Buttons/src/ColorThemer/MDCContainedButtonColorThemer.h",
+  "src/components/Buttons/src/ColorThemer/MDCContainedButtonColorThemer.m",
+  "src/components/Buttons/src/ColorThemer/MDCFloatingButtonColorThemer.h",
+  "src/components/Buttons/src/ColorThemer/MDCFloatingButtonColorThemer.m",
+  "src/components/Buttons/src/ColorThemer/MDCOutlinedButtonColorThemer.h",
+  "src/components/Buttons/src/ColorThemer/MDCOutlinedButtonColorThemer.m",
+  "src/components/Buttons/src/ColorThemer/MDCTextButtonColorThemer.h",
+  "src/components/Buttons/src/ColorThemer/MDCTextButtonColorThemer.m",
+  "src/components/Buttons/src/ColorThemer/MaterialButtons+ColorThemer.h",
+  "src/components/Buttons/src/MDCButton.h",
+  "src/components/Buttons/src/MDCButton.m",
+  "src/components/Buttons/src/MDCFlatButton.h",
+  "src/components/Buttons/src/MDCFlatButton.m",
+  "src/components/Buttons/src/MDCFloatingButton+Animation.h",
+  "src/components/Buttons/src/MDCFloatingButton+Animation.m",
+  "src/components/Buttons/src/MDCFloatingButton.h",
+  "src/components/Buttons/src/MDCFloatingButton.m",
+  "src/components/Buttons/src/MDCRaisedButton.h",
+  "src/components/Buttons/src/MDCRaisedButton.m",
+  "src/components/Buttons/src/MaterialButtons.h",
+  "src/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.h",
+  "src/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.m",
+  "src/components/Buttons/src/ShapeThemer/MaterialButtons+ShapeThemer.h",
+  "src/components/Buttons/src/Theming/MDCButton+MaterialTheming.h",
+  "src/components/Buttons/src/Theming/MDCButton+MaterialTheming.m",
+  "src/components/Buttons/src/Theming/MDCFloatingButton+MaterialTheming.h",
+  "src/components/Buttons/src/Theming/MDCFloatingButton+MaterialTheming.m",
+  "src/components/Buttons/src/Theming/MaterialButtons+Theming.h",
+  "src/components/Buttons/src/TitleColorAccessibilityMutator/MDCButtonTitleColorAccessibilityMutator.h",
+  "src/components/Buttons/src/TitleColorAccessibilityMutator/MDCButtonTitleColorAccessibilityMutator.m",
+  "src/components/Buttons/src/TitleColorAccessibilityMutator/MaterialButtons+TitleColorAccessibilityMutator.h",
+  "src/components/Buttons/src/TypographyThemer/MDCButtonTypographyThemer.h",
+  "src/components/Buttons/src/TypographyThemer/MDCButtonTypographyThemer.m",
+  "src/components/Buttons/src/TypographyThemer/MaterialButtons+TypographyThemer.h",
+  "src/components/Buttons/src/private/MDCButton+Subclassing.h",
+  "src/components/Buttons/src/private/MDCFloatingButtonModeAnimator.h",
+  "src/components/Buttons/src/private/MDCFloatingButtonModeAnimator.m",
+  "src/components/Buttons/src/private/MDCFloatingButtonModeAnimatorDelegate.h",
+  "src/components/Cards/src/MDCCard.h",
+  "src/components/Cards/src/MDCCard.m",
+  "src/components/Cards/src/MDCCardCollectionCell.h",
+  "src/components/Cards/src/MDCCardCollectionCell.m",
+  "src/components/Cards/src/MaterialCards.h",
+  "src/components/Cards/src/Theming/MDCCard+MaterialTheming.h",
+  "src/components/Cards/src/Theming/MDCCard+MaterialTheming.m",
+  "src/components/Cards/src/Theming/MDCCardCollectionCell+MaterialTheming.h",
+  "src/components/Cards/src/Theming/MDCCardCollectionCell+MaterialTheming.m",
+  "src/components/Cards/src/Theming/MaterialCards+Theming.h",
+  "src/components/Cards/src/UICollectionViewController+MDCCardReordering.h",
+  "src/components/Cards/src/UICollectionViewController+MDCCardReordering.m",
+  "src/components/Chips/src/MDCChipCollectionViewCell.h",
+  "src/components/Chips/src/MDCChipCollectionViewCell.m",
+  "src/components/Chips/src/MDCChipCollectionViewFlowLayout.h",
+  "src/components/Chips/src/MDCChipCollectionViewFlowLayout.m",
+  "src/components/Chips/src/MDCChipField.h",
+  "src/components/Chips/src/MDCChipField.m",
+  "src/components/Chips/src/MDCChipFieldDelegate.h",
+  "src/components/Chips/src/MDCChipView.h",
+  "src/components/Chips/src/MDCChipView.m",
+  "src/components/Chips/src/MaterialChips.h",
+  "src/components/Chips/src/Theming/MDCChipView+MaterialTheming.h",
+  "src/components/Chips/src/Theming/MDCChipView+MaterialTheming.m",
+  "src/components/Chips/src/Theming/MaterialChips+Theming.h",
+  "src/components/Chips/src/private/MDCChipView+Private.h",
+  "src/components/CollectionCells/src/MDCCollectionViewCell.h",
+  "src/components/CollectionCells/src/MDCCollectionViewCell.m",
+  "src/components/CollectionCells/src/MDCCollectionViewTextCell.h",
+  "src/components/CollectionCells/src/MDCCollectionViewTextCell.m",
+  "src/components/CollectionCells/src/MaterialCollectionCells.h",
+  "src/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h",
+  "src/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m",
+  "src/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h",
+  "src/components/Collections/src/MDCCollectionViewController.h",
+  "src/components/Collections/src/MDCCollectionViewController.m",
+  "src/components/Collections/src/MDCCollectionViewEditing.h",
+  "src/components/Collections/src/MDCCollectionViewEditingDelegate.h",
+  "src/components/Collections/src/MDCCollectionViewFlowLayout.h",
+  "src/components/Collections/src/MDCCollectionViewFlowLayout.m",
+  "src/components/Collections/src/MDCCollectionViewStyling.h",
+  "src/components/Collections/src/MDCCollectionViewStylingDelegate.h",
+  "src/components/Collections/src/MaterialCollections.h",
+  "src/components/Collections/src/private/MDCCollectionGridBackgroundView.h",
+  "src/components/Collections/src/private/MDCCollectionGridBackgroundView.m",
+  "src/components/Collections/src/private/MDCCollectionInfoBarView.h",
+  "src/components/Collections/src/private/MDCCollectionInfoBarView.m",
+  "src/components/Collections/src/private/MDCCollectionInfoBarViewDelegate.h",
+  "src/components/Collections/src/private/MDCCollectionStringResources.h",
+  "src/components/Collections/src/private/MDCCollectionStringResources.m",
+  "src/components/Collections/src/private/MDCCollectionViewEditor.h",
+  "src/components/Collections/src/private/MDCCollectionViewEditor.m",
+  "src/components/Collections/src/private/MDCCollectionViewStyler.h",
+  "src/components/Collections/src/private/MDCCollectionViewStyler.m",
+  "src/components/Collections/src/private/MaterialCollectionsStrings.h",
+  "src/components/Collections/src/private/MaterialCollectionsStrings_table.h",
+  "src/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.h",
+  "src/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.m",
+  "src/components/Dialogs/src/ColorThemer/MaterialDialogs+ColorThemer.h",
+  "src/components/Dialogs/src/MDCAlertController+ButtonForAction.h",
+  "src/components/Dialogs/src/MDCAlertController+ButtonForAction.m",
+  "src/components/Dialogs/src/MDCAlertController+Customize.h",
+  "src/components/Dialogs/src/MDCAlertController.h",
+  "src/components/Dialogs/src/MDCAlertController.m",
+  "src/components/Dialogs/src/MDCAlertControllerDelegate.h",
+  "src/components/Dialogs/src/MDCAlertControllerView.h",
+  "src/components/Dialogs/src/MDCDialogPresentationController.h",
+  "src/components/Dialogs/src/MDCDialogPresentationController.m",
+  "src/components/Dialogs/src/MDCDialogPresentationControllerDelegate.h",
+  "src/components/Dialogs/src/MDCDialogTransitionController.h",
+  "src/components/Dialogs/src/MDCDialogTransitionController.m",
+  "src/components/Dialogs/src/MaterialDialogs.h",
+  "src/components/Dialogs/src/Theming/MDCAlertController+MaterialTheming.h",
+  "src/components/Dialogs/src/Theming/MDCAlertController+MaterialTheming.m",
+  "src/components/Dialogs/src/Theming/MDCDialogPresentationController+MaterialTheming.h",
+  "src/components/Dialogs/src/Theming/MDCDialogPresentationController+MaterialTheming.m",
+  "src/components/Dialogs/src/Theming/MaterialDialogs+Theming.h",
+  "src/components/Dialogs/src/TypographyThemer/MDCAlertTypographyThemer.h",
+  "src/components/Dialogs/src/TypographyThemer/MDCAlertTypographyThemer.m",
+  "src/components/Dialogs/src/TypographyThemer/MaterialDialogs+TypographyThemer.h",
+  "src/components/Dialogs/src/UIViewController+MaterialDialogs.h",
+  "src/components/Dialogs/src/UIViewController+MaterialDialogs.m",
+  "src/components/Dialogs/src/private/MDCAlertActionManager.h",
+  "src/components/Dialogs/src/private/MDCAlertActionManager.m",
+  "src/components/Dialogs/src/private/MDCAlertControllerView+Private.h",
+  "src/components/Dialogs/src/private/MDCAlertControllerView+Private.m",
+  "src/components/Dialogs/src/private/MDCDialogShadowedView.h",
+  "src/components/Dialogs/src/private/MDCDialogShadowedView.m",
+  "src/components/Dialogs/src/private/MaterialDialogsStrings.h",
+  "src/components/Dialogs/src/private/MaterialDialogsStrings_table.h",
+  "src/components/Elevation/src/MDCElevatable.h",
+  "src/components/Elevation/src/MDCElevationOverriding.h",
+  "src/components/Elevation/src/MaterialElevation.h",
+  "src/components/Elevation/src/UIColor+MaterialElevation.h",
+  "src/components/Elevation/src/UIColor+MaterialElevation.m",
+  "src/components/Elevation/src/UIView+MaterialElevationResponding.h",
+  "src/components/Elevation/src/UIView+MaterialElevationResponding.m",
+  "src/components/FeatureHighlight/src/ColorThemer/MDCFeatureHighlightColorThemer.h",
+  "src/components/FeatureHighlight/src/ColorThemer/MDCFeatureHighlightColorThemer.m",
+  "src/components/FeatureHighlight/src/ColorThemer/MaterialFeatureHighlight+ColorThemer.h",
+  "src/components/FeatureHighlight/src/FeatureHighlightAccessibilityMutator/MDCFeatureHighlightAccessibilityMutator.h",
+  "src/components/FeatureHighlight/src/FeatureHighlightAccessibilityMutator/MDCFeatureHighlightAccessibilityMutator.m",
+  "src/components/FeatureHighlight/src/FeatureHighlightAccessibilityMutator/MaterialFeatureHighlight+FeatureHighlightAccessibilityMutator.h",
+  "src/components/FeatureHighlight/src/MDCFeatureHighlightView.h",
+  "src/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h",
+  "src/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m",
+  "src/components/FeatureHighlight/src/MaterialFeatureHighlight.h",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightDismissGestureRecognizer.h",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightDismissGestureRecognizer.m",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightView+Private.h",
+  "src/components/FeatureHighlight/src/private/MDCFeatureHighlightView+Private.m",
+  "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MDCFlexibleHeaderView+canAlwaysExpandToMaximumHeight.h",
+  "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MaterialFlexibleHeader+CanAlwaysExpandToMaximumHeight.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderSafeAreaDelegate.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderView+ShiftBehavior.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderView.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderView.m",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewAnimationDelegate.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewDelegate.h",
+  "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewLayoutDelegate.h",
+  "src/components/FlexibleHeader/src/MaterialFlexibleHeader.h",
+  "src/components/FlexibleHeader/src/ShiftBehavior/MDCFlexibleHeaderShiftBehavior.h",
+  "src/components/FlexibleHeader/src/ShiftBehavior/MaterialFlexibleHeader+ShiftBehavior.h",
+  "src/components/FlexibleHeader/src/ShiftBehaviorEnabledWithStatusBar/MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar.h",
+  "src/components/FlexibleHeader/src/ShiftBehaviorEnabledWithStatusBar/MaterialFlexibleHeader+ShiftBehaviorEnabledWithStatusBar.h",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderHairline.h",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderHairline.m",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderMinMaxHeight.h",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderMinMaxHeight.m",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderMinMaxHeightDelegate.h",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderShifter.h",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderShifter.m",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderTopSafeArea.h",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderTopSafeArea.m",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderTopSafeAreaDelegate.h",
+  "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderView+Private.h",
+  "src/components/FlexibleHeader/src/private/MDCStatusBarShifter.h",
+  "src/components/FlexibleHeader/src/private/MDCStatusBarShifter.m",
+  "src/components/FlexibleHeader/src/private/MDCStatusBarShifterDelegate.h",
+  "src/components/HeaderStackView/src/ColorThemer/MDCHeaderStackViewColorThemer.h",
+  "src/components/HeaderStackView/src/ColorThemer/MDCHeaderStackViewColorThemer.m",
+  "src/components/HeaderStackView/src/ColorThemer/MaterialHeaderStackView+ColorThemer.h",
+  "src/components/HeaderStackView/src/MDCHeaderStackView.h",
+  "src/components/HeaderStackView/src/MDCHeaderStackView.m",
+  "src/components/HeaderStackView/src/MaterialHeaderStackView.h",
+  "src/components/Ink/src/MDCInkGestureRecognizer.h",
+  "src/components/Ink/src/MDCInkGestureRecognizer.m",
+  "src/components/Ink/src/MDCInkTouchController.h",
+  "src/components/Ink/src/MDCInkTouchController.m",
+  "src/components/Ink/src/MDCInkTouchControllerDelegate.h",
+  "src/components/Ink/src/MDCInkView.h",
+  "src/components/Ink/src/MDCInkView.m",
+  "src/components/Ink/src/MDCInkViewDelegate.h",
+  "src/components/Ink/src/MaterialInk.h",
+  "src/components/Ink/src/private/MDCInkLayer.h",
+  "src/components/Ink/src/private/MDCInkLayer.m",
+  "src/components/Ink/src/private/MDCInkLayerDelegate.h",
+  "src/components/Ink/src/private/MDCLegacyInkLayer+Private.h",
+  "src/components/Ink/src/private/MDCLegacyInkLayer.h",
+  "src/components/Ink/src/private/MDCLegacyInkLayer.m",
+  "src/components/Ink/src/private/MDCLegacyInkLayerDelegate.h",
+  "src/components/Ink/src/private/MDCLegacyInkLayerRippleDelegate.h",
+  "src/components/LibraryInfo/src/MDCLibraryInfo.h",
+  "src/components/LibraryInfo/src/MDCLibraryInfo.m",
+  "src/components/LibraryInfo/src/MaterialLibraryInfo.h",
+  "src/components/List/src/MDCBaseCell.h",
+  "src/components/List/src/MDCBaseCell.m",
+  "src/components/List/src/MDCSelfSizingLayoutAttributes.h",
+  "src/components/List/src/MDCSelfSizingStereoCell.h",
+  "src/components/List/src/MDCSelfSizingStereoCell.m",
+  "src/components/List/src/MaterialList.h",
+  "src/components/List/src/Theming/MDCBaseCell+MaterialTheming.h",
+  "src/components/List/src/Theming/MDCBaseCell+MaterialTheming.m",
+  "src/components/List/src/Theming/MDCSelfSizingStereoCell+MaterialTheming.h",
+  "src/components/List/src/Theming/MDCSelfSizingStereoCell+MaterialTheming.m",
+  "src/components/List/src/Theming/MaterialList+Theming.h",
+  "src/components/List/src/private/MDCSelfSizingStereoCellLayout.h",
+  "src/components/List/src/private/MDCSelfSizingStereoCellLayout.m",
+  "src/components/NavigationBar/src/ColorThemer/MDCNavigationBarColorThemer.h",
+  "src/components/NavigationBar/src/ColorThemer/MDCNavigationBarColorThemer.m",
+  "src/components/NavigationBar/src/ColorThemer/MaterialNavigationBar+ColorThemer.h",
+  "src/components/NavigationBar/src/MDCNavigationBar.h",
+  "src/components/NavigationBar/src/MDCNavigationBar.m",
+  "src/components/NavigationBar/src/MaterialNavigationBar.h",
+  "src/components/NavigationBar/src/TypographyThemer/MDCNavigationBarTypographyThemer.h",
+  "src/components/NavigationBar/src/TypographyThemer/MDCNavigationBarTypographyThemer.m",
+  "src/components/NavigationBar/src/TypographyThemer/MaterialNavigationBar+TypographyThemer.h",
+  "src/components/NavigationDrawer/src/ColorThemer/MDCBottomDrawerColorThemer.h",
+  "src/components/NavigationDrawer/src/ColorThemer/MDCBottomDrawerColorThemer.m",
+  "src/components/NavigationDrawer/src/ColorThemer/MaterialNavigationDrawer+ColorThemer.h",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerHeader.h",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.h",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.m",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerPresentationControllerDelegate.h",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerState.h",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerTransitionController.h",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerTransitionController.m",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerViewController.h",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerViewController.m",
+  "src/components/NavigationDrawer/src/MDCBottomDrawerViewControllerDelegate.h",
+  "src/components/NavigationDrawer/src/MaterialNavigationDrawer.h",
+  "src/components/NavigationDrawer/src/Theming/MDCBottomDrawerViewController+MaterialTheming.h",
+  "src/components/NavigationDrawer/src/Theming/MDCBottomDrawerViewController+MaterialTheming.m",
+  "src/components/NavigationDrawer/src/Theming/MaterialNavigationDrawer+Theming.h",
+  "src/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.h",
+  "src/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m",
+  "src/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewControllerDelegate.h",
+  "src/components/NavigationDrawer/src/private/MDCBottomDrawerHeaderMask.h",
+  "src/components/NavigationDrawer/src/private/MDCBottomDrawerHeaderMask.m",
+  "src/components/NavigationDrawer/src/private/MDCBottomDrawerShadowedView.h",
+  "src/components/OverlayWindow/src/MDCOverlayWindow.h",
+  "src/components/OverlayWindow/src/MDCOverlayWindow.m",
+  "src/components/OverlayWindow/src/MaterialOverlayWindow.h",
+  "src/components/PageControl/src/MDCPageControl.h",
+  "src/components/PageControl/src/MDCPageControl.m",
+  "src/components/PageControl/src/MaterialPageControl.h",
+  "src/components/PageControl/src/private/MDCPageControlIndicator.h",
+  "src/components/PageControl/src/private/MDCPageControlIndicator.m",
+  "src/components/PageControl/src/private/MDCPageControlTrackLayer.h",
+  "src/components/PageControl/src/private/MDCPageControlTrackLayer.m",
+  "src/components/PageControl/src/private/MaterialPageControlStrings.h",
+  "src/components/PageControl/src/private/MaterialPageControlStrings_table.h",
+  "src/components/Palettes/src/MDCPalettes.h",
+  "src/components/Palettes/src/MDCPalettes.m",
+  "src/components/Palettes/src/MaterialPalettes.h",
+  "src/components/Palettes/src/private/MDCPaletteExpansions.h",
+  "src/components/Palettes/src/private/MDCPaletteExpansions.m",
+  "src/components/Palettes/src/private/MDCPaletteNames.h",
+  "src/components/Palettes/src/private/MDCPaletteNames.m",
+  "src/components/ProgressView/src/MDCProgressView.h",
+  "src/components/ProgressView/src/MDCProgressView.m",
+  "src/components/ProgressView/src/MaterialProgressView.h",
+  "src/components/ProgressView/src/Theming/MDCProgressView+MaterialTheming.h",
+  "src/components/ProgressView/src/Theming/MDCProgressView+MaterialTheming.m",
+  "src/components/ProgressView/src/Theming/MaterialProgressView+Theming.h",
+  "src/components/ProgressView/src/private/MDCProgressGradientView.h",
+  "src/components/ProgressView/src/private/MDCProgressGradientView.m",
+  "src/components/ProgressView/src/private/MaterialProgressViewStrings.h",
+  "src/components/ProgressView/src/private/MaterialProgressViewStrings_table.h",
+  "src/components/Ripple/src/MDCRippleTouchController.h",
+  "src/components/Ripple/src/MDCRippleTouchController.m",
+  "src/components/Ripple/src/MDCRippleTouchControllerDelegate.h",
+  "src/components/Ripple/src/MDCRippleView.h",
+  "src/components/Ripple/src/MDCRippleView.m",
+  "src/components/Ripple/src/MDCRippleViewDelegate.h",
+  "src/components/Ripple/src/MDCStatefulRippleView.h",
+  "src/components/Ripple/src/MDCStatefulRippleView.m",
+  "src/components/Ripple/src/MaterialRipple.h",
+  "src/components/Ripple/src/private/MDCRippleLayer.h",
+  "src/components/Ripple/src/private/MDCRippleLayer.m",
+  "src/components/Ripple/src/private/MDCRippleLayerDelegate.h",
+  "src/components/ShadowElevations/src/MDCShadowElevations.h",
+  "src/components/ShadowElevations/src/MaterialShadowElevations.h",
+  "src/components/ShadowElevations/src/MaterialShadowElevationsDummy.m",
+  "src/components/ShadowLayer/src/MDCShadowLayer.h",
+  "src/components/ShadowLayer/src/MDCShadowLayer.m",
+  "src/components/ShadowLayer/src/MaterialShadowLayer.h",
+  "src/components/ShapeLibrary/src/MDCCornerTreatment+CornerTypeInitalizer.h",
+  "src/components/ShapeLibrary/src/MDCCornerTreatment+CornerTypeInitalizer.m",
+  "src/components/ShapeLibrary/src/MDCCurvedCornerTreatment.h",
+  "src/components/ShapeLibrary/src/MDCCurvedCornerTreatment.m",
+  "src/components/ShapeLibrary/src/MDCCurvedRectShapeGenerator.h",
+  "src/components/ShapeLibrary/src/MDCCurvedRectShapeGenerator.m",
+  "src/components/ShapeLibrary/src/MDCCutCornerTreatment.h",
+  "src/components/ShapeLibrary/src/MDCCutCornerTreatment.m",
+  "src/components/ShapeLibrary/src/MDCPillShapeGenerator.h",
+  "src/components/ShapeLibrary/src/MDCPillShapeGenerator.m",
+  "src/components/ShapeLibrary/src/MDCRoundedCornerTreatment.h",
+  "src/components/ShapeLibrary/src/MDCRoundedCornerTreatment.m",
+  "src/components/ShapeLibrary/src/MDCSlantedRectShapeGenerator.h",
+  "src/components/ShapeLibrary/src/MDCSlantedRectShapeGenerator.m",
+  "src/components/ShapeLibrary/src/MDCTriangleEdgeTreatment.h",
+  "src/components/ShapeLibrary/src/MDCTriangleEdgeTreatment.m",
+  "src/components/ShapeLibrary/src/MaterialShapeLibrary.h",
+  "src/components/Shapes/src/MDCCornerTreatment.h",
+  "src/components/Shapes/src/MDCCornerTreatment.m",
+  "src/components/Shapes/src/MDCEdgeTreatment.h",
+  "src/components/Shapes/src/MDCEdgeTreatment.m",
+  "src/components/Shapes/src/MDCPathGenerator.h",
+  "src/components/Shapes/src/MDCPathGenerator.m",
+  "src/components/Shapes/src/MDCRectangleShapeGenerator.h",
+  "src/components/Shapes/src/MDCRectangleShapeGenerator.m",
+  "src/components/Shapes/src/MDCShapeGenerating.h",
+  "src/components/Shapes/src/MDCShapedShadowLayer.h",
+  "src/components/Shapes/src/MDCShapedShadowLayer.m",
+  "src/components/Shapes/src/MDCShapedView.h",
+  "src/components/Shapes/src/MDCShapedView.m",
+  "src/components/Shapes/src/MaterialShapes.h",
+  "src/components/Slider/src/ColorThemer/MDCSliderColorThemer.h",
+  "src/components/Slider/src/ColorThemer/MDCSliderColorThemer.m",
+  "src/components/Slider/src/ColorThemer/MaterialSlider+ColorThemer.h",
+  "src/components/Slider/src/MDCSlider.h",
+  "src/components/Slider/src/MDCSlider.m",
+  "src/components/Slider/src/MDCSliderDelegate.h",
+  "src/components/Slider/src/MaterialSlider.h",
+  "src/components/Slider/src/private/MDCSlider+Private.h",
+  "src/components/Slider/src/private/MDCSlider_Subclassable.h",
+  "src/components/Snackbar/src/FontThemer/MDCSnackbarFontThemer.h",
+  "src/components/Snackbar/src/FontThemer/MDCSnackbarFontThemer.m",
+  "src/components/Snackbar/src/FontThemer/MaterialSnackbar+FontThemer.h",
+  "src/components/Snackbar/src/MDCSnackbarAlignment.h",
+  "src/components/Snackbar/src/MDCSnackbarError.h",
+  "src/components/Snackbar/src/MDCSnackbarError.m",
+  "src/components/Snackbar/src/MDCSnackbarManager.h",
+  "src/components/Snackbar/src/MDCSnackbarManager.m",
+  "src/components/Snackbar/src/MDCSnackbarManagerDelegate.h",
+  "src/components/Snackbar/src/MDCSnackbarMessage.h",
+  "src/components/Snackbar/src/MDCSnackbarMessage.m",
+  "src/components/Snackbar/src/MDCSnackbarMessageView.h",
+  "src/components/Snackbar/src/MDCSnackbarMessageView.m",
+  "src/components/Snackbar/src/MaterialSnackbar.h",
+  "src/components/Snackbar/src/TypographyThemer/MDCSnackbarTypographyThemer.h",
+  "src/components/Snackbar/src/TypographyThemer/MDCSnackbarTypographyThemer.m",
+  "src/components/Snackbar/src/TypographyThemer/MaterialSnackbar+TypographyThemer.h",
+  "src/components/Snackbar/src/private/MDCSnackbarManagerInternal.h",
+  "src/components/Snackbar/src/private/MDCSnackbarMessageInternal.h",
+  "src/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h",
+  "src/components/Snackbar/src/private/MDCSnackbarOverlayView.h",
+  "src/components/Snackbar/src/private/MDCSnackbarOverlayView.m",
+  "src/components/Snackbar/src/private/MaterialSnackbarStrings.h",
+  "src/components/Snackbar/src/private/MaterialSnackbarStrings_table.h",
+  "src/components/Tabs/src/ExtendedAlignment/MDCTabBarExtendedAlignment.h",
+  "src/components/Tabs/src/MDCTabBar.h",
+  "src/components/Tabs/src/MDCTabBar.m",
+  "src/components/Tabs/src/MDCTabBarAlignment.h",
+  "src/components/Tabs/src/MDCTabBarControllerDelegate.h",
+  "src/components/Tabs/src/MDCTabBarDelegate.h",
+  "src/components/Tabs/src/MDCTabBarDisplayDelegate.h",
+  "src/components/Tabs/src/MDCTabBarIndicatorAttributes.h",
+  "src/components/Tabs/src/MDCTabBarIndicatorAttributes.m",
+  "src/components/Tabs/src/MDCTabBarIndicatorContext.h",
+  "src/components/Tabs/src/MDCTabBarIndicatorTemplate.h",
+  "src/components/Tabs/src/MDCTabBarItemAppearance.h",
+  "src/components/Tabs/src/MDCTabBarTextTransform.h",
+  "src/components/Tabs/src/MDCTabBarUnderlineIndicatorTemplate.h",
+  "src/components/Tabs/src/MDCTabBarUnderlineIndicatorTemplate.m",
+  "src/components/Tabs/src/MDCTabBarViewController.h",
+  "src/components/Tabs/src/MDCTabBarViewController.m",
+  "src/components/Tabs/src/MaterialTabs.h",
+  "src/components/Tabs/src/SizeClassDelegate/MDCTabBarSizeClassDelegate.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarItem.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarItem.m",
+  "src/components/Tabs/src/TabBarView/MDCTabBarItemCustomViewing.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarView.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarView.m",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewCustomViewable.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewDelegate.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorAttributes.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorAttributes.m",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorContext.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorTemplate.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewUnderlineIndicatorTemplate.h",
+  "src/components/Tabs/src/TabBarView/MDCTabBarViewUnderlineIndicatorTemplate.m",
+  "src/components/Tabs/src/TabBarView/MaterialTabs+TabBarView.h",
+  "src/components/Tabs/src/TabBarView/private/MDCTabBarViewIndicatorView.h",
+  "src/components/Tabs/src/TabBarView/private/MDCTabBarViewIndicatorView.m",
+  "src/components/Tabs/src/TabBarView/private/MDCTabBarViewItemView.h",
+  "src/components/Tabs/src/TabBarView/private/MDCTabBarViewItemView.m",
+  "src/components/Tabs/src/TabBarView/private/MDCTabBarViewPrivateIndicatorContext.h",
+  "src/components/Tabs/src/TabBarView/private/MDCTabBarViewPrivateIndicatorContext.m",
+  "src/components/Tabs/src/Theming/MDCTabBar+MaterialTheming.h",
+  "src/components/Tabs/src/Theming/MDCTabBar+MaterialTheming.m",
+  "src/components/Tabs/src/Theming/MaterialTabs+Theming.h",
+  "src/components/Tabs/src/TypographyThemer/MDCTabBarTypographyThemer.h",
+  "src/components/Tabs/src/TypographyThemer/MDCTabBarTypographyThemer.m",
+  "src/components/Tabs/src/TypographyThemer/MaterialTabs+TypographyThemer.h",
+  "src/components/Tabs/src/private/MDCItemBar.h",
+  "src/components/Tabs/src/private/MDCItemBar.m",
+  "src/components/Tabs/src/private/MDCItemBarAlignment.h",
+  "src/components/Tabs/src/private/MDCItemBarBadge.h",
+  "src/components/Tabs/src/private/MDCItemBarBadge.m",
+  "src/components/Tabs/src/private/MDCItemBarCell+Private.h",
+  "src/components/Tabs/src/private/MDCItemBarCell.h",
+  "src/components/Tabs/src/private/MDCItemBarCell.m",
+  "src/components/Tabs/src/private/MDCItemBarDelegate.h",
+  "src/components/Tabs/src/private/MDCItemBarStringConstants.h",
+  "src/components/Tabs/src/private/MDCItemBarStyle.h",
+  "src/components/Tabs/src/private/MDCItemBarStyle.m",
+  "src/components/Tabs/src/private/MDCTabBarIndicatorView.h",
+  "src/components/Tabs/src/private/MDCTabBarIndicatorView.m",
+  "src/components/Tabs/src/private/MDCTabBarPrivateIndicatorContext.h",
+  "src/components/Tabs/src/private/MDCTabBarPrivateIndicatorContext.m",
+  "src/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h",
+  "src/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.m",
+  "src/components/TextControls/src/BaseTextAreas/MaterialTextControls+BaseTextAreas.h",
+  "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaLayout.h",
+  "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaLayout.m",
+  "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaTextView.h",
+  "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaTextView.m",
+  "src/components/TextControls/src/BaseTextFields/MDCBaseTextField.h",
+  "src/components/TextControls/src/BaseTextFields/MDCBaseTextField.m",
+  "src/components/TextControls/src/BaseTextFields/MaterialTextControls+BaseTextFields.h",
+  "src/components/TextControls/src/Enums/MDCTextControlLabelBehavior.h",
+  "src/components/TextControls/src/Enums/MDCTextControlState.h",
+  "src/components/TextControls/src/Enums/MDCTextControlState.m",
+  "src/components/TextControls/src/Enums/MaterialTextControls+Enums.h",
+  "src/components/TextControls/src/FilledTextAreas/MDCFilledTextArea.h",
+  "src/components/TextControls/src/FilledTextAreas/MDCFilledTextArea.m",
+  "src/components/TextControls/src/FilledTextAreas/MaterialTextControls+FilledTextAreas.h",
+  "src/components/TextControls/src/FilledTextAreasTheming/MDCFilledTextArea+MaterialTheming.h",
+  "src/components/TextControls/src/FilledTextAreasTheming/MDCFilledTextArea+MaterialTheming.m",
+  "src/components/TextControls/src/FilledTextAreasTheming/MaterialTextControls+FilledTextAreasTheming.h",
+  "src/components/TextControls/src/FilledTextFields/MDCFilledTextField.h",
+  "src/components/TextControls/src/FilledTextFields/MDCFilledTextField.m",
+  "src/components/TextControls/src/FilledTextFields/MaterialTextControls+FilledTextFields.h",
+  "src/components/TextControls/src/FilledTextFieldsTheming/MDCFilledTextField+MaterialTheming.h",
+  "src/components/TextControls/src/FilledTextFieldsTheming/MDCFilledTextField+MaterialTheming.m",
+  "src/components/TextControls/src/FilledTextFieldsTheming/MaterialTextControls+FilledTextFieldsTheming.h",
+  "src/components/TextControls/src/OutlinedTextAreas/MDCOutlinedTextArea.h",
+  "src/components/TextControls/src/OutlinedTextAreas/MDCOutlinedTextArea.m",
+  "src/components/TextControls/src/OutlinedTextAreas/MaterialTextControls+OutlinedTextAreas.h",
+  "src/components/TextControls/src/OutlinedTextAreasTheming/MDCOutlinedTextArea+MaterialTheming.h",
+  "src/components/TextControls/src/OutlinedTextAreasTheming/MDCOutlinedTextArea+MaterialTheming.m",
+  "src/components/TextControls/src/OutlinedTextAreasTheming/MaterialTextControls+OutlinedTextAreasTheming.h",
+  "src/components/TextControls/src/OutlinedTextFields/MDCOutlinedTextField.h",
+  "src/components/TextControls/src/OutlinedTextFields/MDCOutlinedTextField.m",
+  "src/components/TextControls/src/OutlinedTextFields/MaterialTextControls+OutlinedTextFields.h",
+  "src/components/TextControls/src/OutlinedTextFieldsTheming/MDCOutlinedTextField+MaterialTheming.h",
+  "src/components/TextControls/src/OutlinedTextFieldsTheming/MDCOutlinedTextField+MaterialTheming.m",
+  "src/components/TextControls/src/OutlinedTextFieldsTheming/MaterialTextControls+OutlinedTextFieldsTheming.h",
+  "src/components/TextControls/src/UnderlinedTextFields/MDCUnderlinedTextField.h",
+  "src/components/TextControls/src/UnderlinedTextFields/MDCUnderlinedTextField.m",
+  "src/components/TextControls/src/UnderlinedTextFields/MaterialTextControls+UnderlinedTextFields.h",
+  "src/components/TextControls/src/UnderlinedTextFieldsTheming/MDCUnderlinedTextField+MaterialTheming.h",
+  "src/components/TextControls/src/UnderlinedTextFieldsTheming/MDCUnderlinedTextField+MaterialTheming.m",
+  "src/components/TextControls/src/UnderlinedTextFieldsTheming/MaterialTextControls+UnderlinedTextFieldsTheming.h",
+  "src/components/TextFields/src/ColorThemer/MDCFilledTextFieldColorThemer.h",
+  "src/components/TextFields/src/ColorThemer/MDCFilledTextFieldColorThemer.m",
+  "src/components/TextFields/src/ColorThemer/MaterialTextFields+ColorThemer.h",
+  "src/components/TextFields/src/MDCIntrinsicHeightTextView.h",
+  "src/components/TextFields/src/MDCIntrinsicHeightTextView.m",
+  "src/components/TextFields/src/MDCMultilineTextField.h",
+  "src/components/TextFields/src/MDCMultilineTextField.m",
+  "src/components/TextFields/src/MDCMultilineTextInputDelegate.h",
+  "src/components/TextFields/src/MDCMultilineTextInputLayoutDelegate.h",
+  "src/components/TextFields/src/MDCTextField.h",
+  "src/components/TextFields/src/MDCTextField.m",
+  "src/components/TextFields/src/MDCTextFieldPositioningDelegate.h",
+  "src/components/TextFields/src/MDCTextInput.h",
+  "src/components/TextFields/src/MDCTextInputBorderView.h",
+  "src/components/TextFields/src/MDCTextInputBorderView.m",
+  "src/components/TextFields/src/MDCTextInputCharacterCounter.h",
+  "src/components/TextFields/src/MDCTextInputController.h",
+  "src/components/TextFields/src/MDCTextInputControllerBase.h",
+  "src/components/TextFields/src/MDCTextInputControllerBase.m",
+  "src/components/TextFields/src/MDCTextInputControllerFilled.h",
+  "src/components/TextFields/src/MDCTextInputControllerFilled.m",
+  "src/components/TextFields/src/MDCTextInputControllerFloatingPlaceholder.h",
+  "src/components/TextFields/src/MDCTextInputControllerFullWidth.h",
+  "src/components/TextFields/src/MDCTextInputControllerFullWidth.m",
+  "src/components/TextFields/src/MDCTextInputControllerLegacyDefault.h",
+  "src/components/TextFields/src/MDCTextInputControllerLegacyDefault.m",
+  "src/components/TextFields/src/MDCTextInputControllerLegacyFullWidth.h",
+  "src/components/TextFields/src/MDCTextInputControllerLegacyFullWidth.m",
+  "src/components/TextFields/src/MDCTextInputControllerOutlined.h",
+  "src/components/TextFields/src/MDCTextInputControllerOutlined.m",
+  "src/components/TextFields/src/MDCTextInputControllerOutlinedTextArea.h",
+  "src/components/TextFields/src/MDCTextInputControllerOutlinedTextArea.m",
+  "src/components/TextFields/src/MDCTextInputControllerUnderline.h",
+  "src/components/TextFields/src/MDCTextInputControllerUnderline.m",
+  "src/components/TextFields/src/MDCTextInputUnderlineView.h",
+  "src/components/TextFields/src/MDCTextInputUnderlineView.m",
+  "src/components/TextFields/src/MaterialTextFields.h",
+  "src/components/TextFields/src/Theming/MDCTextInputControllerFilled+MaterialTheming.h",
+  "src/components/TextFields/src/Theming/MDCTextInputControllerFilled+MaterialTheming.m",
+  "src/components/TextFields/src/Theming/MDCTextInputControllerOutlined+MaterialTheming.h",
+  "src/components/TextFields/src/Theming/MDCTextInputControllerOutlined+MaterialTheming.m",
+  "src/components/TextFields/src/Theming/MDCTextInputControllerUnderline+MaterialTheming.h",
+  "src/components/TextFields/src/Theming/MDCTextInputControllerUnderline+MaterialTheming.m",
+  "src/components/TextFields/src/Theming/MaterialTextFields+Theming.h",
+  "src/components/TextFields/src/private/MDCTextInputAllCharactersCounter.m",
+  "src/components/TextFields/src/private/MDCTextInputArt.h",
+  "src/components/TextFields/src/private/MDCTextInputCommonFundament.h",
+  "src/components/TextFields/src/private/MDCTextInputCommonFundament.m",
+  "src/components/TextFields/src/private/MDCTextInputControllerBase+Subclassing.h",
+  "src/components/Themes/src/MDCColorScheme.h",
+  "src/components/Themes/src/MDCFontScheme.h",
+  "src/components/Themes/src/MDCTonalColorScheme.h",
+  "src/components/Themes/src/MDCTonalPalette.h",
+  "src/components/Themes/src/MaterialThemes.h",
+  "src/components/Typography/src/MDCFontScaler.h",
+  "src/components/Typography/src/MDCFontScaler.m",
+  "src/components/Typography/src/MDCFontTextStyle.h",
+  "src/components/Typography/src/MDCTypography.h",
+  "src/components/Typography/src/MDCTypography.m",
+  "src/components/Typography/src/MaterialTypography.h",
+  "src/components/Typography/src/UIFont+MaterialScalable.h",
+  "src/components/Typography/src/UIFont+MaterialScalable.m",
+  "src/components/Typography/src/UIFont+MaterialSimpleEquality.h",
+  "src/components/Typography/src/UIFont+MaterialSimpleEquality.m",
+  "src/components/Typography/src/UIFont+MaterialTypography.h",
+  "src/components/Typography/src/UIFont+MaterialTypography.m",
+  "src/components/Typography/src/UIFontDescriptor+MaterialTypography.h",
+  "src/components/Typography/src/UIFontDescriptor+MaterialTypography.m",
+  "src/components/Typography/src/private/MDCFontTraits.h",
+  "src/components/Typography/src/private/MDCFontTraits.m",
+  "src/components/Typography/src/private/MDCTypographyUtilities.h",
+  "src/components/Typography/src/private/MDCTypographyUtilities.m",
+  "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h",
+  "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m",
+  "src/components/private/Application/src/MaterialApplication.h",
+  "src/components/private/Application/src/UIApplication+MDCAppExtensions.h",
+  "src/components/private/Application/src/UIApplication+MDCAppExtensions.m",
+  "src/components/private/Beta/src/MaterialBetaComponent.h",
+  "src/components/private/Color/src/MaterialColor.h",
+  "src/components/private/Color/src/UIColor+MaterialBlending.h",
+  "src/components/private/Color/src/UIColor+MaterialBlending.m",
+  "src/components/private/Color/src/UIColor+MaterialDynamic.h",
+  "src/components/private/Color/src/UIColor+MaterialDynamic.m",
+  "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h",
+  "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m",
+  "src/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h",
+  "src/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m",
+  "src/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h",
+  "src/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m",
+  "src/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h",
+  "src/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m",
+  "src/components/private/Icons/icons/ic_color_lens/src/MaterialIcons+ic_color_lens.h",
+  "src/components/private/Icons/icons/ic_color_lens/src/MaterialIcons+ic_color_lens.m",
+  "src/components/private/Icons/icons/ic_feedback/src/MaterialIcons+ic_feedback.h",
+  "src/components/private/Icons/icons/ic_feedback/src/MaterialIcons+ic_feedback.m",
+  "src/components/private/Icons/icons/ic_help_outline/src/MaterialIcons+ic_help_outline.h",
+  "src/components/private/Icons/icons/ic_help_outline/src/MaterialIcons+ic_help_outline.m",
+  "src/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h",
+  "src/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m",
+  "src/components/private/Icons/icons/ic_more_horiz/src/MaterialIcons+ic_more_horiz.h",
+  "src/components/private/Icons/icons/ic_more_horiz/src/MaterialIcons+ic_more_horiz.m",
+  "src/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h",
+  "src/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m",
+  "src/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h",
+  "src/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m",
+  "src/components/private/Icons/icons/ic_settings/src/MaterialIcons+ic_settings.h",
+  "src/components/private/Icons/icons/ic_settings/src/MaterialIcons+ic_settings.m",
+  "src/components/private/Icons/src/MDCIcons+BundleLoader.h",
+  "src/components/private/Icons/src/MDCIcons.h",
+  "src/components/private/Icons/src/MDCIcons.m",
+  "src/components/private/Icons/src/MaterialIcons.h",
+  "src/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h",
+  "src/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m",
+  "src/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h",
+  "src/components/private/Math/src/MDCMath.h",
+  "src/components/private/Math/src/MaterialMath.h",
+  "src/components/private/Math/src/MaterialMathDummy.m",
+  "src/components/private/Overlay/src/MDCOverlayImplementor.h",
+  "src/components/private/Overlay/src/MDCOverlayObserver.h",
+  "src/components/private/Overlay/src/MDCOverlayObserver.m",
+  "src/components/private/Overlay/src/MDCOverlayTransitioning.h",
+  "src/components/private/Overlay/src/MaterialOverlay.h",
+  "src/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h",
+  "src/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m",
+  "src/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h",
+  "src/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m",
+  "src/components/private/Overlay/src/private/MDCOverlayObserverTransition.h",
+  "src/components/private/Overlay/src/private/MDCOverlayObserverTransition.m",
+  "src/components/private/Overlay/src/private/MDCOverlayUtilities.h",
+  "src/components/private/Overlay/src/private/MDCOverlayUtilities.m",
+  "src/components/private/Snapshot/src/MaterialSnapshot.h",
+  "src/components/private/Snapshot/src/SnapshotUtilities/UIImage+MDCSnapshot.h",
+  "src/components/private/Snapshot/src/SnapshotUtilities/UIImage+MDCSnapshot.m",
+  "src/components/private/Snapshot/src/SnapshotUtilities/UIView+MDCSnapshot.h",
+  "src/components/private/Snapshot/src/SnapshotUtilities/UIView+MDCSnapshot.m",
+  "src/components/private/Snapshot/src/SourceDummies/MDCSnapshotSourceDummy.h",
+  "src/components/private/Snapshot/src/SourceDummies/MDCSnapshotSourceDummy.m",
+  "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlStyleBase.h",
+  "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlStyleBase.m",
+  "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlVerticalPositioningReferenceBase.h",
+  "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlVerticalPositioningReferenceBase.m",
+  "src/components/private/TextControlsPrivate/src/BaseStyle/MaterialTextControlsPrivate+BaseStyle.h",
+  "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlStyleFilled.h",
+  "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlStyleFilled.m",
+  "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlVerticalPositioningReferenceFilled.h",
+  "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlVerticalPositioningReferenceFilled.m",
+  "src/components/private/TextControlsPrivate/src/FilledStyle/MaterialTextControlsPrivate+FilledStyle.h",
+  "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlStyleOutlined.h",
+  "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlStyleOutlined.m",
+  "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlVerticalPositioningReferenceOutlined.h",
+  "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlVerticalPositioningReferenceOutlined.m",
+  "src/components/private/TextControlsPrivate/src/OutlinedStyle/MaterialTextControlsPrivate+OutlinedStyle.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControl.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControl.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelDrawPriority.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelView.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelView.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelViewLayout.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelViewLayout.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlColorViewModel.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlColorViewModel.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlGradientManager.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlGradientManager.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlHorizontalPositioningReference.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlHorizontalPositioningReference.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelAnimation.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelAnimation.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelPosition.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelPosition.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlVerticalPositioningReference.h",
+  "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlVerticalPositioningReference.m",
+  "src/components/private/TextControlsPrivate/src/Shared/MaterialTextControlsPrivate+Shared.h",
+  "src/components/private/TextControlsPrivate/src/Shared/UIBezierPath+MDCTextControlStyle.h",
+  "src/components/private/TextControlsPrivate/src/Shared/UIBezierPath+MDCTextControlStyle.m",
+  "src/components/private/TextControlsPrivate/src/TextFields/MDCBaseTextFieldLayout.h",
+  "src/components/private/TextControlsPrivate/src/TextFields/MDCBaseTextFieldLayout.m",
+  "src/components/private/TextControlsPrivate/src/TextFields/MaterialTextControlsPrivate+TextFields.h",
+  "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlStyleUnderlined.h",
+  "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlStyleUnderlined.m",
+  "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlVerticalPositioningReferenceUnderlined.h",
+  "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlVerticalPositioningReferenceUnderlined.m",
+  "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MaterialTextControlsPrivate+UnderlinedStyle.h",
+  "src/components/private/ThumbTrack/src/MDCNumericValueLabel.h",
+  "src/components/private/ThumbTrack/src/MDCNumericValueLabel.m",
+  "src/components/private/ThumbTrack/src/MDCThumbTrack.h",
+  "src/components/private/ThumbTrack/src/MDCThumbTrack.m",
+  "src/components/private/ThumbTrack/src/MDCThumbView.h",
+  "src/components/private/ThumbTrack/src/MDCThumbView.m",
+  "src/components/private/ThumbTrack/src/MaterialThumbTrack.h",
+  "src/components/private/ThumbTrack/src/private/MDCThumbTrack+Private.h",
+  "src/components/private/UIMetrics/src/MDCLayoutMetrics.h",
+  "src/components/private/UIMetrics/src/MDCLayoutMetrics.m",
+  "src/components/private/UIMetrics/src/MaterialUIMetrics.h",
+  "src/components/schemes/Color/src/MDCLegacyColorScheme.h",
+  "src/components/schemes/Color/src/MDCLegacyColorScheme.m",
+  "src/components/schemes/Color/src/MDCLegacyTonalColorScheme.h",
+  "src/components/schemes/Color/src/MDCLegacyTonalColorScheme.m",
+  "src/components/schemes/Color/src/MDCLegacyTonalPalette.h",
+  "src/components/schemes/Color/src/MDCLegacyTonalPalette.m",
+  "src/components/schemes/Color/src/MDCSemanticColorScheme.h",
+  "src/components/schemes/Color/src/MDCSemanticColorScheme.m",
+  "src/components/schemes/Color/src/MaterialColorScheme.h",
+  "src/components/schemes/Container/src/MDCContainerScheme.h",
+  "src/components/schemes/Container/src/MDCContainerScheme.m",
+  "src/components/schemes/Container/src/MaterialContainerScheme.h",
+  "src/components/schemes/Shape/src/MDCShapeCategory.h",
+  "src/components/schemes/Shape/src/MDCShapeCategory.m",
+  "src/components/schemes/Shape/src/MDCShapeScheme.h",
+  "src/components/schemes/Shape/src/MDCShapeScheme.m",
+  "src/components/schemes/Shape/src/MaterialShapeScheme.h",
+  "src/components/schemes/Typography/src/BasicFontScheme/MDCBasicFontScheme.h",
+  "src/components/schemes/Typography/src/BasicFontScheme/MDCBasicFontScheme.m",
+  "src/components/schemes/Typography/src/BasicFontScheme/MaterialTypographyScheme+BasicFontScheme.h",
+  "src/components/schemes/Typography/src/MDCLegacyFontScheme.h",
+  "src/components/schemes/Typography/src/MDCTypographyScheme.h",
+  "src/components/schemes/Typography/src/MDCTypographyScheme.m",
+  "src/components/schemes/Typography/src/MaterialTypographyScheme.h",
+  "src/components/schemes/Typography/src/Scheming/MDCTypographyScheming.h",
+  "src/components/schemes/Typography/src/Scheming/MaterialTypographyScheme+Scheming.h",
+]
+
 config("public_configs") {
   visibility = [ ":*" ]
 
@@ -749,836 +1582,7 @@
 }
 
 target("ios_framework_bundle", "material_components_ios") {
-  sources = [
-    # List generated by the following commands:
-    # $ cd src/ios/third_party/material_components_ios
-    # $ find src -path 'src/components/*/src/*.[hm]' -a \! -path '*Test*'|\
-    #   sed -e 's:\(.*\):    "\1",:'|sort -u
-    "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.h",
-    "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetScheme.m",
-    "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.h",
-    "src/components/ActionSheet/src/ActionSheetThemer/MDCActionSheetThemer.m",
-    "src/components/ActionSheet/src/ActionSheetThemer/MaterialActionSheet+ActionSheetThemer.h",
-    "src/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.h",
-    "src/components/ActionSheet/src/ColorThemer/MDCActionSheetColorThemer.m",
-    "src/components/ActionSheet/src/ColorThemer/MaterialActionSheet+ColorThemer.h",
-    "src/components/ActionSheet/src/MDCActionSheetAction.h",
-    "src/components/ActionSheet/src/MDCActionSheetController.h",
-    "src/components/ActionSheet/src/MDCActionSheetController.m",
-    "src/components/ActionSheet/src/MDCActionSheetControllerDelegate.h",
-    "src/components/ActionSheet/src/MaterialActionSheet.h",
-    "src/components/ActionSheet/src/Theming/MDCActionSheetController+MaterialTheming.h",
-    "src/components/ActionSheet/src/Theming/MDCActionSheetController+MaterialTheming.m",
-    "src/components/ActionSheet/src/Theming/MaterialActionSheet+Theming.h",
-    "src/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.h",
-    "src/components/ActionSheet/src/TypographyThemer/MDCActionSheetTypographyThemer.m",
-    "src/components/ActionSheet/src/TypographyThemer/MaterialActionSheet+TypographyThemer.h",
-    "src/components/ActionSheet/src/private/MDCActionSheetHeaderView.h",
-    "src/components/ActionSheet/src/private/MDCActionSheetHeaderView.m",
-    "src/components/ActionSheet/src/private/MDCActionSheetItemTableViewCell.h",
-    "src/components/ActionSheet/src/private/MDCActionSheetItemTableViewCell.m",
-    "src/components/ActivityIndicator/src/MDCActivityIndicator.h",
-    "src/components/ActivityIndicator/src/MDCActivityIndicator.m",
-    "src/components/ActivityIndicator/src/MDCActivityIndicatorDelegate.h",
-    "src/components/ActivityIndicator/src/MaterialActivityIndicator.h",
-    "src/components/ActivityIndicator/src/private/MDCActivityIndicator+Private.h",
-    "src/components/ActivityIndicator/src/private/MDCActivityIndicatorMotionSpec.h",
-    "src/components/ActivityIndicator/src/private/MDCActivityIndicatorMotionSpec.m",
-    "src/components/ActivityIndicator/src/private/MaterialActivityIndicatorStrings.h",
-    "src/components/ActivityIndicator/src/private/MaterialActivityIndicatorStrings_table.h",
-    "src/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.h",
-    "src/components/AnimationTiming/src/CAMediaTimingFunction+MDCAnimationTiming.m",
-    "src/components/AnimationTiming/src/MaterialAnimationTiming.h",
-    "src/components/AnimationTiming/src/UIView+MDCTimingFunction.h",
-    "src/components/AnimationTiming/src/UIView+MDCTimingFunction.m",
-    "src/components/AppBar/src/ColorThemer/MDCAppBarColorThemer.h",
-    "src/components/AppBar/src/ColorThemer/MDCAppBarColorThemer.m",
-    "src/components/AppBar/src/ColorThemer/MaterialAppBar+ColorThemer.h",
-    "src/components/AppBar/src/MDCAppBar.h",
-    "src/components/AppBar/src/MDCAppBarContainerViewController.h",
-    "src/components/AppBar/src/MDCAppBarContainerViewController.m",
-    "src/components/AppBar/src/MDCAppBarNavigationController.h",
-    "src/components/AppBar/src/MDCAppBarNavigationController.m",
-    "src/components/AppBar/src/MDCAppBarNavigationControllerToBeDeprecatedDelegate.h",
-    "src/components/AppBar/src/MDCAppBarViewController.h",
-    "src/components/AppBar/src/MDCAppBarViewController.m",
-    "src/components/AppBar/src/MDCAppBarViewControllerAccessibilityPerformEscapeDelegate.h",
-    "src/components/AppBar/src/MaterialAppBar.h",
-    "src/components/AppBar/src/Theming/MDCAppBarViewController+MaterialTheming.h",
-    "src/components/AppBar/src/Theming/MDCAppBarViewController+MaterialTheming.m",
-    "src/components/AppBar/src/Theming/MaterialAppBar+Theming.h",
-    "src/components/AppBar/src/TypographyThemer/MDCAppBarTypographyThemer.h",
-    "src/components/AppBar/src/TypographyThemer/MDCAppBarTypographyThemer.m",
-    "src/components/AppBar/src/TypographyThemer/MaterialAppBar+TypographyThemer.h",
-    "src/components/AppBar/src/private/MaterialAppBarStrings.h",
-    "src/components/AppBar/src/private/MaterialAppBarStrings_table.h",
-    "src/components/Availability/src/MDCAvailability.h",
-    "src/components/Availability/src/MaterialAvailability.h",
-    "src/components/Banner/src/MDCBannerView.h",
-    "src/components/Banner/src/MDCBannerView.m",
-    "src/components/Banner/src/MaterialBanner.h",
-    "src/components/Banner/src/Theming/MDCBannerView+MaterialTheming.h",
-    "src/components/Banner/src/Theming/MDCBannerView+MaterialTheming.m",
-    "src/components/Banner/src/Theming/MaterialBanner+Theming.h",
-    "src/components/BottomAppBar/src/MDCBottomAppBarView.h",
-    "src/components/BottomAppBar/src/MDCBottomAppBarView.m",
-    "src/components/BottomAppBar/src/MaterialBottomAppBar.h",
-    "src/components/BottomAppBar/src/private/MDCBottomAppBarAttributes.h",
-    "src/components/BottomAppBar/src/private/MDCBottomAppBarLayer.h",
-    "src/components/BottomAppBar/src/private/MDCBottomAppBarLayer.m",
-    "src/components/BottomNavigation/src/MDCBottomNavigationBar.h",
-    "src/components/BottomNavigation/src/MDCBottomNavigationBar.m",
-    "src/components/BottomNavigation/src/MDCBottomNavigationBarController.h",
-    "src/components/BottomNavigation/src/MDCBottomNavigationBarController.m",
-    "src/components/BottomNavigation/src/MDCBottomNavigationBarControllerDelegate.h",
-    "src/components/BottomNavigation/src/MDCBottomNavigationBarDelegate.h",
-    "src/components/BottomNavigation/src/MaterialBottomNavigation.h",
-    "src/components/BottomNavigation/src/MaterialBottomNavigationBeta.h",
-    "src/components/BottomNavigation/src/Theming/MDCBottomNavigationBar+MaterialTheming.h",
-    "src/components/BottomNavigation/src/Theming/MDCBottomNavigationBar+MaterialTheming.m",
-    "src/components/BottomNavigation/src/Theming/MaterialBottomNavigation+Theming.h",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationBar+Private.h",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationItemBadge.h",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationItemBadge.m",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.h",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationItemView.m",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationLargeItemDialogView.h",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationLargeItemDialogView.m",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationSystemDialogView.h",
-    "src/components/BottomNavigation/src/private/MDCBottomNavigationSystemDialogView.m",
-    "src/components/BottomNavigation/src/private/MaterialBottomNavigationStrings.h",
-    "src/components/BottomNavigation/src/private/MaterialBottomNavigationStrings_table.h",
-    "src/components/BottomSheet/src/MDCBottomSheetController.h",
-    "src/components/BottomSheet/src/MDCBottomSheetController.m",
-    "src/components/BottomSheet/src/MDCBottomSheetControllerDelegate.h",
-    "src/components/BottomSheet/src/MDCBottomSheetPresentationController.h",
-    "src/components/BottomSheet/src/MDCBottomSheetPresentationController.m",
-    "src/components/BottomSheet/src/MDCBottomSheetPresentationControllerDelegate.h",
-    "src/components/BottomSheet/src/MDCBottomSheetTransitionController.h",
-    "src/components/BottomSheet/src/MDCBottomSheetTransitionController.m",
-    "src/components/BottomSheet/src/MDCSheetState.h",
-    "src/components/BottomSheet/src/MaterialBottomSheet.h",
-    "src/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.h",
-    "src/components/BottomSheet/src/ShapeThemer/MDCBottomSheetControllerShapeThemer.m",
-    "src/components/BottomSheet/src/ShapeThemer/MaterialBottomSheet+ShapeThemer.h",
-    "src/components/BottomSheet/src/UIViewController+MaterialBottomSheet.h",
-    "src/components/BottomSheet/src/UIViewController+MaterialBottomSheet.m",
-    "src/components/BottomSheet/src/private/MDCDraggableView.h",
-    "src/components/BottomSheet/src/private/MDCDraggableView.m",
-    "src/components/BottomSheet/src/private/MDCDraggableViewDelegate.h",
-    "src/components/BottomSheet/src/private/MDCSheetBehavior.h",
-    "src/components/BottomSheet/src/private/MDCSheetBehavior.m",
-    "src/components/BottomSheet/src/private/MDCSheetContainerView.h",
-    "src/components/BottomSheet/src/private/MDCSheetContainerView.m",
-    "src/components/BottomSheet/src/private/MDCSheetContainerViewDelegate.h",
-    "src/components/ButtonBar/src/MDCButtonBar.h",
-    "src/components/ButtonBar/src/MDCButtonBar.m",
-    "src/components/ButtonBar/src/MDCButtonBarButton.h",
-    "src/components/ButtonBar/src/MDCButtonBarDelegate.h",
-    "src/components/ButtonBar/src/MaterialButtonBar.h",
-    "src/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.h",
-    "src/components/ButtonBar/src/private/MDCAppBarButtonBarBuilder.m",
-    "src/components/ButtonBar/src/private/MDCButtonBar+Private.h",
-    "src/components/ButtonBar/src/private/MDCButtonBarButton.m",
-    "src/components/Buttons/src/ButtonThemer/MDCButtonScheme.h",
-    "src/components/Buttons/src/ButtonThemer/MDCButtonScheme.m",
-    "src/components/Buttons/src/ButtonThemer/MDCContainedButtonThemer.h",
-    "src/components/Buttons/src/ButtonThemer/MDCContainedButtonThemer.m",
-    "src/components/Buttons/src/ButtonThemer/MDCTextButtonThemer.h",
-    "src/components/Buttons/src/ButtonThemer/MDCTextButtonThemer.m",
-    "src/components/Buttons/src/ButtonThemer/MaterialButtons+ButtonThemer.h",
-    "src/components/Buttons/src/ColorThemer/MDCButtonColorThemer.h",
-    "src/components/Buttons/src/ColorThemer/MDCButtonColorThemer.m",
-    "src/components/Buttons/src/ColorThemer/MDCContainedButtonColorThemer.h",
-    "src/components/Buttons/src/ColorThemer/MDCContainedButtonColorThemer.m",
-    "src/components/Buttons/src/ColorThemer/MDCFloatingButtonColorThemer.h",
-    "src/components/Buttons/src/ColorThemer/MDCFloatingButtonColorThemer.m",
-    "src/components/Buttons/src/ColorThemer/MDCOutlinedButtonColorThemer.h",
-    "src/components/Buttons/src/ColorThemer/MDCOutlinedButtonColorThemer.m",
-    "src/components/Buttons/src/ColorThemer/MDCTextButtonColorThemer.h",
-    "src/components/Buttons/src/ColorThemer/MDCTextButtonColorThemer.m",
-    "src/components/Buttons/src/ColorThemer/MaterialButtons+ColorThemer.h",
-    "src/components/Buttons/src/MDCButton.h",
-    "src/components/Buttons/src/MDCButton.m",
-    "src/components/Buttons/src/MDCFlatButton.h",
-    "src/components/Buttons/src/MDCFlatButton.m",
-    "src/components/Buttons/src/MDCFloatingButton+Animation.h",
-    "src/components/Buttons/src/MDCFloatingButton+Animation.m",
-    "src/components/Buttons/src/MDCFloatingButton.h",
-    "src/components/Buttons/src/MDCFloatingButton.m",
-    "src/components/Buttons/src/MDCRaisedButton.h",
-    "src/components/Buttons/src/MDCRaisedButton.m",
-    "src/components/Buttons/src/MaterialButtons.h",
-    "src/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.h",
-    "src/components/Buttons/src/ShapeThemer/MDCButtonShapeThemer.m",
-    "src/components/Buttons/src/ShapeThemer/MaterialButtons+ShapeThemer.h",
-    "src/components/Buttons/src/Theming/MDCButton+MaterialTheming.h",
-    "src/components/Buttons/src/Theming/MDCButton+MaterialTheming.m",
-    "src/components/Buttons/src/Theming/MDCFloatingButton+MaterialTheming.h",
-    "src/components/Buttons/src/Theming/MDCFloatingButton+MaterialTheming.m",
-    "src/components/Buttons/src/Theming/MaterialButtons+Theming.h",
-    "src/components/Buttons/src/TitleColorAccessibilityMutator/MDCButtonTitleColorAccessibilityMutator.h",
-    "src/components/Buttons/src/TitleColorAccessibilityMutator/MDCButtonTitleColorAccessibilityMutator.m",
-    "src/components/Buttons/src/TitleColorAccessibilityMutator/MaterialButtons+TitleColorAccessibilityMutator.h",
-    "src/components/Buttons/src/TypographyThemer/MDCButtonTypographyThemer.h",
-    "src/components/Buttons/src/TypographyThemer/MDCButtonTypographyThemer.m",
-    "src/components/Buttons/src/TypographyThemer/MaterialButtons+TypographyThemer.h",
-    "src/components/Buttons/src/private/MDCButton+Subclassing.h",
-    "src/components/Buttons/src/private/MDCFloatingButtonModeAnimator.h",
-    "src/components/Buttons/src/private/MDCFloatingButtonModeAnimator.m",
-    "src/components/Buttons/src/private/MDCFloatingButtonModeAnimatorDelegate.h",
-    "src/components/Cards/src/MDCCard.h",
-    "src/components/Cards/src/MDCCard.m",
-    "src/components/Cards/src/MDCCardCollectionCell.h",
-    "src/components/Cards/src/MDCCardCollectionCell.m",
-    "src/components/Cards/src/MaterialCards.h",
-    "src/components/Cards/src/Theming/MDCCard+MaterialTheming.h",
-    "src/components/Cards/src/Theming/MDCCard+MaterialTheming.m",
-    "src/components/Cards/src/Theming/MDCCardCollectionCell+MaterialTheming.h",
-    "src/components/Cards/src/Theming/MDCCardCollectionCell+MaterialTheming.m",
-    "src/components/Cards/src/Theming/MaterialCards+Theming.h",
-    "src/components/Cards/src/UICollectionViewController+MDCCardReordering.h",
-    "src/components/Cards/src/UICollectionViewController+MDCCardReordering.m",
-    "src/components/Chips/src/MDCChipCollectionViewCell.h",
-    "src/components/Chips/src/MDCChipCollectionViewCell.m",
-    "src/components/Chips/src/MDCChipCollectionViewFlowLayout.h",
-    "src/components/Chips/src/MDCChipCollectionViewFlowLayout.m",
-    "src/components/Chips/src/MDCChipField.h",
-    "src/components/Chips/src/MDCChipField.m",
-    "src/components/Chips/src/MDCChipFieldDelegate.h",
-    "src/components/Chips/src/MDCChipView.h",
-    "src/components/Chips/src/MDCChipView.m",
-    "src/components/Chips/src/MaterialChips.h",
-    "src/components/Chips/src/Theming/MDCChipView+MaterialTheming.h",
-    "src/components/Chips/src/Theming/MDCChipView+MaterialTheming.m",
-    "src/components/Chips/src/Theming/MaterialChips+Theming.h",
-    "src/components/Chips/src/private/MDCChipView+Private.h",
-    "src/components/CollectionCells/src/MDCCollectionViewCell.h",
-    "src/components/CollectionCells/src/MDCCollectionViewCell.m",
-    "src/components/CollectionCells/src/MDCCollectionViewTextCell.h",
-    "src/components/CollectionCells/src/MDCCollectionViewTextCell.m",
-    "src/components/CollectionCells/src/MaterialCollectionCells.h",
-    "src/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.h",
-    "src/components/CollectionLayoutAttributes/src/MDCCollectionViewLayoutAttributes.m",
-    "src/components/CollectionLayoutAttributes/src/MaterialCollectionLayoutAttributes.h",
-    "src/components/Collections/src/MDCCollectionViewController.h",
-    "src/components/Collections/src/MDCCollectionViewController.m",
-    "src/components/Collections/src/MDCCollectionViewEditing.h",
-    "src/components/Collections/src/MDCCollectionViewEditingDelegate.h",
-    "src/components/Collections/src/MDCCollectionViewFlowLayout.h",
-    "src/components/Collections/src/MDCCollectionViewFlowLayout.m",
-    "src/components/Collections/src/MDCCollectionViewStyling.h",
-    "src/components/Collections/src/MDCCollectionViewStylingDelegate.h",
-    "src/components/Collections/src/MaterialCollections.h",
-    "src/components/Collections/src/private/MDCCollectionGridBackgroundView.h",
-    "src/components/Collections/src/private/MDCCollectionGridBackgroundView.m",
-    "src/components/Collections/src/private/MDCCollectionInfoBarView.h",
-    "src/components/Collections/src/private/MDCCollectionInfoBarView.m",
-    "src/components/Collections/src/private/MDCCollectionInfoBarViewDelegate.h",
-    "src/components/Collections/src/private/MDCCollectionStringResources.h",
-    "src/components/Collections/src/private/MDCCollectionStringResources.m",
-    "src/components/Collections/src/private/MDCCollectionViewEditor.h",
-    "src/components/Collections/src/private/MDCCollectionViewEditor.m",
-    "src/components/Collections/src/private/MDCCollectionViewStyler.h",
-    "src/components/Collections/src/private/MDCCollectionViewStyler.m",
-    "src/components/Collections/src/private/MaterialCollectionsStrings.h",
-    "src/components/Collections/src/private/MaterialCollectionsStrings_table.h",
-    "src/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.h",
-    "src/components/Dialogs/src/ColorThemer/MDCAlertColorThemer.m",
-    "src/components/Dialogs/src/ColorThemer/MaterialDialogs+ColorThemer.h",
-    "src/components/Dialogs/src/MDCAlertController+ButtonForAction.h",
-    "src/components/Dialogs/src/MDCAlertController+ButtonForAction.m",
-    "src/components/Dialogs/src/MDCAlertController+Customize.h",
-    "src/components/Dialogs/src/MDCAlertController.h",
-    "src/components/Dialogs/src/MDCAlertController.m",
-    "src/components/Dialogs/src/MDCAlertControllerDelegate.h",
-    "src/components/Dialogs/src/MDCAlertControllerView.h",
-    "src/components/Dialogs/src/MDCDialogPresentationController.h",
-    "src/components/Dialogs/src/MDCDialogPresentationController.m",
-    "src/components/Dialogs/src/MDCDialogPresentationControllerDelegate.h",
-    "src/components/Dialogs/src/MDCDialogTransitionController.h",
-    "src/components/Dialogs/src/MDCDialogTransitionController.m",
-    "src/components/Dialogs/src/MaterialDialogs.h",
-    "src/components/Dialogs/src/Theming/MDCAlertController+MaterialTheming.h",
-    "src/components/Dialogs/src/Theming/MDCAlertController+MaterialTheming.m",
-    "src/components/Dialogs/src/Theming/MDCDialogPresentationController+MaterialTheming.h",
-    "src/components/Dialogs/src/Theming/MDCDialogPresentationController+MaterialTheming.m",
-    "src/components/Dialogs/src/Theming/MaterialDialogs+Theming.h",
-    "src/components/Dialogs/src/TypographyThemer/MDCAlertTypographyThemer.h",
-    "src/components/Dialogs/src/TypographyThemer/MDCAlertTypographyThemer.m",
-    "src/components/Dialogs/src/TypographyThemer/MaterialDialogs+TypographyThemer.h",
-    "src/components/Dialogs/src/UIViewController+MaterialDialogs.h",
-    "src/components/Dialogs/src/UIViewController+MaterialDialogs.m",
-    "src/components/Dialogs/src/private/MDCAlertActionManager.h",
-    "src/components/Dialogs/src/private/MDCAlertActionManager.m",
-    "src/components/Dialogs/src/private/MDCAlertControllerView+Private.h",
-    "src/components/Dialogs/src/private/MDCAlertControllerView+Private.m",
-    "src/components/Dialogs/src/private/MDCDialogShadowedView.h",
-    "src/components/Dialogs/src/private/MDCDialogShadowedView.m",
-    "src/components/Dialogs/src/private/MaterialDialogsStrings.h",
-    "src/components/Dialogs/src/private/MaterialDialogsStrings_table.h",
-    "src/components/Elevation/src/MDCElevatable.h",
-    "src/components/Elevation/src/MDCElevationOverriding.h",
-    "src/components/Elevation/src/MaterialElevation.h",
-    "src/components/Elevation/src/UIColor+MaterialElevation.h",
-    "src/components/Elevation/src/UIColor+MaterialElevation.m",
-    "src/components/Elevation/src/UIView+MaterialElevationResponding.h",
-    "src/components/Elevation/src/UIView+MaterialElevationResponding.m",
-    "src/components/FeatureHighlight/src/ColorThemer/MDCFeatureHighlightColorThemer.h",
-    "src/components/FeatureHighlight/src/ColorThemer/MDCFeatureHighlightColorThemer.m",
-    "src/components/FeatureHighlight/src/ColorThemer/MaterialFeatureHighlight+ColorThemer.h",
-    "src/components/FeatureHighlight/src/FeatureHighlightAccessibilityMutator/MDCFeatureHighlightAccessibilityMutator.h",
-    "src/components/FeatureHighlight/src/FeatureHighlightAccessibilityMutator/MDCFeatureHighlightAccessibilityMutator.m",
-    "src/components/FeatureHighlight/src/FeatureHighlightAccessibilityMutator/MaterialFeatureHighlight+FeatureHighlightAccessibilityMutator.h",
-    "src/components/FeatureHighlight/src/MDCFeatureHighlightView.h",
-    "src/components/FeatureHighlight/src/MDCFeatureHighlightViewController.h",
-    "src/components/FeatureHighlight/src/MDCFeatureHighlightViewController.m",
-    "src/components/FeatureHighlight/src/MaterialFeatureHighlight.h",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.h",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightAnimationController.m",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightDismissGestureRecognizer.h",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightDismissGestureRecognizer.m",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.h",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightLayer.m",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightView+Private.h",
-    "src/components/FeatureHighlight/src/private/MDCFeatureHighlightView+Private.m",
-    "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MDCFlexibleHeaderView+canAlwaysExpandToMaximumHeight.h",
-    "src/components/FlexibleHeader/src/CanAlwaysExpandToMaximumHeight/MaterialFlexibleHeader+CanAlwaysExpandToMaximumHeight.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderContainerViewController.m",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderSafeAreaDelegate.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderView+ShiftBehavior.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderView.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderView.m",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewAnimationDelegate.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewController.m",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewDelegate.h",
-    "src/components/FlexibleHeader/src/MDCFlexibleHeaderViewLayoutDelegate.h",
-    "src/components/FlexibleHeader/src/MaterialFlexibleHeader.h",
-    "src/components/FlexibleHeader/src/ShiftBehavior/MDCFlexibleHeaderShiftBehavior.h",
-    "src/components/FlexibleHeader/src/ShiftBehavior/MaterialFlexibleHeader+ShiftBehavior.h",
-    "src/components/FlexibleHeader/src/ShiftBehaviorEnabledWithStatusBar/MDCFlexibleHeaderShiftBehaviorEnabledWithStatusBar.h",
-    "src/components/FlexibleHeader/src/ShiftBehaviorEnabledWithStatusBar/MaterialFlexibleHeader+ShiftBehaviorEnabledWithStatusBar.h",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderHairline.h",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderHairline.m",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderMinMaxHeight.h",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderMinMaxHeight.m",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderMinMaxHeightDelegate.h",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderShifter.h",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderShifter.m",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderTopSafeArea.h",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderTopSafeArea.m",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderTopSafeAreaDelegate.h",
-    "src/components/FlexibleHeader/src/private/MDCFlexibleHeaderView+Private.h",
-    "src/components/FlexibleHeader/src/private/MDCStatusBarShifter.h",
-    "src/components/FlexibleHeader/src/private/MDCStatusBarShifter.m",
-    "src/components/FlexibleHeader/src/private/MDCStatusBarShifterDelegate.h",
-    "src/components/HeaderStackView/src/ColorThemer/MDCHeaderStackViewColorThemer.h",
-    "src/components/HeaderStackView/src/ColorThemer/MDCHeaderStackViewColorThemer.m",
-    "src/components/HeaderStackView/src/ColorThemer/MaterialHeaderStackView+ColorThemer.h",
-    "src/components/HeaderStackView/src/MDCHeaderStackView.h",
-    "src/components/HeaderStackView/src/MDCHeaderStackView.m",
-    "src/components/HeaderStackView/src/MaterialHeaderStackView.h",
-    "src/components/Ink/src/MDCInkGestureRecognizer.h",
-    "src/components/Ink/src/MDCInkGestureRecognizer.m",
-    "src/components/Ink/src/MDCInkTouchController.h",
-    "src/components/Ink/src/MDCInkTouchController.m",
-    "src/components/Ink/src/MDCInkTouchControllerDelegate.h",
-    "src/components/Ink/src/MDCInkView.h",
-    "src/components/Ink/src/MDCInkView.m",
-    "src/components/Ink/src/MDCInkViewDelegate.h",
-    "src/components/Ink/src/MaterialInk.h",
-    "src/components/Ink/src/private/MDCInkLayer.h",
-    "src/components/Ink/src/private/MDCInkLayer.m",
-    "src/components/Ink/src/private/MDCInkLayerDelegate.h",
-    "src/components/Ink/src/private/MDCLegacyInkLayer+Private.h",
-    "src/components/Ink/src/private/MDCLegacyInkLayer.h",
-    "src/components/Ink/src/private/MDCLegacyInkLayer.m",
-    "src/components/Ink/src/private/MDCLegacyInkLayerDelegate.h",
-    "src/components/Ink/src/private/MDCLegacyInkLayerRippleDelegate.h",
-    "src/components/LibraryInfo/src/MDCLibraryInfo.h",
-    "src/components/LibraryInfo/src/MDCLibraryInfo.m",
-    "src/components/LibraryInfo/src/MaterialLibraryInfo.h",
-    "src/components/List/src/MDCBaseCell.h",
-    "src/components/List/src/MDCBaseCell.m",
-    "src/components/List/src/MDCSelfSizingLayoutAttributes.h",
-    "src/components/List/src/MDCSelfSizingStereoCell.h",
-    "src/components/List/src/MDCSelfSizingStereoCell.m",
-    "src/components/List/src/MaterialList.h",
-    "src/components/List/src/Theming/MDCBaseCell+MaterialTheming.h",
-    "src/components/List/src/Theming/MDCBaseCell+MaterialTheming.m",
-    "src/components/List/src/Theming/MDCSelfSizingStereoCell+MaterialTheming.h",
-    "src/components/List/src/Theming/MDCSelfSizingStereoCell+MaterialTheming.m",
-    "src/components/List/src/Theming/MaterialList+Theming.h",
-    "src/components/List/src/private/MDCSelfSizingStereoCellLayout.h",
-    "src/components/List/src/private/MDCSelfSizingStereoCellLayout.m",
-    "src/components/NavigationBar/src/ColorThemer/MDCNavigationBarColorThemer.h",
-    "src/components/NavigationBar/src/ColorThemer/MDCNavigationBarColorThemer.m",
-    "src/components/NavigationBar/src/ColorThemer/MaterialNavigationBar+ColorThemer.h",
-    "src/components/NavigationBar/src/MDCNavigationBar.h",
-    "src/components/NavigationBar/src/MDCNavigationBar.m",
-    "src/components/NavigationBar/src/MaterialNavigationBar.h",
-    "src/components/NavigationBar/src/TypographyThemer/MDCNavigationBarTypographyThemer.h",
-    "src/components/NavigationBar/src/TypographyThemer/MDCNavigationBarTypographyThemer.m",
-    "src/components/NavigationBar/src/TypographyThemer/MaterialNavigationBar+TypographyThemer.h",
-    "src/components/NavigationDrawer/src/ColorThemer/MDCBottomDrawerColorThemer.h",
-    "src/components/NavigationDrawer/src/ColorThemer/MDCBottomDrawerColorThemer.m",
-    "src/components/NavigationDrawer/src/ColorThemer/MaterialNavigationDrawer+ColorThemer.h",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerHeader.h",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.h",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerPresentationController.m",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerPresentationControllerDelegate.h",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerState.h",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerTransitionController.h",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerTransitionController.m",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerViewController.h",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerViewController.m",
-    "src/components/NavigationDrawer/src/MDCBottomDrawerViewControllerDelegate.h",
-    "src/components/NavigationDrawer/src/MaterialNavigationDrawer.h",
-    "src/components/NavigationDrawer/src/Theming/MDCBottomDrawerViewController+MaterialTheming.h",
-    "src/components/NavigationDrawer/src/Theming/MDCBottomDrawerViewController+MaterialTheming.m",
-    "src/components/NavigationDrawer/src/Theming/MaterialNavigationDrawer+Theming.h",
-    "src/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.h",
-    "src/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewController.m",
-    "src/components/NavigationDrawer/src/private/MDCBottomDrawerContainerViewControllerDelegate.h",
-    "src/components/NavigationDrawer/src/private/MDCBottomDrawerHeaderMask.h",
-    "src/components/NavigationDrawer/src/private/MDCBottomDrawerHeaderMask.m",
-    "src/components/NavigationDrawer/src/private/MDCBottomDrawerShadowedView.h",
-    "src/components/OverlayWindow/src/MDCOverlayWindow.h",
-    "src/components/OverlayWindow/src/MDCOverlayWindow.m",
-    "src/components/OverlayWindow/src/MaterialOverlayWindow.h",
-    "src/components/PageControl/src/MDCPageControl.h",
-    "src/components/PageControl/src/MDCPageControl.m",
-    "src/components/PageControl/src/MaterialPageControl.h",
-    "src/components/PageControl/src/private/MDCPageControlIndicator.h",
-    "src/components/PageControl/src/private/MDCPageControlIndicator.m",
-    "src/components/PageControl/src/private/MDCPageControlTrackLayer.h",
-    "src/components/PageControl/src/private/MDCPageControlTrackLayer.m",
-    "src/components/PageControl/src/private/MaterialPageControlStrings.h",
-    "src/components/PageControl/src/private/MaterialPageControlStrings_table.h",
-    "src/components/Palettes/src/MDCPalettes.h",
-    "src/components/Palettes/src/MDCPalettes.m",
-    "src/components/Palettes/src/MaterialPalettes.h",
-    "src/components/Palettes/src/private/MDCPaletteExpansions.h",
-    "src/components/Palettes/src/private/MDCPaletteExpansions.m",
-    "src/components/Palettes/src/private/MDCPaletteNames.h",
-    "src/components/Palettes/src/private/MDCPaletteNames.m",
-    "src/components/ProgressView/src/MDCProgressView.h",
-    "src/components/ProgressView/src/MDCProgressView.m",
-    "src/components/ProgressView/src/MaterialProgressView.h",
-    "src/components/ProgressView/src/Theming/MDCProgressView+MaterialTheming.h",
-    "src/components/ProgressView/src/Theming/MDCProgressView+MaterialTheming.m",
-    "src/components/ProgressView/src/Theming/MaterialProgressView+Theming.h",
-    "src/components/ProgressView/src/private/MDCProgressGradientView.h",
-    "src/components/ProgressView/src/private/MDCProgressGradientView.m",
-    "src/components/ProgressView/src/private/MaterialProgressViewStrings.h",
-    "src/components/ProgressView/src/private/MaterialProgressViewStrings_table.h",
-    "src/components/Ripple/src/MDCRippleTouchController.h",
-    "src/components/Ripple/src/MDCRippleTouchController.m",
-    "src/components/Ripple/src/MDCRippleTouchControllerDelegate.h",
-    "src/components/Ripple/src/MDCRippleView.h",
-    "src/components/Ripple/src/MDCRippleView.m",
-    "src/components/Ripple/src/MDCRippleViewDelegate.h",
-    "src/components/Ripple/src/MDCStatefulRippleView.h",
-    "src/components/Ripple/src/MDCStatefulRippleView.m",
-    "src/components/Ripple/src/MaterialRipple.h",
-    "src/components/Ripple/src/private/MDCRippleLayer.h",
-    "src/components/Ripple/src/private/MDCRippleLayer.m",
-    "src/components/Ripple/src/private/MDCRippleLayerDelegate.h",
-    "src/components/ShadowElevations/src/MDCShadowElevations.h",
-    "src/components/ShadowElevations/src/MaterialShadowElevations.h",
-    "src/components/ShadowElevations/src/MaterialShadowElevationsDummy.m",
-    "src/components/ShadowLayer/src/MDCShadowLayer.h",
-    "src/components/ShadowLayer/src/MDCShadowLayer.m",
-    "src/components/ShadowLayer/src/MaterialShadowLayer.h",
-    "src/components/ShapeLibrary/src/MDCCornerTreatment+CornerTypeInitalizer.h",
-    "src/components/ShapeLibrary/src/MDCCornerTreatment+CornerTypeInitalizer.m",
-    "src/components/ShapeLibrary/src/MDCCurvedCornerTreatment.h",
-    "src/components/ShapeLibrary/src/MDCCurvedCornerTreatment.m",
-    "src/components/ShapeLibrary/src/MDCCurvedRectShapeGenerator.h",
-    "src/components/ShapeLibrary/src/MDCCurvedRectShapeGenerator.m",
-    "src/components/ShapeLibrary/src/MDCCutCornerTreatment.h",
-    "src/components/ShapeLibrary/src/MDCCutCornerTreatment.m",
-    "src/components/ShapeLibrary/src/MDCPillShapeGenerator.h",
-    "src/components/ShapeLibrary/src/MDCPillShapeGenerator.m",
-    "src/components/ShapeLibrary/src/MDCRoundedCornerTreatment.h",
-    "src/components/ShapeLibrary/src/MDCRoundedCornerTreatment.m",
-    "src/components/ShapeLibrary/src/MDCSlantedRectShapeGenerator.h",
-    "src/components/ShapeLibrary/src/MDCSlantedRectShapeGenerator.m",
-    "src/components/ShapeLibrary/src/MDCTriangleEdgeTreatment.h",
-    "src/components/ShapeLibrary/src/MDCTriangleEdgeTreatment.m",
-    "src/components/ShapeLibrary/src/MaterialShapeLibrary.h",
-    "src/components/Shapes/src/MDCCornerTreatment.h",
-    "src/components/Shapes/src/MDCCornerTreatment.m",
-    "src/components/Shapes/src/MDCEdgeTreatment.h",
-    "src/components/Shapes/src/MDCEdgeTreatment.m",
-    "src/components/Shapes/src/MDCPathGenerator.h",
-    "src/components/Shapes/src/MDCPathGenerator.m",
-    "src/components/Shapes/src/MDCRectangleShapeGenerator.h",
-    "src/components/Shapes/src/MDCRectangleShapeGenerator.m",
-    "src/components/Shapes/src/MDCShapeGenerating.h",
-    "src/components/Shapes/src/MDCShapedShadowLayer.h",
-    "src/components/Shapes/src/MDCShapedShadowLayer.m",
-    "src/components/Shapes/src/MDCShapedView.h",
-    "src/components/Shapes/src/MDCShapedView.m",
-    "src/components/Shapes/src/MaterialShapes.h",
-    "src/components/Slider/src/ColorThemer/MDCSliderColorThemer.h",
-    "src/components/Slider/src/ColorThemer/MDCSliderColorThemer.m",
-    "src/components/Slider/src/ColorThemer/MaterialSlider+ColorThemer.h",
-    "src/components/Slider/src/MDCSlider.h",
-    "src/components/Slider/src/MDCSlider.m",
-    "src/components/Slider/src/MDCSliderDelegate.h",
-    "src/components/Slider/src/MaterialSlider.h",
-    "src/components/Slider/src/private/MDCSlider+Private.h",
-    "src/components/Slider/src/private/MDCSlider_Subclassable.h",
-    "src/components/Snackbar/src/FontThemer/MDCSnackbarFontThemer.h",
-    "src/components/Snackbar/src/FontThemer/MDCSnackbarFontThemer.m",
-    "src/components/Snackbar/src/FontThemer/MaterialSnackbar+FontThemer.h",
-    "src/components/Snackbar/src/MDCSnackbarAlignment.h",
-    "src/components/Snackbar/src/MDCSnackbarManager.h",
-    "src/components/Snackbar/src/MDCSnackbarManager.m",
-    "src/components/Snackbar/src/MDCSnackbarManagerDelegate.h",
-    "src/components/Snackbar/src/MDCSnackbarMessage.h",
-    "src/components/Snackbar/src/MDCSnackbarMessage.m",
-    "src/components/Snackbar/src/MDCSnackbarMessageView.h",
-    "src/components/Snackbar/src/MDCSnackbarMessageView.m",
-    "src/components/Snackbar/src/MaterialSnackbar.h",
-    "src/components/Snackbar/src/TypographyThemer/MDCSnackbarTypographyThemer.h",
-    "src/components/Snackbar/src/TypographyThemer/MDCSnackbarTypographyThemer.m",
-    "src/components/Snackbar/src/TypographyThemer/MaterialSnackbar+TypographyThemer.h",
-    "src/components/Snackbar/src/private/MDCSnackbarManagerInternal.h",
-    "src/components/Snackbar/src/private/MDCSnackbarMessageInternal.h",
-    "src/components/Snackbar/src/private/MDCSnackbarMessageViewInternal.h",
-    "src/components/Snackbar/src/private/MDCSnackbarOverlayView.h",
-    "src/components/Snackbar/src/private/MDCSnackbarOverlayView.m",
-    "src/components/Snackbar/src/private/MaterialSnackbarStrings.h",
-    "src/components/Snackbar/src/private/MaterialSnackbarStrings_table.h",
-    "src/components/Tabs/src/ExtendedAlignment/MDCTabBarExtendedAlignment.h",
-    "src/components/Tabs/src/MDCTabBar.h",
-    "src/components/Tabs/src/MDCTabBar.m",
-    "src/components/Tabs/src/MDCTabBarAlignment.h",
-    "src/components/Tabs/src/MDCTabBarControllerDelegate.h",
-    "src/components/Tabs/src/MDCTabBarDelegate.h",
-    "src/components/Tabs/src/MDCTabBarDisplayDelegate.h",
-    "src/components/Tabs/src/MDCTabBarIndicatorAttributes.h",
-    "src/components/Tabs/src/MDCTabBarIndicatorAttributes.m",
-    "src/components/Tabs/src/MDCTabBarIndicatorContext.h",
-    "src/components/Tabs/src/MDCTabBarIndicatorTemplate.h",
-    "src/components/Tabs/src/MDCTabBarItemAppearance.h",
-    "src/components/Tabs/src/MDCTabBarTextTransform.h",
-    "src/components/Tabs/src/MDCTabBarUnderlineIndicatorTemplate.h",
-    "src/components/Tabs/src/MDCTabBarUnderlineIndicatorTemplate.m",
-    "src/components/Tabs/src/MDCTabBarViewController.h",
-    "src/components/Tabs/src/MDCTabBarViewController.m",
-    "src/components/Tabs/src/MaterialTabs.h",
-    "src/components/Tabs/src/SizeClassDelegate/MDCTabBarSizeClassDelegate.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarItem.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarItem.m",
-    "src/components/Tabs/src/TabBarView/MDCTabBarItemCustomViewing.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarView.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarView.m",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewCustomViewable.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewDelegate.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorAttributes.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorAttributes.m",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorContext.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewIndicatorTemplate.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewUnderlineIndicatorTemplate.h",
-    "src/components/Tabs/src/TabBarView/MDCTabBarViewUnderlineIndicatorTemplate.m",
-    "src/components/Tabs/src/TabBarView/MaterialTabs+TabBarView.h",
-    "src/components/Tabs/src/TabBarView/private/MDCTabBarViewIndicatorView.h",
-    "src/components/Tabs/src/TabBarView/private/MDCTabBarViewIndicatorView.m",
-    "src/components/Tabs/src/TabBarView/private/MDCTabBarViewItemView.h",
-    "src/components/Tabs/src/TabBarView/private/MDCTabBarViewItemView.m",
-    "src/components/Tabs/src/TabBarView/private/MDCTabBarViewPrivateIndicatorContext.h",
-    "src/components/Tabs/src/TabBarView/private/MDCTabBarViewPrivateIndicatorContext.m",
-    "src/components/Tabs/src/Theming/MDCTabBar+MaterialTheming.h",
-    "src/components/Tabs/src/Theming/MDCTabBar+MaterialTheming.m",
-    "src/components/Tabs/src/Theming/MaterialTabs+Theming.h",
-    "src/components/Tabs/src/TypographyThemer/MDCTabBarTypographyThemer.h",
-    "src/components/Tabs/src/TypographyThemer/MDCTabBarTypographyThemer.m",
-    "src/components/Tabs/src/TypographyThemer/MaterialTabs+TypographyThemer.h",
-    "src/components/Tabs/src/private/MDCItemBar.h",
-    "src/components/Tabs/src/private/MDCItemBar.m",
-    "src/components/Tabs/src/private/MDCItemBarAlignment.h",
-    "src/components/Tabs/src/private/MDCItemBarBadge.h",
-    "src/components/Tabs/src/private/MDCItemBarBadge.m",
-    "src/components/Tabs/src/private/MDCItemBarCell+Private.h",
-    "src/components/Tabs/src/private/MDCItemBarCell.h",
-    "src/components/Tabs/src/private/MDCItemBarCell.m",
-    "src/components/Tabs/src/private/MDCItemBarDelegate.h",
-    "src/components/Tabs/src/private/MDCItemBarStringConstants.h",
-    "src/components/Tabs/src/private/MDCItemBarStyle.h",
-    "src/components/Tabs/src/private/MDCItemBarStyle.m",
-    "src/components/Tabs/src/private/MDCTabBarIndicatorView.h",
-    "src/components/Tabs/src/private/MDCTabBarIndicatorView.m",
-    "src/components/Tabs/src/private/MDCTabBarPrivateIndicatorContext.h",
-    "src/components/Tabs/src/private/MDCTabBarPrivateIndicatorContext.m",
-    "src/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.h",
-    "src/components/TextControls/src/BaseTextAreas/MDCBaseTextArea.m",
-    "src/components/TextControls/src/BaseTextAreas/MaterialTextControls+BaseTextAreas.h",
-    "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaLayout.h",
-    "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaLayout.m",
-    "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaTextView.h",
-    "src/components/TextControls/src/BaseTextAreas/private/MDCBaseTextAreaTextView.m",
-    "src/components/TextControls/src/BaseTextFields/MDCBaseTextField.h",
-    "src/components/TextControls/src/BaseTextFields/MDCBaseTextField.m",
-    "src/components/TextControls/src/BaseTextFields/MaterialTextControls+BaseTextFields.h",
-    "src/components/TextControls/src/Enums/MDCTextControlLabelBehavior.h",
-    "src/components/TextControls/src/Enums/MDCTextControlState.h",
-    "src/components/TextControls/src/Enums/MDCTextControlState.m",
-    "src/components/TextControls/src/Enums/MaterialTextControls+Enums.h",
-    "src/components/TextControls/src/FilledTextAreas/MDCFilledTextArea.h",
-    "src/components/TextControls/src/FilledTextAreas/MDCFilledTextArea.m",
-    "src/components/TextControls/src/FilledTextAreas/MaterialTextControls+FilledTextAreas.h",
-    "src/components/TextControls/src/FilledTextAreasTheming/MDCFilledTextArea+MaterialTheming.h",
-    "src/components/TextControls/src/FilledTextAreasTheming/MDCFilledTextArea+MaterialTheming.m",
-    "src/components/TextControls/src/FilledTextAreasTheming/MaterialTextControls+FilledTextAreasTheming.h",
-    "src/components/TextControls/src/FilledTextFields/MDCFilledTextField.h",
-    "src/components/TextControls/src/FilledTextFields/MDCFilledTextField.m",
-    "src/components/TextControls/src/FilledTextFields/MaterialTextControls+FilledTextFields.h",
-    "src/components/TextControls/src/FilledTextFieldsTheming/MDCFilledTextField+MaterialTheming.h",
-    "src/components/TextControls/src/FilledTextFieldsTheming/MDCFilledTextField+MaterialTheming.m",
-    "src/components/TextControls/src/FilledTextFieldsTheming/MaterialTextControls+FilledTextFieldsTheming.h",
-    "src/components/TextControls/src/OutlinedTextAreas/MDCOutlinedTextArea.h",
-    "src/components/TextControls/src/OutlinedTextAreas/MDCOutlinedTextArea.m",
-    "src/components/TextControls/src/OutlinedTextAreas/MaterialTextControls+OutlinedTextAreas.h",
-    "src/components/TextControls/src/OutlinedTextAreasTheming/MDCOutlinedTextArea+MaterialTheming.h",
-    "src/components/TextControls/src/OutlinedTextAreasTheming/MDCOutlinedTextArea+MaterialTheming.m",
-    "src/components/TextControls/src/OutlinedTextAreasTheming/MaterialTextControls+OutlinedTextAreasTheming.h",
-    "src/components/TextControls/src/OutlinedTextFields/MDCOutlinedTextField.h",
-    "src/components/TextControls/src/OutlinedTextFields/MDCOutlinedTextField.m",
-    "src/components/TextControls/src/OutlinedTextFields/MaterialTextControls+OutlinedTextFields.h",
-    "src/components/TextControls/src/OutlinedTextFieldsTheming/MDCOutlinedTextField+MaterialTheming.h",
-    "src/components/TextControls/src/OutlinedTextFieldsTheming/MDCOutlinedTextField+MaterialTheming.m",
-    "src/components/TextControls/src/OutlinedTextFieldsTheming/MaterialTextControls+OutlinedTextFieldsTheming.h",
-    "src/components/TextControls/src/UnderlinedTextFields/MDCUnderlinedTextField.h",
-    "src/components/TextControls/src/UnderlinedTextFields/MDCUnderlinedTextField.m",
-    "src/components/TextControls/src/UnderlinedTextFields/MaterialTextControls+UnderlinedTextFields.h",
-    "src/components/TextControls/src/UnderlinedTextFieldsTheming/MDCUnderlinedTextField+MaterialTheming.h",
-    "src/components/TextControls/src/UnderlinedTextFieldsTheming/MDCUnderlinedTextField+MaterialTheming.m",
-    "src/components/TextControls/src/UnderlinedTextFieldsTheming/MaterialTextControls+UnderlinedTextFieldsTheming.h",
-    "src/components/TextFields/src/ColorThemer/MDCFilledTextFieldColorThemer.h",
-    "src/components/TextFields/src/ColorThemer/MDCFilledTextFieldColorThemer.m",
-    "src/components/TextFields/src/ColorThemer/MaterialTextFields+ColorThemer.h",
-    "src/components/TextFields/src/MDCIntrinsicHeightTextView.h",
-    "src/components/TextFields/src/MDCIntrinsicHeightTextView.m",
-    "src/components/TextFields/src/MDCMultilineTextField.h",
-    "src/components/TextFields/src/MDCMultilineTextField.m",
-    "src/components/TextFields/src/MDCMultilineTextInputDelegate.h",
-    "src/components/TextFields/src/MDCMultilineTextInputLayoutDelegate.h",
-    "src/components/TextFields/src/MDCTextField.h",
-    "src/components/TextFields/src/MDCTextField.m",
-    "src/components/TextFields/src/MDCTextFieldPositioningDelegate.h",
-    "src/components/TextFields/src/MDCTextInput.h",
-    "src/components/TextFields/src/MDCTextInputBorderView.h",
-    "src/components/TextFields/src/MDCTextInputBorderView.m",
-    "src/components/TextFields/src/MDCTextInputCharacterCounter.h",
-    "src/components/TextFields/src/MDCTextInputController.h",
-    "src/components/TextFields/src/MDCTextInputControllerBase.h",
-    "src/components/TextFields/src/MDCTextInputControllerBase.m",
-    "src/components/TextFields/src/MDCTextInputControllerFilled.h",
-    "src/components/TextFields/src/MDCTextInputControllerFilled.m",
-    "src/components/TextFields/src/MDCTextInputControllerFloatingPlaceholder.h",
-    "src/components/TextFields/src/MDCTextInputControllerFullWidth.h",
-    "src/components/TextFields/src/MDCTextInputControllerFullWidth.m",
-    "src/components/TextFields/src/MDCTextInputControllerLegacyDefault.h",
-    "src/components/TextFields/src/MDCTextInputControllerLegacyDefault.m",
-    "src/components/TextFields/src/MDCTextInputControllerLegacyFullWidth.h",
-    "src/components/TextFields/src/MDCTextInputControllerLegacyFullWidth.m",
-    "src/components/TextFields/src/MDCTextInputControllerOutlined.h",
-    "src/components/TextFields/src/MDCTextInputControllerOutlined.m",
-    "src/components/TextFields/src/MDCTextInputControllerOutlinedTextArea.h",
-    "src/components/TextFields/src/MDCTextInputControllerOutlinedTextArea.m",
-    "src/components/TextFields/src/MDCTextInputControllerUnderline.h",
-    "src/components/TextFields/src/MDCTextInputControllerUnderline.m",
-    "src/components/TextFields/src/MDCTextInputUnderlineView.h",
-    "src/components/TextFields/src/MDCTextInputUnderlineView.m",
-    "src/components/TextFields/src/MaterialTextFields.h",
-    "src/components/TextFields/src/Theming/MDCTextInputControllerFilled+MaterialTheming.h",
-    "src/components/TextFields/src/Theming/MDCTextInputControllerFilled+MaterialTheming.m",
-    "src/components/TextFields/src/Theming/MDCTextInputControllerOutlined+MaterialTheming.h",
-    "src/components/TextFields/src/Theming/MDCTextInputControllerOutlined+MaterialTheming.m",
-    "src/components/TextFields/src/Theming/MDCTextInputControllerUnderline+MaterialTheming.h",
-    "src/components/TextFields/src/Theming/MDCTextInputControllerUnderline+MaterialTheming.m",
-    "src/components/TextFields/src/Theming/MaterialTextFields+Theming.h",
-    "src/components/TextFields/src/private/MDCTextInputAllCharactersCounter.m",
-    "src/components/TextFields/src/private/MDCTextInputArt.h",
-    "src/components/TextFields/src/private/MDCTextInputCommonFundament.h",
-    "src/components/TextFields/src/private/MDCTextInputCommonFundament.m",
-    "src/components/TextFields/src/private/MDCTextInputControllerBase+Subclassing.h",
-    "src/components/Themes/src/MDCColorScheme.h",
-    "src/components/Themes/src/MDCFontScheme.h",
-    "src/components/Themes/src/MDCTonalColorScheme.h",
-    "src/components/Themes/src/MDCTonalPalette.h",
-    "src/components/Themes/src/MaterialThemes.h",
-    "src/components/Typography/src/MDCFontScaler.h",
-    "src/components/Typography/src/MDCFontScaler.m",
-    "src/components/Typography/src/MDCFontTextStyle.h",
-    "src/components/Typography/src/MDCTypography.h",
-    "src/components/Typography/src/MDCTypography.m",
-    "src/components/Typography/src/MaterialTypography.h",
-    "src/components/Typography/src/UIFont+MaterialScalable.h",
-    "src/components/Typography/src/UIFont+MaterialScalable.m",
-    "src/components/Typography/src/UIFont+MaterialSimpleEquality.h",
-    "src/components/Typography/src/UIFont+MaterialSimpleEquality.m",
-    "src/components/Typography/src/UIFont+MaterialTypography.h",
-    "src/components/Typography/src/UIFont+MaterialTypography.m",
-    "src/components/Typography/src/UIFontDescriptor+MaterialTypography.h",
-    "src/components/Typography/src/UIFontDescriptor+MaterialTypography.m",
-    "src/components/Typography/src/private/MDCFontTraits.h",
-    "src/components/Typography/src/private/MDCFontTraits.m",
-    "src/components/Typography/src/private/MDCTypographyUtilities.h",
-    "src/components/Typography/src/private/MDCTypographyUtilities.m",
-    "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.h",
-    "src/components/Typography/src/private/UIFont+MaterialTypographyPrivate.m",
-    "src/components/private/Application/src/MaterialApplication.h",
-    "src/components/private/Application/src/UIApplication+MDCAppExtensions.h",
-    "src/components/private/Application/src/UIApplication+MDCAppExtensions.m",
-    "src/components/private/Beta/src/MaterialBetaComponent.h",
-    "src/components/private/Color/src/MaterialColor.h",
-    "src/components/private/Color/src/UIColor+MaterialBlending.h",
-    "src/components/private/Color/src/UIColor+MaterialBlending.m",
-    "src/components/private/Color/src/UIColor+MaterialDynamic.h",
-    "src/components/private/Color/src/UIColor+MaterialDynamic.m",
-    "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.h",
-    "src/components/private/Icons/icons/ic_arrow_back/src/MaterialIcons+ic_arrow_back.m",
-    "src/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.h",
-    "src/components/private/Icons/icons/ic_check/src/MaterialIcons+ic_check.m",
-    "src/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.h",
-    "src/components/private/Icons/icons/ic_check_circle/src/MaterialIcons+ic_check_circle.m",
-    "src/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.h",
-    "src/components/private/Icons/icons/ic_chevron_right/src/MaterialIcons+ic_chevron_right.m",
-    "src/components/private/Icons/icons/ic_color_lens/src/MaterialIcons+ic_color_lens.h",
-    "src/components/private/Icons/icons/ic_color_lens/src/MaterialIcons+ic_color_lens.m",
-    "src/components/private/Icons/icons/ic_feedback/src/MaterialIcons+ic_feedback.h",
-    "src/components/private/Icons/icons/ic_feedback/src/MaterialIcons+ic_feedback.m",
-    "src/components/private/Icons/icons/ic_help_outline/src/MaterialIcons+ic_help_outline.h",
-    "src/components/private/Icons/icons/ic_help_outline/src/MaterialIcons+ic_help_outline.m",
-    "src/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.h",
-    "src/components/private/Icons/icons/ic_info/src/MaterialIcons+ic_info.m",
-    "src/components/private/Icons/icons/ic_more_horiz/src/MaterialIcons+ic_more_horiz.h",
-    "src/components/private/Icons/icons/ic_more_horiz/src/MaterialIcons+ic_more_horiz.m",
-    "src/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.h",
-    "src/components/private/Icons/icons/ic_radio_button_unchecked/src/MaterialIcons+ic_radio_button_unchecked.m",
-    "src/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.h",
-    "src/components/private/Icons/icons/ic_reorder/src/MaterialIcons+ic_reorder.m",
-    "src/components/private/Icons/icons/ic_settings/src/MaterialIcons+ic_settings.h",
-    "src/components/private/Icons/icons/ic_settings/src/MaterialIcons+ic_settings.m",
-    "src/components/private/Icons/src/MDCIcons+BundleLoader.h",
-    "src/components/private/Icons/src/MDCIcons.h",
-    "src/components/private/Icons/src/MDCIcons.m",
-    "src/components/private/Icons/src/MaterialIcons.h",
-    "src/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.h",
-    "src/components/private/KeyboardWatcher/src/MDCKeyboardWatcher.m",
-    "src/components/private/KeyboardWatcher/src/MaterialKeyboardWatcher.h",
-    "src/components/private/Math/src/MDCMath.h",
-    "src/components/private/Math/src/MaterialMath.h",
-    "src/components/private/Math/src/MaterialMathDummy.m",
-    "src/components/private/Overlay/src/MDCOverlayImplementor.h",
-    "src/components/private/Overlay/src/MDCOverlayObserver.h",
-    "src/components/private/Overlay/src/MDCOverlayObserver.m",
-    "src/components/private/Overlay/src/MDCOverlayTransitioning.h",
-    "src/components/private/Overlay/src/MaterialOverlay.h",
-    "src/components/private/Overlay/src/private/MDCOverlayAnimationObserver.h",
-    "src/components/private/Overlay/src/private/MDCOverlayAnimationObserver.m",
-    "src/components/private/Overlay/src/private/MDCOverlayObserverOverlay.h",
-    "src/components/private/Overlay/src/private/MDCOverlayObserverOverlay.m",
-    "src/components/private/Overlay/src/private/MDCOverlayObserverTransition.h",
-    "src/components/private/Overlay/src/private/MDCOverlayObserverTransition.m",
-    "src/components/private/Overlay/src/private/MDCOverlayUtilities.h",
-    "src/components/private/Overlay/src/private/MDCOverlayUtilities.m",
-    "src/components/private/Snapshot/src/MaterialSnapshot.h",
-    "src/components/private/Snapshot/src/SnapshotUtilities/UIImage+MDCSnapshot.h",
-    "src/components/private/Snapshot/src/SnapshotUtilities/UIImage+MDCSnapshot.m",
-    "src/components/private/Snapshot/src/SnapshotUtilities/UIView+MDCSnapshot.h",
-    "src/components/private/Snapshot/src/SnapshotUtilities/UIView+MDCSnapshot.m",
-    "src/components/private/Snapshot/src/SourceDummies/MDCSnapshotSourceDummy.h",
-    "src/components/private/Snapshot/src/SourceDummies/MDCSnapshotSourceDummy.m",
-    "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlStyleBase.h",
-    "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlStyleBase.m",
-    "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlVerticalPositioningReferenceBase.h",
-    "src/components/private/TextControlsPrivate/src/BaseStyle/MDCTextControlVerticalPositioningReferenceBase.m",
-    "src/components/private/TextControlsPrivate/src/BaseStyle/MaterialTextControlsPrivate+BaseStyle.h",
-    "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlStyleFilled.h",
-    "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlStyleFilled.m",
-    "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlVerticalPositioningReferenceFilled.h",
-    "src/components/private/TextControlsPrivate/src/FilledStyle/MDCTextControlVerticalPositioningReferenceFilled.m",
-    "src/components/private/TextControlsPrivate/src/FilledStyle/MaterialTextControlsPrivate+FilledStyle.h",
-    "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlStyleOutlined.h",
-    "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlStyleOutlined.m",
-    "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlVerticalPositioningReferenceOutlined.h",
-    "src/components/private/TextControlsPrivate/src/OutlinedStyle/MDCTextControlVerticalPositioningReferenceOutlined.m",
-    "src/components/private/TextControlsPrivate/src/OutlinedStyle/MaterialTextControlsPrivate+OutlinedStyle.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControl.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControl.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelDrawPriority.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelView.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelView.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelViewLayout.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlAssistiveLabelViewLayout.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlColorViewModel.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlColorViewModel.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlGradientManager.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlGradientManager.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlHorizontalPositioningReference.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlHorizontalPositioningReference.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelAnimation.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelAnimation.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelPosition.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlLabelPosition.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlVerticalPositioningReference.h",
-    "src/components/private/TextControlsPrivate/src/Shared/MDCTextControlVerticalPositioningReference.m",
-    "src/components/private/TextControlsPrivate/src/Shared/MaterialTextControlsPrivate+Shared.h",
-    "src/components/private/TextControlsPrivate/src/Shared/UIBezierPath+MDCTextControlStyle.h",
-    "src/components/private/TextControlsPrivate/src/Shared/UIBezierPath+MDCTextControlStyle.m",
-    "src/components/private/TextControlsPrivate/src/TextFields/MDCBaseTextFieldLayout.h",
-    "src/components/private/TextControlsPrivate/src/TextFields/MDCBaseTextFieldLayout.m",
-    "src/components/private/TextControlsPrivate/src/TextFields/MaterialTextControlsPrivate+TextFields.h",
-    "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlStyleUnderlined.h",
-    "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlStyleUnderlined.m",
-    "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlVerticalPositioningReferenceUnderlined.h",
-    "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MDCTextControlVerticalPositioningReferenceUnderlined.m",
-    "src/components/private/TextControlsPrivate/src/UnderlinedStyle/MaterialTextControlsPrivate+UnderlinedStyle.h",
-    "src/components/private/ThumbTrack/src/MDCNumericValueLabel.h",
-    "src/components/private/ThumbTrack/src/MDCNumericValueLabel.m",
-    "src/components/private/ThumbTrack/src/MDCThumbTrack.h",
-    "src/components/private/ThumbTrack/src/MDCThumbTrack.m",
-    "src/components/private/ThumbTrack/src/MDCThumbView.h",
-    "src/components/private/ThumbTrack/src/MDCThumbView.m",
-    "src/components/private/ThumbTrack/src/MaterialThumbTrack.h",
-    "src/components/private/ThumbTrack/src/private/MDCThumbTrack+Private.h",
-    "src/components/private/UIMetrics/src/MDCLayoutMetrics.h",
-    "src/components/private/UIMetrics/src/MDCLayoutMetrics.m",
-    "src/components/private/UIMetrics/src/MaterialUIMetrics.h",
-    "src/components/schemes/Color/src/MDCLegacyColorScheme.h",
-    "src/components/schemes/Color/src/MDCLegacyColorScheme.m",
-    "src/components/schemes/Color/src/MDCLegacyTonalColorScheme.h",
-    "src/components/schemes/Color/src/MDCLegacyTonalColorScheme.m",
-    "src/components/schemes/Color/src/MDCLegacyTonalPalette.h",
-    "src/components/schemes/Color/src/MDCLegacyTonalPalette.m",
-    "src/components/schemes/Color/src/MDCSemanticColorScheme.h",
-    "src/components/schemes/Color/src/MDCSemanticColorScheme.m",
-    "src/components/schemes/Color/src/MaterialColorScheme.h",
-    "src/components/schemes/Container/src/MDCContainerScheme.h",
-    "src/components/schemes/Container/src/MDCContainerScheme.m",
-    "src/components/schemes/Container/src/MaterialContainerScheme.h",
-    "src/components/schemes/Shape/src/MDCShapeCategory.h",
-    "src/components/schemes/Shape/src/MDCShapeCategory.m",
-    "src/components/schemes/Shape/src/MDCShapeScheme.h",
-    "src/components/schemes/Shape/src/MDCShapeScheme.m",
-    "src/components/schemes/Shape/src/MaterialShapeScheme.h",
-    "src/components/schemes/Typography/src/BasicFontScheme/MDCBasicFontScheme.h",
-    "src/components/schemes/Typography/src/BasicFontScheme/MDCBasicFontScheme.m",
-    "src/components/schemes/Typography/src/BasicFontScheme/MaterialTypographyScheme+BasicFontScheme.h",
-    "src/components/schemes/Typography/src/MDCLegacyFontScheme.h",
-    "src/components/schemes/Typography/src/MDCTypographyScheme.h",
-    "src/components/schemes/Typography/src/MDCTypographyScheme.m",
-    "src/components/schemes/Typography/src/MaterialTypographyScheme.h",
-    "src/components/schemes/Typography/src/Scheming/MDCTypographyScheming.h",
-    "src/components/schemes/Typography/src/Scheming/MaterialTypographyScheme+Scheming.h",
-  ]
+  sources = _mdc_sources
 
   info_plist = "Info.plist"
   output_name = "MaterialComponents"
diff --git a/ios/web/BUILD.gn b/ios/web/BUILD.gn
index 64bc565f..926f82394 100644
--- a/ios/web/BUILD.gn
+++ b/ios/web/BUILD.gn
@@ -503,6 +503,7 @@
     "web_state/ui/crw_web_view_scroll_view_proxy_unittest.mm",
     "web_state/ui/html_element_fetch_request_unittest.mm",
     "web_state/ui/web_view_js_utils_unittest.mm",
+    "web_state/ui/wk_content_rule_list_util_unittest.mm",
     "web_state/ui/wk_web_view_configuration_provider_unittest.mm",
   ]
 }
diff --git a/ios/web/OWNERS b/ios/web/OWNERS
index 6b318d4..d0ecec8 100644
--- a/ios/web/OWNERS
+++ b/ios/web/OWNERS
@@ -1,6 +1,5 @@
 eugenebut@chromium.org
 gambard@chromium.org
-kkhorimoto@chromium.org
 marq@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
diff --git a/ios/web/browser_state.mm b/ios/web/browser_state.mm
index 111e655..3d992db9 100644
--- a/ios/web/browser_state.mm
+++ b/ios/web/browser_state.mm
@@ -11,6 +11,7 @@
 #include "base/guid.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
 #include "base/process/process_handle.h"
 #include "base/task/post_task.h"
@@ -21,6 +22,7 @@
 #include "ios/web/public/security/certificate_policy_cache.h"
 #include "ios/web/public/thread/web_task_traits.h"
 #include "ios/web/public/thread/web_thread.h"
+#import "ios/web/web_state/ui/wk_content_rule_list_provider.h"
 #include "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
 #include "ios/web/webui/url_data_manager_ios_backend.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
@@ -193,8 +195,10 @@
 }
 
 void BrowserState::SetCookieBlockingMode(
-    CookieBlockingMode cookie_blocking_mode) {
+    CookieBlockingMode cookie_blocking_mode,
+    base::OnceClosure callback) {
   if (cookie_blocking_mode == cookie_blocking_mode_) {
+    std::move(callback).Run();
     return;
   }
   cookie_blocking_mode_ = cookie_blocking_mode;
@@ -204,6 +208,15 @@
   // source of the injected Javascript depends on the current cookie blocking
   // mode to set up the blocking correctly.
   config_provider.UpdateScripts();
+
+  config_provider.GetContentRuleListProvider()->UpdateContentRuleLists(
+      base::BindOnce(
+          [](base::OnceClosure callback, bool success) {
+            base::UmaHistogramBoolean(
+                "IOS.ContentRuleListProviderUpdateSuccess", success);
+            std::move(callback).Run();
+          },
+          std::move(callback)));
 }
 
 }  // namespace web
diff --git a/ios/web/browser_state_unittest.mm b/ios/web/browser_state_unittest.mm
index 4f921cd..5d01e68 100644
--- a/ios/web/browser_state_unittest.mm
+++ b/ios/web/browser_state_unittest.mm
@@ -7,6 +7,8 @@
 #import <WebKit/WebKit.h>
 
 #include "base/supports_user_data.h"
+#import "base/test/bind_test_util.h"
+#import "base/test/ios/wait_util.h"
 #include "ios/web/public/browsing_data/cookie_blocking_mode.h"
 #include "ios/web/public/test/fakes/test_browser_state.h"
 #import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
@@ -17,6 +19,9 @@
 #error "This file requires ARC support."
 #endif
 
+using base::test::ios::WaitUntilConditionOrTimeout;
+using base::test::ios::kWaitForPageLoadTimeout;
+
 namespace {
 class TestSupportsUserData : public base::SupportsUserData {
  public:
@@ -48,7 +53,15 @@
 // to change.
 TEST_F(BrowserStateTest, SetCookieBlockingMode) {
   web::TestBrowserState browser_state;
-  browser_state.SetCookieBlockingMode(web::CookieBlockingMode::kAllow);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  browser_state.SetCookieBlockingMode(
+      web::CookieBlockingMode::kAllow,
+      base::BindLambdaForTesting([&]() { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   web::WKWebViewConfigurationProvider& config_provider =
       web::WKWebViewConfigurationProvider::FromBrowserState(&browser_state);
@@ -64,7 +77,14 @@
       [original_scripts isEqualToArray:config_provider.GetWebViewConfiguration()
                                            .userContentController.userScripts]);
 
-  browser_state.SetCookieBlockingMode(web::CookieBlockingMode::kBlock);
+  success = false;
+  browser_state.SetCookieBlockingMode(
+      web::CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&]() { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   NSArray<WKUserScript*>* updated_scripts =
       [[NSArray alloc] initWithArray:wkscripts copyItems:NO];
diff --git a/ios/web/cookie_blocking_inttest.mm b/ios/web/cookie_blocking_inttest.mm
index 9dd1da8..1bbb5ba3 100644
--- a/ios/web/cookie_blocking_inttest.mm
+++ b/ios/web/cookie_blocking_inttest.mm
@@ -5,6 +5,7 @@
 #import <WebKit/WebKit.h>
 
 #include "base/strings/utf_string_conversions.h"
+#import "base/test/bind_test_util.h"
 #import "base/test/ios/wait_util.h"
 #include "ios/testing/embedded_test_server_handlers.h"
 #include "ios/web/public/browsing_data/cookie_blocking_mode.h"
@@ -76,7 +77,14 @@
 // Tests that cookies are accessible from JavaScript in all frames
 // when the blocking mode is set to allow.
 TEST_F(CookieBlockingTest, CookiesAllowed) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kAllow);
+  bool success = false;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kAllow,
+      base::BindLambdaForTesting([&] { success = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -104,7 +112,15 @@
 // Tests that cookies are inaccessable from JavaScript in all frames
 // when the blocking mode is set to block.
 TEST_F(CookieBlockingTest, CookiesBlocked) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kBlock);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&]() { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -131,8 +147,15 @@
 // Tests that cookies are accessible from JavaScript on the main page, but
 // inaccessible from a third-party iframe when third party cookies are blocked.
 TEST_F(CookieBlockingTest, ThirdPartyCookiesBlocked) {
+  __block bool success = false;
+  bool* success_ptr = &success;
   GetBrowserState()->SetCookieBlockingMode(
-      CookieBlockingMode::kBlockThirdParty);
+      CookieBlockingMode::kBlockThirdParty,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -164,8 +187,15 @@
 // Tests that a first-party iframe can still access cookies when third party
 // cookies are blocked.
 TEST_F(CookieBlockingTest, FirstPartyCookiesNotBlockedWhenThirdPartyBlocked) {
+  __block bool success = false;
+  bool* success_ptr = &success;
   GetBrowserState()->SetCookieBlockingMode(
-      CookieBlockingMode::kBlockThirdParty);
+      CookieBlockingMode::kBlockThirdParty,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   GURL iframe_url = server_.GetURL(kIFrameUrl);
   std::string url_spec = kPageUrl + net::EscapeQueryParamValue(
@@ -192,7 +222,15 @@
 // Tests that the document.cookie override cannot be deleted by external
 // JavaScript.
 TEST_F(CookieBlockingTest, CookiesBlockedUndeletable) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kBlock);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -217,7 +255,15 @@
 // Tests that localStorage is accessible from JavaScript in all frames
 // when the blocking mode is set to allow.
 TEST_F(CookieBlockingTest, LocalStorageAllowed) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kAllow);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kAllow,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -250,7 +296,15 @@
 // Tests that localStorage is inaccessable from JavaScript in all frames
 // when the blocking mode is set to block.
 TEST_F(CookieBlockingTest, LocalStorageBlocked) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kBlock);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -284,7 +338,15 @@
 
 // Tests that the localStorage override is undeletable via extra JavaScript.
 TEST_F(CookieBlockingTest, LocalStorageBlockedUndeletable) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kBlock);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -316,7 +378,15 @@
 // Tests that sessionStorage is accessible from JavaScript in all frames
 // when the blocking mode is set to allow.
 TEST_F(CookieBlockingTest, SessionStorageAllowed) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kAllow);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kAllow,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -349,7 +419,15 @@
 // Tests that sessionStorage is inaccessable from JavaScript in all frames
 // when the blocking mode is set to block.
 TEST_F(CookieBlockingTest, SessionStorageBlocked) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kBlock);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
@@ -383,7 +461,15 @@
 
 // Tests that the sessionStorage override is undeletable via extra JavaScript.
 TEST_F(CookieBlockingTest, SessionStorageBlockedUndeletable) {
-  GetBrowserState()->SetCookieBlockingMode(CookieBlockingMode::kBlock);
+  __block bool success = false;
+  bool* success_ptr = &success;
+  GetBrowserState()->SetCookieBlockingMode(
+      CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&] { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
 
   // Use arbitrary third party url for iframe.
   GURL iframe_url = third_party_server_.GetURL(kIFrameUrl);
diff --git a/ios/web/download/download_session_cookie_storage.mm b/ios/web/download/download_session_cookie_storage.mm
index a9296f92..cbd1205 100644
--- a/ios/web/download/download_session_cookie_storage.mm
+++ b/ios/web/download/download_session_cookie_storage.mm
@@ -55,7 +55,7 @@
         net::CanonicalCookieFromSystemCookie(cookie, base::Time());
     if (canonical_cookie
             .IncludeForRequestURL(gURL, options, cookieAccessSemantics)
-            .IsInclude())
+            .status.IsInclude())
       [result addObject:cookie];
   }
   return [result copy];
diff --git a/ios/web/js_messaging/page_script_util_unittest.mm b/ios/web/js_messaging/page_script_util_unittest.mm
index 0ae886a..5d72e9f5 100644
--- a/ios/web/js_messaging/page_script_util_unittest.mm
+++ b/ios/web/js_messaging/page_script_util_unittest.mm
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "base/strings/sys_string_conversions.h"
+#import "base/test/bind_test_util.h"
 #import "base/test/ios/wait_util.h"
 #import "ios/web/common/web_view_creation_util.h"
 #include "ios/web/public/browsing_data/cookie_blocking_mode.h"
@@ -22,6 +23,9 @@
 #error "This file requires ARC support."
 #endif
 
+using base::test::ios::WaitUntilConditionOrTimeout;
+using base::test::ios::kWaitForPageLoadTimeout;
+
 namespace web {
 namespace {
 
@@ -60,18 +64,41 @@
 // state in the DocumentStartScriptForAllFrames.
 TEST_F(PageScriptUtilTest, AllFrameStartCookieReplacement) {
   web::BrowserState* browser_state = GetBrowserState();
-  browser_state->SetCookieBlockingMode(web::CookieBlockingMode::kAllow);
+
+  __block bool success = false;
+  bool* success_ptr = &success;
+  browser_state->SetCookieBlockingMode(
+      web::CookieBlockingMode::kAllow,
+      base::BindLambdaForTesting([&]() { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
+
   NSString* script = GetDocumentStartScriptForAllFrames(browser_state);
   EXPECT_EQ(0U, [script rangeOfString:@"$(COOKIE_STATE)"].length);
   EXPECT_LT(0U, [script rangeOfString:@"(\"allow\")"].length);
 
+  success = false;
   browser_state->SetCookieBlockingMode(
-      web::CookieBlockingMode::kBlockThirdParty);
+      web::CookieBlockingMode::kBlockThirdParty,
+      base::BindLambdaForTesting([&]() { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
   script = GetDocumentStartScriptForAllFrames(browser_state);
   EXPECT_EQ(0U, [script rangeOfString:@"$(COOKIE_STATE)"].length);
   EXPECT_LT(0U, [script rangeOfString:@"(\"block-third-party\")"].length);
 
-  browser_state->SetCookieBlockingMode(web::CookieBlockingMode::kBlock);
+  success = false;
+  browser_state->SetCookieBlockingMode(
+      web::CookieBlockingMode::kBlock,
+      base::BindLambdaForTesting([&]() { *success_ptr = true; }));
+
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^{
+    return success;
+  }));
   script = GetDocumentStartScriptForAllFrames(browser_state);
   EXPECT_EQ(0U, [script rangeOfString:@"$(COOKIE_STATE)"].length);
   EXPECT_LT(0U, [script rangeOfString:@"(\"block\")"].length);
diff --git a/ios/web/navigation/OWNERS b/ios/web/navigation/OWNERS
index 4488d78ab..ed372ce 100644
--- a/ios/web/navigation/OWNERS
+++ b/ios/web/navigation/OWNERS
@@ -1,8 +1,7 @@
 ajuma@chromium.org
 danyao@chromium.org
 eugenebut@chromium.org
-kkhorimoto@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
-# COMPONENT: UI>Browser>Navigation
\ No newline at end of file
+# COMPONENT: UI>Browser>Navigation
diff --git a/ios/web/net/cookies/wk_http_system_cookie_store.mm b/ios/web/net/cookies/wk_http_system_cookie_store.mm
index ac89fb4..1e64e71 100644
--- a/ios/web/net/cookies/wk_http_system_cookie_store.mm
+++ b/ios/web/net/cookies/wk_http_system_cookie_store.mm
@@ -56,7 +56,7 @@
   }
   return canonical_cookie
       .IncludeForRequestURL(url, options, cookie_access_semantics)
-      .IsInclude();
+      .status.IsInclude();
 }
 
 }  // namespace
diff --git a/ios/web/public/browser_state.h b/ios/web/public/browser_state.h
index 1d91150..64aae2f 100644
--- a/ios/web/public/browser_state.h
+++ b/ios/web/public/browser_state.h
@@ -98,7 +98,10 @@
   // Sets the cookie blocking mode for this browser state. This will only affect
   // WebStates that are loaded after this mode is set. WebStates with live web
   // content will not have the mode correctly setup until they are reloaded.
-  void SetCookieBlockingMode(CookieBlockingMode cookie_blocking_mode);
+  // Some tasks here may be asynchronous, so |callback| will be called after
+  // the cookie blocking mode is set correctly. This may happen immediately.
+  void SetCookieBlockingMode(CookieBlockingMode cookie_blocking_mode,
+                             base::OnceClosure callback);
 
  protected:
   BrowserState();
diff --git a/ios/web/session/OWNERS b/ios/web/session/OWNERS
index b57bf3f8..599a9fa4 100644
--- a/ios/web/session/OWNERS
+++ b/ios/web/session/OWNERS
@@ -1,5 +1,4 @@
 eugenebut@chromium.org
-kkhorimoto@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/web/web_state/ui/BUILD.gn b/ios/web/web_state/ui/BUILD.gn
index 5f89ebe..756b234 100644
--- a/ios/web/web_state/ui/BUILD.gn
+++ b/ios/web/web_state/ui/BUILD.gn
@@ -124,6 +124,10 @@
   ]
 
   sources = [
+    "wk_content_rule_list_provider.h",
+    "wk_content_rule_list_provider.mm",
+    "wk_content_rule_list_util.h",
+    "wk_content_rule_list_util.mm",
     "wk_web_view_configuration_provider.h",
     "wk_web_view_configuration_provider.mm",
     "wk_web_view_configuration_provider_observer.h",
diff --git a/ios/web/web_state/ui/OWNERS b/ios/web/web_state/ui/OWNERS
index e639d04a..1c067184 100644
--- a/ios/web/web_state/ui/OWNERS
+++ b/ios/web/web_state/ui/OWNERS
@@ -1,6 +1,5 @@
 danyao@chromium.org
 eugenebut@chromium.org
-kkhorimoto@chromium.org
 
 # TEAM: ios-directory-owners@chromium.org
 # OS: iOS
diff --git a/ios/web/web_state/ui/wk_content_rule_list_provider.h b/ios/web/web_state/ui/wk_content_rule_list_provider.h
new file mode 100644
index 0000000..d7b1e86
--- /dev/null
+++ b/ios/web/web_state/ui/wk_content_rule_list_provider.h
@@ -0,0 +1,64 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_WEB_STATE_UI_WK_CONTENT_RULE_LIST_PROVIDER_H_
+#define IOS_WEB_WEB_STATE_UI_WK_CONTENT_RULE_LIST_PROVIDER_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#import "ios/web/web_state/ui/wk_web_view_configuration_provider_observer.h"
+
+@class WKContentRuleList;
+@class WKUserContentController;
+
+namespace web {
+
+class BrowserState;
+enum class CookieBlockingMode;
+
+// A provider class that handles compiling and configuring Content Blocker
+// rules.
+class WKContentRuleListProvider {
+ public:
+  explicit WKContentRuleListProvider(BrowserState* browser_state);
+  ~WKContentRuleListProvider();
+
+  // Sets the WKUserContentController that this provider will install its rules
+  // on.
+  void SetUserContentController(
+      WKUserContentController* user_content_controller);
+
+  // Updates and re-installs the Content Blocker rules using any new state.
+  // This may be asynchronous if a rule list hasn't been compiled yet, so
+  // |callback| will be called after the mode is set. It will be called with
+  // true if the update is successful and false otherwise (most likely because
+  // rules were updated again before the first set of rules was fully
+  // installed).
+  void UpdateContentRuleLists(base::OnceCallback<void(bool)> callback);
+
+ private:
+  WKContentRuleListProvider(const WKContentRuleListProvider&) = delete;
+  WKContentRuleListProvider& operator=(const WKContentRuleListProvider&) =
+      delete;
+
+  // Installs the content rule list that should be installed given the current
+  // block setting.
+  void InstallContentRuleLists();
+
+  // Uninstalls all content rule lists installed by this provider.
+  void UninstallContentRuleLists();
+
+  BrowserState* browser_state_;
+  __weak WKUserContentController* user_content_controller_;
+  WKContentRuleList* block_content_rule_list_;
+  WKContentRuleList* block_third_party_content_rule_list_;
+
+  base::OnceCallback<void(bool)> update_callback_;
+
+  base::WeakPtrFactory<WKContentRuleListProvider> weak_ptr_factory_;
+};
+
+}  // namespace web
+
+#endif  // IOS_WEB_WEB_STATE_UI_WK_CONTENT_RULE_LIST_PROVIDER_H_
diff --git a/ios/web/web_state/ui/wk_content_rule_list_provider.mm b/ios/web/web_state/ui/wk_content_rule_list_provider.mm
new file mode 100644
index 0000000..27ebdf0
--- /dev/null
+++ b/ios/web/web_state/ui/wk_content_rule_list_provider.mm
@@ -0,0 +1,108 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web/web_state/ui/wk_content_rule_list_provider.h"
+
+#import <Foundation/Foundation.h>
+#import <WebKit/WebKit.h>
+
+#include "ios/web/public/browser_state.h"
+#include "ios/web/public/browsing_data/cookie_blocking_mode.h"
+#import "ios/web/web_state/ui/wk_content_rule_list_util.h"
+#import "ios/web/web_state/ui/wk_web_view_configuration_provider.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace web {
+
+WKContentRuleListProvider::WKContentRuleListProvider(
+    BrowserState* browser_state)
+    : browser_state_(browser_state), weak_ptr_factory_(this) {
+  base::WeakPtr<WKContentRuleListProvider> weak_this =
+      weak_ptr_factory_.GetWeakPtr();
+  [WKContentRuleListStore.defaultStore
+      compileContentRuleListForIdentifier:@"block"
+                   encodedContentRuleList:CreateCookieBlockingJsonRuleList(
+                                              CookieBlockingMode::kBlock)
+                        completionHandler:^(WKContentRuleList* rule_list,
+                                            NSError* error) {
+                          if (!weak_this.get()) {
+                            return;
+                          }
+                          block_content_rule_list_ = rule_list;
+                          InstallContentRuleLists();
+                        }];
+  [WKContentRuleListStore.defaultStore
+      compileContentRuleListForIdentifier:@"block-third-party"
+                   encodedContentRuleList:
+                       CreateCookieBlockingJsonRuleList(
+                           CookieBlockingMode::kBlockThirdParty)
+                        completionHandler:^(WKContentRuleList* rule_list,
+                                            NSError* error) {
+                          if (!weak_this.get()) {
+                            return;
+                          }
+                          block_third_party_content_rule_list_ = rule_list;
+                          InstallContentRuleLists();
+                        }];
+}
+
+WKContentRuleListProvider::~WKContentRuleListProvider() {}
+
+void WKContentRuleListProvider::UpdateContentRuleLists(
+    base::OnceCallback<void(bool)> callback) {
+  if (update_callback_) {
+    std::move(update_callback_).Run(false);
+  }
+  update_callback_ = std::move(callback);
+  InstallContentRuleLists();
+}
+
+void WKContentRuleListProvider::InstallContentRuleLists() {
+  UninstallContentRuleLists();
+  switch (browser_state_->GetCookieBlockingMode()) {
+    case CookieBlockingMode::kAllow:
+      if (update_callback_) {
+        std::move(update_callback_).Run(true);
+      }
+      break;
+    case CookieBlockingMode::kBlockThirdParty:
+      if (block_third_party_content_rule_list_) {
+        [user_content_controller_
+            addContentRuleList:block_third_party_content_rule_list_];
+        if (update_callback_) {
+          std::move(update_callback_).Run(true);
+        }
+      }
+      break;
+    case CookieBlockingMode::kBlock:
+      if (block_content_rule_list_) {
+        [user_content_controller_ addContentRuleList:block_content_rule_list_];
+        if (update_callback_) {
+          std::move(update_callback_).Run(true);
+        }
+      }
+      break;
+  }
+}
+
+void WKContentRuleListProvider::UninstallContentRuleLists() {
+  if (block_content_rule_list_) {
+    [user_content_controller_ removeContentRuleList:block_content_rule_list_];
+  }
+  if (block_third_party_content_rule_list_) {
+    [user_content_controller_
+        removeContentRuleList:block_third_party_content_rule_list_];
+  }
+}
+
+void WKContentRuleListProvider::SetUserContentController(
+    WKUserContentController* user_content_controller) {
+  user_content_controller_ = user_content_controller;
+  InstallContentRuleLists();
+}
+
+}  // namespace web
diff --git a/ios/web/web_state/ui/wk_content_rule_list_util.h b/ios/web/web_state/ui/wk_content_rule_list_util.h
new file mode 100644
index 0000000..73fff54
--- /dev/null
+++ b/ios/web/web_state/ui/wk_content_rule_list_util.h
@@ -0,0 +1,19 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_WEB_WEB_STATE_UI_WK_CONTENT_RULE_LIST_UTIL_H_
+#define IOS_WEB_WEB_STATE_UI_WK_CONTENT_RULE_LIST_UTIL_H_
+
+#import <Foundation/Foundation.h>
+
+namespace web {
+enum class CookieBlockingMode;
+
+// Creates the rules json as a string for cookie blocking following the format
+// expected by the Content Blocker API.
+NSString* CreateCookieBlockingJsonRuleList(CookieBlockingMode block_mode);
+
+}  // namespace web
+
+#endif  // IOS_WEB_WEB_STATE_UI_WK_CONTENT_RULE_LIST_UTIL_H_
diff --git a/ios/web/web_state/ui/wk_content_rule_list_util.mm b/ios/web/web_state/ui/wk_content_rule_list_util.mm
new file mode 100644
index 0000000..816246d
--- /dev/null
+++ b/ios/web/web_state/ui/wk_content_rule_list_util.mm
@@ -0,0 +1,40 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web/web_state/ui/wk_content_rule_list_util.h"
+
+#include "base/check.h"
+#include "ios/web/public/browsing_data/cookie_blocking_mode.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace web {
+
+NSString* CreateCookieBlockingJsonRuleList(CookieBlockingMode block_mode) {
+  DCHECK(block_mode != CookieBlockingMode::kAllow);
+  NSMutableDictionary* overall_block = [@{
+    @"trigger" : [@{
+      @"url-filter" : @".*",
+    } mutableCopy],
+    @"action" : @{
+      @"type" : @"block-cookies",
+    },
+  } mutableCopy];
+
+  if (block_mode == CookieBlockingMode::kBlockThirdParty) {
+    overall_block[@"trigger"][@"load-type"] = @[ @"third-party" ];
+  }
+
+  NSData* json_data =
+      [NSJSONSerialization dataWithJSONObject:@[ overall_block ]
+                                      options:NSJSONWritingPrettyPrinted
+                                        error:nil];
+  NSString* json_string = [[NSString alloc] initWithData:json_data
+                                                encoding:NSUTF8StringEncoding];
+  return json_string;
+}
+
+}  // namespace web
diff --git a/ios/web/web_state/ui/wk_content_rule_list_util_unittest.mm b/ios/web/web_state/ui/wk_content_rule_list_util_unittest.mm
new file mode 100644
index 0000000..3c680915
--- /dev/null
+++ b/ios/web/web_state/ui/wk_content_rule_list_util_unittest.mm
@@ -0,0 +1,60 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/web/web_state/ui/wk_content_rule_list_util.h"
+
+#include "ios/web/public/browsing_data/cookie_blocking_mode.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#import "testing/gtest_mac.h"
+#include "testing/platform_test.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace web {
+namespace {
+
+using WKContentRuleListUtilTest = PlatformTest;
+
+// Tests that the JSON created for block mode contains the correct keys.
+TEST_F(WKContentRuleListUtilTest, JSONBlock) {
+  NSString* rules_string =
+      CreateCookieBlockingJsonRuleList(CookieBlockingMode::kBlock);
+  NSData* rules_data = [rules_string dataUsingEncoding:NSUTF8StringEncoding];
+  id json = [NSJSONSerialization JSONObjectWithData:rules_data
+                                            options:0
+                                              error:nil];
+
+  // The Apple API says Content Blocker rules must be an array of rules.
+  ASSERT_TRUE([json isKindOfClass:[NSArray class]]);
+
+  id block_rule = json[0];
+  ASSERT_TRUE([block_rule isKindOfClass:[NSDictionary class]]);
+  ASSERT_NSEQ(@".*", block_rule[@"trigger"][@"url-filter"]);
+  ASSERT_NSEQ(@"block-cookies", block_rule[@"action"][@"type"]);
+}
+
+// Tests that the JSON created for block third party mode contains the correct
+// keys.
+TEST_F(WKContentRuleListUtilTest, JSONBlockThirdParty) {
+  NSString* rules_string =
+      CreateCookieBlockingJsonRuleList(CookieBlockingMode::kBlockThirdParty);
+  NSData* rules_data = [rules_string dataUsingEncoding:NSUTF8StringEncoding];
+  id json = [NSJSONSerialization JSONObjectWithData:rules_data
+                                            options:0
+                                              error:nil];
+
+  // The Apple API says Content Blocker rules must be an array of rules.
+  ASSERT_TRUE([json isKindOfClass:[NSArray class]]);
+
+  id block_rule = json[0];
+  ASSERT_TRUE([block_rule isKindOfClass:[NSDictionary class]]);
+  ASSERT_NSEQ(@".*", block_rule[@"trigger"][@"url-filter"]);
+  ASSERT_NSEQ(@"third-party", block_rule[@"trigger"][@"load-type"][0]);
+  ASSERT_NSEQ(@"block-cookies", block_rule[@"action"][@"type"]);
+}
+
+}  // namespace
+}  // namespace web
diff --git a/ios/web/web_state/ui/wk_web_view_configuration_provider.h b/ios/web/web_state/ui/wk_web_view_configuration_provider.h
index 1f86ba8c..9c67e519 100644
--- a/ios/web/web_state/ui/wk_web_view_configuration_provider.h
+++ b/ios/web/web_state/ui/wk_web_view_configuration_provider.h
@@ -16,6 +16,7 @@
 namespace web {
 
 class BrowserState;
+class WKContentRuleListProvider;
 class WKWebViewConfigurationProviderObserver;
 
 // A provider class associated with a single web::BrowserState object. Manages
@@ -63,6 +64,10 @@
   // (this will be enforced in debug builds).
   CRWWKScriptMessageRouter* GetScriptMessageRouter();
 
+  // Returns WKContentRuleListProvider associated with WKWebViewConfiguration.
+  // Callers must not retain the returned object.
+  WKContentRuleListProvider* GetContentRuleListProvider();
+
   // Recreates and re-adds all injected Javascript into the current
   // configuration. This will only affect WebStates that are loaded after a call
   // to this function. All current WebStates will keep their existing Javascript
@@ -87,6 +92,7 @@
   WKWebViewConfiguration* configuration_ = nil;
   CRWWKScriptMessageRouter* router_;
   BrowserState* browser_state_;
+  std::unique_ptr<WKContentRuleListProvider> content_rule_list_provider_;
 
   // A list of observers notified when WKWebViewConfiguration changes.
   // This observer list has its' check_empty flag set to false, because
diff --git a/ios/web/web_state/ui/wk_web_view_configuration_provider.mm b/ios/web/web_state/ui/wk_web_view_configuration_provider.mm
index 6bd30dcb..382f4a1a 100644
--- a/ios/web/web_state/ui/wk_web_view_configuration_provider.mm
+++ b/ios/web/web_state/ui/wk_web_view_configuration_provider.mm
@@ -18,6 +18,7 @@
 #import "ios/web/js_messaging/page_script_util.h"
 #include "ios/web/public/browser_state.h"
 #include "ios/web/public/web_client.h"
+#import "ios/web/web_state/ui/wk_content_rule_list_provider.h"
 #import "ios/web/web_state/ui/wk_web_view_configuration_provider_observer.h"
 #import "ios/web/webui/crw_web_ui_scheme_handler.h"
 
@@ -90,7 +91,9 @@
 
 WKWebViewConfigurationProvider::WKWebViewConfigurationProvider(
     BrowserState* browser_state)
-    : browser_state_(browser_state) {}
+    : browser_state_(browser_state),
+      content_rule_list_provider_(
+          std::make_unique<WKContentRuleListProvider>(browser_state)) {}
 
 WKWebViewConfigurationProvider::~WKWebViewConfigurationProvider() = default;
 
@@ -159,6 +162,9 @@
                            forURLScheme:base::SysUTF8ToNSString(scheme)];
   }
 
+  content_rule_list_provider_->SetUserContentController(
+      configuration_.userContentController);
+
   for (auto& observer : observers_)
     observer.DidCreateNewConfiguration(this, configuration_);
 
@@ -196,6 +202,11 @@
   return router_;
 }
 
+WKContentRuleListProvider*
+WKWebViewConfigurationProvider::GetContentRuleListProvider() {
+  return content_rule_list_provider_.get();
+}
+
 void WKWebViewConfigurationProvider::UpdateScripts() {
   [configuration_.userContentController removeAllUserScripts];
   // Main frame script depends upon scripts injected into all frames, so the
diff --git a/ios/web/web_state/ui/wk_web_view_configuration_provider_unittest.mm b/ios/web/web_state/ui/wk_web_view_configuration_provider_unittest.mm
index 92124bd..dbcf1168 100644
--- a/ios/web/web_state/ui/wk_web_view_configuration_provider_unittest.mm
+++ b/ios/web/web_state/ui/wk_web_view_configuration_provider_unittest.mm
@@ -252,5 +252,13 @@
   EXPECT_NE(config, actual);
 }
 
+TEST_F(WKWebViewConfigurationProviderTest, GetContentRuleListProvider) {
+  std::unique_ptr<TestBrowserState> browser_state =
+      std::make_unique<TestBrowserState>();
+  WKWebViewConfigurationProvider& provider = GetProvider(browser_state.get());
+
+  EXPECT_NE(nil, provider.GetContentRuleListProvider());
+}
+
 }  // namespace
 }  // namespace web
diff --git a/ipc/ipc_fuzzing_tests.cc b/ipc/ipc_fuzzing_tests.cc
index ca8827b..2058f95 100644
--- a/ipc/ipc_fuzzing_tests.cc
+++ b/ipc/ipc_fuzzing_tests.cc
@@ -141,8 +141,7 @@
 
 class SimpleListener : public IPC::Listener {
  public:
-  SimpleListener() : other_(NULL) {
-  }
+  SimpleListener() : other_(nullptr) {}
   void Init(IPC::Sender* s) {
     other_ = s;
   }
@@ -223,8 +222,7 @@
 
 class FuzzerClientListener : public SimpleListener {
  public:
-  FuzzerClientListener() : last_msg_(NULL) {
-  }
+  FuzzerClientListener() : last_msg_(nullptr) {}
 
   bool OnMessageReceived(const IPC::Message& msg) override {
     last_msg_ = new IPC::Message(msg);
diff --git a/ipc/ipc_logging.cc b/ipc/ipc_logging.cc
index 905b1611..3fcaed4 100644
--- a/ipc/ipc_logging.cc
+++ b/ipc/ipc_logging.cc
@@ -48,9 +48,9 @@
       enabled_on_stderr_(false),
       enabled_color_(false),
       queue_invoke_later_pending_(false),
-      sender_(NULL),
+      sender_(nullptr),
       main_thread_(base::ThreadTaskRunnerHandle::Get()),
-      consumer_(NULL) {
+      consumer_(nullptr) {
 #if defined(OS_WIN)
   // getenv triggers an unsafe warning. Simply check how big of a buffer
   // would be needed to fetch the value to see if the enviornment variable is
diff --git a/ipc/ipc_mojo_perftest.cc b/ipc/ipc_mojo_perftest.cc
index df562d4..723b96d 100644
--- a/ipc/ipc_mojo_perftest.cc
+++ b/ipc/ipc_mojo_perftest.cc
@@ -42,7 +42,7 @@
  public:
   explicit PerformanceChannelListener(const std::string& label)
       : label_(label),
-        sender_(NULL),
+        sender_(nullptr),
         msg_count_(0),
         msg_size_(0),
         sync_(false),
diff --git a/ipc/ipc_perftest_util.cc b/ipc/ipc_perftest_util.cc
index cf35d3cd..4945f83c 100644
--- a/ipc/ipc_perftest_util.cc
+++ b/ipc/ipc_perftest_util.cc
@@ -19,7 +19,7 @@
       static_cast<base::SingleThreadTaskRunner*>(runner.get()));
 }
 
-ChannelReflectorListener::ChannelReflectorListener() : channel_(NULL) {
+ChannelReflectorListener::ChannelReflectorListener() : channel_(nullptr) {
   VLOG(1) << "Client listener up";
 }
 
diff --git a/ipc/ipc_sync_channel_unittest.cc b/ipc/ipc_sync_channel_unittest.cc
index 31a734b8..aacfa42 100644
--- a/ipc/ipc_sync_channel_unittest.cc
+++ b/ipc/ipc_sync_channel_unittest.cc
@@ -56,7 +56,7 @@
         mode_(mode),
         ipc_thread_((thread_name + "_ipc").c_str()),
         listener_thread_((thread_name + "_listener").c_str()),
-        overrided_thread_(NULL),
+        overrided_thread_(nullptr),
         shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
                         base::WaitableEvent::InitialState::NOT_SIGNALED),
         is_shutdown_(false) {}
@@ -73,7 +73,7 @@
         mode_(mode),
         ipc_thread_("ipc thread"),
         listener_thread_("listener thread"),
-        overrided_thread_(NULL),
+        overrided_thread_(nullptr),
         shutdown_event_(base::WaitableEvent::ResetPolicy::MANUAL,
                         base::WaitableEvent::InitialState::NOT_SIGNALED),
         is_shutdown_(false) {}
@@ -1770,7 +1770,8 @@
 class ReentrantReplyServer2 : public Worker {
  public:
   ReentrantReplyServer2(mojo::ScopedMessagePipeHandle channel_handle)
-      : Worker(std::move(channel_handle), Channel::MODE_SERVER), reply_(NULL) {}
+      : Worker(std::move(channel_handle), Channel::MODE_SERVER),
+        reply_(nullptr) {}
 
  private:
   bool OnMessageReceived(const Message& message) override {
diff --git a/ipc/ipc_test_channel_listener.h b/ipc/ipc_test_channel_listener.h
index 75635f7d..2a4cda9 100644
--- a/ipc/ipc_test_channel_listener.h
+++ b/ipc/ipc_test_channel_listener.h
@@ -21,7 +21,7 @@
   static const size_t kLongMessageStringNumBytes = 50000;
   static void SendOneMessage(Sender* sender, const char* text);
 
-  TestChannelListener() : sender_(NULL), messages_left_(50) {}
+  TestChannelListener() : sender_(nullptr), messages_left_(50) {}
   ~TestChannelListener() override {}
 
   bool OnMessageReceived(const Message& message) override;
diff --git a/ipc/sync_socket_unittest.cc b/ipc/sync_socket_unittest.cc
index e346bae..f6c0aa8 100644
--- a/ipc/sync_socket_unittest.cc
+++ b/ipc/sync_socket_unittest.cc
@@ -57,8 +57,7 @@
 // messages from the client.
 class SyncSocketServerListener : public IPC::Listener {
  public:
-  SyncSocketServerListener() : chan_(NULL) {
-  }
+  SyncSocketServerListener() : chan_(nullptr) {}
 
   void Init(IPC::Channel* chan) {
     chan_ = chan;
diff --git a/jingle/glue/thread_wrapper_unittest.cc b/jingle/glue/thread_wrapper_unittest.cc
index 47c7ab0f..7d8fe9cc 100644
--- a/jingle/glue/thread_wrapper_unittest.cc
+++ b/jingle/glue/thread_wrapper_unittest.cc
@@ -80,9 +80,7 @@
   }
 
  protected:
-  ThreadWrapperTest()
-      : thread_(NULL) {
-  }
+  ThreadWrapperTest() : thread_(nullptr) {}
 
   void SetUp() override {
     JingleThreadWrapper::EnsureForCurrentMessageLoop();
diff --git a/jingle/notifier/listener/non_blocking_push_client_unittest.cc b/jingle/notifier/listener/non_blocking_push_client_unittest.cc
index acb7e3c..13f7b0e 100644
--- a/jingle/notifier/listener/non_blocking_push_client_unittest.cc
+++ b/jingle/notifier/listener/non_blocking_push_client_unittest.cc
@@ -26,7 +26,7 @@
 
 class NonBlockingPushClientTest : public testing::Test {
  protected:
-  NonBlockingPushClientTest() : fake_push_client_(NULL) {}
+  NonBlockingPushClientTest() : fake_push_client_(nullptr) {}
 
   ~NonBlockingPushClientTest() override {}
 
diff --git a/media/audio/audio_output_device.cc b/media/audio/audio_output_device.cc
index 92448e7..f451d73a 100644
--- a/media/audio/audio_output_device.cc
+++ b/media/audio/audio_output_device.cc
@@ -33,7 +33,7 @@
     const AudioSinkParameters& sink_params,
     base::TimeDelta authorization_timeout)
     : io_task_runner_(io_task_runner),
-      callback_(NULL),
+      callback_(nullptr),
       ipc_(std::move(ipc)),
       state_(IDLE),
       session_id_(sink_params.session_id),
diff --git a/media/audio/null_audio_sink.cc b/media/audio/null_audio_sink.cc
index 56d7c23b9..ceda2ae 100644
--- a/media/audio/null_audio_sink.cc
+++ b/media/audio/null_audio_sink.cc
@@ -18,7 +18,7 @@
     : initialized_(false),
       started_(false),
       playing_(false),
-      callback_(NULL),
+      callback_(nullptr),
       task_runner_(task_runner) {}
 
 NullAudioSink::~NullAudioSink() = default;
diff --git a/media/base/mime_util_internal.cc b/media/base/mime_util_internal.cc
index 3034781..e77f5d93 100644
--- a/media/base/mime_util_internal.cc
+++ b/media/base/mime_util_internal.cc
@@ -285,11 +285,10 @@
   const CodecSet wav_codecs{PCM};
   const CodecSet ogg_audio_codecs{FLAC, OPUS, VORBIS};
 
-#if !defined(OS_ANDROID)
-  CodecSet ogg_video_codecs{THEORA, VP8};
-#else
-  CodecSet ogg_video_codecs;
-#endif  // !defined(OS_ANDROID)
+  CodecSet ogg_video_codecs{VP8};
+#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
+  ogg_video_codecs.emplace(THEORA);
+#endif  // BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS)
 
   CodecSet ogg_codecs(ogg_audio_codecs);
   ogg_codecs.insert(ogg_video_codecs.begin(), ogg_video_codecs.end());
diff --git a/media/base/mime_util_unittest.cc b/media/base/mime_util_unittest.cc
index 3125845..819390fe1 100644
--- a/media/base/mime_util_unittest.cc
+++ b/media/base/mime_util_unittest.cc
@@ -148,11 +148,7 @@
 
   EXPECT_TRUE(IsSupportedMediaMimeType("audio/ogg"));
   EXPECT_TRUE(IsSupportedMediaMimeType("application/ogg"));
-#if defined(OS_ANDROID)
-  EXPECT_FALSE(IsSupportedMediaMimeType("video/ogg"));
-#else
   EXPECT_TRUE(IsSupportedMediaMimeType("video/ogg"));
-#endif  // OS_ANDROID
 
   EXPECT_EQ(kHlsSupported, IsSupportedMediaMimeType("application/x-mpegurl"));
   EXPECT_EQ(kHlsSupported, IsSupportedMediaMimeType("Application/X-MPEGURL"));
diff --git a/media/blink/webinbandtexttrack_impl.cc b/media/blink/webinbandtexttrack_impl.cc
index df182a7b..18fa8de 100644
--- a/media/blink/webinbandtexttrack_impl.cc
+++ b/media/blink/webinbandtexttrack_impl.cc
@@ -8,17 +8,15 @@
 
 namespace media {
 
-WebInbandTextTrackImpl::WebInbandTextTrackImpl(
-    Kind kind,
-    const blink::WebString& label,
-    const blink::WebString& language,
-    const blink::WebString& id)
-    : client_(NULL),
+WebInbandTextTrackImpl::WebInbandTextTrackImpl(Kind kind,
+                                               const blink::WebString& label,
+                                               const blink::WebString& language,
+                                               const blink::WebString& id)
+    : client_(nullptr),
       kind_(kind),
       label_(label),
       language_(language),
-      id_(id) {
-}
+      id_(id) {}
 
 WebInbandTextTrackImpl::~WebInbandTextTrackImpl() {
   DCHECK(!client_);
diff --git a/media/capture/video/chromeos/mojom/BUILD.gn b/media/capture/video/chromeos/mojom/BUILD.gn
index cb72cea..f98d89e 100644
--- a/media/capture/video/chromeos/mojom/BUILD.gn
+++ b/media/capture/video/chromeos/mojom/BUILD.gn
@@ -17,6 +17,7 @@
   deps = [
     "//components/chromeos_camera/common",
     "//media/capture/mojom:image_capture",
+    "//media/mojo/mojom",
     "//ui/gfx/geometry/mojom",
     "//ui/gfx/range/mojom",
   ]
diff --git a/media/cast/net/rtcp/rtcp_builder.cc b/media/cast/net/rtcp/rtcp_builder.cc
index aa296ba..a7fb6509 100644
--- a/media/cast/net/rtcp/rtcp_builder.cc
+++ b/media/cast/net/rtcp/rtcp_builder.cc
@@ -114,7 +114,7 @@
 }  // namespace
 
 RtcpBuilder::RtcpBuilder(uint32_t sending_ssrc)
-    : writer_(NULL, 0), local_ssrc_(sending_ssrc), ptr_of_length_(NULL) {}
+    : writer_(nullptr, 0), local_ssrc_(sending_ssrc), ptr_of_length_(nullptr) {}
 
 RtcpBuilder::~RtcpBuilder() = default;
 
@@ -127,7 +127,7 @@
         << "Packets must be a multiple of 32 bits long";
     *ptr_of_length_ = this_packet_length >> 10;
     *(ptr_of_length_ + 1) = (this_packet_length >> 2) & 0xFF;
-    ptr_of_length_ = NULL;
+    ptr_of_length_ = nullptr;
   }
 }
 
@@ -154,7 +154,7 @@
 PacketRef RtcpBuilder::Finish() {
   PatchLengthField();
   packet_->data.resize(kMaxIpPacketSize - writer_.remaining());
-  writer_ = base::BigEndianWriter(NULL, 0);
+  writer_ = base::BigEndianWriter(nullptr, 0);
   PacketRef ret = packet_;
   packet_.reset();
   return ret;
diff --git a/media/cast/net/rtcp/test_rtcp_packet_builder.cc b/media/cast/net/rtcp/test_rtcp_packet_builder.cc
index 8c00d8e..626ed742 100644
--- a/media/cast/net/rtcp/test_rtcp_packet_builder.cc
+++ b/media/cast/net/rtcp/test_rtcp_packet_builder.cc
@@ -11,9 +11,9 @@
 namespace cast {
 
 TestRtcpPacketBuilder::TestRtcpPacketBuilder()
-    : ptr_of_length_(NULL),
+    : ptr_of_length_(nullptr),
       big_endian_writer_(reinterpret_cast<char*>(buffer_), kMaxIpPacketSize),
-      big_endian_reader_(NULL, 0) {}
+      big_endian_reader_(nullptr, 0) {}
 
 void TestRtcpPacketBuilder::AddSr(uint32_t remote_ssrc,
                                   int number_of_report_blocks) {
@@ -255,7 +255,7 @@
         << "Packets must be a multiple of 32 bits long";
     *ptr_of_length_ = this_packet_length >> 10;
     *(ptr_of_length_ + 1) = (this_packet_length >> 2) & 0xFF;
-    ptr_of_length_ = NULL;
+    ptr_of_length_ = nullptr;
   }
 }
 
diff --git a/media/cast/test/fake_media_source.cc b/media/cast/test/fake_media_source.cc
index 287ab08..3e5ad31 100644
--- a/media/cast/test/fake_media_source.cc
+++ b/media/cast/test/fake_media_source.cc
@@ -87,7 +87,7 @@
       clock_(clock),
       audio_frame_count_(0),
       video_frame_count_(0),
-      av_format_context_(NULL),
+      av_format_context_(nullptr),
       audio_stream_index_(-1),
       playback_rate_(1.0),
       video_stream_index_(-1),
diff --git a/media/cast/test/simulator.cc b/media/cast/test/simulator.cc
index 621abcc..167498c 100644
--- a/media/cast/test/simulator.cc
+++ b/media/cast/test/simulator.cc
@@ -128,7 +128,7 @@
 }
 
 struct PacketProxy {
-  PacketProxy() : receiver(NULL) {}
+  PacketProxy() : receiver(nullptr) {}
   void ReceivePacket(std::unique_ptr<Packet> packet) {
     if (receiver)
       receiver->ReceivePacket(std::move(packet));
diff --git a/media/cast/test/utility/udp_proxy.cc b/media/cast/test/utility/udp_proxy.cc
index 408d76b8..e228a79a 100644
--- a/media/cast/test/utility/udp_proxy.cc
+++ b/media/cast/test/utility/udp_proxy.cc
@@ -348,7 +348,7 @@
 class InterruptedPoissonProcess::InternalBuffer : public PacketPipe {
  public:
   InternalBuffer(base::WeakPtr<InterruptedPoissonProcess> ipp, size_t size)
-      : ipp_(ipp), stored_size_(0), stored_limit_(size), clock_(NULL) {}
+      : ipp_(ipp), stored_size_(0), stored_limit_(size), clock_(nullptr) {}
 
   void Send(std::unique_ptr<Packet> packet) final {
     // Drop if buffer is full.
@@ -409,7 +409,7 @@
     double coef_burstiness,
     double coef_variance,
     uint32_t rand_seed)
-    : clock_(NULL),
+    : clock_(nullptr),
       average_rates_(average_rates),
       coef_burstiness_(coef_burstiness),
       coef_variance_(coef_variance),
diff --git a/media/formats/common/offset_byte_queue.cc b/media/formats/common/offset_byte_queue.cc
index b355e1a..e898a65a 100644
--- a/media/formats/common/offset_byte_queue.cc
+++ b/media/formats/common/offset_byte_queue.cc
@@ -8,12 +8,12 @@
 
 namespace media {
 
-OffsetByteQueue::OffsetByteQueue() : buf_(NULL), size_(0), head_(0) {}
+OffsetByteQueue::OffsetByteQueue() : buf_(nullptr), size_(0), head_(0) {}
 OffsetByteQueue::~OffsetByteQueue() = default;
 
 void OffsetByteQueue::Reset() {
   queue_.Reset();
-  buf_ = NULL;
+  buf_ = nullptr;
   size_ = 0;
   head_ = 0;
 }
@@ -25,7 +25,7 @@
 }
 
 void OffsetByteQueue::Peek(const uint8_t** buf, int* size) {
-  *buf = size_ > 0 ? buf_ : NULL;
+  *buf = size_ > 0 ? buf_ : nullptr;
   *size = size_;
 }
 
@@ -38,7 +38,7 @@
 void OffsetByteQueue::PeekAt(int64_t offset, const uint8_t** buf, int* size) {
   DCHECK(offset >= head());
   if (offset < head() || offset >= tail()) {
-    *buf = NULL;
+    *buf = nullptr;
     *size = 0;
     return;
   }
diff --git a/media/gpu/windows/d3d11_vp9_accelerator.cc b/media/gpu/windows/d3d11_vp9_accelerator.cc
index 852b5fd8..3be9252 100644
--- a/media/gpu/windows/d3d11_vp9_accelerator.cc
+++ b/media/gpu/windows/d3d11_vp9_accelerator.cc
@@ -101,7 +101,6 @@
   COPY_PARAM(frame_context_idx);
   COPY_PARAM(reset_frame_context);
   COPY_PARAM(allow_high_precision_mv);
-  COPY_PARAM(refresh_frame_context);
   COPY_PARAM(frame_parallel_decoding_mode);
   COPY_PARAM(intra_only);
   COPY_PARAM(frame_context_idx);
@@ -125,6 +124,18 @@
   SET_PARAM(log2_tile_rows, tile_rows_log2);
 #undef COPY_PARAM
 #undef SET_PARAM
+
+  // This is taken, approximately, from libvpx.
+  gfx::Size this_frame_size(pic.frame_hdr->frame_width,
+                            pic.frame_hdr->frame_height);
+  pic_params->use_prev_in_find_mv_refs = last_frame_size_ == this_frame_size &&
+                                         !pic.frame_hdr->error_resilient_mode &&
+                                         !pic.frame_hdr->intra_only &&
+                                         last_show_frame_;
+
+  // TODO(liberato): So, uh, do we ever need to reset this?
+  last_frame_size_ = this_frame_size;
+  last_show_frame_ = pic.frame_hdr->show_frame;
 }
 
 void D3D11VP9Accelerator::CopyReferenceFrames(
diff --git a/media/gpu/windows/d3d11_vp9_accelerator.h b/media/gpu/windows/d3d11_vp9_accelerator.h
index a79fdac..dc262d6 100644
--- a/media/gpu/windows/d3d11_vp9_accelerator.h
+++ b/media/gpu/windows/d3d11_vp9_accelerator.h
@@ -76,6 +76,10 @@
   ComD3D11VideoDevice video_device_;
   std::unique_ptr<VideoContextWrapper> video_context_;
 
+  // Used to set |use_prev_in_find_mv_refs| properly.
+  gfx::Size last_frame_size_;
+  bool last_show_frame_ = false;
+
   DISALLOW_COPY_AND_ASSIGN(D3D11VP9Accelerator);
 };
 
diff --git a/media/mojo/mojom/BUILD.gn b/media/mojo/mojom/BUILD.gn
index f86298e..c71a429 100644
--- a/media/mojo/mojom/BUILD.gn
+++ b/media/mojo/mojom/BUILD.gn
@@ -62,6 +62,7 @@
     "//gpu/ipc/common:interfaces",
     "//media/learning/mojo/public/mojom",
     "//mojo/public/mojom/base",
+    "//services/network/public/mojom",
     "//services/service_manager/public/mojom",
     "//ui/gfx/geometry/mojom",
     "//ui/gfx/mojom",
diff --git a/media/mojo/mojom/speech_recognition_service.mojom b/media/mojo/mojom/speech_recognition_service.mojom
index 6835c22c..85d517ef1 100644
--- a/media/mojo/mojom/speech_recognition_service.mojom
+++ b/media/mojo/mojom/speech_recognition_service.mojom
@@ -5,15 +5,18 @@
 module media.mojom;
 
 import "media/mojo/mojom/media_types.mojom";
+import "services/network/public/mojom/url_loader_factory.mojom";
 
 // The main interface a client uses to interact with a speech recognition
 // service process. Every renderer can own one or more
 // Remote<SpeechRecognitionContext>, with the receiver bound through the
-// BrowserInterfaceBroker.
+// BrowserInterfaceBroker. Returns a flag indicating whether multichannel
+// audio is supported by the speech recognition service.
 interface SpeechRecognitionContext {
   // Bind the recognizers to the speech recognition service.
   BindRecognizer(pending_receiver<SpeechRecognitionRecognizer> receiver,
-                 pending_remote<SpeechRecognitionRecognizerClient> client);
+                 pending_remote<SpeechRecognitionRecognizerClient> client)
+                 => (bool is_multichannel_supported);
 };
 
 // The main interface to a speech secognition service process.
@@ -22,6 +25,23 @@
 interface SpeechRecognitionService {
   // Bind the context to a new instance of the speech recognition.
   BindContext(pending_receiver<SpeechRecognitionContext> context);
+
+  // Sets the URL loader factory used to create network requests.
+  SetUrlLoaderFactory(
+      pending_remote<network.mojom.URLLoaderFactory> url_loader_factory);
+
+  // Binds the speech recognition service client used by the speech
+  // recognition service to send messages back to the client.
+  BindSpeechRecognitionServiceClient(
+      pending_remote<SpeechRecognitionServiceClient> client);
+};
+
+// The interface used to send messages from the speech recognition service
+// back to the consumer of the service.
+interface SpeechRecognitionServiceClient {
+  // Executed when the network service crashes, prompting the client to
+  // reset the URL loader factory.
+  OnNetworkServiceDisconnect();
 };
 
 // The interface used to pass raw audio from the renderer to the speech
diff --git a/media/parsers/vp8_bool_decoder.cc b/media/parsers/vp8_bool_decoder.cc
index 1760773..fb715e5 100644
--- a/media/parsers/vp8_bool_decoder.cc
+++ b/media/parsers/vp8_bool_decoder.cc
@@ -82,15 +82,14 @@
 };
 
 Vp8BoolDecoder::Vp8BoolDecoder()
-    : user_buffer_(NULL),
-      user_buffer_end_(NULL),
+    : user_buffer_(nullptr),
+      user_buffer_end_(nullptr),
       value_(0),
       count_(-8),
-      range_(255) {
-}
+      range_(255) {}
 
 bool Vp8BoolDecoder::Initialize(const uint8_t* data, size_t size) {
-  if (data == NULL || size == 0)
+  if (data == nullptr || size == 0)
     return false;
   user_buffer_start_ = data;
   user_buffer_ = data;
@@ -102,7 +101,7 @@
 }
 
 void Vp8BoolDecoder::FillDecoder() {
-  DCHECK(user_buffer_ != NULL);
+  DCHECK(user_buffer_ != nullptr);
   int shift = VP8_BD_VALUE_BIT - CHAR_BIT - (count_ + CHAR_BIT);
   size_t bytes_left = user_buffer_end_ - user_buffer_;
   size_t bits_left = bytes_left * CHAR_BIT;
diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc
index 31c033f..051d203 100644
--- a/media/renderers/renderer_impl.cc
+++ b/media/renderers/renderer_impl.cc
@@ -93,7 +93,7 @@
       video_renderer_(std::move(video_renderer)),
       current_audio_stream_(nullptr),
       current_video_stream_(nullptr),
-      time_source_(NULL),
+      time_source_(nullptr),
       time_ticking_(false),
       playback_rate_(0.0),
       audio_buffering_state_(BUFFERING_HAVE_NOTHING),
diff --git a/media/video/fake_video_encode_accelerator.cc b/media/video/fake_video_encode_accelerator.cc
index 783f8f0b..8400e490 100644
--- a/media/video/fake_video_encode_accelerator.cc
+++ b/media/video/fake_video_encode_accelerator.cc
@@ -17,7 +17,7 @@
     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
     : task_runner_(task_runner),
       will_initialization_succeed_(true),
-      client_(NULL),
+      client_(nullptr),
       next_frame_is_first_frame_(true) {}
 
 FakeVideoEncodeAccelerator::~FakeVideoEncodeAccelerator() {
diff --git a/media/video/h264_bit_reader.cc b/media/video/h264_bit_reader.cc
index 0fe2270..45c3d75c 100644
--- a/media/video/h264_bit_reader.cc
+++ b/media/video/h264_bit_reader.cc
@@ -8,7 +8,7 @@
 namespace media {
 
 H264BitReader::H264BitReader()
-    : data_(NULL),
+    : data_(nullptr),
       bytes_left_(0),
       curr_byte_(0),
       num_remaining_bits_in_curr_byte_(0),
diff --git a/mojo/public/js/ts/bindings/tests/BUILD.gn b/mojo/public/js/ts/bindings/tests/BUILD.gn
index 75add07..185cf37 100644
--- a/mojo/public/js/ts/bindings/tests/BUILD.gn
+++ b/mojo/public/js/ts/bindings/tests/BUILD.gn
@@ -17,6 +17,7 @@
     "export4.test-mojom",
     "import.test-mojom",
     "module.test-mojom",
+    "structs.test-mojom",
   ]
   use_typescript_sources = true
 }
diff --git a/mojo/public/js/ts/bindings/tests/structs.test-mojom b/mojo/public/js/ts/bindings/tests/structs.test-mojom
new file mode 100644
index 0000000..ca5956d
--- /dev/null
+++ b/mojo/public/js/ts/bindings/tests/structs.test-mojom
@@ -0,0 +1,31 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module mojo.tstest;
+
+struct EmptyStruct {
+};
+
+struct IntStruct {
+  int8 value;
+};
+
+struct BoolStruct {
+  bool value;
+};
+
+struct NoDefaultValuesStruct {
+  bool bool_value;
+  int8 int8_value;
+  uint8 uint8_value;
+  int16 int16_value;
+  uint16 uint16_value;
+  int32 int32_value;
+  uint32 uint32_value;
+  int64 int64_value;
+  uint64 uint64_value;
+  float float_value;
+  double double_value;
+  string string_value;
+};
diff --git a/mojo/public/tools/bindings/generators/mojom_ts_generator.py b/mojo/public/tools/bindings/generators/mojom_ts_generator.py
index e375399..3c8b9eb 100644
--- a/mojo/public/tools/bindings/generators/mojom_ts_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_ts_generator.py
@@ -39,6 +39,9 @@
     return '.'.join(generator.ToCamel(word, lower_initial=True)
                         for word in mojom_namespace.split('.'))
 
+  def StylizeField(self, mojom_name):
+    return generator.ToCamel(mojom_name, lower_initial=True)
+
   def StylizeConstant(self, mojom_name):
     return generator.ToUpperSnakeCase(mojom_name)
 
@@ -46,9 +49,10 @@
 class Generator(generator.Generator):
   def _GetParameters(self, use_es_modules=False):
     return {
-      "module": self.module,
-      "use_es_modules": use_es_modules,
-      "enums": self.module.enums,
+        "module": self.module,
+        "use_es_modules": use_es_modules,
+        "enums": self.module.enums,
+        "structs": self.module.structs,
     }
 
   @staticmethod
diff --git a/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl b/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl
index d219a88..6f959b6b 100644
--- a/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/ts_templates/module_definition.tmpl
@@ -1,4 +1,4 @@
-{%- if not use_es_modules %}
+{%- if not use_es_modules -%}
 namespace {{module.namespace}} {
 {% endif %}
 {#--- Constants #}
@@ -8,7 +8,7 @@
 {%- endfor %}
 
 {#--- Enums #}
-{% for enum in enums %}
+{%- for enum in enums %}
 export enum {{enum.name}} {
 {%- for field in enum.fields %}
   {{field.name}} = {{field.numeric_value}},
@@ -22,6 +22,15 @@
 }
 {% endfor %}
 
+{#--- Structs #}
+{%- for struct in structs %}
+export interface {{struct.name}} {
+{%- for packed_field in struct.packed.packed_fields %}
+    {{packed_field.field.name}}: {{packed_field.field.kind|typescript_type_with_nullability}};
+{%- endfor %}
+}
+{% endfor %}
+
 {%- if not use_es_modules %}
 } // namespace {{module.namespace}}
 {% endif %}
diff --git a/net/BUILD.gn b/net/BUILD.gn
index c5206a3c..f12fb41 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -542,6 +542,8 @@
       "cookies/canonical_cookie.h",
       "cookies/cookie_access_delegate.cc",
       "cookies/cookie_access_delegate.h",
+      "cookies/cookie_access_result.cc",
+      "cookies/cookie_access_result.h",
       "cookies/cookie_change_dispatcher.cc",
       "cookies/cookie_change_dispatcher.h",
       "cookies/cookie_constants.cc",
diff --git a/net/base/features.cc b/net/base/features.cc
index b4ac15a..50f3f33f 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -43,6 +43,9 @@
 const base::FeatureParam<bool> kDnsHttpssvcControlDomainWildcard{
     &kDnsHttpssvc, "DnsHttpssvcControlDomainWildcard", false};
 
+const base::Feature kAvoidH2Reprioritization{"AvoidH2Reprioritization",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
 namespace dns_httpssvc_experiment {
 namespace {
 bool ListContainsDomain(const std::string& domain_list,
diff --git a/net/base/features.h b/net/base/features.h
index aa2081eb6..8b3c0798 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -29,6 +29,9 @@
 // cause us to upgrade the URL to HTTPS and/or to attempt QUIC.
 NET_EXPORT extern const base::Feature kDnsHttpssvc;
 
+// Disable H2 reprioritization, in order to measure its impact.
+NET_EXPORT extern const base::Feature kAvoidH2Reprioritization;
+
 // Determine which kind of record should be queried: HTTPSSVC or INTEGRITY. No
 // more than one of these feature parameters should be enabled at once. In the
 // event that both are enabled, |kDnsHttpssvcUseIntegrity| takes priority, and
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index a4c7aec..ef98fcdc 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -570,7 +570,7 @@
   return cookie_util::IsDomainMatch(domain_, host);
 }
 
-CookieInclusionStatus CanonicalCookie::IncludeForRequestURL(
+CookieAccessResult CanonicalCookie::IncludeForRequestURL(
     const GURL& url,
     const CookieOptions& options,
     CookieAccessSemantics access_semantics) const {
@@ -689,7 +689,7 @@
   }
 
   // TODO(chlily): Log metrics.
-  return status;
+  return CookieAccessResult(effective_same_site, status);
 }
 
 CookieInclusionStatus CanonicalCookie::IsSetPermittedInContext(
@@ -856,10 +856,10 @@
 
 // static
 std::string CanonicalCookie::BuildCookieLine(
-    const CookieStatusList& cookie_status_list) {
+    const CookieAccessResultList& cookie_access_result_list) {
   std::string cookie_line;
-  for (const auto& cookie_with_status : cookie_status_list) {
-    const CanonicalCookie& cookie = cookie_with_status.cookie;
+  for (const auto& cookie_with_access_result : cookie_access_result_list) {
+    const CanonicalCookie& cookie = cookie_with_access_result.cookie;
     AppendCookieLineEntry(cookie, &cookie_line);
   }
   return cookie_line;
diff --git a/net/cookies/canonical_cookie.h b/net/cookies/canonical_cookie.h
index 2e7f982..aa538085 100644
--- a/net/cookies/canonical_cookie.h
+++ b/net/cookies/canonical_cookie.h
@@ -14,6 +14,7 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "net/base/net_export.h"
+#include "net/cookies/cookie_access_result.h"
 #include "net/cookies/cookie_constants.h"
 #include "net/cookies/cookie_inclusion_status.h"
 #include "net/cookies/cookie_options.h"
@@ -26,11 +27,13 @@
 class CanonicalCookie;
 
 struct CookieWithStatus;
+struct CookieWithAccessResult;
 struct CookieAndLineWithStatus;
 
 using CookieList = std::vector<CanonicalCookie>;
 using CookieStatusList = std::vector<CookieWithStatus>;
 using CookieAndLineStatusList = std::vector<CookieAndLineWithStatus>;
+using CookieAccessResultList = std::vector<CookieWithAccessResult>;
 
 class NET_EXPORT CanonicalCookie {
  public:
@@ -228,7 +231,7 @@
   // request |url| using the CookieInclusionStatus enum. HTTP only cookies can
   // be filter by using appropriate cookie |options|. PLEASE NOTE that this
   // method does not check whether a cookie is expired or not!
-  CookieInclusionStatus IncludeForRequestURL(
+  CookieAccessResult IncludeForRequestURL(
       const GURL& url,
       const CookieOptions& options,
       CookieAccessSemantics access_semantics =
@@ -294,8 +297,9 @@
   // by |cookies|. The string is built in the same order as the given list.
   static std::string BuildCookieLine(const CookieList& cookies);
 
-  // Same as above but takes a CookieStatusList (ignores the statuses).
-  static std::string BuildCookieLine(const CookieStatusList& cookies);
+  // Same as above but takes a CookieAccessResultList
+  // (ignores the access result).
+  static std::string BuildCookieLine(const CookieAccessResultList& cookies);
 
  private:
   FRIEND_TEST_ALL_PREFIXES(CanonicalCookieTest, TestPrefixHistograms);
@@ -388,6 +392,11 @@
   CookieInclusionStatus status;
 };
 
+struct CookieWithAccessResult {
+  CanonicalCookie cookie;
+  CookieAccessResult access_result;
+};
+
 }  // namespace net
 
 #endif  // NET_COOKIES_CANONICAL_COOKIE_H_
diff --git a/net/cookies/canonical_cookie_unittest.cc b/net/cookies/canonical_cookie_unittest.cc
index 1dca473..77465c8 100644
--- a/net/cookies/canonical_cookie_unittest.cc
+++ b/net/cookies/canonical_cookie_unittest.cc
@@ -656,22 +656,22 @@
 
   std::unique_ptr<CanonicalCookie> cookie(
       CanonicalCookie::Create(url, "A=2", creation_time, server_time));
-  EXPECT_TRUE(cookie->IncludeForRequestURL(url, options).IsInclude());
+  EXPECT_TRUE(cookie->IncludeForRequestURL(url, options).status.IsInclude());
   EXPECT_TRUE(cookie
                   ->IncludeForRequestURL(GURL("http://www.example.com/foo/bar"),
                                          options)
-                  .IsInclude());
+                  .status.IsInclude());
   EXPECT_TRUE(cookie
                   ->IncludeForRequestURL(
                       GURL("https://www.example.com/foo/bar"), options)
-                  .IsInclude());
+                  .status.IsInclude());
   EXPECT_TRUE(
       cookie->IncludeForRequestURL(GURL("https://sub.example.com"), options)
-          .HasExactlyExclusionReasonsForTesting(
+          .status.HasExactlyExclusionReasonsForTesting(
               {CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH}));
   EXPECT_TRUE(
       cookie->IncludeForRequestURL(GURL("https://sub.www.example.com"), options)
-          .HasExactlyExclusionReasonsForTesting(
+          .status.HasExactlyExclusionReasonsForTesting(
               {CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH}));
 
   // Test that cookie with a cookie path that does not match the url path are
@@ -679,22 +679,23 @@
   cookie = CanonicalCookie::Create(url, "A=2; Path=/foo/bar", creation_time,
                                    server_time);
   EXPECT_TRUE(cookie->IncludeForRequestURL(url, options)
-                  .HasExactlyExclusionReasonsForTesting(
+                  .status.HasExactlyExclusionReasonsForTesting(
                       {CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
   EXPECT_TRUE(
       cookie
           ->IncludeForRequestURL(
               GURL("http://www.example.com/foo/bar/index.html"), options)
-          .IsInclude());
+          .status.IsInclude());
 
   // Test that a secure cookie is not included for a non secure URL.
   GURL secure_url("https://www.example.com");
   cookie = CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
                                    server_time);
   EXPECT_TRUE(cookie->IsSecure());
-  EXPECT_TRUE(cookie->IncludeForRequestURL(secure_url, options).IsInclude());
+  EXPECT_TRUE(
+      cookie->IncludeForRequestURL(secure_url, options).status.IsInclude());
   EXPECT_TRUE(cookie->IncludeForRequestURL(url, options)
-                  .HasExactlyExclusionReasonsForTesting(
+                  .status.HasExactlyExclusionReasonsForTesting(
                       {CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 
   // Test that http only cookies are only included if the include httponly flag
@@ -703,10 +704,10 @@
   cookie =
       CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time);
   EXPECT_TRUE(cookie->IsHttpOnly());
-  EXPECT_TRUE(cookie->IncludeForRequestURL(url, options).IsInclude());
+  EXPECT_TRUE(cookie->IncludeForRequestURL(url, options).status.IsInclude());
   options.set_exclude_httponly();
   EXPECT_TRUE(cookie->IncludeForRequestURL(url, options)
-                  .HasExactlyExclusionReasonsForTesting(
+                  .status.HasExactlyExclusionReasonsForTesting(
                       {CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 }
 
@@ -737,16 +738,16 @@
     std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
         url, test.cookie_line, creation_time, base::nullopt /* server_time */);
     EXPECT_EQ(test.expected_samesite, cookie->SameSite());
-    EXPECT_EQ(test.expected_effective_samesite,
-              cookie->GetEffectiveSameSiteForTesting(access_semantics));
 
     CookieOptions request_options;
     request_options.set_same_site_cookie_context(
         test.request_options_samesite_context);
+    net::CookieAccessResult access_result =
+        cookie->IncludeForRequestURL(url, request_options, access_semantics);
 
-    EXPECT_EQ(
-        test.expected_inclusion_status,
-        cookie->IncludeForRequestURL(url, request_options, access_semantics));
+    EXPECT_EQ(test.expected_inclusion_status, access_result.status);
+    EXPECT_EQ(test.expected_effective_samesite,
+              access_result.effective_same_site);
   }
 }
 
@@ -1016,17 +1017,17 @@
     EXPECT_TRUE(
         cookie
             ->IncludeForRequestURL(url, options, CookieAccessSemantics::UNKNOWN)
-            .HasExactlyExclusionReasonsForTesting(
+            .status.HasExactlyExclusionReasonsForTesting(
                 {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
     EXPECT_TRUE(
         cookie
             ->IncludeForRequestURL(url, options, CookieAccessSemantics::LEGACY)
-            .IsInclude());
+            .status.IsInclude());
     EXPECT_TRUE(
         cookie
             ->IncludeForRequestURL(url, options,
                                    CookieAccessSemantics::NONLEGACY)
-            .HasExactlyExclusionReasonsForTesting(
+            .status.HasExactlyExclusionReasonsForTesting(
                 {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
   }
   // Features off:
@@ -1041,17 +1042,17 @@
     EXPECT_TRUE(
         cookie
             ->IncludeForRequestURL(url, options, CookieAccessSemantics::UNKNOWN)
-            .IsInclude());
+            .status.IsInclude());
     EXPECT_TRUE(
         cookie
             ->IncludeForRequestURL(url, options, CookieAccessSemantics::LEGACY)
-            .IsInclude());
+            .status.IsInclude());
     // If the semantics is Nonlegacy, only reject the cookie if the
     // SameSite=None-must-be-Secure feature is enabled.
     EXPECT_TRUE(cookie
                     ->IncludeForRequestURL(url, options,
                                            CookieAccessSemantics::NONLEGACY)
-                    .IsInclude());
+                    .status.IsInclude());
   }
 }
 
@@ -1072,7 +1073,7 @@
       base::Time(), true /* secure */, true /* httponly */,
       CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT);
   EXPECT_TRUE(cookie1.IncludeForRequestURL(url, options)
-                  .HasExactlyExclusionReasonsForTesting(
+                  .status.HasExactlyExclusionReasonsForTesting(
                       {CookieInclusionStatus::EXCLUDE_HTTP_ONLY,
                        CookieInclusionStatus::EXCLUDE_SECURE_ONLY,
                        CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH,
diff --git a/net/cookies/cookie_access_result.cc b/net/cookies/cookie_access_result.cc
new file mode 100644
index 0000000..182dc53f
--- /dev/null
+++ b/net/cookies/cookie_access_result.cc
@@ -0,0 +1,25 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cookies/cookie_access_result.h"
+
+namespace net {
+
+CookieAccessResult::CookieAccessResult() = default;
+
+CookieAccessResult::CookieAccessResult(
+    CookieEffectiveSameSite effective_same_site,
+    CookieInclusionStatus status)
+    : effective_same_site(effective_same_site), status(status) {}
+
+CookieAccessResult::CookieAccessResult(const CookieAccessResult&) = default;
+
+CookieAccessResult& CookieAccessResult::operator=(
+    const CookieAccessResult& cookie_access_result) = default;
+
+CookieAccessResult::CookieAccessResult(CookieAccessResult&&) = default;
+
+CookieAccessResult::~CookieAccessResult() = default;
+
+}  // namespace net
diff --git a/net/cookies/cookie_access_result.h b/net/cookies/cookie_access_result.h
new file mode 100644
index 0000000..a21305b
--- /dev/null
+++ b/net/cookies/cookie_access_result.h
@@ -0,0 +1,34 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_COOKIES_COOKIE_ACCESS_RESULT_H_
+#define NET_COOKIES_COOKIE_ACCESS_RESULT_H_
+
+#include "net/base/net_export.h"
+#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_inclusion_status.h"
+
+namespace net {
+
+struct NET_EXPORT CookieAccessResult {
+  CookieAccessResult();
+  CookieAccessResult(CookieEffectiveSameSite effective_same_site,
+                     CookieInclusionStatus status);
+
+  CookieAccessResult(const CookieAccessResult& cookie_access_result);
+
+  CookieAccessResult& operator=(const CookieAccessResult& cookie_access_result);
+
+  CookieAccessResult(CookieAccessResult&& cookie_access_result);
+
+  ~CookieAccessResult();
+
+  CookieEffectiveSameSite effective_same_site =
+      CookieEffectiveSameSite::LAX_MODE;
+  CookieInclusionStatus status;
+};
+
+}  // namespace net
+
+#endif  // NET_COOKIES_COOKIE_ACCESS_RESULT_H_
diff --git a/net/cookies/cookie_deletion_info.cc b/net/cookies/cookie_deletion_info.cc
index b451dc2..6429510e8 100644
--- a/net/cookies/cookie_deletion_info.cc
+++ b/net/cookies/cookie_deletion_info.cc
@@ -116,7 +116,7 @@
       !cookie
            .IncludeForRequestURL(url.value(), CookieOptions::MakeAllInclusive(),
                                  access_semantics)
-           .IsInclude()) {
+           .status.IsInclude()) {
     return false;
   }
 
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index 0429bd62..477b47a7 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -581,8 +581,8 @@
                                              GetCookieListCallback callback) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
-  CookieStatusList included_cookies;
-  CookieStatusList excluded_cookies;
+  CookieAccessResultList included_cookies;
+  CookieAccessResultList excluded_cookies;
   if (HasCookieableScheme(url)) {
     std::vector<CanonicalCookie*> cookie_ptrs;
     FindCookiesForRegistryControlledHost(url, &cookie_ptrs);
@@ -953,8 +953,8 @@
     const GURL url,
     const CookieOptions options,
     std::vector<CanonicalCookie*>* cookie_ptrs,
-    CookieStatusList* included_cookies,
-    CookieStatusList* excluded_cookies) {
+    CookieAccessResultList* included_cookies,
+    CookieAccessResultList* excluded_cookies) {
   DCHECK(thread_checker_.CalledOnValidThread());
 
   // Probe to save statistics relatively frequently.  We do it here rather
@@ -968,12 +968,12 @@
     // Filter out cookies that should not be included for a request to the
     // given |url|. HTTP only cookies are filtered depending on the passed
     // cookie |options|.
-    CookieInclusionStatus status = (*it)->IncludeForRequestURL(
+    CookieAccessResult access_result = (*it)->IncludeForRequestURL(
         url, options, GetAccessSemanticsForCookieGet(**it));
 
-    if (!status.IsInclude()) {
+    if (!access_result.status.IsInclude()) {
       if (options.return_excluded_cookies())
-        excluded_cookies->push_back({**it, status});
+        excluded_cookies->push_back({**it, access_result});
       continue;
     }
 
@@ -982,7 +982,7 @@
 
     MaybeRecordCookieAccessWithOptions(**it, options, false);
 
-    included_cookies->push_back({**it, status});
+    included_cookies->push_back({**it, access_result});
   }
 }
 
diff --git a/net/cookies/cookie_monster.h b/net/cookies/cookie_monster.h
index 0e4fa9e20..9908e6f8 100644
--- a/net/cookies/cookie_monster.h
+++ b/net/cookies/cookie_monster.h
@@ -402,8 +402,8 @@
   void FilterCookiesWithOptions(const GURL url,
                                 const CookieOptions options,
                                 std::vector<CanonicalCookie*>* cookie_ptrs,
-                                CookieStatusList* included_cookies,
-                                CookieStatusList* excluded_cookies);
+                                CookieAccessResultList* included_cookies,
+                                CookieAccessResultList* excluded_cookies);
 
   // Possibly delete an existing cookie equivalent to |cookie_being_set| (same
   // path, domain, and name).
diff --git a/net/cookies/cookie_monster_change_dispatcher.cc b/net/cookies/cookie_monster_change_dispatcher.cc
index 28cfe347..6bd731f4 100644
--- a/net/cookies/cookie_monster_change_dispatcher.cc
+++ b/net/cookies/cookie_monster_change_dispatcher.cc
@@ -61,7 +61,7 @@
       !cookie
            .IncludeForRequestURL(url_, CookieOptions::MakeAllInclusive(),
                                  change.access_semantics)
-           .IsInclude()) {
+           .status.IsInclude()) {
     return;
   }
 
diff --git a/net/cookies/cookie_monster_perftest.cc b/net/cookies/cookie_monster_perftest.cc
index 3eeef5c..96d16f5 100644
--- a/net/cookies/cookie_monster_perftest.cc
+++ b/net/cookies/cookie_monster_perftest.cc
@@ -123,9 +123,9 @@
   }
 
  private:
-  void Run(const CookieStatusList& cookie_list,
-           const CookieStatusList& excluded_cookies) {
-    cookie_list_ = cookie_util::StripStatuses(cookie_list);
+  void Run(const CookieAccessResultList& cookie_list,
+           const CookieAccessResultList& excluded_cookies) {
+    cookie_list_ = cookie_util::StripAccessResults(cookie_list);
     CookieTestCallback::Run();
   }
   CookieList cookie_list_;
diff --git a/net/cookies/cookie_monster_unittest.cc b/net/cookies/cookie_monster_unittest.cc
index c4d874c..fc83d6a 100644
--- a/net/cookies/cookie_monster_unittest.cc
+++ b/net/cookies/cookie_monster_unittest.cc
@@ -135,7 +135,7 @@
     return callback.cookies();
   }
 
-  CookieStatusList GetExcludedCookiesForURLWithOptions(
+  CookieAccessResultList GetExcludedCookiesForURLWithOptions(
       CookieMonster* cm,
       const GURL& url,
       const CookieOptions& options) {
@@ -1236,25 +1236,26 @@
   base::RunLoop run_loop;
   cookie_monster_->GetCookieListWithOptionsAsync(
       http_www_foo_.url(), CookieOptions::MakeAllInclusive(),
-      base::BindLambdaForTesting([&](const CookieStatusList& cookies,
-                                     const CookieStatusList& excluded_list) {
-        // This should complete before the set.
-        get_cookie_list_callback_was_run = true;
-        EXPECT_FALSE(set_cookies_callback.was_run());
-        EXPECT_THAT(cookies, MatchesCookieLine("X=1"));
-        // Can't use TakeCommandSummary here since ExecuteLoads is walking
-        // through the data it takes.
-        EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ",
-                  CommandSummary(persistent_store_->commands()));
+      base::BindLambdaForTesting(
+          [&](const CookieAccessResultList& cookies,
+              const CookieAccessResultList& excluded_list) {
+            // This should complete before the set.
+            get_cookie_list_callback_was_run = true;
+            EXPECT_FALSE(set_cookies_callback.was_run());
+            EXPECT_THAT(cookies, MatchesCookieLine("X=1"));
+            // Can't use TakeCommandSummary here since ExecuteLoads is walking
+            // through the data it takes.
+            EXPECT_EQ("LOAD; LOAD_FOR_KEY:foo.com; ",
+                      CommandSummary(persistent_store_->commands()));
 
-        // Queue up a second get. It should see the result of the set queued
-        // before it.
-        cookie_monster_->GetCookieListWithOptionsAsync(
-            http_www_foo_.url(), CookieOptions::MakeAllInclusive(),
-            get_cookie_list_callback_deferred.MakeCallback());
+            // Queue up a second get. It should see the result of the set queued
+            // before it.
+            cookie_monster_->GetCookieListWithOptionsAsync(
+                http_www_foo_.url(), CookieOptions::MakeAllInclusive(),
+                get_cookie_list_callback_deferred.MakeCallback());
 
-        run_loop.Quit();
-      }));
+            run_loop.Quit();
+          }));
 
   cookie_monster_->SetCanonicalCookieAsync(
       CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
@@ -1617,7 +1618,7 @@
   CookieOptions do_not_return_excluded;
   do_not_return_excluded.unset_return_excluded_cookies();
 
-  CookieStatusList excluded_cookies = GetExcludedCookiesForURLWithOptions(
+  CookieAccessResultList excluded_cookies = GetExcludedCookiesForURLWithOptions(
       cm.get(), http_www_foo_.url(), do_not_return_excluded);
   auto iter = excluded_cookies.begin();
 
@@ -1631,7 +1632,7 @@
   ASSERT_TRUE(iter != excluded_cookies.end());
   EXPECT_EQ(http_www_foo_.Format(".%D"), iter->cookie.Domain());
   EXPECT_EQ("E", iter->cookie.Name());
-  EXPECT_TRUE(iter->status.HasExactlyExclusionReasonsForTesting(
+  EXPECT_TRUE(iter->access_result.status.HasExactlyExclusionReasonsForTesting(
       {CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 
   ASSERT_TRUE(++iter == excluded_cookies.end());
@@ -1651,13 +1652,13 @@
   ASSERT_TRUE(iter != excluded_cookies.end());
   EXPECT_EQ(http_www_foo_.host(), iter->cookie.Domain());
   EXPECT_EQ("A", iter->cookie.Name());
-  EXPECT_TRUE(iter->status.HasExactlyExclusionReasonsForTesting(
+  EXPECT_TRUE(iter->access_result.status.HasExactlyExclusionReasonsForTesting(
       {CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 
   ASSERT_TRUE(++iter != excluded_cookies.end());
   EXPECT_EQ(http_www_foo_.Format(".%D"), iter->cookie.Domain());
   EXPECT_EQ("E", iter->cookie.Name());
-  EXPECT_TRUE(iter->status.HasExactlyExclusionReasonsForTesting(
+  EXPECT_TRUE(iter->access_result.status.HasExactlyExclusionReasonsForTesting(
       {CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
 
   ASSERT_TRUE(++iter == excluded_cookies.end());
@@ -1718,14 +1719,14 @@
   EXPECT_TRUE(
       CreateAndSetCookie(cm.get(), http_www_foo_.url(), "E=F;", options));
 
-  CookieStatusList excluded_cookies =
+  CookieAccessResultList excluded_cookies =
       GetExcludedCookiesForURL(cm.get(), www_foo_foo_.url());
   auto it = excluded_cookies.begin();
 
   ASSERT_TRUE(it != excluded_cookies.end());
   EXPECT_EQ("C", it->cookie.Name());
   EXPECT_EQ("/bar", it->cookie.Path());
-  EXPECT_TRUE(it->status.HasExactlyExclusionReasonsForTesting(
+  EXPECT_TRUE(it->access_result.status.HasExactlyExclusionReasonsForTesting(
       {CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
 
   ASSERT_TRUE(++it == excluded_cookies.end());
@@ -1736,7 +1737,7 @@
   ASSERT_TRUE(it != excluded_cookies.end());
   EXPECT_EQ("A", it->cookie.Name());
   EXPECT_EQ("/foo", it->cookie.Path());
-  EXPECT_TRUE(it->status.HasExactlyExclusionReasonsForTesting(
+  EXPECT_TRUE(it->access_result.status.HasExactlyExclusionReasonsForTesting(
       {CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
 
   ASSERT_TRUE(++it == excluded_cookies.end());
diff --git a/net/cookies/cookie_store.h b/net/cookies/cookie_store.h
index 252cacae..47f2942 100644
--- a/net/cookies/cookie_store.h
+++ b/net/cookies/cookie_store.h
@@ -46,8 +46,8 @@
  public:
   // Callback definitions.
   using GetCookieListCallback =
-      base::OnceCallback<void(const CookieStatusList& included_cookies,
-                              const CookieStatusList& excluded_list)>;
+      base::OnceCallback<void(const CookieAccessResultList& included_cookies,
+                              const CookieAccessResultList& excluded_list)>;
   using GetAllCookiesCallback =
       base::OnceCallback<void(const CookieList& cookies)>;
   // |access_semantics_list| is guaranteed to the same length as |cookies|.
diff --git a/net/cookies/cookie_store_test_callbacks.cc b/net/cookies/cookie_store_test_callbacks.cc
index a582a6e..67461b50 100644
--- a/net/cookies/cookie_store_test_callbacks.cc
+++ b/net/cookies/cookie_store_test_callbacks.cc
@@ -60,10 +60,11 @@
 
 GetCookieListCallback::~GetCookieListCallback() = default;
 
-void GetCookieListCallback::Run(const CookieStatusList& cookies,
-                                const CookieStatusList& excluded_cookies) {
-  cookies_with_statuses_ = cookies;
-  cookies_ = cookie_util::StripStatuses(cookies);
+void GetCookieListCallback::Run(
+    const CookieAccessResultList& cookies,
+    const CookieAccessResultList& excluded_cookies) {
+  cookies_with_access_results_ = cookies;
+  cookies_ = cookie_util::StripAccessResults(cookies);
   excluded_cookies_ = excluded_cookies;
   CallbackEpilogue();
 }
diff --git a/net/cookies/cookie_store_test_callbacks.h b/net/cookies/cookie_store_test_callbacks.h
index 54b00b5..b3195c20 100644
--- a/net/cookies/cookie_store_test_callbacks.h
+++ b/net/cookies/cookie_store_test_callbacks.h
@@ -109,26 +109,27 @@
 
   ~GetCookieListCallback();
 
-  void Run(const CookieStatusList& cookies,
-           const CookieStatusList& excluded_cookies);
+  void Run(const CookieAccessResultList& cookies,
+           const CookieAccessResultList& excluded_cookies);
 
   // Makes a callback that will invoke Run. Assumes that |this| will be kept
   // alive till the time the callback is used.
-  base::OnceCallback<void(const CookieStatusList&, const CookieStatusList&)>
+  base::OnceCallback<void(const CookieAccessResultList&,
+                          const CookieAccessResultList&)>
   MakeCallback() {
     return base::BindOnce(&GetCookieListCallback::Run, base::Unretained(this));
   }
 
   const CookieList& cookies() { return cookies_; }
-  const CookieStatusList& cookies_with_statuses() {
-    return cookies_with_statuses_;
+  const CookieAccessResultList& cookies_with_access_results() {
+    return cookies_with_access_results_;
   }
-  const CookieStatusList& excluded_cookies() { return excluded_cookies_; }
+  const CookieAccessResultList& excluded_cookies() { return excluded_cookies_; }
 
  private:
   CookieList cookies_;
-  CookieStatusList cookies_with_statuses_;
-  CookieStatusList excluded_cookies_;
+  CookieAccessResultList cookies_with_access_results_;
+  CookieAccessResultList excluded_cookies_;
 };
 
 class GetAllCookiesCallback : public CookieCallback {
diff --git a/net/cookies/cookie_store_test_helpers.cc b/net/cookies/cookie_store_test_helpers.cc
index 6d4cab6..aae0c873 100644
--- a/net/cookies/cookie_store_test_helpers.cc
+++ b/net/cookies/cookie_store_test_helpers.cc
@@ -79,10 +79,10 @@
 }
 
 void DelayedCookieMonster::GetCookieListWithOptionsInternalCallback(
-    const CookieStatusList& cookie_list,
-    const CookieStatusList& excluded_cookies) {
-  cookie_status_list_ = cookie_list;
-  cookie_list_ = cookie_util::StripStatuses(cookie_status_list_);
+    const CookieAccessResultList& cookie_list,
+    const CookieAccessResultList& excluded_cookies) {
+  cookie_access_result_list_ = cookie_list;
+  cookie_list_ = cookie_util::StripAccessResults(cookie_access_result_list_);
   did_run_ = true;
 }
 
@@ -135,7 +135,8 @@
 void DelayedCookieMonster::InvokeGetCookieListCallback(
     CookieMonster::GetCookieListCallback callback) {
   if (!callback.is_null())
-    std::move(callback).Run(cookie_status_list_, CookieStatusList());
+    std::move(callback).Run(cookie_access_result_list_,
+                            CookieAccessResultList());
 }
 
 void DelayedCookieMonster::DeleteCanonicalCookieAsync(
diff --git a/net/cookies/cookie_store_test_helpers.h b/net/cookies/cookie_store_test_helpers.h
index 325d0aa..5f9f03d 100644
--- a/net/cookies/cookie_store_test_helpers.h
+++ b/net/cookies/cookie_store_test_helpers.h
@@ -90,8 +90,8 @@
 
   void GetCookiesWithOptionsInternalCallback(const std::string& cookie);
   void GetCookieListWithOptionsInternalCallback(
-      const CookieStatusList& cookie,
-      const CookieStatusList& excluded_cookies);
+      const CookieAccessResultList& cookie,
+      const CookieAccessResultList& excluded_cookies);
 
   // Invoke the original callbacks.
 
@@ -109,7 +109,7 @@
   CookieInclusionStatus result_;
   std::string cookie_;
   std::string cookie_line_;
-  CookieStatusList cookie_status_list_;
+  CookieAccessResultList cookie_access_result_list_;
   CookieList cookie_list_;
 
   DISALLOW_COPY_AND_ASSIGN(DelayedCookieMonster);
diff --git a/net/cookies/cookie_store_unittest.h b/net/cookies/cookie_store_unittest.h
index 2163649..026ed96b 100644
--- a/net/cookies/cookie_store_unittest.h
+++ b/net/cookies/cookie_store_unittest.h
@@ -171,7 +171,8 @@
   }
 
   // This does not update the access time on the cookies.
-  CookieStatusList GetExcludedCookiesForURL(CookieStore* cs, const GURL& url) {
+  CookieAccessResultList GetExcludedCookiesForURL(CookieStore* cs,
+                                                  const GURL& url) {
     DCHECK(cs);
     GetCookieListCallback callback;
     CookieOptions options = CookieOptions::MakeAllInclusive();
diff --git a/net/cookies/cookie_util.cc b/net/cookies/cookie_util.cc
index 87a1681..6a00dc9 100644
--- a/net/cookies/cookie_util.cc
+++ b/net/cookies/cookie_util.cc
@@ -626,10 +626,12 @@
       std::move(callback));
 }
 
-CookieList StripStatuses(const CookieStatusList& cookie_status_list) {
+CookieList StripAccessResults(
+    const CookieAccessResultList& cookie_access_results_list) {
   CookieList cookies;
-  for (const CookieWithStatus& cookie_with_status : cookie_status_list) {
-    cookies.push_back(cookie_with_status.cookie);
+  for (const CookieWithAccessResult& cookie_with_access_result :
+       cookie_access_results_list) {
+    cookies.push_back(cookie_with_access_result.cookie);
   }
   return cookies;
 }
diff --git a/net/cookies/cookie_util.h b/net/cookies/cookie_util.h
index 4b4dcc5..d5125b6 100644
--- a/net/cookies/cookie_util.h
+++ b/net/cookies/cookie_util.h
@@ -215,9 +215,10 @@
 NET_EXPORT base::OnceCallback<void(CookieInclusionStatus)>
 AdaptCookieInclusionStatusToBool(base::OnceCallback<void(bool)> callback);
 
-// Turn a CookieStatusList into a CookieList by stripping out the statuses
-// (for callers who don't care about the statuses).
-NET_EXPORT CookieList StripStatuses(const CookieStatusList& cookie_status_list);
+// Turn a CookieAccessResultList into a CookieList by stripping out access
+// results (for callers who only care about cookies).
+NET_EXPORT CookieList
+StripAccessResults(const CookieAccessResultList& cookie_access_result_list);
 
 }  // namespace cookie_util
 }  // namespace net
diff --git a/net/dns/dns_hosts.cc b/net/dns/dns_hosts.cc
index 13ee84b7..04b1596e 100644
--- a/net/dns/dns_hosts.cc
+++ b/net/dns/dns_hosts.cc
@@ -7,7 +7,6 @@
 #include "base/check.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
-#include "base/metrics/histogram_macros.h"
 #include "base/strings/string_util.h"
 #include "net/dns/dns_util.h"
 
@@ -199,9 +198,6 @@
   if (!base::GetFileSize(path, &size))
     return false;
 
-  UMA_HISTOGRAM_COUNTS_1M("AsyncDNS.HostsSize",
-                          static_cast<base::HistogramBase::Sample>(size));
-
   // Reject HOSTS files larger than |kMaxHostsSize| bytes.
   const int64_t kMaxHostsSize = 1 << 25;  // 32MB
   if (size > kMaxHostsSize)
diff --git a/net/dns/dns_transaction_unittest.cc b/net/dns/dns_transaction_unittest.cc
index a405e21..025caf3 100644
--- a/net/dns/dns_transaction_unittest.cc
+++ b/net/dns/dns_transaction_unittest.cc
@@ -2184,9 +2184,10 @@
     loop_to_quit_->Quit();
   }
 
-  void GetCookieListCallback(const net::CookieStatusList& list,
-                             const net::CookieStatusList& excluded_cookies) {
-    list_ = cookie_util::StripStatuses(list);
+  void GetCookieListCallback(
+      const net::CookieAccessResultList& list,
+      const net::CookieAccessResultList& excluded_cookies) {
+    list_ = cookie_util::StripAccessResults(list);
     loop_to_quit_->Quit();
   }
 
diff --git a/net/dns/host_resolver_manager.cc b/net/dns/host_resolver_manager.cc
index ba0786e..52c94a8 100644
--- a/net/dns/host_resolver_manager.cc
+++ b/net/dns/host_resolver_manager.cc
@@ -2523,7 +2523,7 @@
       query_types.push_back(query_type_);
     }
 
-    MDnsClient* client;
+    MDnsClient* client = nullptr;
     int rv = resolver_->GetOrCreateMdnsClient(&client);
     mdns_task_ =
         std::make_unique<HostResolverMdnsTask>(client, hostname_, query_types);
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json
index 0731a9a5..82498ef 100644
--- a/net/http/transport_security_state_static.json
+++ b/net/http/transport_security_state_static.json
@@ -1648,7 +1648,6 @@
     { "name": "ethack.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fabianfischer.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fastcomcorp.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "gizzo.sk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "itshost.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jmedved.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "keepclean.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -2239,7 +2238,6 @@
     { "name": "fa-works.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "getmango.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "gokmenguresci.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "goodwin43.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "gotspot.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "gra2.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hledejpravnika.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -4481,7 +4479,6 @@
     { "name": "unitel2000.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "unixadm.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "unoccupyabq.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "unterschicht.tv", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "unwiredbrain.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "uvarov.pw", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "valentin-sundermann.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -5387,7 +5384,6 @@
     { "name": "tresorsecurity.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "urphp.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "v0tti.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "vagrantup.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "wegner.no", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "wilddog.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "wlzhiyin.cn", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -5927,7 +5923,6 @@
     { "name": "logicsale.it", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "loginseite.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "loli.bz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "lonal.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "loopstart.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lpm-uk.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lubot.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -6130,7 +6125,6 @@
     { "name": "richardhering.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "ringingliberty.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rix.ninja", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "rkmantpur.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "robertkrueger.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rodehutskors.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rodney.id.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -6767,7 +6761,6 @@
     { "name": "palatin.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "pamplona.tv", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "panaceallc.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "panmetro.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "panni.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "paradoxdesigns.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "parithy.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -8339,7 +8332,6 @@
     { "name": "cmahy.be", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cni-certing.it", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "coachingconsultancy.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "coam.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cocolovesdaddy.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "codeferm.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "coderhangout.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -9762,7 +9754,6 @@
     { "name": "simonsreich.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "simplepractice.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "simplixos.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "simplymozzo.se", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "singleuse.link", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "singlu10.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "sinosky.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -15123,7 +15114,6 @@
     { "name": "tracetracker.no", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "todoescine.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "topaxi.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "tradinews.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "trafficquality.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thomasvochten.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thedarkartsandcrafts.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -16448,7 +16438,6 @@
     { "name": "trynowrinkleseyeserum.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tragmi.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thijsvanderveen.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "tradinews.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "transcricentro.pt", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tobi-mayer.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "theschool.jp", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -17172,7 +17161,6 @@
     { "name": "ecomlane.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "duncanwinfrey.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "droni.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "eddyn.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "egbert.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "droomhuis-in-de-friese-meren-kopen.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "droomhuisophetplattelandverkopen.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -17226,7 +17214,6 @@
     { "name": "et180.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "especificosba.com.mx", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "eengezinswoningverkopen.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "eastmanbusinessinstitute.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "enginepit.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "buildingclouds.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "erick.blog", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -18599,7 +18586,6 @@
     { "name": "unblocked.works", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "upmchealthsecurity.us", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tumagiri.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "usability.gov", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "uctarna.online", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "utilitarianism.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "twee-onder-een-kap-woning-in-leeuwarden-kopen.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -19258,7 +19244,6 @@
     { "name": "co-yutaka.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "coding.lv", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "channellife.asia", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "clovissantos.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "codelitmus.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "craigwfox.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cnbs.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -19418,7 +19403,6 @@
     { "name": "dohanews.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dorfbaeck.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dreamaholic.club", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "domaine-aigoual-cevennes.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dopravni-modely.cz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "drabbin.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "duckbase.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -20557,7 +20541,6 @@
     { "name": "radiomodem.dk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "progressivecfo.co.nz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "pianetaottica.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "prepaid-voip.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "readingandmath.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "ravengergaming.ga", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "rbti.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -20969,7 +20952,6 @@
     { "name": "tomiler.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tobiassachs.cf", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "teulon.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "theobromos.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tolud.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tlcdn.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "thesignalco.com.au", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -22700,7 +22682,6 @@
     { "name": "bltc.org.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "bluefrag.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "blues-and-pictures.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "bluteklab.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "bnty.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "bobep.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "boboates.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -23028,7 +23009,6 @@
     { "name": "cvninja.pl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cwrcoding.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cyber-computer.club", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "cyber.cafe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cybercecurity.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cyberwars.dk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "cyoda.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -23196,7 +23176,6 @@
     { "name": "dzomo.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "e-migration.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "e-newshub.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "e-pokupki.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "e-tune-mt.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "e-vau.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "e-wishlist.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -23973,7 +23952,6 @@
     { "name": "kirainmoe.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kisallatorvos.hu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kisstube.tv", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "kitchen-profi.com.ua", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kittyhacker101.tk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kjg-bachrain.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kjoglum.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -26652,7 +26630,6 @@
     { "name": "eidolons.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "egeozcan.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "encouragemarketing.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "ecirtam.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "electragirl.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "elosrah.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dtx.sk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -26673,7 +26650,6 @@
     { "name": "elliff.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dovenzorgmalawi.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "efa-football.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "emil.click", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "elektro-roth.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "eolme.ml", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "drlazarina.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -27011,7 +26987,6 @@
     { "name": "gugert.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "harveyauzorst.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hammer-schnaps.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "hanfox.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "handyglas.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "gynaecology.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "haruue.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -27735,7 +27710,6 @@
     { "name": "netki.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "napcae.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "myrig.ru", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "nebul.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nakanishi-paint.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nedwave.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "newbownerton.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -29210,7 +29184,6 @@
     { "name": "alroniks.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "anttitenhunen.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "aevpn.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "b8a.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "aqua-fitness-nacht.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "asmdz.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "ammoulianiapartments.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -29536,7 +29509,6 @@
     { "name": "downtimerobot.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "downtimerobot.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dualascent.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "dev-bluep.pantheonsite.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "drogoz.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "dosomeworks.biz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "droidgyan.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -29825,7 +29797,6 @@
     { "name": "hostworkz.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fire-wolf.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hiteco.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "gencmedya.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "heverhagen.rocks", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "horkel.cf", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hfu.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -29990,7 +29961,6 @@
     { "name": "kremalicious.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kabashop.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "keycenter.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "kitchen-profi.by", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kobofarm.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kostecki.org", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kevinroebert.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -30003,7 +29973,6 @@
     { "name": "koryfi.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "jacobsenarquitetura.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "kitatec.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "konoe.studio", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lannainnovation.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "lazulu.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "leadgenie.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -30250,7 +30219,6 @@
     { "name": "nba2k.co", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nba2k.live", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nba2k.download", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "myliveupdates.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "microbiote-insectes-vecteurs.group", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nba2k.tw", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nba.vg", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -30325,7 +30293,6 @@
     { "name": "notablog.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "nyphox.ovh", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "numwave.nl", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "mrksk.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "neurocny.cloud", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "netscaler.expert", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "opposer.me", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -32787,7 +32754,6 @@
     { "name": "failover.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "failover.eu", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fakerli.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "fakti.bg", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "familie-leu.ch", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "familletouret.fr", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fantasyescortsbirmingham.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -32821,7 +32787,6 @@
     { "name": "firstq.xyz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fiuxy.bz", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fl0222.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "flehm.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "flets-ms.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "fliacuello.com.ar", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "flightzero.cf", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -33219,7 +33184,6 @@
     { "name": "melakaltenegger.at", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "melaniebernhardt.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "melbourneapartments.website", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "melikoff.es", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "melina-schefczyk.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "memetrash.co.uk", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "memorygame.io", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -33725,7 +33689,6 @@
     { "name": "tridimage.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "trymegadrol.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tsuki.moe", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "ttbonline.gov", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "ttdsevaonline.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "turigum.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "tutanota.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -34157,7 +34120,6 @@
     { "name": "helpantiaging.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hevertonfreitas.com.br", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hfcbank.com.gh", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "hh-medic.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hiddenmalta.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hiltonarubabeachservices.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "himens.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -34174,7 +34136,6 @@
     { "name": "hotelsinformer.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "house-of-japan.co.jp", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hp42.de", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
-    { "name": "hrjfeedstock.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hustlehope.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "hyakumachi.com", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
     { "name": "i-hakul.net", "policy": "bulk-18-weeks", "mode": "force-https", "include_subdomains": true },
@@ -34725,7 +34686,6 @@
     { "name": "bolivarfm.com.ve", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "boogiebouncecastles.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "boosinflatablegames.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "bopp.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "born2bounce.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bounce-a-mania.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bounce-a-roo.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -37209,7 +37169,6 @@
     { "name": "waltellis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "waterleeftinbeek.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "waterschaplimburg.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "wdodelta.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wearedisneyland.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "webartex.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "websiterent.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -38316,7 +38275,6 @@
     { "name": "euvo.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eva-select.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "evailoil.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "evamira.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "event64.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "everydaywp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "evilsite.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -38611,7 +38569,6 @@
     { "name": "klseet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kocherev.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kochereva.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kochhar.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kogcoder.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "koka-shop.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "koninkrijk.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -39692,7 +39649,6 @@
     { "name": "euro-servers.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eurofrank.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "europeanpreppers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "evamachkova.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "evenementenhoekvanholland.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "examsmate.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "expoort.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -44365,7 +44321,6 @@
     { "name": "kobejet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kooliveeb.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kovehitus.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ladraiglaan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lalajj.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lederer-it.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "libricks.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -46074,7 +46029,6 @@
     { "name": "boattrader.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bonami.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bordadoenpedreria.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "brand-foo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "brand-foo.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "brand-foo.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bsee.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -47478,7 +47432,6 @@
     { "name": "retronet.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "returnpath.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "reussir-ma-fete.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "revirt.global", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "rmm-i.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "root.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "royalasianescorts.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -48431,7 +48384,6 @@
     { "name": "l33te.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lachlan-harris.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lancashirecca.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "latiendauno.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "laufers.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lauraenvoyage.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lawyerkf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -49824,8 +49776,6 @@
     { "name": "loigiai.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "loihay.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "loli.tube", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "loyaltyondemand.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "loyaltyondemand.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lsmpx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lucasbergen.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "luke6887.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -50631,7 +50581,6 @@
     { "name": "huonit.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hyperstack.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "iaf.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "iam.lc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ibodyiq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "idealimplant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "idratherbequilting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -51784,7 +51733,6 @@
     { "name": "ihakkitekin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ilookz.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "industriafranchini.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "infinitomaisum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "infomir.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "infuzeit.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "inglebycakes.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -52645,7 +52593,6 @@
     { "name": "dorpshuis-dwarsgracht.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dr-it.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "drump-truck.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "drwang.group", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dschwarzachtaler.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dsgnet.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dubious-website.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -53102,8 +53049,6 @@
     { "name": "savingsoftheyear.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "schgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "schoeller.click", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "scholar.group", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "scholar.site", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "scholledev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "seachef.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "secpoc.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -53748,7 +53693,6 @@
     { "name": "vlakem.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vos-systems.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vtuber.art", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "webutils.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "weems.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "whirlpool.net.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "whiskygentle.men", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -56069,7 +56013,6 @@
     { "name": "kermadec.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kevin-ta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kgv-schlauroth.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kiisu.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kinderpneumologie.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kinerd.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kinesiomed-cryosauna.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -56569,7 +56512,6 @@
     { "name": "section77.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "securist.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "secvault.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "sedomicilier.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "seedcoworking.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "segnidisegni.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sekikawa.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -57691,7 +57633,6 @@
     { "name": "lancelhoff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lancemanion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "latinmusicrecords.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "leaf-consulting.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lehmitz-weinstuben.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "leibniz-gymnasium-altdorf.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lequest.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -58563,7 +58504,6 @@
     { "name": "flibusta.appspot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fmstr.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "followmystaff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "fono.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "forbidden-mods.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ford.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ford.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -58599,7 +58539,6 @@
     { "name": "gehrke.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "general-plast.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "geniofinanciero.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "gesnex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gfedating.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ghost-legion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "givingtools.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -58615,7 +58554,6 @@
     { "name": "gostargazing.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "goufaan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "graandco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "grenlandkiropraktor.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "grupodatco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gtn-pravda.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gyakori.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -59596,7 +59534,6 @@
     { "name": "inoxmavang.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "isaropiping.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jabba.homelinux.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "joeseago.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jonas.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jxkangyifu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jz585.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -59657,7 +59594,6 @@
     { "name": "nyoliveoil.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oaktonhouseandgardens.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "omenprinting.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "orangesquash.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ordekho.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "organicskincare.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oximo.lviv.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -60883,7 +60819,6 @@
     { "name": "achat-volets-roulants.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "addistribution.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "agenciamseo.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ak47-miyamoto.spdns.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "alabordage.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "alfredapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "altijdleroy.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -60892,7 +60827,6 @@
     { "name": "anarajaoui.ma", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aoe9.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aptumseguros.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "arabhardware.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arcobalabs.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "artacadia.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asemanhotel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -61212,7 +61146,6 @@
     { "name": "traha.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tulsaworkshop.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tupass.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tw-hosting.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tyroremotes.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "uberactivist.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ultimatepaleoguide.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -61767,7 +61700,6 @@
     { "name": "euroroad17.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "expertpanel.gc.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "exvs.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "eythorsson.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "facesdr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "faggut.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fanzhencha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -62090,7 +62022,6 @@
     { "name": "africankitchen.gallery", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "akrep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "albareport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "alexlambertz.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "algebra-quiz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "allesovertech.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "alloutsec.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -62843,7 +62774,6 @@
     { "name": "determapp.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dhelixnet.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "die-pleners.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "direct.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "directscripts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "distraction.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dmoj.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -66121,7 +66051,6 @@
     { "name": "d9397.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d9721.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "d9728.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "datelah.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dd5197.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dd9297.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dd9397.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -66944,7 +66873,6 @@
     { "name": "linkk9.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lndrive.space", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "londonindustry.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lorenzocompeticion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lsiq.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "luckystorevn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "madsstorm.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -68278,7 +68206,6 @@
     { "name": "werkenbijsherpa.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wervingenselectieamsterdam.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wikibuy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "workingon.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wowin58.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wowin88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ww6729.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -68505,7 +68432,6 @@
     { "name": "eons.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eqassociates.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "erfolgsmaschine.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "eshterry.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "especialistagoogleadwords.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "espyder.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "euc.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -68783,7 +68709,6 @@
     { "name": "2222k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "222k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2264707.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "2isk.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "3333k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "36594.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "518k8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -69099,7 +69024,6 @@
     { "name": "mklenterprises.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mklenterprisesacademy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mklenterprisescoaching.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "mmpaymentsystem.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "momobako.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "moosmaus.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "motorzone.od.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -69514,7 +69438,6 @@
     { "name": "osterlensyd.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pandiora.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pcr24.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "pixelabs.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "planet.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "popitsnack.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "proctorauth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70204,7 +70127,6 @@
     { "name": "kleinhelena.dynv6.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kmnsk.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kotonozaka.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks0816.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "labavn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "labibikids.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "landassessmentservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70284,7 +70206,6 @@
     { "name": "ocnjapartment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "okasurfbali.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oliverah.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "orebolt.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "orged.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ostechnix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "otoma.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70348,7 +70269,6 @@
     { "name": "sagenesykkel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sainikbiswas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "salesblackbelt.coach", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "saluddecalidad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sam-cousins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sampleappservice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sduconnect.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -70602,7 +70522,6 @@
     { "name": "588e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "58w66.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "62222.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "8102d88.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "88btt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "91milk.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "a2os.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -72151,7 +72070,6 @@
     { "name": "906vv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "90920.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "90n13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "918aav.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "918nn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "91d91.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "940365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73181,8 +73099,6 @@
     { "name": "kresimir-blazevic.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kryptologie.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ks023.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks0566.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks0668.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ks257.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ks318.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ks641.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -73471,7 +73387,6 @@
     { "name": "olivejs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ollo.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "omretreats.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "one-news.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "onlineautodealered.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ooo-santal.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "operanavigation.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -74319,7 +74234,6 @@
     { "name": "1lc22.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "1lc55.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "1vpns.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "2000meter.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2018j95.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2019j95.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2020j95.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -76598,7 +76512,6 @@
     { "name": "undeadpirates.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "unitedmatrix.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "universal-tutorial.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "unlocktechs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "unternehmensbewertung.pro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "upgradedpoints.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "v800d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77008,7 +76921,6 @@
     { "name": "t5880.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "t81818.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "temperandtantrum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "termbackti.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "terra-24.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thealonas.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thealonas.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -77839,7 +77751,6 @@
     { "name": "1lc44.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "220control.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "33weishang.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "369018.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "50milli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "5eki.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "690938.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -78534,7 +78445,6 @@
     { "name": "52062n.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "52062o.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "52062s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "8869ks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "88djl.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "9118inc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aanwp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -78543,8 +78453,6 @@
     { "name": "acneintelligence.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "acunetix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "agencyalacarte.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "agks89.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "agks998.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "airconrandburg.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aljaspod.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "alpharoofga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -78652,7 +78560,6 @@
     { "name": "honeymaze.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ictindia.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "incomeproshoutr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "irequi.re", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "itsallaboutplumbing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "itschromeos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jakse.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -78671,9 +78578,6 @@
     { "name": "knowledgebuilds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kroyclothing.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "krupacars.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks0558.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks0660.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks597.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ks89.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kstr.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lacochinacounselor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -78913,7 +78817,6 @@
     { "name": "callmewhatever.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cameramark.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "canhas.report", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "cardozovargas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cardozovargas.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "casashmodel.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ceramiche.roma.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -79431,7 +79334,6 @@
     { "name": "harrisonm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hendranicholas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hl8id.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "hl8th.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hosteons.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hotelmonal.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hvenetworks.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81302,7 +81204,6 @@
     { "name": "illange.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "inspiresurgery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "intrixgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "intrixlifestyle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "inyr.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ipinfo.tw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "irenkuhn.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81796,7 +81697,6 @@
     { "name": "fonamperu.org.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "forfeiture.gov", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "forthewin.rocks", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "forumstandaardisatie.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "foselectro.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fozzie.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "frankieistanbul.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -81879,10 +81779,7 @@
     { "name": "k852.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "k860.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "k865.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "k865.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "k86690.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "k867.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "k867.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "k869.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "k87071.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "k87072.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -82072,7 +81969,6 @@
     { "name": "lc8md77.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc90000.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9108.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lc9256.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9862.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9899.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lc9900.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -82611,7 +82507,6 @@
     { "name": "openbayes.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "osano.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "paardenpro.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "pacificintegration.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "packetoverflow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "panthi.lk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "parfum-selbermachen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83137,7 +83032,6 @@
     { "name": "myqservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nachovni.pp.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "naiaokami.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "nategreen.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ndx.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "netferie.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "netferie.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83182,7 +83076,6 @@
     { "name": "nic.youtube", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nic.zip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nihaarpstars.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ningrui.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nocommentsallowed.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nordvestkysten.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nordvestkysten.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83268,7 +83161,6 @@
     { "name": "seedboite.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "selltous.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "senshot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "seriesdatv.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "servermaster.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "setuplog.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sevilinux.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -83778,7 +83670,6 @@
     { "name": "on-targettrainingcourses.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "on-this.link", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "onlineltctraining.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "op3y.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "openstakes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "opstory.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ornsyn.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -86097,7 +85988,6 @@
     { "name": "maxiglobal.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "meekhak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "meldpuntemma.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "melento.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "metadedi.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "microcyber.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mijnkwadraad.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -86280,7 +86170,6 @@
     { "name": "valutienda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vectordtg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vegner.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "verymetal.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vibgyorhigh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "viceversa2013.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "videograb.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -87757,7 +87646,6 @@
     { "name": "sanctum.geek.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sandra-perlbach.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "saorsat.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "sarahjanecreates.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "saronikos.guide", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "scatterscasino.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "schafzwitschern.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -88409,7 +88297,6 @@
     { "name": "zolotoy-standart.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "01.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "038899.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "0verl0rd.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "1248.ink", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "1eanda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2fr3.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -88656,7 +88543,6 @@
     { "name": "nutritionalsupplement.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "obliviate.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "officevibe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "onlinecasinolisboa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "opendoorcounselingpa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "opnaarsalto.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "opticasocialvision.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -88808,37 +88694,12 @@
     { "name": "x59788.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "x59888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "x59988.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98f.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98g.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98h.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98i.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98k.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98l.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98m.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98n.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98o.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98p.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98q.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98r.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98s.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98w.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98y.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x98z.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x993.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xamax.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xemcloud.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xiaoneijun.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xiaoneimao.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xn--lti-3qa.lv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xpj000444.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xpj000555.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xpj000666.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xpj678678.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xpj909.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xpjbeting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xpjcs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yellsy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yourbusinesscommunity.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yourpalmbeachcountyrealtor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -88959,7 +88820,6 @@
     { "name": "bet7234.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "betza.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bicicletassym.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "bidadari.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "biotecommunity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bizeasesupport.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "blixtv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -89069,7 +88929,6 @@
     { "name": "fauxcams.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fenriragic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fetishblend.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "fieldelite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "finprison.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fish-n-chips.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "fitrecepty.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -89859,7 +89718,6 @@
     { "name": "palessit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pcf-frankfurt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pipscprd.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "poirierlavoie.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pojdnafp.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pomdoc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "poquiloco.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -90204,7 +90062,6 @@
     { "name": "chanderson.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "chaoscommunication.camp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "chaturbate.global", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "chaussmomes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "checkmedia.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "christoph-gadow.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cimaflash.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -90539,7 +90396,6 @@
     { "name": "iemsamex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ifashionable.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "iganesh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ikhwanto.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ilawgix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ilovehoney.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "imoasis.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -90708,7 +90564,6 @@
     { "name": "megazine3.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "meinforum.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "meldwekker.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "mentorbuk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "menurutparaahli.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mettin.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "meziblog.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -90718,7 +90573,6 @@
     { "name": "milanvit.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "milehighmaniac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mileyweasel.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "millim.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "minicampingshalom.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mississippigenealogy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mitchkalf.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -91246,7 +91100,6 @@
     { "name": "xtom.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xtom.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xtom.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "xuexi.icu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xxxuno.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yahav.co.il", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "yasic.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -91268,14 +91121,12 @@
     { "name": "00228vip5.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228vip6.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228vip8.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "00228vv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228w.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228ww.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228x.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228xx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228y.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228yy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "00228z.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "00228zz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "01zemi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "0cdn.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -91405,7 +91256,6 @@
     { "name": "archim.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arest.web.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "arganwinkel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "artchic.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aryankhera.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asgardiamc.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "assessortrainingonline.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -91427,7 +91277,6 @@
     { "name": "avionschool.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "axisins.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "azadcyber.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "b00228.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "b77018.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "baixarvideosgratis.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bajarvideosinstagram.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -91561,7 +91410,6 @@
     { "name": "cr1coffee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "creati.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "crossconnected.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "crowdfundingwaterresearch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cs-kurnik.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cube-filing.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cumulus.photo", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -92291,12 +92139,10 @@
     { "name": "symbolic.software", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "synergenxhealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "synth.style", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "t00228.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "t4gh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tadzkitchen.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tamboa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tanahtinggi.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "tandoanh.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tapple.world", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "taxi-meridian.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tcspartner.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -92457,7 +92303,6 @@
     { "name": "www00228d.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "www00228e.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "wwwn888.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "x00228.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xavio-design.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xbblog.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "xbots.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -94167,7 +94012,6 @@
     { "name": "itabi.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "itajvi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "itsapps.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "j51365.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jackwarren.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jakartacloudhosting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jamiehansonyoga.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -94273,21 +94117,6 @@
     { "name": "outrider.ai", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "owmobility.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "p7jl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88813.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88814.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88816.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88817.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88823.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88825.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88827.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88829.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88835.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88836.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88845.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88848.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88856.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p88867.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "p888a.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pablosaraiva.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "panelesyperfiles.com.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "papascave.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -94458,7 +94287,6 @@
     { "name": "vichama.pe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "victorique.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "visse-if.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "vns6654.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "vosges-tourisme.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "w123.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "warmteshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -95842,7 +95670,6 @@
     { "name": "gutterguardcharlotte.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "guttershutter.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "habibitravels.com.ng", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "hae.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "haizrulamrie.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "hby.cx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "heckmann.photos", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -99591,7 +99418,6 @@
     { "name": "gpl25.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gppro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "graberbooks.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "grabtech.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "gracia-club.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "graciasmarvin.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "graduados.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -100028,7 +99854,6 @@
     { "name": "imeria.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "imgo.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "imgo.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "imiku.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "immoraldoctors.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "immortal-it.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "immune.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -101705,7 +101530,6 @@
     { "name": "mywebserver.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "myweightlosstips.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "myzarabot.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "n-mail.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "n3rd0rama.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nabeer.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nabiev.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -101919,7 +101743,6 @@
     { "name": "no-terrorism.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "no-war-on-iraq.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "noart.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "nocoffeetech.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nocturnos.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nodde.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "nonemail.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -102212,7 +102035,6 @@
     { "name": "overtunes.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ovez.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ovodakadarkut.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "owall.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oxaliz.gq", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oxbridge.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "oxigenoinformatica.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -105764,7 +105586,6 @@
     { "name": "claudia-halfter.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "claudiahalfter.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "clean.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "clouditme.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cm-valenca.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "codefive.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "colah.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -105990,7 +105811,6 @@
     { "name": "konzepttreu.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kood13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "koood13.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kouroshnet.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "krishnakalisaha.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kurenivka.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kurniasihmandiri.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106020,7 +105840,6 @@
     { "name": "macc.org.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "madebythijmen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "magicorama.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "maleylabapplications.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mansys.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "maratondeclics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "matjarkom.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106180,7 +105999,6 @@
     { "name": "thesemperfibeard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tomasdrtina.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tomphenix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "top10antivirus.review", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "torohandyman.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tsaama2.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tsproesasac.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106304,7 +106122,6 @@
     { "name": "boundless-designs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "brazilhealth.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "breteuilcommerceartisanat.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "brexitmart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "bride.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "butlerdisposal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "camshowhive.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106645,7 +106462,6 @@
     { "name": "pro-dog.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "proficiodigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "proficiodigital.sk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "proitsecurity.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "protection-plexi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "protection-plexi.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "psicologomogidascruzes.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106660,7 +106476,6 @@
     { "name": "rabec.com.sa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "refansta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "renedekoeijer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "reseau-protestant.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ricor.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "riley.love", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "rinton.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106774,7 +106589,6 @@
     { "name": "zook.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "016910804.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "123start.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "2002000.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "2makeu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "4driver.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "4hypo.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106857,7 +106671,6 @@
     { "name": "campus-competences.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "candalgic.com.tr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "canopy.garden", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "captainkids.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cardoneshop.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "careify.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cateromarket.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106899,7 +106712,6 @@
     { "name": "covidmodel.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cpad.org.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "crea.codes", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "creatapeak.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "credee.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cricoff.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "crohnszone.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -106922,7 +106734,6 @@
     { "name": "digino.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "digino.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "digino.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "digitalmarketerconsultant.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dioxido.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dnddobbelstenen.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "dossierweb.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -107037,11 +106848,6 @@
     { "name": "korkortonline.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "krome.sg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "krpaforum.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks178.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks187.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks500.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks700.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "ks800.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "l2l.vn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lablic-beta.work", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "langages-programmation.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -107643,7 +107449,6 @@
     { "name": "kibazen.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kinklist.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kinkyheretics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "kitajagakawasan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kmzs123.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kocovi.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kokily.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -107803,7 +107608,6 @@
     { "name": "sharonsplace.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "shouohkai-dental.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "sipln.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "skrealtyplus.co.th", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "smaden.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "smikom.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "snitch.rocks", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -107988,7 +107792,6 @@
     { "name": "casalor.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cccp-o.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ccnexus.global", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "cdxmaster.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cecilgreens.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ceifx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "certified-cpr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -108513,7 +108316,6 @@
     { "name": "artesaniaselmagodeoz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "artisansofsleep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "artizlibranza.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "artworksthatlookgood.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asabharwal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asalearn.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "assignmentshelp.co.ke", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -108943,7 +108745,6 @@
     { "name": "pueblanmilksnake.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "purepowercycle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "pygmyleafchameleon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "qnixon.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "quietapple.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "quoteee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ratsmicedormice.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -109024,7 +108825,6 @@
     { "name": "theartofe.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thebookiejoint.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thefireflygrill.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "thepainapple.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thrivebymitchelle.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "timecaptis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tirion.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -109373,7 +109173,6 @@
     { "name": "laptopnewbie.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "laudlab.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "laudworks.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "lc9915.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "leales.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lecoquelicot.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "legterm.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -109386,7 +109185,6 @@
     { "name": "localcryptos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lojasmary.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "longoconsulting.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "los-hoppers.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lost-illusions.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lostserial.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lourencolar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -109938,7 +109736,6 @@
     { "name": "fortcommunity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "freecam-sex.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "freedailygifts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "freegovernmentcellphoneguide.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "freehdporn.tv", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "freehqporno.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "freshmusicsheets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110001,7 +109798,6 @@
     { "name": "implantologiadentalgt.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "impressionusa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "incnjp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "innovationreno.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "interchangeillawarra.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "internetstones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "invicti.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110221,7 +110017,6 @@
     { "name": "taskman.london", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "taxisantandreudelabarca.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tch-forum.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "techaid24.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tecnologia.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "tecnomagazine.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "teknologiia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110235,7 +110030,6 @@
     { "name": "thefoxtalk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thehomemademasks.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "theocoffee.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "theologique.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thepalateportfolio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "therra.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "thevirtualdetective.games", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110344,7 +110138,6 @@
     { "name": "arnamur.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "asteq.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "athorcis.ovh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "atmondigital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "avalontechsv.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "avtorlab.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aykonet.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110445,7 +110238,6 @@
     { "name": "draughts64.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "draughts64.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "e-facture.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "e2essentialelements.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "earthpoints.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "eightyfour.pictures", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ejcabinets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110560,7 +110352,6 @@
     { "name": "jobs.schwarz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jobsjets.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "johncunningham.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "joshuamccracken.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "julioteixeira.pt", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "justforsunn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "jwala.diamonds", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110581,7 +110372,6 @@
     { "name": "koredia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kosterenpartners.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "krilotek.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "krimzy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kswork.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "labelledigital.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "lagaleria-ag.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110616,7 +110406,6 @@
     { "name": "marcyacademiademusica.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "markellos-olive.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "marthus.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "masayahingguro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mastercheat.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "masterpizzaiolo.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mathieuescos.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110639,7 +110428,6 @@
     { "name": "mojezegarki.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "morgan.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "moviles.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "mrbikerentals.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mrpanipiales.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mrunang.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "mvwr.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110874,7 +110662,6 @@
     { "name": "aceofdiamondspainting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "acephalafashion.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "adhyayanclasses.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "aec-box.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "aepx.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "agilecyber.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ainouno.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -110939,7 +110726,6 @@
     { "name": "cbtl-see.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "cdseditora.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "chamonixcamera.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "christiangaro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ciel.coffee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "ciph.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "civilcorner.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -111094,7 +110880,6 @@
     { "name": "kedero.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kevinperrow.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "keyserve.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
-    { "name": "knightsbr1dge.red", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kochcommunity.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kopieid.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "kreidl.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
@@ -111348,6 +111133,541 @@
     { "name": "zhouzhi.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zuhausejobs.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     { "name": "zzcc.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "00000000-0000-0000-0000-000000000000.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "0x3a.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "0x6470.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "22.ag", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "2makeu.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3654.vip", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "3pif.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "533sss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "761.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abellagranitecountertops.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abogadamediadora.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "abrightsolution.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acidoascorbico.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "acuvate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adeloveshipping.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adenopatia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "adesachatbottecnicowab01.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "afoch.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aguilarsoluciones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aimanance.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aimmail.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aksot.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alanbleiweiss.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alanina.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alexandraschmidt.coach", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alianet.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "alng.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "altokep.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "amdrumors.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aminovega.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "andreamonicahug.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "angelzapien.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antihistaminico.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antikeo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "antoni.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "aptctg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "armarinhosalves.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asana.biz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asana.plus", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asesoramientosolay.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ashevillemenshealth.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asian-rugby-exchange-fest.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asitanc.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asm802.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asm802.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asoziales-netzwerk.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "astrolab.mx", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "asylinfo.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "atrakcjenaeventy.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "babylurve.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "backlotgaming.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bajarjuegos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bandaumnikov.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "belzlongroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "benjaminleupold.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "besiconstruct.be", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bestsiteporn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "betalgroup.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "betterbusiness.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bfkkutu.kr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bharatology.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biologo.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bitbroker.exchange", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "biuromowcow.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bjecard.buzz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blackhat.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blardiblah.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "blogtechnologiczny.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bnb.direct", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bodas.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "boehm.sh", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "booked.md", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bremermaschinenbau.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brewit.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "brighterimagelab.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bsmsl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bsmsoluciones.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bss.solutions", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bsurfcr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "budofjoy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "bugfuzz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buscalotodo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "buzzword24.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "c2athletics.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "c3stream.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cancersintomas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carlingforddental.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "carnetdeconducir.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "catartofsweden.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "centrmrt.spb.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "checkrz.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chesstempo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "chnroute.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "christianyleny.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ciclodekrebs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ciclodelcarbono.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ciclohidrologico.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cinematictouch.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "clarkhowell.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cloudomation.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cloudplan.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cmrconstructions.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cms-world.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cnpkg.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coderslight.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coenzima.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "coindica.com.ve", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "collegium-musicum-bocholt.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "comprar.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "comviodemo.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "condictor.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "conphungtourist.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "conpulpademanzana.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consolebros.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "consumercouncil.je", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "contralegem.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "correo.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cosmic-relations.co.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cottage.direct", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "covid19.govt.nz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cozzack.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cpucheu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "crashbolsa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "criscond.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "csaerotherm.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cuties.chat", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cv-developpeur-web.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "cyberskyline.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "d-taube.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daoplatthanhhoa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "daycubrem.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dealbeathn.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deathcult.fun", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "debattinnlegg.no", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dela.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deltav.ml", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dendi-staging.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dendisoftware.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depedtambayan.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "depedtambayan.net.ph", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "deportes.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dienmattroichonthanh.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "directmailctr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "discordextremelist.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "docedic.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "docedic.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "docsrev-aws.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "doterrashop.ec", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "drawjar.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dreamytheatre.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dupuis.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dutchpentathlon.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "dyregrave.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "earthsocialism.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eisei-iinkai.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eldiariodemof.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "elektroruoff.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "emvitals.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eod-dissemination-uat.azurewebsites.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eod-dissemination.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eosinofilos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "est-tatsujin.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "etf2l.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "eurocom.bg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "execupharm.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exentio.sexy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "expand.technology", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "exyusubs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ezhub.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ezone57.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "feastofplants.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "federaljob.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "femiwiki.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ferad.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fernandezvilar.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fibune.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "findcheap.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fleeb.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "flowlytics.host", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fn-0.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "foundationrepairpro.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "fprinnovaciones.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freefinancialhelp.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "freegaypornhd.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "futbito.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "futbolcba.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "garrow.se", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "geekynutritionist.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "georgiebailey.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "getscif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gillettechampions.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "golovabol.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "goodseed.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gordonbeeming.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gosiberia.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gpsmith.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "grahamsmith.tech", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "growthlab.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gruveo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gryphzia.cf", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "guythomasevans.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "gzfc.com.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "harumi-cl.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "headfullofdynamite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heavymetalonline.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "heimdall-home.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hellopowerserg.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hestegrovvaren.dk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "higleyarts.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hiranosayuri-piano.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "histhist.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hobbslanddevelopment.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "home-page.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "hourai.gg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "huesers.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ideagenpentana.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "idowp.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "illuminaterecovery.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "immijobs.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "immobilier-swiss.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "immoe.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "inoreader.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "instaart.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "invisitone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "iox.is", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itaro.ee", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "itaro.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jandj.yachts", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jefcorlabs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jloh.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jmeno.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "johnmac.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "joomladeveloper.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jrulka.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "justpractice.ca", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "jwala.eu.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kadooonline.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "katerinastudio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kathrin-maren-enders.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kgky.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kidan.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kimino-school.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kinetikos.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kiseki.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kitaplus.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kreuzbergflieger.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "kstasinos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "labels.co.ke", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laby.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lacarna.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lagloriadehuampani.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lajas.com.ve", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "laoudit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "larenas.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ldbeauty.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "legowerewolf.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "leo.co.ke", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "letriolet-tignes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lightquantum.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "link.sb", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "listazakupow.com.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "littlefingersindia.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "livetv.tube", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "llredac.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lolifamily.js.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lovesquirting.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lukaskollmer.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "lumien.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "luxeblades.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "m-a-i-l.us", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "macabacus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "machinerysource.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "magetsi.co.zw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mahmalci.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marcillacetfils.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mariages.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marinasmad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "marleenjacobi.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "martinschulze.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "massdesigners.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mathiasheise.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "matrimonio.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mattmorrissound.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mayacoa.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medsanuk.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "medstatix-dev.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "megatorrenthd.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mf58.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mhcouncil.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "middle.io", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "midl.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "millennium-thisiswhoweare.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "millersprolandscape.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "miriamgamburd.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "missbitcoin.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mitchkiah.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mlsvallarta.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "modax.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "monmiel.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "moonbyte.at", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "motolinesupply.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "movihut.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "msngr.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mtran.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "multimediosmonti.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "museodefutbol.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "musicwind.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "muydelgada.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "my.urown.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mybokx.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myheartlaundry.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myload.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mysouschef.herokuapp.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "mytransmissionexperts.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "myzoograd.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "natuurlijkmooi-meppel.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nekochan.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "neoseo.com.ua", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "netzabfragen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ngo-online.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nistorvictor.software", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nmcep.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nobitex.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "noktaradyo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "notteit.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "novi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nuclea.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "nya.one", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oboivam.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "obs.plus", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ocastrowork.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "office.urown.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "offsetservices.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "onpaws.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "open-fixture-library.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "operationtulip.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oralb-prestazioni-odontoiatriche.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oralbregalaoralb.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "organicseo4u.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "osaka-hero-project.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "osteopathe-voisine.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "outervision.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "oversightboard.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pachamamaproduct.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paketverfolgung.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "paviformas.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "peelawayyourpain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "perved.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petitsfreresdespauvres.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "petya.cc", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pfarrhaus-mon.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "phw.org.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "picomedia.ir", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pnp.ac.id", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pockets.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "polaxtor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pornfreesites.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pornmad.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "porthos.com.ar", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "powerscif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "powerserg.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "powersergfeds.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "powersergisrc.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "powersergsecure.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pozitone.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "poziworld.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pradmin.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prestatyn-scala.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prestatynflowershow.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "prijmeni.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "printwasteminimizer.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "problemysholkama.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "producciondealimentos.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "productive-garden.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "project-scarlett.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "projectarmy.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "promospg.es", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "proservices-informatique.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "protrainerbrasil.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "psc.gov.ws", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pujasharma.associates", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pv-golf.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "pvao.gov.ph", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "qigehl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "quentindestombes.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raderamig.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "radiation-oncologist.gr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "raniwan.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rasc.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rbn.is", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "readyscif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "readysetscif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "regalador.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reinheft.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "remigius-michael.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "reviewpipe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "richfieldsean.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "road-safety.cz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rodnik-pansionat.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "roishopper.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rosewebdesignstudio.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "roveridx.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rpcinmobiliaria.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "rpj.life", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "russell-tech.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "s2.coach", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "safefreepornsites.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "safescif.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "safetydrivessuccess.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "samuelcoles.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sanitix.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "santandertrade.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sarahjaneredmond.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "saxobroko.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "schoffelcountry.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scifplus.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scifsafe.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scorb.com.br", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "scroll-to-top-button.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sentralshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shakalaka.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shincastella.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "shoppingjin.pk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sieliakus.nl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "simplylocalhosting.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sincromyl.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sitinjau.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slabstage.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "slavblog.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smithandellis.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "smltour.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sns.med.sa", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "snsdomain.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "solaxfaq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "solviq.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "soykaf.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "spicystove.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sportify-design.fr", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sportspassbremen.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "squarepocketdesign.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "starthubs.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stilus-patent.ru", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stla.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stomwhite.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "storage-base.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stuartparsons.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "stuudium.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sugarsalted.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "svse.global", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "svseglobal.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "swiffertirimborsa.it", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "sypreformas.tk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tangochoang.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "taroe.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "team957.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "techgarage.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tenken1010.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thekokuin.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thelaurelchiropractor.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "themenucard.online", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "themusicalsafari.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thewaytoyourself.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "thoplam.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tiendamaquillajes.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tilcra.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tinmarin.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tradeshift.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trains.sexy", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "transdev.blog", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "transdev.club", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tridnice.eu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "trpl.host", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "tryfrontline.cloud", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "twilo-host.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "txyz.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "typesofdogs.info", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "ubsolutions.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "unblockedgames.live", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "up.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "uradvd.best", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "urby.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "url.kg", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "useworkshop.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "valsorey.ch", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vapourtown.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "verso.money", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vibetribe.co.za", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "videoclases.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vietnamhairs.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vinyl-digital.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "visabuddy.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vision-painting.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vpnstreamer.com.au", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "vrallart.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "walla.store", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wallatienda.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "warrenhousevets.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wass.ga", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "watchtolearn.co", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wdesk.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "weitweg.xyz", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wenzelarifiandi.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whatco.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whiskey.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whiskey.money", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whiskey.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whisky.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whisky.money", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whiskymy.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whiskyshop.com.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whiskyshop.my", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "whmcs.xn--9dbq2a", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "winkli.ddns.net", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "winnersaffiliate.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wis.moe", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wivcfinancialservices.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wivenhoeforum.co.uk", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wngs-creative.hu", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "womywomwoo.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "woodwicker.cl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "worldfinancenews.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "wpspeedking.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--avocai-timioara-kmf1a.ro", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xn--hsers-kva.de", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "xunmengdu.com", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yarowork.jp", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yellowsource.org", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yescool.cn", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yozakura.me", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "yuth.in", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zegarkidlakazdego.pl", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zotan.email", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zotan.network", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
+    { "name": "zotan.pw", "policy": "bulk-1-year", "mode": "force-https", "include_subdomains": true },
     // END OF 1-YEAR BULK HSTS ENTRIES
 
     // Only eTLD+1 domains can be submitted automatically to hstspreload.org,
diff --git a/net/proxy_resolution/configured_proxy_resolution_service.cc b/net/proxy_resolution/configured_proxy_resolution_service.cc
index c699df2..68fc89b5 100644
--- a/net/proxy_resolution/configured_proxy_resolution_service.cc
+++ b/net/proxy_resolution/configured_proxy_resolution_service.cc
@@ -391,34 +391,6 @@
   return url.ReplaceComponents(replacements);
 }
 
-// Do not change the enumerated value as it is relied on by histograms.
-enum class PacUrlSchemeForHistogram {
-  kOther = 0,
-
-  kHttp = 1,
-  kHttps = 2,
-  kFtp = 3,
-  kFile = 4,
-  kData = 5,
-
-  kMaxValue = kData,
-};
-
-PacUrlSchemeForHistogram GetPacUrlScheme(const GURL& pac_url) {
-  if (pac_url.SchemeIs("http"))
-    return PacUrlSchemeForHistogram::kHttp;
-  if (pac_url.SchemeIs("https"))
-    return PacUrlSchemeForHistogram::kHttps;
-  if (pac_url.SchemeIs("data"))
-    return PacUrlSchemeForHistogram::kData;
-  if (pac_url.SchemeIs("ftp"))
-    return PacUrlSchemeForHistogram::kFtp;
-  if (pac_url.SchemeIs("file"))
-    return PacUrlSchemeForHistogram::kFile;
-
-  return PacUrlSchemeForHistogram::kOther;
-}
-
 }  // namespace
 
 // ConfiguredProxyResolutionService::InitProxyResolver
@@ -1511,11 +1483,6 @@
     });
   }
 
-  if (config.value().has_pac_url()) {
-    UMA_HISTOGRAM_ENUMERATION("Net.ProxyResolutionService.PacUrlScheme",
-                              GetPacUrlScheme(config.value().pac_url()));
-  }
-
   // Set the new configuration as the most recently fetched one.
   fetched_config_ = effective_config;
 
diff --git a/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc b/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc
index 9b129ee2..c9a5fb01 100644
--- a/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc
+++ b/net/proxy_resolution/configured_proxy_resolution_service_unittest.cc
@@ -346,42 +346,6 @@
   return GetJobsForURLs(map, urls);
 }
 
-// Helper class to verify the bucket counts for PacUrlScheme histogram.
-class PacUrlSchemeHistogramTester {
- public:
-  void VerifyHistogram() const {
-    const char kPacUrlSchemeHistogram[] =
-        "Net.ProxyResolutionService.PacUrlScheme";
-
-    int total = GetTotal();
-
-    histograms_.ExpectTotalCount(kPacUrlSchemeHistogram, total);
-
-    if (total > 0) {
-      histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 0, num_other);
-      histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 1, num_http);
-      histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 2, num_https);
-      histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 3, num_ftp);
-      histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 4, num_file);
-      histograms_.ExpectBucketCount(kPacUrlSchemeHistogram, 5, num_data);
-    }
-  }
-
-  int num_http = 0;
-  int num_https = 0;
-  int num_ftp = 0;
-  int num_data = 0;
-  int num_file = 0;
-  int num_other = 0;
-
- private:
-  int GetTotal() const {
-    return num_http + num_https + num_ftp + num_data + num_file + num_other;
-  }
-
-  base::HistogramTester histograms_;
-};
-
 }  // namespace
 
 TEST_F(ConfiguredProxyResolutionServiceTest, Direct) {
@@ -3999,61 +3963,6 @@
   EXPECT_TRUE(info.is_direct());
 }
 
-// Tests that the URL scheme for PAC files gets output to the histogram.
-TEST_F(ConfiguredProxyResolutionServiceTest, PacUrlSchemeHistogram) {
-  PacUrlSchemeHistogramTester pac_histogram;
-
-  MockProxyConfigService* config_service =
-      new MockProxyConfigService(ProxyConfig::CreateDirect());
-
-  ConfiguredProxyResolutionService service(
-      base::WrapUnique(config_service),
-      std::make_unique<MockAsyncProxyResolverFactory>(false), nullptr,
-      /*quick_check_enabled=*/true);
-
-  pac_histogram.VerifyHistogram();
-
-  // Set an http:// PAC.
-  config_service->SetPacUrlConfig("http://example.test/");
-  pac_histogram.num_http++;
-  pac_histogram.VerifyHistogram();
-
-  // Set an https:// PAC.
-  config_service->SetPacUrlConfig("hTTps://example.test/wpad.dat");
-  pac_histogram.num_https++;
-  pac_histogram.VerifyHistogram();
-
-  // Set an ftp:// PAC.
-  config_service->SetPacUrlConfig("ftp://example.test/pac.js");
-  pac_histogram.num_ftp++;
-  pac_histogram.VerifyHistogram();
-
-  // Set an file:// PAC.
-  config_service->SetPacUrlConfig("file://example.test/boo");
-  pac_histogram.num_file++;
-  pac_histogram.VerifyHistogram();
-
-  // Set an mailto: PAC.
-  config_service->SetPacUrlConfig("mailto:foo@example.test");
-  pac_histogram.num_other++;
-  pac_histogram.VerifyHistogram();
-
-  // Set an data: PAC.
-  config_service->SetPacUrlConfig("data:,Hello%2C%20World!");
-  pac_histogram.num_data++;
-  pac_histogram.VerifyHistogram();
-
-  // Set an filesystem: PAC.
-  config_service->SetPacUrlConfig("filesystem:http://example.test/pac.js");
-  pac_histogram.num_other++;
-  pac_histogram.VerifyHistogram();
-
-  // Set another https:// as PAC.
-  config_service->SetPacUrlConfig("https://example2.test/wpad.dat");
-  pac_histogram.num_https++;
-  pac_histogram.VerifyHistogram();
-}
-
 const char* kImplicityBypassedHosts[] = {
     "localhost",
     "localhost.",
diff --git a/net/quic/crypto/proof_verifier_chromium.cc b/net/quic/crypto/proof_verifier_chromium.cc
index 33f341f..82558389 100644
--- a/net/quic/crypto/proof_verifier_chromium.cc
+++ b/net/quic/crypto/proof_verifier_chromium.cc
@@ -641,6 +641,7 @@
 
 quic::QuicAsyncStatus ProofVerifierChromium::VerifyCertChain(
     const std::string& hostname,
+    const uint16_t /*port*/,
     const std::vector<std::string>& certs,
     const std::string& ocsp_response,
     const std::string& cert_sct,
diff --git a/net/quic/crypto/proof_verifier_chromium.h b/net/quic/crypto/proof_verifier_chromium.h
index bef7745..f05da2e 100644
--- a/net/quic/crypto/proof_verifier_chromium.h
+++ b/net/quic/crypto/proof_verifier_chromium.h
@@ -95,6 +95,7 @@
       std::unique_ptr<quic::ProofVerifierCallback> callback) override;
   quic::QuicAsyncStatus VerifyCertChain(
       const std::string& hostname,
+      const uint16_t port,
       const std::vector<std::string>& certs,
       const std::string& ocsp_response,
       const std::string& cert_sct,
diff --git a/net/quic/crypto/proof_verifier_chromium_test.cc b/net/quic/crypto/proof_verifier_chromium_test.cc
index e17397f..1150311f 100644
--- a/net/quic/crypto/proof_verifier_chromium_test.cc
+++ b/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -1003,7 +1003,7 @@
   std::unique_ptr<DummyProofVerifierCallback> callback(
       new DummyProofVerifierCallback);
   quic::QuicAsyncStatus status = proof_verifier.VerifyCertChain(
-      kTestHostname, certs_, /*ocsp_response=*/std::string(),
+      kTestHostname, kTestPort, certs_, /*ocsp_response=*/std::string(),
       /*cert_sct=*/std::string(), verify_context_.get(), &error_details_,
       &details_, std::move(callback));
   ASSERT_EQ(quic::QUIC_SUCCESS, status);
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc
index 61561a8a..42df283 100644
--- a/net/quic/quic_chromium_client_session_test.cc
+++ b/net/quic/quic_chromium_client_session_test.cc
@@ -1752,7 +1752,7 @@
   quic::test::QuicStreamPeer::SendBuffer(stream).SaveStreamData(iov, 1, 0, 4);
   quic::test::QuicStreamPeer::SetStreamBytesWritten(4, stream);
   session_->WritevData(stream->id(), 4, 0, quic::NO_FIN,
-                       quic::NOT_RETRANSMISSION, QuicheNullOpt);
+                       quic::NOT_RETRANSMISSION, QUICHE_NULLOPT);
 
   EXPECT_TRUE(socket_data.AllReadDataConsumed());
   EXPECT_TRUE(socket_data.AllWriteDataConsumed());
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h
index f08ace05..744b2aa 100644
--- a/net/quic/quic_flags_list.h
+++ b/net/quic/quic_flags_list.h
@@ -292,13 +292,6 @@
 // If true, server push will be allowed in QUIC versions using HTTP/3.
 QUIC_FLAG(bool, FLAGS_quic_enable_http3_server_push, false)
 
-// If true, disable QuicDispatcher workaround that replies to invalid QUIC
-// packets from the Android Conformance Test.
-QUIC_FLAG(
-    bool,
-    FLAGS_quic_reloadable_flag_quic_remove_android_conformance_test_workaround,
-    true)
-
 // The divisor that controls how often MAX_STREAMS frames are sent.
 QUIC_FLAG(int32_t, FLAGS_quic_max_streams_window_divisor, 2)
 
@@ -315,38 +308,18 @@
           FLAGS_quic_reloadable_flag_quic_bbr2_fewer_startup_round_trips,
           false)
 
-// If true, remove draining_streams_ from QuicSession.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_deprecate_draining_streams,
-          true)
-
-// If true, break session/stream close loop.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_break_session_stream_close_loop,
-          true)
-
 // Replace the usage of ConnectionData::encryption_level in
 // quic_time_wait_list_manager with a new TimeWaitAction.
 QUIC_FLAG(bool,
           FLAGS_quic_restart_flag_quic_replace_time_wait_list_encryption_level,
           true)
 
-// If true, move Goolge QUIC stream accounting to LegacyQuicStreamIdManager.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_stream_id_manager_handles_accounting,
-          true)
-
 // If true, enables support for TLS resumption in QUIC.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_enable_tls_resumption, false)
 
 // When true, QUIC's BBRv2 ignores inflight_lo in PROBE_BW.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_bbr2_ignore_inflight_lo, false)
 
-// If true, notify handshakers when connection closes.
-QUIC_FLAG(bool,
-          FLAGS_quic_reloadable_flag_quic_notify_handshaker_on_connection_close,
-          true)
-
 // If true, for QUIC + TLS, change default encryption level when new encryption
 // key is available.
 QUIC_FLAG(bool,
@@ -388,13 +361,6 @@
           FLAGS_quic_restart_flag_quic_google_transport_param_send_new,
           true)
 
-// If true, if a buffered MTU packet causes a write to return MSG_TOO_BIG, this
-// error will be ignored.
-QUIC_FLAG(
-    bool,
-    FLAGS_quic_reloadable_flag_quic_ignore_msg_too_big_from_buffered_packets,
-    true)
-
 // If true, check ShouldGeneratePacket for every crypto packet.
 QUIC_FLAG(bool,
           FLAGS_quic_reloadable_flag_quic_fix_checking_should_generate_packet,
@@ -411,7 +377,7 @@
 QUIC_FLAG(
     bool,
     FLAGS_quic_reloadable_flag_quic_fix_write_pending_crypto_retransmission,
-    false)
+    true)
 
 // If true, clear last_inflight_packets_sent_time_ of a packet number space when
 // there is no bytes in flight.
@@ -439,7 +405,7 @@
 
 // When true, always check the amplification limit before writing, not just for
 // handshake packets.
-QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_move_amplification_limit, false)
+QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_move_amplification_limit, true)
 
 // If true, SendAllPendingAcks always send the earliest ACK.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_always_send_earliest_ack, false)
@@ -456,3 +422,9 @@
 // If true, do not arm PTO on half RTT packets if they are the only ones in
 // flight.
 QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_fix_server_pto_timeout, false)
+
+// If true, default-enable 5RTO blachole detection.
+QUIC_FLAG(
+    bool,
+    FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection,
+    true)
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index cf6d4b1..e4593de 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -253,7 +253,7 @@
     auto* verify_callback_ptr = verify_callback.get();
     quic::QuicAsyncStatus status =
         crypto_config->proof_verifier()->VerifyCertChain(
-            server_id_.host(), cached->certs(),
+            server_id_.host(), server_id_.port(), cached->certs(),
             /*ocsp_response=*/std::string(), cached->cert_sct(),
             verify_context_.get(), &verify_error_details_, &verify_details_,
             std::move(verify_callback));
diff --git a/net/quiche/common/platform/impl/quiche_optional_impl.h b/net/quiche/common/platform/impl/quiche_optional_impl.h
index bbdb0a80..9d16486 100644
--- a/net/quiche/common/platform/impl/quiche_optional_impl.h
+++ b/net/quiche/common/platform/impl/quiche_optional_impl.h
@@ -12,7 +12,7 @@
 template <typename T>
 using QuicheOptionalImpl = base::Optional<T>;
 
-#define QuicheNullOptImpl base::nullopt
+#define QUICHE_NULLOPT_IMPL base::nullopt
 
 }  // namespace quiche
 
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index 1da8390..807d051 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -5177,7 +5177,7 @@
   NormalSpdyTransactionHelper helper(request_, DEFAULT_PRIORITY, log_, nullptr);
   helper.RunToCompletion(&data);
   TransactionHelperResult out = helper.output();
-  EXPECT_THAT(out.rv, IsError(ERR_ABORTED));
+  EXPECT_THAT(out.rv, IsError(ERR_HTTP2_PROTOCOL_ERROR));
 }
 
 // Request should be retried on a new connection upon receiving a GOAWAY frame
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 09a74086..39938ef 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -27,6 +27,7 @@
 #include "base/trace_event/memory_usage_estimator.h"
 #include "base/trace_event/trace_event.h"
 #include "base/values.h"
+#include "net/base/features.h"
 #include "net/base/url_util.h"
 #include "net/cert/asn1_util.h"
 #include "net/cert/cert_verify_result.h"
@@ -1317,6 +1318,9 @@
 
   DCHECK(IsStreamActive(stream_id));
 
+  if (base::FeatureList::IsEnabled(features::kAvoidH2Reprioritization))
+    return;
+
   auto updates = priority_dependency_state_.OnStreamUpdate(
       stream_id, ConvertRequestPriorityToSpdyPriority(new_priority));
   for (auto u : updates) {
@@ -3137,7 +3141,7 @@
   } else if (error_code == spdy::ERROR_CODE_NO_ERROR) {
     StartGoingAway(last_accepted_stream_id, ERR_HTTP2_SERVER_REFUSED_STREAM);
   } else {
-    StartGoingAway(last_accepted_stream_id, ERR_ABORTED);
+    StartGoingAway(last_accepted_stream_id, ERR_HTTP2_PROTOCOL_ERROR);
   }
   // This is to handle the case when we already don't have any active
   // streams (i.e., StartGoingAway() did nothing). Otherwise, we have
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 57c0997..d688eb7 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -6232,7 +6232,11 @@
                              "alternative.example.org",
                              443,
                              86400,
-                             spdy::SpdyAltSvcWireFormat::VersionVector()) {}
+                             spdy::SpdyAltSvcWireFormat::VersionVector()) {
+    // Since the default |alternative_service_| is QUIC, need to enable QUIC for
+    // the not added tests to be meaningful.
+    session_deps_.enable_quic = true;
+  }
 
   void AddSocketData(const spdy::SpdyAltSvcIR& altsvc_ir) {
     altsvc_frame_ = spdy_util_.SerializeFrame(altsvc_ir);
@@ -6258,8 +6262,6 @@
 };
 
 TEST_F(AltSvcFrameTest, ProcessAltSvcFrame) {
-  session_deps_.enable_quic = true;
-
   const char origin[] = "https://mail.example.org";
   spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 0);
   altsvc_ir.add_altsvc(alternative_service_);
@@ -6391,8 +6393,6 @@
 }
 
 TEST_F(AltSvcFrameTest, ProcessAltSvcFrameOnActiveStream) {
-  session_deps_.enable_quic = true;
-
   spdy::SpdyAltSvcIR altsvc_ir(/* stream_id = */ 1);
   altsvc_ir.add_altsvc(alternative_service_);
 
@@ -6450,8 +6450,6 @@
 
 TEST_F(AltSvcFrameTest,
        ProcessAltSvcFrameOnActiveStreamWithNetworkIsolationKey) {
-  session_deps_.enable_quic = true;
-
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
       // enabled_features
diff --git a/net/url_request/url_request.cc b/net/url_request/url_request.cc
index 7a31814e..2797525 100644
--- a/net/url_request/url_request.cc
+++ b/net/url_request/url_request.cc
@@ -395,7 +395,7 @@
   return job_->GetResponseCode();
 }
 
-void URLRequest::set_maybe_sent_cookies(CookieStatusList cookies) {
+void URLRequest::set_maybe_sent_cookies(CookieAccessResultList cookies) {
   maybe_sent_cookies_ = std::move(cookies);
 }
 
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 10e141d..bc68fcb 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -541,7 +541,7 @@
   // Returns whether secure DNS should be disabled for the request.
   bool disable_secure_dns() { return disable_secure_dns_; }
 
-  void set_maybe_sent_cookies(CookieStatusList cookies);
+  void set_maybe_sent_cookies(CookieAccessResultList cookies);
   void set_maybe_stored_cookies(CookieAndLineStatusList cookies);
 
   // These lists contain a list of cookies that are associated with the given
@@ -555,7 +555,7 @@
   // and only contain the cookies relevant to the most recent roundtrip.
 
   // Populated while the http request is being built.
-  const CookieStatusList& maybe_sent_cookies() const {
+  const CookieAccessResultList& maybe_sent_cookies() const {
     return maybe_sent_cookies_;
   }
   // Populated after the response headers are received.
@@ -864,7 +864,7 @@
   PrivacyMode privacy_mode_;
   bool disable_secure_dns_;
 
-  CookieStatusList maybe_sent_cookies_;
+  CookieAccessResultList maybe_sent_cookies_;
   CookieAndLineStatusList maybe_stored_cookies_;
 
 #if BUILDFLAG(ENABLE_REPORTING)
diff --git a/net/url_request/url_request_http_job.cc b/net/url_request/url_request_http_job.cc
index 80130a8..e67d5e2 100644
--- a/net/url_request/url_request_http_job.cc
+++ b/net/url_request/url_request_http_job.cc
@@ -552,14 +552,14 @@
 
 void URLRequestHttpJob::SetCookieHeaderAndStart(
     const CookieOptions& options,
-    const CookieStatusList& cookies_with_status_list,
-    const CookieStatusList& excluded_list) {
+    const CookieAccessResultList& cookies_with_access_result_list,
+    const CookieAccessResultList& excluded_list) {
   DCHECK(request_->maybe_sent_cookies().empty());
 
   bool can_get_cookies = CanGetCookies();
-  if (!cookies_with_status_list.empty() && can_get_cookies) {
+  if (!cookies_with_access_result_list.empty() && can_get_cookies) {
     std::string cookie_line =
-        CanonicalCookie::BuildCookieLine(cookies_with_status_list);
+        CanonicalCookie::BuildCookieLine(cookies_with_access_result_list);
     UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
     request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
                                           cookie_line);
@@ -569,7 +569,7 @@
 
     // TODO(crbug.com/1031664): Reduce the number of times the cookie list is
     // iterated over. Get metrics for every cookie which is included.
-    for (const auto& c : cookies_with_status_list) {
+    for (const auto& c : cookies_with_access_result_list) {
       bool request_is_secure = request_->url().SchemeIsCryptographic();
       net::CookieSourceScheme cookie_scheme = c.cookie.SourceScheme();
       CookieRequestScheme cookie_request_schemes;
@@ -599,36 +599,40 @@
     }
   }
 
-  // Report status for things in |excluded_list| and |cookies_with_status_list|
+  // Report status for things in |excluded_list| and
+  // |cookies_with_access_result_list|
   // after the delegate got a chance to block them.
-  CookieStatusList maybe_sent_cookies = excluded_list;
+  CookieAccessResultList maybe_sent_cookies = excluded_list;
 
   if (!can_get_cookies) {
-    for (CookieStatusList::iterator it = maybe_sent_cookies.begin();
+    for (CookieAccessResultList::iterator it = maybe_sent_cookies.begin();
          it != maybe_sent_cookies.end(); ++it) {
-      it->status.AddExclusionReason(
+      it->access_result.status.AddExclusionReason(
           CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
     }
   }
-  for (const auto& cookie_with_status : cookies_with_status_list) {
-    CookieInclusionStatus status = cookie_with_status.status;
+
+  for (const auto& cookie_with_access_result :
+       cookies_with_access_result_list) {
+    CookieAccessResult access_result = cookie_with_access_result.access_result;
     if (!can_get_cookies) {
-      status.AddExclusionReason(
+      access_result.status.AddExclusionReason(
           CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
     }
-    maybe_sent_cookies.push_back({cookie_with_status.cookie, status});
+    maybe_sent_cookies.push_back(
+        {cookie_with_access_result.cookie, access_result});
   }
 
   if (request_->net_log().IsCapturing()) {
-    for (const auto& cookie_and_status : maybe_sent_cookies) {
+    for (const auto& cookie_with_access_result : maybe_sent_cookies) {
       request_->net_log().AddEvent(
           NetLogEventType::COOKIE_INCLUSION_STATUS,
           [&](NetLogCaptureMode capture_mode) {
             return CookieInclusionStatusNetLogParams(
-                "send", cookie_and_status.cookie.Name(),
-                cookie_and_status.cookie.Domain(),
-                cookie_and_status.cookie.Path(), cookie_and_status.status,
-                capture_mode);
+                "send", cookie_with_access_result.cookie.Name(),
+                cookie_with_access_result.cookie.Domain(),
+                cookie_with_access_result.cookie.Path(),
+                cookie_with_access_result.access_result.status, capture_mode);
           });
     }
   }
diff --git a/net/url_request/url_request_http_job.h b/net/url_request/url_request_http_job.h
index f8564c12..cc6eecb5 100644
--- a/net/url_request/url_request_http_job.h
+++ b/net/url_request/url_request_http_job.h
@@ -168,8 +168,8 @@
 
   // Callback functions for Cookie Monster
   void SetCookieHeaderAndStart(const CookieOptions& options,
-                               const CookieStatusList& cookie_list,
-                               const CookieStatusList& excluded_list);
+                               const CookieAccessResultList& cookie_list,
+                               const CookieAccessResultList& excluded_list);
 
   // Another Cookie Monster callback
   void OnSetCookieResult(const CookieOptions& options,
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 3bf83b5..d08ecb8 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -6824,13 +6824,13 @@
     EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
     EXPECT_TRUE(
         req->maybe_sent_cookies()[0]
-            .status.HasExactlyExclusionReasonsForTesting(
+            .access_result.status.HasExactlyExclusionReasonsForTesting(
                 {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
                  net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
     EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
     EXPECT_TRUE(
         req->maybe_sent_cookies()[1]
-            .status.HasExactlyExclusionReasonsForTesting(
+            .access_result.status.HasExactlyExclusionReasonsForTesting(
                 {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
     auto entries =
         net_log.GetEntriesWithType(NetLogEventType::COOKIE_INCLUSION_STATUS);
@@ -6894,10 +6894,10 @@
     ASSERT_EQ(2u, req->maybe_sent_cookies().size());
     EXPECT_EQ("path_cookie", req->maybe_sent_cookies()[0].cookie.Name());
     EXPECT_TRUE(req->maybe_sent_cookies()[0]
-                    .status.HasExactlyExclusionReasonsForTesting(
+                    .access_result.status.HasExactlyExclusionReasonsForTesting(
                         {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
     EXPECT_EQ("stored_cookie", req->maybe_sent_cookies()[1].cookie.Name());
-    EXPECT_TRUE(req->maybe_sent_cookies()[1].status.IsInclude());
+    EXPECT_TRUE(req->maybe_sent_cookies()[1].access_result.status.IsInclude());
     auto entries =
         net_log.GetEntriesWithType(NetLogEventType::COOKIE_INCLUSION_STATUS);
     EXPECT_EQ(2u, entries.size());
@@ -7018,13 +7018,14 @@
     ASSERT_EQ(1u, req->maybe_sent_cookies().size());
     EXPECT_EQ("cookienosamesite", req->maybe_sent_cookies()[0].cookie.Name());
     EXPECT_TRUE(req->maybe_sent_cookies()[0]
-                    .status.HasExactlyExclusionReasonsForTesting(
+                    .access_result.status.HasExactlyExclusionReasonsForTesting(
                         {CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
                          CookieInclusionStatus::
                              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
     // Cookie should not be warned about because it was blocked because of user
     // preferences.
-    EXPECT_FALSE(req->maybe_sent_cookies()[0].status.ShouldWarn());
+    EXPECT_FALSE(
+        req->maybe_sent_cookies()[0].access_result.status.ShouldWarn());
   }
   network_delegate.unset_block_get_cookies();
 
@@ -7064,22 +7065,23 @@
     // with longest first. See CookieSorter() in cookie_monster.cc.
     EXPECT_EQ("cookiewithpath", req->maybe_sent_cookies()[0].cookie.Name());
     EXPECT_TRUE(req->maybe_sent_cookies()[0]
-                    .status.HasExactlyExclusionReasonsForTesting(
+                    .access_result.status.HasExactlyExclusionReasonsForTesting(
                         {CookieInclusionStatus::EXCLUDE_NOT_ON_PATH,
                          CookieInclusionStatus::
                              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
-    EXPECT_FALSE(req->maybe_sent_cookies()[0].status.ShouldWarn());
+    EXPECT_FALSE(
+        req->maybe_sent_cookies()[0].access_result.status.ShouldWarn());
     // Cookie that was only blocked because of unspecified SameSite should be
     // warned about.
     EXPECT_EQ("cookienosamesite", req->maybe_sent_cookies()[1].cookie.Name());
     EXPECT_TRUE(req->maybe_sent_cookies()[1]
-                    .status.HasExactlyExclusionReasonsForTesting(
+                    .access_result.status.HasExactlyExclusionReasonsForTesting(
                         {CookieInclusionStatus::
                              EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
-    EXPECT_TRUE(
-        req->maybe_sent_cookies()[1].status.HasExactlyWarningReasonsForTesting(
-            {CookieInclusionStatus::
-                 WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
+    EXPECT_TRUE(req->maybe_sent_cookies()[1]
+                    .access_result.status.HasExactlyWarningReasonsForTesting(
+                        {CookieInclusionStatus::
+                             WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
   }
 }
 
@@ -7200,7 +7202,7 @@
     EXPECT_TRUE(
         request->maybe_sent_cookies()
             .front()
-            .status.HasExactlyExclusionReasonsForTesting(
+            .access_result.status.HasExactlyExclusionReasonsForTesting(
                 {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
 
     // Check maybe_sent_cookies on second roundtrip.
@@ -7235,7 +7237,7 @@
     EXPECT_TRUE(
         request->maybe_sent_cookies()
             .front()
-            .status.HasExactlyExclusionReasonsForTesting(
+            .access_result.status.HasExactlyExclusionReasonsForTesting(
                 {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
   }
 }
@@ -7608,7 +7610,7 @@
     EXPECT_TRUE(
         request->maybe_sent_cookies()
             .front()
-            .status.HasExactlyExclusionReasonsForTesting(
+            .access_result.status.HasExactlyExclusionReasonsForTesting(
                 {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
 
     // Check maybe_sent_cookies on second round trip
@@ -7639,7 +7641,7 @@
     EXPECT_TRUE(
         request->maybe_sent_cookies()
             .front()
-            .status.HasExactlyExclusionReasonsForTesting(
+            .access_result.status.HasExactlyExclusionReasonsForTesting(
                 {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
   }
 }
diff --git a/net/websockets/websocket_stream_cookie_test.cc b/net/websockets/websocket_stream_cookie_test.cc
index 6e26562..f2e105f 100644
--- a/net/websockets/websocket_stream_cookie_test.cc
+++ b/net/websockets/websocket_stream_cookie_test.cc
@@ -122,10 +122,10 @@
       base::OnceClosure task,
       base::WeakPtr<bool> weak_is_called,
       base::WeakPtr<CookieList> weak_result,
-      const CookieStatusList& cookie_list,
-      const CookieStatusList& excluded_cookies) {
+      const CookieAccessResultList& cookie_list,
+      const CookieAccessResultList& excluded_cookies) {
     *weak_is_called = true;
-    *weak_result = cookie_util::StripStatuses(cookie_list);
+    *weak_result = cookie_util::StripAccessResults(cookie_list);
     base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
   }
 };
diff --git a/printing/page_number.cc b/printing/page_number.cc
index adbf330..14c02c4 100644
--- a/printing/page_number.cc
+++ b/printing/page_number.cc
@@ -18,7 +18,7 @@
 }
 
 PageNumber::PageNumber()
-    : ranges_(NULL),
+    : ranges_(nullptr),
       page_number_(-1),
       page_range_index_(-1),
       document_page_count_(0) {}
diff --git a/remoting/base/typed_buffer.h b/remoting/base/typed_buffer.h
index 7e64d8f..782b283d 100644
--- a/remoting/base/typed_buffer.h
+++ b/remoting/base/typed_buffer.h
@@ -25,7 +25,7 @@
   TypedBuffer() : TypedBuffer(0) {}
 
   // Creates an instance of the object allocating a buffer of the given size.
-  explicit TypedBuffer(uint32_t length) : buffer_(NULL), length_(length) {
+  explicit TypedBuffer(uint32_t length) : buffer_(nullptr), length_(length) {
     if (length_ > 0)
       buffer_ = reinterpret_cast<T*>(new uint8_t[length_]);
   }
diff --git a/remoting/host/desktop_resizer_x11.cc b/remoting/host/desktop_resizer_x11.cc
index 7378d57..966f9143 100644
--- a/remoting/host/desktop_resizer_x11.cc
+++ b/remoting/host/desktop_resizer_x11.cc
@@ -144,7 +144,6 @@
   // its resolution.
   void SwitchToMode(const char* name);
 
-  XDisplay* const display_;
   x11::Connection connection_;
   x11::RandR* const randr_ = nullptr;
   const x11::Screen* const screen_ = nullptr;
@@ -157,8 +156,7 @@
 };
 
 DesktopResizerX11::DesktopResizerX11()
-    : display_(XOpenDisplay(nullptr)),
-      randr_(connection_.randr()),
+    : randr_(connection_.randr()),
       screen_(connection_.default_screen()),
       root_(screen_->root),
       exact_resize_(base::CommandLine::ForCurrentProcess()->HasSwitch(
@@ -181,16 +179,18 @@
   // X server socket by the time the resize function returns, hence the
   // file descriptor is never seen as readable.
   if (has_randr_) {
-    while (XEventsQueued(display_, QueuedAlready)) {
+    while (XEventsQueued(connection_.display(), QueuedAlready)) {
       XEvent event;
-      XNextEvent(display_, &event);
+      XNextEvent(connection_.display(), &event);
       XRRUpdateConfiguration(&event);
     }
   }
 
   ScreenResolution result(
-      webrtc::DesktopSize(DisplayWidth(display_, DefaultScreen(display_)),
-                          DisplayHeight(display_, DefaultScreen(display_))),
+      webrtc::DesktopSize(DisplayWidth(connection_.display(),
+                                       DefaultScreen(connection_.display())),
+                          DisplayHeight(connection_.display(),
+                                        DefaultScreen(connection_.display()))),
       webrtc::DesktopVector(kDefaultDPI, kDefaultDPI));
   return result;
 }
@@ -240,7 +240,7 @@
 
   // Grab the X server while we're changing the display resolution. This ensures
   // that the display configuration doesn't change under our feet.
-  ScopedXGrabServer grabber(display_);
+  ScopedXGrabServer grabber(connection_.display());
 
   if (exact_resize_)
     SetResolutionNewMode(resolution);
@@ -319,7 +319,7 @@
   if (!resources_.Refresh(randr_, root_))
     return;
   x11::RandR::Mode mode_id = resources_.GetIdForMode(name);
-  if (mode_id != kInvalidMode)
+  if (mode_id == kInvalidMode)
     return;
   randr_->AddOutputMode({
       resources_.GetOutput(),
diff --git a/remoting/protocol/audio_source.h b/remoting/protocol/audio_source.h
index d36d378..cbbe700 100644
--- a/remoting/protocol/audio_source.h
+++ b/remoting/protocol/audio_source.h
@@ -17,7 +17,7 @@
 
 class AudioSource {
  public:
-  typedef base::Callback<void(std::unique_ptr<AudioPacket> packet)>
+  typedef base::RepeatingCallback<void(std::unique_ptr<AudioPacket> packet)>
       PacketCapturedCallback;
 
   virtual ~AudioSource() {}
diff --git a/remoting/protocol/authenticator.h b/remoting/protocol/authenticator.h
index 9e1d82c..fda5e72 100644
--- a/remoting/protocol/authenticator.h
+++ b/remoting/protocol/authenticator.h
@@ -83,7 +83,7 @@
   // Callback used for layered Authenticator implementations, particularly
   // third-party and pairing authenticators. They use this callback to create
   // base SPAKE2 authenticators.
-  typedef base::Callback<std::unique_ptr<Authenticator>(
+  typedef base::RepeatingCallback<std::unique_ptr<Authenticator>(
       const std::string& shared_secret,
       Authenticator::State initial_state)>
       CreateBaseAuthenticatorCallback;
diff --git a/remoting/protocol/channel_authenticator.h b/remoting/protocol/channel_authenticator.h
index a6b1904e..8da6fad 100644
--- a/remoting/protocol/channel_authenticator.h
+++ b/remoting/protocol/channel_authenticator.h
@@ -20,7 +20,7 @@
 // should be used only once for one channel.
 class ChannelAuthenticator {
  public:
-  typedef base::Callback<void(int error, std::unique_ptr<P2PStreamSocket>)>
+  typedef base::OnceCallback<void(int error, std::unique_ptr<P2PStreamSocket>)>
       DoneCallback;
 
   virtual ~ChannelAuthenticator() {}
@@ -29,7 +29,7 @@
   // authentication is finished. Callback may be invoked before this method
   // returns, and may delete the calling authenticator.
   virtual void SecureAndAuthenticate(std::unique_ptr<P2PStreamSocket> socket,
-                                     const DoneCallback& done_callback) = 0;
+                                     DoneCallback done_callback) = 0;
 };
 
 }  // namespace protocol
diff --git a/remoting/protocol/client_authentication_config.h b/remoting/protocol/client_authentication_config.h
index 4847c33..9e235383 100644
--- a/remoting/protocol/client_authentication_config.h
+++ b/remoting/protocol/client_authentication_config.h
@@ -12,18 +12,20 @@
 namespace remoting {
 namespace protocol {
 
-typedef base::Callback<void(const std::string& secret)> SecretFetchedCallback;
-typedef base::Callback<void(
+typedef base::RepeatingCallback<void(const std::string& secret)>
+    SecretFetchedCallback;
+typedef base::RepeatingCallback<void(
     bool pairing_supported,
-    const SecretFetchedCallback& secret_fetched_callback)> FetchSecretCallback;
+    const SecretFetchedCallback& secret_fetched_callback)>
+    FetchSecretCallback;
 
 // Callback passed to |FetchTokenCallback|, and called once the client
 // authentication finishes. |token| is an opaque string that should be sent
 // directly to the host. |shared_secret| should be used by the client to
 // create a V2Authenticator. In case of failure, the callback is called with
 // an empty |token| and |shared_secret|.
-typedef base::Callback<void(const std::string& token,
-                            const std::string& shared_secret)>
+typedef base::RepeatingCallback<void(const std::string& token,
+                                     const std::string& shared_secret)>
     ThirdPartyTokenFetchedCallback;
 
 // Fetches a third party token from |token_url|. |host_public_key| is sent to
@@ -32,7 +34,7 @@
 // "hostjid:abc@example.com/123 clientjid:def@example.org/456".
 // |token_fetched_callback| is called when the client authentication ends, on
 // the same thread on which FetchThirdPartyTokenCallback was originally called.
-typedef base::Callback<void(
+typedef base::RepeatingCallback<void(
     const std::string& token_url,
     const std::string& scope,
     const ThirdPartyTokenFetchedCallback& token_fetched_callback)>
diff --git a/remoting/protocol/data_channel_manager.h b/remoting/protocol/data_channel_manager.h
index 32b0198..9891b335 100644
--- a/remoting/protocol/data_channel_manager.h
+++ b/remoting/protocol/data_channel_manager.h
@@ -20,9 +20,9 @@
 // register a function to handle data from a named data channel.
 class DataChannelManager final {
  public:
-  using CreateHandlerCallback = base::Callback<void(
-      const std::string& name,
-      std::unique_ptr<MessagePipe> pipe)>;
+  using CreateHandlerCallback =
+      base::RepeatingCallback<void(const std::string& name,
+                                   std::unique_ptr<MessagePipe> pipe)>;
 
   DataChannelManager();
   ~DataChannelManager();
diff --git a/remoting/protocol/fake_authenticator.cc b/remoting/protocol/fake_authenticator.cc
index 8861b12..b0f46175 100644
--- a/remoting/protocol/fake_authenticator.cc
+++ b/remoting/protocol/fake_authenticator.cc
@@ -29,10 +29,10 @@
 
 void FakeChannelAuthenticator::SecureAndAuthenticate(
     std::unique_ptr<P2PStreamSocket> socket,
-    const DoneCallback& done_callback) {
+    DoneCallback done_callback) {
   socket_ = std::move(socket);
 
-  done_callback_ = done_callback;
+  done_callback_ = std::move(done_callback);
 
   if (async_) {
     if (result_ != net::OK) {
diff --git a/remoting/protocol/fake_authenticator.h b/remoting/protocol/fake_authenticator.h
index deb89d5..eeb2475 100644
--- a/remoting/protocol/fake_authenticator.h
+++ b/remoting/protocol/fake_authenticator.h
@@ -21,7 +21,7 @@
 
   // ChannelAuthenticator interface.
   void SecureAndAuthenticate(std::unique_ptr<P2PStreamSocket> socket,
-                             const DoneCallback& done_callback) override;
+                             DoneCallback done_callback) override;
 
  private:
   void OnAuthBytesWritten(int result);
diff --git a/remoting/protocol/ice_transport_unittest.cc b/remoting/protocol/ice_transport_unittest.cc
index 2c1e214..2730246a 100644
--- a/remoting/protocol/ice_transport_unittest.cc
+++ b/remoting/protocol/ice_transport_unittest.cc
@@ -54,7 +54,7 @@
 
 class TestTransportEventHandler : public IceTransport::EventHandler {
  public:
-  typedef base::Callback<void(ErrorCode error)> ErrorCallback;
+  typedef base::RepeatingCallback<void(ErrorCode error)> ErrorCallback;
 
   TestTransportEventHandler() = default;
   ~TestTransportEventHandler() = default;
diff --git a/remoting/protocol/jingle_session.h b/remoting/protocol/jingle_session.h
index 6004ac4..6a074a9 100644
--- a/remoting/protocol/jingle_session.h
+++ b/remoting/protocol/jingle_session.h
@@ -47,7 +47,8 @@
  private:
   friend class JingleSessionManager;
 
-  typedef base::Callback<void(JingleMessageReply::ErrorType)> ReplyCallback;
+  typedef base::RepeatingCallback<void(JingleMessageReply::ErrorType)>
+      ReplyCallback;
 
   explicit JingleSession(JingleSessionManager* session_manager);
 
diff --git a/remoting/protocol/message_reader.h b/remoting/protocol/message_reader.h
index 03f7083..b20421eb 100644
--- a/remoting/protocol/message_reader.h
+++ b/remoting/protocol/message_reader.h
@@ -36,9 +36,9 @@
 // e.g. when we the sender sends multiple messages in one TCP packet.
 class MessageReader {
  public:
-  typedef base::Callback<void(std::unique_ptr<CompoundBuffer> message)>
+  typedef base::RepeatingCallback<void(std::unique_ptr<CompoundBuffer> message)>
       MessageReceivedCallback;
-  typedef base::Callback<void(int)> ReadFailedCallback;
+  typedef base::RepeatingCallback<void(int)> ReadFailedCallback;
 
   MessageReader();
   virtual ~MessageReader();
diff --git a/remoting/protocol/monitored_video_stub.h b/remoting/protocol/monitored_video_stub.h
index cfc51e7..9d894cf 100644
--- a/remoting/protocol/monitored_video_stub.h
+++ b/remoting/protocol/monitored_video_stub.h
@@ -30,7 +30,7 @@
  public:
   // Callback to be called when channel state changes.  The Callback should not
   // destroy the MonitoredVideoStub object.
-  typedef base::Callback<void(bool connected)> ChannelStateCallback;
+  typedef base::RepeatingCallback<void(bool connected)> ChannelStateCallback;
 
   static const int kConnectivityCheckDelaySeconds = 2;
 
diff --git a/remoting/protocol/pseudotcp_adapter_unittest.cc b/remoting/protocol/pseudotcp_adapter_unittest.cc
index bd22c32d..61e512c 100644
--- a/remoting/protocol/pseudotcp_adapter_unittest.cc
+++ b/remoting/protocol/pseudotcp_adapter_unittest.cc
@@ -79,10 +79,7 @@
 
 class FakeSocket : public P2PDatagramSocket {
  public:
-  FakeSocket()
-      : rate_limiter_(NULL),
-        latency_ms_(0) {
-  }
+  FakeSocket() : rate_limiter_(nullptr), latency_ms_(0) {}
   ~FakeSocket() override = default;
 
   void AppendInputPacket(const std::vector<char>& data) {
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.cc b/remoting/protocol/ssl_hmac_channel_authenticator.cc
index 98e83ec0..27e1bf87 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator.cc
+++ b/remoting/protocol/ssl_hmac_channel_authenticator.cc
@@ -245,10 +245,10 @@
 
 void SslHmacChannelAuthenticator::SecureAndAuthenticate(
     std::unique_ptr<P2PStreamSocket> socket,
-    const DoneCallback& done_callback) {
+    DoneCallback done_callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-  done_callback_ = done_callback;
+  done_callback_ = std::move(done_callback);
 
   int result;
   if (is_ssl_server()) {
diff --git a/remoting/protocol/ssl_hmac_channel_authenticator.h b/remoting/protocol/ssl_hmac_channel_authenticator.h
index 3be3a28e8..64be0c1 100644
--- a/remoting/protocol/ssl_hmac_channel_authenticator.h
+++ b/remoting/protocol/ssl_hmac_channel_authenticator.h
@@ -64,7 +64,7 @@
 
   // ChannelAuthenticator interface.
   void SecureAndAuthenticate(std::unique_ptr<P2PStreamSocket> socket,
-                             const DoneCallback& done_callback) override;
+                             DoneCallback done_callback) override;
 
  private:
   class P2PStreamSocketAdapter;
diff --git a/remoting/protocol/stream_message_pipe_adapter.cc b/remoting/protocol/stream_message_pipe_adapter.cc
index 17ba74d..33d7699 100644
--- a/remoting/protocol/stream_message_pipe_adapter.cc
+++ b/remoting/protocol/stream_message_pipe_adapter.cc
@@ -21,8 +21,8 @@
 
 StreamMessagePipeAdapter::StreamMessagePipeAdapter(
     std::unique_ptr<P2PStreamSocket> socket,
-    const ErrorCallback& error_callback)
-    : socket_(std::move(socket)), error_callback_(error_callback) {
+    ErrorCallback error_callback)
+    : socket_(std::move(socket)), error_callback_(std::move(error_callback)) {
   DCHECK(socket_);
   DCHECK(error_callback_);
 }
diff --git a/remoting/protocol/stream_message_pipe_adapter.h b/remoting/protocol/stream_message_pipe_adapter.h
index 3bcb96c..ebdd2ec 100644
--- a/remoting/protocol/stream_message_pipe_adapter.h
+++ b/remoting/protocol/stream_message_pipe_adapter.h
@@ -22,10 +22,10 @@
 // P2PStreamSocket.
 class StreamMessagePipeAdapter : public MessagePipe {
  public:
-  typedef base::Callback<void(int)> ErrorCallback;
+  typedef base::OnceCallback<void(int)> ErrorCallback;
 
   StreamMessagePipeAdapter(std::unique_ptr<P2PStreamSocket> socket,
-                           const ErrorCallback& error_callback);
+                           ErrorCallback error_callback);
   ~StreamMessagePipeAdapter() override;
 
   // MessagePipe interface.
@@ -49,7 +49,7 @@
 
 class StreamMessageChannelFactoryAdapter : public MessageChannelFactory {
  public:
-  typedef base::Callback<void(int)> ErrorCallback;
+  typedef base::RepeatingCallback<void(int)> ErrorCallback;
 
   StreamMessageChannelFactoryAdapter(
       StreamChannelFactory* stream_channel_factory,
diff --git a/services/audio/output_controller.cc b/services/audio/output_controller.cc
index e8c05d1..9d68bca8 100644
--- a/services/audio/output_controller.cc
+++ b/services/audio/output_controller.cc
@@ -150,7 +150,7 @@
       task_runner_(audio_manager->GetTaskRunner()),
       construction_time_(base::TimeTicks::Now()),
       output_device_id_(output_device_id),
-      stream_(NULL),
+      stream_(nullptr),
       disable_local_output_(false),
       volume_(1.0),
       state_(kEmpty),
diff --git a/services/device/public/cpp/hid/hid_report_descriptor_item.cc b/services/device/public/cpp/hid/hid_report_descriptor_item.cc
index fd406fe6..c40fd7d 100644
--- a/services/device/public/cpp/hid/hid_report_descriptor_item.cc
+++ b/services/device/public/cpp/hid/hid_report_descriptor_item.cc
@@ -26,8 +26,8 @@
     size_t size,
     HidReportDescriptorItem* previous)
     : previous_(previous),
-      next_(NULL),
-      parent_(NULL),
+      next_(nullptr),
+      parent_(nullptr),
       shortData_(0),
       payload_size_(0) {
   Header* header = (Header*)&bytes[0];
diff --git a/services/image_annotation/annotator.cc b/services/image_annotation/annotator.cc
index 53de4424..4c8b943 100644
--- a/services/image_annotation/annotator.cc
+++ b/services/image_annotation/annotator.cc
@@ -737,8 +737,11 @@
     // |request_infos_|, and this method should only execute once per request
     // key.
     const auto request_info_it = request_infos_.find(request_key);
-    if (request_info_it == request_infos_.end())
+    if (request_info_it == request_infos_.end()) {
+      LOG(ERROR) << "Could not find request key in request_infos_: "
+                 << request_key.first << "," << request_key.second;
       continue;
+    }
 
     const auto image_result = result_lookup != results.end()
                                   ? result_lookup->second.Clone()
diff --git a/services/image_annotation/annotator.h b/services/image_annotation/annotator.h
index 572ba32..56ddf90f 100644
--- a/services/image_annotation/annotator.h
+++ b/services/image_annotation/annotator.h
@@ -107,6 +107,7 @@
   FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, ComputePreferredLanguage);
   FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, FetchServerLanguages);
   FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, ServerLanguagesMustContainEnglish);
+  FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, LanguageFallback);
 
   // The relevant info for a request from a client feature for a single image.
   struct ClientRequestInfo {
diff --git a/services/image_annotation/annotator_unittest.cc b/services/image_annotation/annotator_unittest.cc
index 7803095..40e6b6cc 100644
--- a/services/image_annotation/annotator_unittest.cc
+++ b/services/image_annotation/annotator_unittest.cc
@@ -2173,6 +2173,107 @@
                                   mojom::AnnotationType::kOcr, 1.0, "2")));
 }
 
+// Test that annotation works properly when we need to fall back on a
+// different language because the page language isn't available.
+TEST(AnnotatorTest, LanguageFallback) {
+  base::test::TaskEnvironment test_task_env(
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+  TestServerURLLoaderFactory test_url_factory(
+      "https://ia-pa.googleapis.com/v1/");
+  data_decoder::test::InProcessDataDecoder in_process_data_decoder;
+  base::HistogramTester histogram_tester;
+
+  Annotator annotator(GURL(kTestServerUrl), GURL(""),
+                      std::string() /* api_key */, kThrottle,
+                      1 /* batch_size */, 1.0 /* min_ocr_confidence */,
+                      test_url_factory.AsSharedURLLoaderFactory(),
+                      std::make_unique<TestAnnotatorClient>());
+  annotator.server_languages_ = {"en", "it", "fr"};
+
+  TestImageProcessor processor;
+  base::Optional<mojom::AnnotateImageError> error;
+  std::vector<mojom::Annotation> annotations;
+
+  // Send a request in an unsupported language.
+  annotator.AnnotateImage(kImage1Url, "hu", processor.GetPendingRemote(),
+                          base::BindOnce(&ReportResult, &error, &annotations));
+  test_task_env.RunUntilIdle();
+
+  // Send back image data.
+  std::move(processor.callbacks()[0]).Run({1, 2, 3}, kDescDim, kDescDim);
+  processor.callbacks().pop_back();
+  test_task_env.RunUntilIdle();
+
+  // Fast-forward time so that server sends batch.
+  EXPECT_THAT(test_url_factory.requests(), IsEmpty());
+  test_task_env.FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+  // A single HTTP request for all images should have been sent.
+  test_url_factory.ExpectRequestAndSimulateResponse(
+      "annotation", {} /* expected_headers */, ReformatJson(R"(
+        {
+          "imageRequests": [
+            {
+              "imageId": "https://www.example.com/image1.jpg en",
+              "imageBytes": "AQID",
+              "engineParameters": [
+                {"ocrParameters": {}},
+                {
+                  "descriptionParameters": {
+                    "preferredLanguages": ["en"]
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      )"),
+      R"(
+        {
+          "results": [
+            {
+              "imageId": "https://www.example.com/image1.jpg en",
+              "engineResults": [
+                {
+                  "status": {},
+                  "ocrEngine": {
+                    "ocrRegions": [{
+                      "words": [{
+                        "detectedText": "1",
+                        "confidenceScore": 1.0
+                      }]
+                    }]
+                  }
+                },
+                {
+                  "status": {},
+                  "descriptionEngine": {
+                    "descriptionList": {
+                      "descriptions": [{
+                        "type": "CAPTION",
+                        "text": "Result in fallback language.",
+                        "score": 1.0
+                      }]
+                    }
+                  }
+                }
+              ]
+            }
+          ]
+        }
+      )",
+      net::HTTP_OK);
+  test_task_env.RunUntilIdle();
+
+  // Annotator should have called each callback with its corresponding results.
+  ASSERT_EQ(error, base::nullopt);
+  EXPECT_THAT(
+      annotations,
+      UnorderedElementsAre(AnnotatorEq(mojom::AnnotationType::kOcr, 1.0, "1"),
+                           AnnotatorEq(mojom::AnnotationType::kCaption, 1.0,
+                                       "Result in fallback language.")));
+}
+
 // Test that the specified API key is sent, but only to Google-associated server
 // domains.
 TEST(AnnotatorTest, ApiKey) {
diff --git a/services/network/cookie_manager_unittest.cc b/services/network/cookie_manager_unittest.cc
index 803b3de..b66d553e 100644
--- a/services/network/cookie_manager_unittest.cc
+++ b/services/network/cookie_manager_unittest.cc
@@ -110,25 +110,26 @@
         url, options,
         base::BindLambdaForTesting(
             [&run_loop, &cookies_out](
-                const net::CookieStatusList& cookies,
-                const net::CookieStatusList& excluded_cookies) {
-              cookies_out = net::cookie_util::StripStatuses(cookies);
+                const net::CookieAccessResultList& cookies,
+                const net::CookieAccessResultList& excluded_cookies) {
+              cookies_out = net::cookie_util::StripAccessResults(cookies);
               run_loop.Quit();
             }));
     run_loop.Run();
     return cookies_out;
   }
 
-  net::CookieStatusList GetExcludedCookieList(const GURL& url,
-                                              net::CookieOptions options) {
+  net::CookieAccessResultList GetExcludedCookieList(
+      const GURL& url,
+      net::CookieOptions options) {
     base::RunLoop run_loop;
-    net::CookieStatusList cookies_out;
+    net::CookieAccessResultList cookies_out;
     cookie_service_->GetCookieList(
         url, options,
         base::BindLambdaForTesting(
             [&run_loop, &cookies_out](
-                const net::CookieStatusList& cookies,
-                const net::CookieStatusList& excluded_cookies) {
+                const net::CookieAccessResultList& cookies,
+                const net::CookieAccessResultList& excluded_cookies) {
               cookies_out = excluded_cookies;
               run_loop.Quit();
             }));
@@ -587,7 +588,7 @@
 
   net::CookieOptions excluded_options = options;
   excluded_options.set_return_excluded_cookies();
-  net::CookieStatusList excluded_cookies =
+  net::CookieAccessResultList excluded_cookies =
       service_wrapper()->GetExcludedCookieList(
           GURL("https://foo_host.com/with/path"), excluded_options);
 
@@ -595,8 +596,9 @@
 
   EXPECT_EQ("HttpOnly", excluded_cookies[0].cookie.Name());
   EXPECT_EQ("F", excluded_cookies[0].cookie.Value());
-  EXPECT_TRUE(excluded_cookies[0].status.HasExactlyExclusionReasonsForTesting(
-      {net::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
+  EXPECT_TRUE(excluded_cookies[0]
+                  .access_result.status.HasExactlyExclusionReasonsForTesting(
+                      {net::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
 }
 
 TEST_F(CookieManagerTest, GetCookieListHttpOnly) {
@@ -632,7 +634,7 @@
 
   options.set_return_excluded_cookies();
 
-  net::CookieStatusList excluded_cookies =
+  net::CookieAccessResultList excluded_cookies =
       service_wrapper()->GetExcludedCookieList(
           GURL("https://foo_host.com/with/path"), options);
   ASSERT_EQ(1u, excluded_cookies.size());
@@ -688,7 +690,7 @@
 
   options.set_return_excluded_cookies();
 
-  net::CookieStatusList excluded_cookies =
+  net::CookieAccessResultList excluded_cookies =
       service_wrapper()->GetExcludedCookieList(
           GURL("https://foo_host.com/with/path"), options);
   ASSERT_EQ(2u, excluded_cookies.size());
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index bcc0f13..bd54f82 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -84,19 +84,6 @@
 
 constexpr const char kTimingAllowOrigin[] = "Timing-Allow-Origin";
 
-bool IsBodyNotNullAndSourceNull(const ResourceRequestBody* request_body) {
-  if (!request_body)
-    return false;
-  const std::vector<DataElement>* elements = request_body->elements();
-  if (elements->size() == 0u)
-    return false;
-  // https://fetch.spec.whatwg.org/#concept-bodyinit-extract
-  // Body's source is null means the body is not extracted from ReadableStream.
-  if (elements->size() > 1u)
-    return false;
-  return elements->at(0).type() == mojom::DataElementType::kChunkedDataPipe;
-}
-
 }  // namespace
 
 CorsURLLoader::CorsURLLoader(
@@ -382,7 +369,7 @@
   // If |actualResponse|’s status is not 303, |request|’s body is non-null, and
   // |request|’s body’s source is null, then return a network error.
   if (redirect_info.status_code != net::HTTP_SEE_OTHER &&
-      IsBodyNotNullAndSourceNull(request_.request_body.get())) {
+      network::URLLoader::HasStreamingUploadBody(&request_)) {
     HandleComplete(URLLoaderCompletionStatus(net::ERR_INVALID_ARGUMENT));
     return;
   }
diff --git a/services/network/cors/preflight_controller_unittest.cc b/services/network/cors/preflight_controller_unittest.cc
index 619787b..14fe73e 100644
--- a/services/network/cors/preflight_controller_unittest.cc
+++ b/services/network/cors/preflight_controller_unittest.cc
@@ -290,7 +290,7 @@
       int32_t process_id,
       int32_t routing_id,
       const std::string& devtools_request_id,
-      const net::CookieStatusList& cookies_with_status,
+      const net::CookieAccessResultList& cookies_with_access_result,
       std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override {
     on_raw_request_called_ = true;
   }
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index 26c5a7f..26fcead4 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -1000,11 +1000,13 @@
       ct_policy->excluded_spkis, ct_policy->excluded_legacy_spkis);
 }
 
-void NetworkContext::AddExpectCT(const std::string& domain,
-                                 base::Time expiry,
-                                 bool enforce,
-                                 const GURL& report_uri,
-                                 AddExpectCTCallback callback) {
+void NetworkContext::AddExpectCT(
+    const std::string& domain,
+    base::Time expiry,
+    bool enforce,
+    const GURL& report_uri,
+    const net::NetworkIsolationKey& network_isolation_key,
+    AddExpectCTCallback callback) {
   net::TransportSecurityState* transport_security_state =
       url_request_context()->transport_security_state();
   if (!transport_security_state) {
@@ -1013,7 +1015,7 @@
   }
 
   transport_security_state->AddExpectCT(domain, expiry, enforce, report_uri,
-                                        net::NetworkIsolationKey::Todo());
+                                        network_isolation_key);
   std::move(callback).Run(true);
 }
 
@@ -1075,8 +1077,10 @@
   outstanding_set_expect_ct_callbacks_.pop();
 }
 
-void NetworkContext::GetExpectCTState(const std::string& domain,
-                                      GetExpectCTStateCallback callback) {
+void NetworkContext::GetExpectCTState(
+    const std::string& domain,
+    const net::NetworkIsolationKey& network_isolation_key,
+    GetExpectCTStateCallback callback) {
   base::DictionaryValue result;
   if (base::IsStringASCII(domain)) {
     net::TransportSecurityState* transport_security_state =
@@ -1084,7 +1088,7 @@
     if (transport_security_state) {
       net::TransportSecurityState::ExpectCTState dynamic_expect_ct_state;
       bool found = transport_security_state->GetDynamicExpectCTState(
-          domain, net::NetworkIsolationKey::Todo(), &dynamic_expect_ct_state);
+          domain, network_isolation_key, &dynamic_expect_ct_state);
 
       // TODO(estark): query static Expect-CT state as well.
       if (found) {
diff --git a/services/network/network_context.h b/services/network/network_context.h
index f90a5b5..b86486d 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -252,10 +252,12 @@
                    base::Time expiry,
                    bool enforce,
                    const GURL& report_uri,
+                   const net::NetworkIsolationKey& network_isolation_key,
                    AddExpectCTCallback callback) override;
   void SetExpectCTTestReport(const GURL& report_uri,
                              SetExpectCTTestReportCallback callback) override;
   void GetExpectCTState(const std::string& domain,
+                        const net::NetworkIsolationKey& network_isolation_key,
                         GetExpectCTStateCallback callback) override;
 #endif  // BUILDFLAG(IS_CT_SUPPORTED)
   void CreateUDPSocket(
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 01323f3..4b4ef0efc 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -2176,11 +2176,12 @@
   run_loop->Quit();
 }
 
-void GetCookieListCallback(base::RunLoop* run_loop,
-                           net::CookieList* result_out,
-                           const net::CookieStatusList& result,
-                           const net::CookieStatusList& excluded_cookies) {
-  *result_out = net::cookie_util::StripStatuses(result);
+void GetCookieListCallback(
+    base::RunLoop* run_loop,
+    net::CookieList* result_out,
+    const net::CookieAccessResultList& result,
+    const net::CookieAccessResultList& excluded_cookies) {
+  *result_out = net::cookie_util::StripAccessResults(result);
   run_loop->Quit();
 }
 
@@ -4305,6 +4306,10 @@
 
 #if BUILDFLAG(IS_CT_SUPPORTED)
 TEST_F(NetworkContextTest, ExpectCT) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      net::features::kPartitionExpectCTStateByNetworkIsolationKey);
+
   std::unique_ptr<NetworkContext> network_context =
       CreateContextWithParams(CreateContextParams());
 
@@ -4314,12 +4319,15 @@
   const bool enforce = true;
   const GURL report_uri = GURL("https://example.com/foo/bar");
 
+  net::NetworkIsolationKey network_isolation_key =
+      net::NetworkIsolationKey::CreateTransient();
+
   // Assert we start with no data for the test host.
   {
     base::Value state;
     base::RunLoop run_loop;
     network_context->GetExpectCTState(
-        kTestDomain,
+        kTestDomain, network_isolation_key,
         base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
     run_loop.Run();
     EXPECT_TRUE(state.is_dict());
@@ -4335,7 +4343,7 @@
     base::RunLoop run_loop;
     bool result = false;
     network_context->AddExpectCT(
-        kTestDomain, expiry, enforce, report_uri,
+        kTestDomain, expiry, enforce, report_uri, network_isolation_key,
         base::BindOnce(&StoreBool, &result, run_loop.QuitClosure()));
     run_loop.Run();
     EXPECT_TRUE(result);
@@ -4346,7 +4354,7 @@
     base::Value state;
     base::RunLoop run_loop;
     network_context->GetExpectCTState(
-        kTestDomain,
+        kTestDomain, network_isolation_key,
         base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
     run_loop.Run();
     EXPECT_TRUE(state.is_dict());
@@ -4372,6 +4380,22 @@
     EXPECT_EQ(report_uri, value->GetString());
   }
 
+  // Using a different NetworkIsolationKey should return no result.
+  {
+    base::Value state;
+    base::RunLoop run_loop;
+    network_context->GetExpectCTState(
+        kTestDomain, net::NetworkIsolationKey::CreateTransient(),
+        base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
+    run_loop.Run();
+    EXPECT_TRUE(state.is_dict());
+
+    const base::Value* result =
+        state.FindKeyOfType("result", base::Value::Type::BOOLEAN);
+    ASSERT_TRUE(result != nullptr);
+    EXPECT_FALSE(result->GetBool());
+  }
+
   // Delete host data.
   {
     bool result;
@@ -4388,7 +4412,7 @@
     base::Value state;
     base::RunLoop run_loop;
     network_context->GetExpectCTState(
-        kTestDomain,
+        kTestDomain, network_isolation_key,
         base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
     run_loop.Run();
     EXPECT_TRUE(state.is_dict());
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.cc b/services/network/public/cpp/cookie_manager_mojom_traits.cc
index 1333056..d4897d16 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -81,6 +81,48 @@
   return false;
 }
 
+network::mojom::CookieEffectiveSameSite EnumTraits<
+    network::mojom::CookieEffectiveSameSite,
+    net::CookieEffectiveSameSite>::ToMojom(net::CookieEffectiveSameSite input) {
+  switch (input) {
+    case net::CookieEffectiveSameSite::NO_RESTRICTION:
+      return network::mojom::CookieEffectiveSameSite::kNoRestriction;
+    case net::CookieEffectiveSameSite::LAX_MODE:
+      return network::mojom::CookieEffectiveSameSite::kLaxMode;
+    case net::CookieEffectiveSameSite::STRICT_MODE:
+      return network::mojom::CookieEffectiveSameSite::kStrictMode;
+    case net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
+      return network::mojom::CookieEffectiveSameSite::kLaxModeAllowUnsafe;
+    default:
+      break;
+  }
+  NOTREACHED();
+  return static_cast<network::mojom::CookieEffectiveSameSite>(input);
+}
+
+bool EnumTraits<network::mojom::CookieEffectiveSameSite,
+                net::CookieEffectiveSameSite>::
+    FromMojom(network::mojom::CookieEffectiveSameSite input,
+              net::CookieEffectiveSameSite* output) {
+  switch (input) {
+    case network::mojom::CookieEffectiveSameSite::kNoRestriction:
+      *output = net::CookieEffectiveSameSite::NO_RESTRICTION;
+      return true;
+    case network::mojom::CookieEffectiveSameSite::kLaxMode:
+      *output = net::CookieEffectiveSameSite::LAX_MODE;
+      return true;
+    case network::mojom::CookieEffectiveSameSite::kStrictMode:
+      *output = net::CookieEffectiveSameSite::STRICT_MODE;
+      return true;
+    case network::mojom::CookieEffectiveSameSite::kLaxModeAllowUnsafe:
+      *output = net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE;
+      return true;
+    default:
+      break;
+  }
+  return false;
+}
+
 network::mojom::CookieSourceScheme
 EnumTraits<network::mojom::CookieSourceScheme,
            net::CookieSourceScheme>::ToMojom(net::CookieSourceScheme input) {
@@ -397,6 +439,39 @@
 }
 
 bool StructTraits<
+    network::mojom::CookieAccessResultDataView,
+    net::CookieAccessResult>::Read(network::mojom::CookieAccessResultDataView c,
+                                   net::CookieAccessResult* out) {
+  net::CookieEffectiveSameSite effective_same_site;
+  net::CookieInclusionStatus status;
+
+  if (!c.ReadEffectiveSameSite(&effective_same_site))
+    return false;
+  if (!c.ReadStatus(&status))
+    return false;
+
+  *out = {effective_same_site, status};
+
+  return true;
+}
+
+bool StructTraits<network::mojom::CookieWithAccessResultDataView,
+                  net::CookieWithAccessResult>::
+    Read(network::mojom::CookieWithAccessResultDataView c,
+         net::CookieWithAccessResult* out) {
+  net::CanonicalCookie cookie;
+  net::CookieAccessResult access_result;
+  if (!c.ReadCookie(&cookie))
+    return false;
+  if (!c.ReadAccessResult(&access_result))
+    return false;
+
+  *out = {cookie, access_result};
+
+  return true;
+}
+
+bool StructTraits<
     network::mojom::CookieChangeInfoDataView,
     net::CookieChangeInfo>::Read(network::mojom::CookieChangeInfoDataView info,
                                  net::CookieChangeInfo* out) {
diff --git a/services/network/public/cpp/cookie_manager_mojom_traits.h b/services/network/public/cpp/cookie_manager_mojom_traits.h
index f56c9ed7..8b5243c 100644
--- a/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -8,6 +8,7 @@
 #include "ipc/ipc_message_utils.h"
 #include "mojo/public/cpp/bindings/enum_traits.h"
 #include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_access_result.h"
 #include "net/cookies/cookie_change_dispatcher.h"
 #include "net/cookies/cookie_constants.h"
 #include "net/cookies/cookie_inclusion_status.h"
@@ -31,6 +32,15 @@
 };
 
 template <>
+struct EnumTraits<network::mojom::CookieEffectiveSameSite,
+                  net::CookieEffectiveSameSite> {
+  static network::mojom::CookieEffectiveSameSite ToMojom(
+      net::CookieEffectiveSameSite input);
+  static bool FromMojom(network::mojom::CookieEffectiveSameSite input,
+                        net::CookieEffectiveSameSite* output);
+};
+
+template <>
 struct EnumTraits<network::mojom::CookieAccessSemantics,
                   net::CookieAccessSemantics> {
   static network::mojom::CookieAccessSemantics ToMojom(
@@ -191,6 +201,36 @@
 };
 
 template <>
+struct StructTraits<network::mojom::CookieAccessResultDataView,
+                    net::CookieAccessResult> {
+  static const net::CookieEffectiveSameSite& effective_same_site(
+      const net::CookieAccessResult& c) {
+    return c.effective_same_site;
+  }
+  static const net::CookieInclusionStatus& status(
+      const net::CookieAccessResult& c) {
+    return c.status;
+  }
+  static bool Read(network::mojom::CookieAccessResultDataView access_result,
+                   net::CookieAccessResult* out);
+};
+
+template <>
+struct StructTraits<network::mojom::CookieWithAccessResultDataView,
+                    net::CookieWithAccessResult> {
+  static const net::CanonicalCookie& cookie(
+      const net::CookieWithAccessResult& c) {
+    return c.cookie;
+  }
+  static const net::CookieAccessResult& access_result(
+      const net::CookieWithAccessResult& c) {
+    return c.access_result;
+  }
+  static bool Read(network::mojom::CookieWithAccessResultDataView cookie,
+                   net::CookieWithAccessResult* out);
+};
+
+template <>
 struct StructTraits<network::mojom::CookieChangeInfoDataView,
                     net::CookieChangeInfo> {
   static const net::CanonicalCookie& cookie(const net::CookieChangeInfo& c) {
diff --git a/services/network/public/cpp/data_element.cc b/services/network/public/cpp/data_element.cc
index a75bb59..9a95984 100644
--- a/services/network/public/cpp/data_element.cc
+++ b/services/network/public/cpp/data_element.cc
@@ -20,7 +20,7 @@
 
 DataElement::DataElement()
     : type_(mojom::DataElementType::kUnknown),
-      bytes_(NULL),
+      bytes_(nullptr),
       offset_(0),
       length_(std::numeric_limits<uint64_t>::max()) {}
 
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 2484343..4d5bef25d 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -356,6 +356,10 @@
           cpp = "::net::CookieSameSite"
         },
         {
+          mojom = "network.mojom.CookieEffectiveSameSite"
+          cpp = "::net::CookieEffectiveSameSite"
+        },
+        {
           mojom = "network.mojom.CookieSameSiteContext"
           cpp = "::net::CookieOptions::SameSiteCookieContext"
         },
@@ -385,6 +389,10 @@
           cpp = "::net::CookieWithStatus"
         },
         {
+          mojom = "network.mojom.CookieWithAccessResult"
+          cpp = "::net::CookieWithAccessResult"
+        },
+        {
           mojom = "network.mojom.CookieAndLineWithStatus"
           cpp = "::net::CookieAndLineWithStatus"
         },
diff --git a/services/network/public/mojom/cookie_manager.mojom b/services/network/public/mojom/cookie_manager.mojom
index 33e3e70..07aaee6 100644
--- a/services/network/public/mojom/cookie_manager.mojom
+++ b/services/network/public/mojom/cookie_manager.mojom
@@ -78,6 +78,13 @@
   // Reserved 3 (was EXTENDED_MODE), next number is 4.
 };
 
+enum CookieEffectiveSameSite {
+  kNoRestriction = 0,
+  kLaxMode = 1,
+  kStrictMode = 2,
+  kLaxModeAllowUnsafe = 3,
+};
+
 enum ContextType {
   CROSS_SITE,
   SAME_SITE_LAX_METHOD_UNSAFE,
@@ -145,6 +152,16 @@
   CookieInclusionStatus status;
 };
 
+struct CookieAccessResult {
+  CookieEffectiveSameSite effective_same_site;
+  CookieInclusionStatus status;
+};
+
+struct CookieWithAccessResult {
+  CanonicalCookie cookie;
+  CookieAccessResult access_result;
+};
+
 // Keep values here in sync with net::CookieChangeCause.
 enum CookieChangeCause {
   // The cookie was inserted.
@@ -276,8 +293,8 @@
   // blocked from being sent along with the reason each cookie was blocked. By
   // default, that option is not set and |excluded_cookies| is an empty list.
   GetCookieList(url.mojom.Url url, CookieOptions cookie_options)
-      => (array<CookieWithStatus> cookies,
-          array<CookieWithStatus> excluded_cookies);
+      => (array<CookieWithAccessResult> cookies,
+          array<CookieWithAccessResult> excluded_cookies);
 
   // Set a cookie.  |source_url| is used to check whether existing secure
   // cookies can be overwritten (secure cookies may be created from a
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index 1b7e84ec..f51c659 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -1051,7 +1051,8 @@
   // header.
   [EnableIf=is_ct_supported]
   AddExpectCT(string host, mojo_base.mojom.Time expiry,
-              bool enforce, url.mojom.Url report_uri) => (bool success);
+              bool enforce, url.mojom.Url report_uri,
+              NetworkIsolationKey network_isolation_key) => (bool success);
 
   // Send a test CT report with dummy data for test purposes.
   [EnableIf=is_ct_supported]
@@ -1060,7 +1061,9 @@
   // Retrieves the expect CT state from the associated network context
   // transport security state.
   [EnableIf=is_ct_supported]
-  GetExpectCTState(string domain) => (mojo_base.mojom.DictionaryValue state);
+  GetExpectCTState(string domain,
+                   NetworkIsolationKey network_isolation_key)
+                   => (mojo_base.mojom.DictionaryValue state);
 
   // Creates a UDP socket. Caller can supply a |listener| interface pointer
   // to listen for incoming datagrams. A null |listener| is acceptable if caller
diff --git a/services/network/public/mojom/network_service.mojom b/services/network/public/mojom/network_service.mojom
index 6ed2fdd..64a0847 100644
--- a/services/network/public/mojom/network_service.mojom
+++ b/services/network/public/mojom/network_service.mojom
@@ -63,7 +63,7 @@
     int32 process_id,
     int32 routing_id,
     string devtool_request_id,
-    array<CookieWithStatus> cookies_with_status,
+    array<CookieWithAccessResult> cookies_with_access_result,
     array<HttpRawHeaderPair> headers);
 
   // Called to send information about the cookies blocked from storage from a
diff --git a/services/network/restricted_cookie_manager.cc b/services/network/restricted_cookie_manager.cc
index 00f5bbd..02f94e1a 100644
--- a/services/network/restricted_cookie_manager.cc
+++ b/services/network/restricted_cookie_manager.cc
@@ -127,7 +127,7 @@
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     if (!change.cookie
              .IncludeForRequestURL(url_, options_, change.access_semantics)
-             .IsInclude()) {
+             .status.IsInclude()) {
       return;
     }
 
@@ -236,8 +236,8 @@
     const net::CookieOptions& net_options,
     mojom::CookieManagerGetOptionsPtr options,
     GetAllForUrlCallback callback,
-    const net::CookieStatusList& cookie_list,
-    const net::CookieStatusList& excluded_cookies) {
+    const net::CookieAccessResultList& cookie_list,
+    const net::CookieAccessResultList& excluded_cookies) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   bool blocked = !cookie_settings_->IsCookieAccessAllowed(
@@ -248,10 +248,11 @@
 
   // TODO(https://crbug.com/977040): Remove once samesite tightening up is
   // rolled out.
-  for (const auto& cookie_and_status : excluded_cookies) {
-    if (cookie_and_status.status.ShouldWarn()) {
+  for (const auto& cookie_and_access_result : excluded_cookies) {
+    if (cookie_and_access_result.access_result.status.ShouldWarn()) {
       result_with_status.push_back(
-          {cookie_and_status.cookie, cookie_and_status.status});
+          {cookie_and_access_result.cookie,
+           cookie_and_access_result.access_result.status});
     }
   }
 
@@ -260,9 +261,9 @@
   mojom::CookieMatchType match_type = options->match_type;
   const std::string& match_name = options->name;
   // TODO(https://crbug.com/993843): Use the statuses passed in |cookie_list|.
-  for (size_t i = 0; i < cookie_list.size(); ++i) {
-    const net::CanonicalCookie& cookie = cookie_list[i].cookie;
-    net::CookieInclusionStatus status = cookie_list[i].status;
+  for (const net::CookieWithAccessResult& cookie_item : cookie_list) {
+    const net::CanonicalCookie& cookie = cookie_item.cookie;
+    net::CookieInclusionStatus status = cookie_item.access_result.status;
     const std::string& cookie_name = cookie.Name();
 
     if (match_type == mojom::CookieMatchType::EQUALS) {
diff --git a/services/network/restricted_cookie_manager.h b/services/network/restricted_cookie_manager.h
index 53285bf1..1b0b508 100644
--- a/services/network/restricted_cookie_manager.h
+++ b/services/network/restricted_cookie_manager.h
@@ -112,8 +112,8 @@
       const net::CookieOptions& net_options,
       mojom::CookieManagerGetOptionsPtr options,
       GetAllForUrlCallback callback,
-      const net::CookieStatusList& cookie_list,
-      const net::CookieStatusList& excluded_cookies);
+      const net::CookieAccessResultList& cookie_list,
+      const net::CookieAccessResultList& excluded_cookies);
 
   // Reports the result of setting the cookie to |network_context_client_|, and
   // invokes the user callback.
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
index eff66d99..4349662b 100644
--- a/services/network/test/test_network_context.h
+++ b/services/network/test/test_network_context.h
@@ -117,10 +117,12 @@
                    base::Time expiry,
                    bool enforce,
                    const GURL& report_uri,
+                   const net::NetworkIsolationKey& network_isolation_key,
                    AddExpectCTCallback callback) override {}
   void SetExpectCTTestReport(const GURL& report_uri,
                              SetExpectCTTestReportCallback callback) override {}
   void GetExpectCTState(const std::string& domain,
+                        const net::NetworkIsolationKey& network_isolation_key,
                         GetExpectCTStateCallback callback) override {}
 #endif  // BUILDFLAG(IS_CT_SUPPORTED)
   void CreateUDPSocket(
diff --git a/services/network/test/test_network_service_client.cc b/services/network/test/test_network_service_client.cc
index efb2858..2ea8f96 100644
--- a/services/network/test/test_network_service_client.cc
+++ b/services/network/test/test_network_service_client.cc
@@ -33,7 +33,7 @@
     int32_t process_id,
     int32_t routing_id,
     const std::string& devtools_request_id,
-    const net::CookieStatusList& cookies_with_status,
+    const net::CookieAccessResultList& cookies_with_access_result,
     std::vector<network::mojom::HttpRawHeaderPairPtr> headers) {}
 
 void TestNetworkServiceClient::OnRawResponse(
diff --git a/services/network/test/test_network_service_client.h b/services/network/test/test_network_service_client.h
index c855c37..b43acef 100644
--- a/services/network/test/test_network_service_client.h
+++ b/services/network/test/test_network_service_client.h
@@ -36,7 +36,7 @@
       int32_t process_id,
       int32_t routing_id,
       const std::string& devtools_request_id,
-      const net::CookieStatusList& cookies_with_status,
+      const net::CookieAccessResultList& cookies_with_access_result,
       std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override;
   void OnRawResponse(
       int32_t process_id,
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 5d98448..26711d6 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -479,7 +479,8 @@
       origin_policy_manager_(nullptr),
       trust_token_helper_factory_(std::move(trust_token_helper_factory)),
       isolated_world_origin_(request.isolated_world_origin),
-      cookie_observer_(std::move(cookie_observer)) {
+      cookie_observer_(std::move(cookie_observer)),
+      has_streaming_upload_body_(HasStreamingUploadBody(&request)) {
   DCHECK(delete_callback_);
   DCHECK(factory_params_);
   if (url_loader_header_client &&
@@ -992,8 +993,29 @@
   url_loader_client_->OnReceiveRedirect(redirect_info, std::move(response));
 }
 
+// static
+bool URLLoader::HasStreamingUploadBody(const ResourceRequest* request) {
+  const ResourceRequestBody* request_body = request->request_body.get();
+  if (!request_body)
+    return false;
+  const std::vector<DataElement>* elements = request_body->elements();
+  if (elements->size() == 0u)
+    return false;
+  // https://fetch.spec.whatwg.org/#concept-bodyinit-extract
+  // Body's source is null means the body is not extracted from ReadableStream.
+  // See blink::PopulateResourceRequest() for actual construction.
+  if (elements->size() > 1u)
+    return false;
+  return elements->at(0).type() == mojom::DataElementType::kChunkedDataPipe;
+}
+
 void URLLoader::OnAuthRequired(net::URLRequest* url_request,
                                const net::AuthChallengeInfo& auth_info) {
+  if (has_streaming_upload_body_) {
+    NotifyCompleted(net::ERR_FAILED);
+    // |this| may have been deleted.
+    return;
+  }
   if (!network_context_client_) {
     OnAuthCredentials(base::nullopt);
     return;
@@ -1725,10 +1747,13 @@
 
   if (cookie_observer_) {
     net::CookieStatusList reported_cookies;
-    for (const auto& cookie_and_status : url_request_->maybe_sent_cookies()) {
-      if (ShouldNotifyAboutCookie(cookie_and_status.status)) {
+    for (const auto& cookie_with_access_result :
+         url_request_->maybe_sent_cookies()) {
+      if (ShouldNotifyAboutCookie(
+              cookie_with_access_result.access_result.status)) {
         reported_cookies.push_back(
-            {cookie_and_status.cookie, cookie_and_status.status});
+            {cookie_with_access_result.cookie,
+             cookie_with_access_result.access_result.status});
       }
     }
 
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 077344d..f5436f1 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -210,6 +210,8 @@
       const net::HttpRequestHeaders& request_headers,
       bool added_during_redirect);
 
+  static bool HasStreamingUploadBody(const ResourceRequest*);
+
  private:
   // This class is used to set the URLLoader as user data on a URLRequest. This
   // is used instead of URLLoader directly because SetUserData requires a
@@ -493,6 +495,8 @@
   // Observer listening to all cookie reads and writes made by this request.
   mojo::Remote<mojom::CookieAccessObserver> cookie_observer_;
 
+  const bool has_streaming_upload_body_;
+
   base::WeakPtrFactory<URLLoader> weak_ptr_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(URLLoader);
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index 2e6c2e9..981fd26d 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -2716,11 +2716,11 @@
       int32_t process_id,
       int32_t routing_id,
       const std::string& devtools_request_id,
-      const net::CookieStatusList& cookies_with_status,
+      const net::CookieAccessResultList& cookies_with_access_result,
       std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override {
     raw_request_cookies_.insert(raw_request_cookies_.end(),
-                                cookies_with_status.begin(),
-                                cookies_with_status.end());
+                                cookies_with_access_result.begin(),
+                                cookies_with_access_result.end());
 
     devtools_request_id_ = devtools_request_id;
 
@@ -2778,7 +2778,7 @@
     return raw_response_cookies_;
   }
 
-  const net::CookieStatusList& raw_request_cookies() const {
+  const net::CookieAccessResultList& raw_request_cookies() const {
     return raw_request_cookies_;
   }
 
@@ -2795,7 +2795,7 @@
   std::string devtools_request_id_;
   base::Optional<std::string> raw_response_headers_;
 
-  net::CookieStatusList raw_request_cookies_;
+  net::CookieAccessResultList raw_request_cookies_;
   base::OnceClosure wait_for_raw_request_;
   size_t wait_for_raw_request_goal_ = 0u;
 
@@ -4066,8 +4066,8 @@
               network_service_client.raw_request_cookies()[0].cookie.Name());
     EXPECT_EQ("b",
               network_service_client.raw_request_cookies()[0].cookie.Value());
-    EXPECT_TRUE(
-        network_service_client.raw_request_cookies()[0].status.IsInclude());
+    EXPECT_TRUE(network_service_client.raw_request_cookies()[0]
+                    .access_result.status.IsInclude());
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
   }
@@ -4120,7 +4120,7 @@
     EXPECT_EQ("b",
               network_service_client.raw_request_cookies()[0].cookie.Value());
     EXPECT_TRUE(network_service_client.raw_request_cookies()[0]
-                    .status.HasExactlyExclusionReasonsForTesting(
+                    .access_result.status.HasExactlyExclusionReasonsForTesting(
                         {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
 
     EXPECT_EQ("TEST", network_service_client.devtools_request_id());
diff --git a/services/preferences/tracked/pref_hash_filter_unittest.cc b/services/preferences/tracked/pref_hash_filter_unittest.cc
index 5dadce21..ecdbe6d 100644
--- a/services/preferences/tracked/pref_hash_filter_unittest.cc
+++ b/services/preferences/tracked/pref_hash_filter_unittest.cc
@@ -542,7 +542,7 @@
                            public prefs::mojom::ResetOnLoadObserver {
  public:
   PrefHashFilterTest()
-      : mock_pref_hash_store_(NULL),
+      : mock_pref_hash_store_(nullptr),
         pref_store_contents_(new base::DictionaryValue),
         mock_validation_delegate_record_(new MockValidationDelegateRecord),
         mock_validation_delegate_(mock_validation_delegate_record_),
diff --git a/services/tracing/public/cpp/trace_event_args_whitelist.cc b/services/tracing/public/cpp/trace_event_args_whitelist.cc
index 34da69af..335d8dc 100644
--- a/services/tracing/public/cpp/trace_event_args_whitelist.cc
+++ b/services/tracing/public/cpp/trace_event_args_whitelist.cc
@@ -38,6 +38,7 @@
 const char* const kRendererHostAllowedArgs[] = {
     "class",           "line", "should_background", "has_pending_views",
     "bytes_allocated", nullptr};
+const char* const kUIAllowedArgs[] = {"dpi", "message_id", nullptr};
 const char* const kV8GCAllowedArgs[] = {"num_items", "num_tasks", nullptr};
 const char* const kTopLevelFlowAllowedArgs[] = {"task_queue_name", nullptr};
 const char* const kTopLevelIpcRunTaskAllowedArgs[] = {"ipc_hash", nullptr};
@@ -92,6 +93,8 @@
     {TRACE_DISABLED_BY_DEFAULT("memory-infra"), "*", kMemoryDumpAllowedArgs},
     {TRACE_DISABLED_BY_DEFAULT("system_stats"), "*", nullptr},
     {TRACE_DISABLED_BY_DEFAULT("v8.gc"), "*", kV8GCAllowedArgs},
+    {"ui", "HWNDMessageHandler::OnWndProc", kUIAllowedArgs},
+    {"ui", "HWNDMessageHandler::OnDwmCompositionChanged", kUIAllowedArgs},
     {"ui", "RenderTextHarfBuzz::FallbackFont", kFallbackFontAllowedArgs},
     {"ui", "RenderTextHarfBuzz::GetFallbackFonts",
      kGetFallbackFontsAllowedArgs},
diff --git a/skia/BUILD.gn b/skia/BUILD.gn
index 30ddca2..2eb485b3 100644
--- a/skia/BUILD.gn
+++ b/skia/BUILD.gn
@@ -433,8 +433,13 @@
   if (is_mac || is_ios) {
     set_sources_assignment_filter([])
     sources += [
-      "//third_party/skia/src/ports/SkFontHost_mac.cpp",
-      "//third_party/skia/src/utils/mac/SkStream_mac.cpp",
+      "//third_party/skia/include/ports/SkFontMgr_mac_ct.h",
+      "//third_party/skia/src/ports/SkFontMgr_mac_ct.cpp",
+      "//third_party/skia/src/ports/SkFontMgr_mac_ct_factory.cpp",
+      "//third_party/skia/src/ports/SkScalerContext_mac_ct.cpp",
+      "//third_party/skia/src/ports/SkScalerContext_mac_ct.h",
+      "//third_party/skia/src/ports/SkTypeface_mac_ct.cpp",
+      "//third_party/skia/src/ports/SkTypeface_mac_ct.h",
     ]
     set_sources_assignment_filter(sources_assignment_filter)
   }
@@ -564,7 +569,13 @@
   if (is_ios) {
     libs = [ "ImageIO.framework" ]
     set_sources_assignment_filter([])
-    sources += [ "//third_party/skia/src/utils/mac/SkCreateCGImageRef.cpp" ]
+    sources += [
+      "//third_party/skia/src/utils/mac/SkCGBase.h",
+      "//third_party/skia/src/utils/mac/SkCGGeometry.h",
+      "//third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.cpp",
+      "//third_party/skia/src/utils/mac/SkCTFontSmoothBehavior.h",
+      "//third_party/skia/src/utils/mac/SkCreateCGImageRef.cpp",
+    ]
     set_sources_assignment_filter(sources_assignment_filter)
   }
 
diff --git a/storage/browser/file_system/sandbox_file_stream_writer.cc b/storage/browser/file_system/sandbox_file_stream_writer.cc
index 4e140b60..afaedd2a 100644
--- a/storage/browser/file_system/sandbox_file_stream_writer.cc
+++ b/storage/browser/file_system/sandbox_file_stream_writer.cc
@@ -223,6 +223,10 @@
   has_pending_operation_ = false;
 
   if (write_response <= 0) {
+    // TODO(crbug.com/1091792): Consider listening explicitly for out
+    // of space errors instead of surfacing all write errors to quota.
+    file_system_context_->quota_manager_proxy()->NotifyWriteFailed(
+        url_.origin());
     if (CancelIfRequested())
       return;
     std::move(write_callback_).Run(write_response);
diff --git a/testing/buildbot/chrome.ci.json b/testing/buildbot/chrome.ci.json
index dc08f9c..f8d23e82 100644
--- a/testing/buildbot/chrome.ci.json
+++ b/testing/buildbot/chrome.ci.json
@@ -1367,8 +1367,11 @@
         "args": [
           "--stop-ui",
           "--env-var",
+          "LIBVA_DRIVERS_PATH",
+          "/usr/local/lib64",
+          "--env-var",
           "LIBVA_DRIVER_NAME",
-          "i965",
+          "fake",
           "--env-var",
           "LIBVA_FOOL_DECODE",
           "1",
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index 14817c3..4b24777 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -724,8 +724,11 @@
         "args": [
           "--stop-ui",
           "--env-var",
+          "LIBVA_DRIVERS_PATH",
+          "/usr/local/lib64",
+          "--env-var",
           "LIBVA_DRIVER_NAME",
-          "i965",
+          "fake",
           "--env-var",
           "LIBVA_FOOL_DECODE",
           "1",
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json
index 475b578..1d2c1ba 100644
--- a/testing/buildbot/chromium.android.fyi.json
+++ b/testing/buildbot/chromium.android.fyi.json
@@ -4779,6 +4779,65 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd.template",
+              "ssd": "1"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json
index 4bb8021..7049d04 100644
--- a/testing/buildbot/chromium.android.json
+++ b/testing/buildbot/chromium.android.json
@@ -5320,6 +5320,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": "LMY48I",
+              "device_os_type": "userdebug",
+              "device_type": "hammerhead",
+              "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -8637,6 +8684,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": 21600,
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -12087,6 +12181,52 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -15403,6 +15543,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -19870,6 +20057,52 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -28094,6 +28327,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -32235,6 +32515,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": "PQ3A.190801.002",
+              "device_os_flavor": "google",
+              "device_os_type": "userdebug",
+              "device_type": "walleye",
+              "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_cts_tests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -36740,6 +37067,65 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd.template",
+              "ssd": "1"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android28",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_28_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_cts_tests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
diff --git a/testing/buildbot/chromium.chromiumos.json b/testing/buildbot/chromium.chromiumos.json
index 26deb0f3..838095e2 100644
--- a/testing/buildbot/chromium.chromiumos.json
+++ b/testing/buildbot/chromium.chromiumos.json
@@ -625,8 +625,11 @@
         "args": [
           "--stop-ui",
           "--env-var",
+          "LIBVA_DRIVERS_PATH",
+          "/usr/local/lib64",
+          "--env-var",
           "LIBVA_DRIVER_NAME",
-          "i965",
+          "fake",
           "--env-var",
           "LIBVA_FOOL_DECODE",
           "1",
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json
index 63e1e26..b30bfe0 100644
--- a/testing/buildbot/chromium.ci.json
+++ b/testing/buildbot/chromium.ci.json
@@ -6924,14 +6924,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6948,7 +6948,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -7093,7 +7093,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -7104,7 +7104,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -7126,7 +7126,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -7135,7 +7135,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -7146,7 +7146,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -7168,7 +7168,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -7177,7 +7177,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -7185,7 +7185,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -7202,7 +7202,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -7460,14 +7460,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -7484,7 +7484,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -7629,7 +7629,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -7640,7 +7640,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -7662,7 +7662,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -7671,7 +7671,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -7682,7 +7682,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -7704,7 +7704,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -7713,7 +7713,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -7721,7 +7721,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -7738,7 +7738,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -7981,14 +7981,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8004,7 +8004,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -8145,7 +8145,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8156,7 +8156,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8177,7 +8177,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -8186,7 +8186,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8197,7 +8197,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8218,7 +8218,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -8254,7 +8254,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -8262,7 +8262,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8278,7 +8278,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -8568,14 +8568,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8592,7 +8592,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -8737,7 +8737,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8748,7 +8748,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8770,7 +8770,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -8779,7 +8779,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8790,7 +8790,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8812,7 +8812,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -8821,7 +8821,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -8829,7 +8829,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8846,7 +8846,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -9183,14 +9183,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -9207,7 +9207,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -9352,7 +9352,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9363,7 +9363,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9385,7 +9385,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -9394,7 +9394,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9405,7 +9405,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9427,7 +9427,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -9436,7 +9436,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -9444,7 +9444,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -9461,7 +9461,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -9750,14 +9750,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -9774,7 +9774,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -9919,7 +9919,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9930,7 +9930,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9952,7 +9952,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -9961,7 +9961,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9972,7 +9972,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9994,7 +9994,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -10003,7 +10003,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -10011,7 +10011,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10028,7 +10028,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -10109,7 +10109,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -10120,7 +10120,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -10142,7 +10142,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -10151,7 +10151,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -10159,7 +10159,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10176,7 +10176,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -10551,14 +10551,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10574,7 +10574,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -10715,7 +10715,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -10726,7 +10726,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -10747,7 +10747,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -10756,7 +10756,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -10767,7 +10767,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -10788,7 +10788,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -10825,7 +10825,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -10833,7 +10833,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10849,7 +10849,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -16546,7 +16546,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -16555,7 +16555,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -16570,7 +16570,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -16579,7 +16579,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -16612,7 +16612,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -16645,7 +16645,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -16678,7 +16678,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--expected-vendor-id",
           "1af4",
           "--expected-device-id",
@@ -16715,7 +16715,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -16728,7 +16728,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -16748,7 +16748,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -16757,7 +16757,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -16770,7 +16770,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -16790,7 +16790,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -16799,7 +16799,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
@@ -16809,7 +16809,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -16824,7 +16824,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -16833,7 +16833,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -16866,7 +16866,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
@@ -16939,7 +16939,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -16947,7 +16947,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -16963,7 +16963,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -16975,7 +16975,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -17011,7 +17011,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -17047,7 +17047,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -17083,7 +17083,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--expected-vendor-id",
           "0",
           "--expected-device-id",
@@ -17123,7 +17123,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -17135,7 +17135,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -17156,7 +17156,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -17168,7 +17168,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -17180,7 +17180,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -17201,7 +17201,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -17213,7 +17213,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--remote=variable_chromeos_device_hostname"
         ],
@@ -17222,7 +17222,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -17238,7 +17238,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -17250,7 +17250,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -17286,7 +17286,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json",
           "--remote=variable_chromeos_device_hostname"
         ],
@@ -35755,14 +35755,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -35777,7 +35777,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -35946,7 +35977,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -35957,7 +35988,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -35977,7 +36008,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -35986,7 +36057,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -35997,7 +36068,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -36017,7 +36088,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -36026,7 +36137,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -36034,7 +36145,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -36049,7 +36160,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -36272,14 +36415,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -36294,7 +36437,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -36431,7 +36605,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -36442,7 +36616,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -36462,7 +36636,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -36471,7 +36685,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -36482,7 +36696,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -36502,7 +36716,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -36511,7 +36765,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -36519,7 +36773,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -36534,7 +36788,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -37054,14 +37340,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -37077,7 +37363,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -37218,7 +37536,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -37229,7 +37547,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -37250,7 +37568,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -37259,7 +37618,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -37270,7 +37629,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -37291,7 +37650,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -37300,7 +37700,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -37308,7 +37708,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -37324,7 +37724,40 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -37646,14 +38079,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -37668,7 +38101,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -37805,7 +38269,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -37816,7 +38280,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -37836,7 +38300,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -37845,7 +38349,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -37856,7 +38360,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -37876,7 +38380,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -37885,7 +38429,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -37893,7 +38437,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -37908,7 +38452,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -38267,14 +38843,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -38290,7 +38866,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -38431,7 +39039,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -38442,7 +39050,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -38463,7 +39071,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -38472,7 +39121,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -38483,7 +39132,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -38504,7 +39153,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -38513,7 +39203,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -38521,7 +39211,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -38537,7 +39227,40 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -38922,14 +39645,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -38944,7 +39667,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -39081,7 +39835,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -39092,7 +39846,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -39112,7 +39866,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -39121,7 +39915,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -39132,7 +39926,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -39152,7 +39946,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -39161,7 +39995,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -39169,7 +40003,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -39184,7 +40018,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -43089,14 +43955,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -43111,7 +43977,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -43280,7 +44177,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -43291,7 +44188,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -43311,7 +44208,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -43320,7 +44257,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -43331,7 +44268,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -43351,7 +44288,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -43360,7 +44337,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -43368,7 +44345,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -43383,7 +44360,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -52569,6 +53578,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": "LMY48I",
+              "device_os_type": "userdebug",
+              "device_type": "hammerhead",
+              "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -55886,6 +56942,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": 21600,
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -57288,14 +58391,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -57309,7 +58412,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -57442,7 +58545,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -57453,7 +58556,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -57472,7 +58575,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -57481,7 +58584,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -57492,7 +58595,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -57511,7 +58614,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -57520,7 +58623,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -57528,7 +58631,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -57542,7 +58645,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -57799,14 +58902,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -57820,7 +58923,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -57953,7 +59056,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -57964,7 +59067,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -57983,7 +59086,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -57992,7 +59095,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -58003,7 +59106,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -58022,7 +59125,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -58031,7 +59134,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -58039,7 +59142,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -58053,7 +59156,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -58325,14 +59428,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -58347,7 +59450,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -58484,7 +59587,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -58495,7 +59598,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -58515,7 +59618,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -58524,7 +59627,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -58535,7 +59638,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -58555,7 +59658,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -58589,7 +59692,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -58597,7 +59700,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -58612,7 +59715,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -59157,7 +60260,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--is-asan"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -59165,7 +60268,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -59185,7 +60288,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -59302,7 +60405,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -59313,7 +60416,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -59338,7 +60441,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -59347,7 +60450,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -59358,7 +60461,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -59383,7 +60486,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -59392,7 +60495,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -59400,7 +60503,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -59420,7 +60523,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -59869,14 +60972,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -59890,7 +60993,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -60023,7 +61126,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -60034,7 +61137,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -60053,7 +61156,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -60062,7 +61165,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -60073,7 +61176,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -60092,7 +61195,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -60125,7 +61228,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -60133,7 +61236,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -60147,7 +61250,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -60548,14 +61651,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -60571,7 +61674,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -60712,7 +61815,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -60723,7 +61826,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -60744,7 +61847,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -60753,7 +61856,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -60764,7 +61867,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -60785,7 +61888,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -60794,7 +61897,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -60802,7 +61905,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -60818,7 +61921,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -61095,14 +62198,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -61118,7 +62221,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -61259,7 +62362,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -61270,7 +62373,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -61291,7 +62394,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -61300,7 +62403,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -61311,7 +62414,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -61332,7 +62435,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -61341,7 +62444,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -61349,7 +62452,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -61365,7 +62468,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -61636,14 +62739,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -61659,7 +62762,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -61800,7 +62903,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -61811,7 +62914,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -61832,7 +62935,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -61841,7 +62944,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -61852,7 +62955,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -61873,7 +62976,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -61908,7 +63011,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -61916,7 +63019,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -61932,7 +63035,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -62373,14 +63476,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -62396,7 +63499,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -62537,7 +63640,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -62548,7 +63651,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -62569,7 +63672,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -62578,7 +63681,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -62589,7 +63692,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -62610,7 +63713,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -62619,7 +63722,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -62627,7 +63730,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -62643,7 +63746,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -63277,14 +64380,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -63300,7 +64403,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -63441,7 +64544,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -63452,7 +64555,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -63473,7 +64576,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -63482,7 +64585,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -63493,7 +64596,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -63514,7 +64617,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -63523,7 +64626,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -63531,7 +64634,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -63547,7 +64650,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -63825,14 +64928,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -63846,7 +64949,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -63979,7 +65082,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -63990,7 +65093,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -64009,7 +65112,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -64018,7 +65121,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -64029,7 +65132,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -64048,7 +65151,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -64081,7 +65184,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -64089,7 +65192,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -64103,7 +65206,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -64280,7 +65383,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -64288,7 +65391,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -64302,7 +65405,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -64439,7 +65542,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -64451,7 +65554,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -64470,7 +65573,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -64479,7 +65582,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -64491,7 +65594,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -64510,7 +65613,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -64544,7 +65647,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -64553,7 +65656,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -64567,7 +65670,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -64722,14 +65825,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -64745,7 +65848,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -64886,7 +65989,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -64897,7 +66000,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -64918,7 +66021,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -64927,7 +66030,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -64938,7 +66041,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -64959,7 +66062,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -64968,7 +66071,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -64976,7 +66079,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -64992,7 +66095,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -65177,14 +66280,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -65200,7 +66303,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -65341,7 +66444,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -65352,7 +66455,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -65373,7 +66476,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -65382,7 +66485,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -65393,7 +66496,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -65414,7 +66517,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -65449,7 +66552,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -65457,7 +66560,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -65473,7 +66576,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -65662,7 +66765,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -65670,7 +66773,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -65686,7 +66789,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -65831,7 +66934,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -65843,7 +66946,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -65864,7 +66967,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -65873,7 +66976,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -65885,7 +66988,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -65906,7 +67009,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -65942,7 +67045,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -65951,7 +67054,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -65967,7 +67070,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -83008,6 +84111,52 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -86324,6 +87473,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -131526,14 +132722,14 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -131548,7 +132744,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -131685,7 +132881,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -131696,7 +132892,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -131716,7 +132912,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -131725,7 +132921,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -131736,7 +132932,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -131756,7 +132952,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -131765,7 +132961,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -131773,7 +132969,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -131788,7 +132984,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -132343,14 +133539,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -132366,7 +133562,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -132509,7 +133705,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -132520,7 +133716,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -132541,7 +133737,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -132550,7 +133746,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -132561,7 +133757,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -132582,7 +133778,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -132650,7 +133846,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -132658,7 +133854,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -132674,7 +133870,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -133232,14 +134428,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -133255,7 +134451,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -133396,7 +134592,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -133407,7 +134603,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -133428,7 +134624,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -133437,7 +134633,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -133448,7 +134644,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -133469,7 +134665,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -133478,7 +134674,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -133486,7 +134682,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -133502,7 +134698,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -134049,14 +135245,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -134071,7 +135267,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -134208,7 +135404,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -134219,7 +135415,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -134239,7 +135435,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -134248,7 +135444,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -134259,7 +135455,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -134279,7 +135475,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -134345,7 +135541,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -134353,7 +135549,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -134368,7 +135564,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -134991,14 +136187,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -135014,7 +136210,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -135155,7 +136351,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -135166,7 +136362,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -135187,7 +136383,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -135196,7 +136392,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -135207,7 +136403,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -135228,7 +136424,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -135296,7 +136492,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -135304,7 +136500,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -135320,7 +136516,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -135921,14 +137117,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -135944,7 +137140,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -136085,7 +137281,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -136096,7 +137292,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -136117,7 +137313,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -136126,7 +137322,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -136137,7 +137333,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -136158,7 +137354,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -136167,7 +137363,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -136175,7 +137371,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -136191,7 +137387,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -136806,14 +138002,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -136828,7 +138024,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -136965,7 +138161,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -136976,7 +138172,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -136996,7 +138192,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -137036,7 +138232,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -137047,7 +138243,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -137067,7 +138263,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -137102,7 +138298,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -137110,7 +138306,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -137125,7 +138321,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -138633,14 +139829,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -138655,7 +139851,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -138792,7 +139988,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -138803,7 +139999,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -138823,7 +140019,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -138863,7 +140059,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -138874,7 +140070,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -138894,7 +140090,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -138928,7 +140124,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -138936,7 +140132,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -138951,7 +140147,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -148101,14 +149297,14 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --no-sandbox"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle --no-sandbox"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -148123,7 +149319,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -148292,7 +149488,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -148303,7 +149499,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -148323,7 +149519,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -148332,7 +149528,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -148343,7 +149539,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -148363,7 +149559,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -148372,7 +149568,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -148380,7 +149576,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -148395,7 +149591,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -148604,7 +149800,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -148612,7 +149808,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -148627,7 +149823,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -148801,7 +149997,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -148813,7 +150009,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -148833,7 +150029,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -148842,7 +150038,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -148854,7 +150050,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -148874,7 +150070,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -148910,7 +150106,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -148919,7 +150115,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -148934,7 +150130,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -149145,7 +150341,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -149153,7 +150349,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -149168,7 +150364,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -149342,7 +150538,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -149354,7 +150550,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -149374,7 +150570,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -149383,7 +150579,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -149395,7 +150591,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -149415,7 +150611,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -149451,7 +150647,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -149460,7 +150656,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -149475,7 +150671,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -150112,14 +151308,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -150135,7 +151331,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -150276,7 +151472,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -150287,7 +151483,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -150308,7 +151504,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -150317,7 +151513,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -150328,7 +151524,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -150349,7 +151545,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -150358,7 +151554,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -150366,7 +151562,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -150382,7 +151578,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -150798,14 +151994,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -150821,7 +152017,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -150962,7 +152158,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -150973,7 +152169,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -150994,7 +152190,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -151003,7 +152199,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -151014,7 +152210,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -151035,7 +152231,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -151044,7 +152240,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -151052,7 +152248,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -151068,7 +152264,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -151552,14 +152748,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -151575,7 +152771,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -151716,7 +152912,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -151727,7 +152923,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -151748,7 +152944,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -151757,7 +152953,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -151768,7 +152964,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -151789,7 +152985,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -151798,7 +152994,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -151806,7 +153002,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -151822,7 +153018,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -152399,14 +153595,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -152422,7 +153618,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -152563,7 +153759,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -152574,7 +153770,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -152595,7 +153791,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -152604,7 +153800,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -152615,7 +153811,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -152636,7 +153832,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -152645,7 +153841,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -152653,7 +153849,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -152669,7 +153865,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -159635,6 +160831,52 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -166344,6 +167586,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -176881,6 +178170,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -181143,6 +182479,65 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd.template",
+              "ssd": "1"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android23",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_23_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android23.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -185481,6 +186876,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": "PQ3A.190801.002",
+              "device_os_flavor": "google",
+              "device_os_type": "userdebug",
+              "device_type": "walleye",
+              "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_cts_tests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -189986,6 +191428,65 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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": [
+            {
+              "cpu": "x86-64",
+              "device_os": null,
+              "device_type": null,
+              "os": "Ubuntu-16.04",
+              "pool": "chromium.tests.avd.template",
+              "ssd": "1"
+            }
+          ],
+          "named_caches": [
+            {
+              "name": "avd_generic_android28",
+              "path": ".android"
+            },
+            {
+              "name": "system_images_android_28_google_apis_x86",
+              "path": ".emulator_sdk"
+            }
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices",
+          "--avd-config=../../tools/android/avd/proto/generic_android28.textpb"
+        ],
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_cts_tests"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -191090,8 +192591,11 @@
         "args": [
           "--stop-ui",
           "--env-var",
+          "LIBVA_DRIVERS_PATH",
+          "/usr/local/lib64",
+          "--env-var",
           "LIBVA_DRIVER_NAME",
-          "i965",
+          "fake",
           "--env-var",
           "LIBVA_FOOL_DECODE",
           "1",
@@ -194537,14 +196041,14 @@
           "--browser=web-engine-shell",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "fuchsia_telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -194557,7 +196061,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -205794,20 +207298,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "base_unittests_iPad Air 2 13.4",
+        "name": "base_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -205824,7 +207328,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -205837,20 +207341,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "base_unittests_iPhone X 13.4",
+        "name": "base_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -205867,7 +207371,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -205880,20 +207384,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_crypto_tests_iPad Air 2 13.4",
+        "name": "boringssl_crypto_tests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -205910,7 +207414,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -205923,20 +207427,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_crypto_tests_iPhone X 13.4",
+        "name": "boringssl_crypto_tests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -205953,7 +207457,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -205966,20 +207470,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_ssl_tests_iPad Air 2 13.4",
+        "name": "boringssl_ssl_tests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -205996,7 +207500,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206009,20 +207513,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_ssl_tests_iPhone X 13.4",
+        "name": "boringssl_ssl_tests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206039,7 +207543,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206052,20 +207556,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "components_unittests_iPad Air 2 13.4",
+        "name": "components_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206082,7 +207586,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206095,20 +207599,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "components_unittests_iPhone X 13.4",
+        "name": "components_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206125,7 +207629,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206138,20 +207642,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "crypto_unittests_iPad Air 2 13.4",
+        "name": "crypto_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206168,7 +207672,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206181,20 +207685,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "crypto_unittests_iPhone X 13.4",
+        "name": "crypto_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206211,7 +207715,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206224,20 +207728,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "gfx_unittests_iPad Air 2 13.4",
+        "name": "gfx_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206254,7 +207758,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206267,20 +207771,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "gfx_unittests_iPhone X 13.4",
+        "name": "gfx_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206297,7 +207801,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206310,20 +207814,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "google_apis_unittests_iPad Air 2 13.4",
+        "name": "google_apis_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206340,7 +207844,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206353,20 +207857,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "google_apis_unittests_iPhone X 13.4",
+        "name": "google_apis_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206383,7 +207887,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206396,20 +207900,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206426,7 +207930,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206439,20 +207943,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206469,7 +207973,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206482,20 +207986,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206512,7 +208016,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206526,20 +208030,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_integration_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_integration_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206556,7 +208060,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206570,20 +208074,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206600,7 +208104,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206614,20 +208118,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206644,7 +208148,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206658,20 +208162,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206688,7 +208192,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206701,20 +208205,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_signin_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_signin_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206731,7 +208235,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206744,20 +208248,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206774,7 +208278,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206787,20 +208291,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206817,7 +208321,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206830,20 +208334,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206860,7 +208364,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206874,20 +208378,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_ui_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_ui_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206904,7 +208408,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206918,20 +208422,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_unittests_iPad Air 2 13.4",
+        "name": "ios_chrome_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206948,7 +208452,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -206961,20 +208465,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_unittests_iPhone X 13.4",
+        "name": "ios_chrome_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -206991,7 +208495,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207004,20 +208508,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207034,7 +208538,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207047,20 +208551,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_web_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_web_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207077,7 +208581,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207090,20 +208594,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_components_unittests_iPad Air 2 13.4",
+        "name": "ios_components_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207120,7 +208624,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207133,20 +208637,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_components_unittests_iPhone X 13.4",
+        "name": "ios_components_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207163,7 +208667,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207176,20 +208680,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_net_unittests_iPad Air 2 13.4",
+        "name": "ios_net_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207206,7 +208710,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207219,20 +208723,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_net_unittests_iPhone X 13.4",
+        "name": "ios_net_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207249,7 +208753,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207262,20 +208766,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_remoting_unittests_iPad Air 2 13.4",
+        "name": "ios_remoting_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207292,7 +208796,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207305,20 +208809,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_remoting_unittests_iPhone X 13.4",
+        "name": "ios_remoting_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207335,7 +208839,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207348,20 +208852,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_showcase_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_showcase_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207378,7 +208882,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207391,20 +208895,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_showcase_eg2tests_module_iPhone X 13.4",
+        "name": "ios_showcase_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207421,7 +208925,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207434,20 +208938,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_testing_unittests_iPad Air 2 13.4",
+        "name": "ios_testing_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207464,7 +208968,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207477,20 +208981,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_testing_unittests_iPhone X 13.4",
+        "name": "ios_testing_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207507,7 +209011,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207520,20 +209024,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_inttests_iPad Air 2 13.4",
+        "name": "ios_web_inttests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207550,7 +209054,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207563,20 +209067,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_inttests_iPhone X 13.4",
+        "name": "ios_web_inttests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207593,7 +209097,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207606,20 +209110,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207636,7 +209140,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207649,20 +209153,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_shell_eg2tests_module_iPhone X 13.4",
+        "name": "ios_web_shell_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207679,7 +209183,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207692,20 +209196,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_unittests_iPad Air 2 13.4",
+        "name": "ios_web_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207722,7 +209226,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207735,20 +209239,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_unittests_iPhone X 13.4",
+        "name": "ios_web_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207765,7 +209269,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207778,20 +209282,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_inttests_iPad Air 2 13.4",
+        "name": "ios_web_view_inttests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207808,7 +209312,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207821,20 +209325,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_inttests_iPhone X 13.4",
+        "name": "ios_web_view_inttests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207851,7 +209355,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207864,20 +209368,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_unittests_iPad Air 2 13.4",
+        "name": "ios_web_view_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207894,7 +209398,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207907,20 +209411,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_unittests_iPhone X 13.4",
+        "name": "ios_web_view_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207937,7 +209441,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207950,20 +209454,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "net_unittests_iPad Air 2 13.4",
+        "name": "net_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -207980,7 +209484,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -207993,20 +209497,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "net_unittests_iPhone X 13.4",
+        "name": "net_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208023,7 +209527,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208036,20 +209540,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "services_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "services_unittests_iPad Air 2 13.4",
+        "name": "services_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208066,7 +209570,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208079,20 +209583,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "services_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "services_unittests_iPhone X 13.4",
+        "name": "services_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208109,7 +209613,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208122,20 +209626,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "skia_unittests_iPad Air 2 13.4",
+        "name": "skia_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208152,7 +209656,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208165,20 +209669,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "skia_unittests_iPhone X 13.4",
+        "name": "skia_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208195,7 +209699,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208208,20 +209712,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "sql_unittests_iPad Air 2 13.4",
+        "name": "sql_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208238,7 +209742,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208251,20 +209755,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "sql_unittests_iPhone X 13.4",
+        "name": "sql_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208281,7 +209785,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208294,20 +209798,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ui_base_unittests_iPad Air 2 13.4",
+        "name": "ui_base_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208324,7 +209828,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208337,20 +209841,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ui_base_unittests_iPhone X 13.4",
+        "name": "ui_base_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208367,7 +209871,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208380,20 +209884,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "url_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "url_unittests_iPad Air 2 13.4",
+        "name": "url_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208410,7 +209914,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -208423,20 +209927,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "url_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "url_unittests_iPhone X 13.4",
+        "name": "url_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -208453,7 +209957,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 56171e3..0d33d368 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -9201,6 +9201,53 @@
             "--bucket",
             "chromium-result-details",
             "--test-name",
+            "weblayer_unittests"
+          ],
+          "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"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "weblayer_unittests",
+        "test_id_prefix": "ninja://weblayer/test:weblayer_unittests/"
+      },
+      {
+        "args": [
+          "--gs-results-bucket=chromium-result-details",
+          "--recover-devices"
+        ],
+        "isolate_profile_data": true,
+        "merge": {
+          "args": [
+            "--bucket",
+            "chromium-result-details",
+            "--test-name",
             "webview_instrumentation_test_apk"
           ],
           "script": "//build/android/pylib/results/presentation/test_results_presentation.py"
@@ -15223,14 +15270,14 @@
           "--browser=web-engine-shell",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "fuchsia_telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -15243,7 +15290,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://content/test:fuchsia_telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -21962,20 +22009,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "base_unittests_iPad Air 2 13.4",
+        "name": "base_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -21992,7 +22039,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22005,20 +22052,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "base_unittests_iPhone X 13.4",
+        "name": "base_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22035,7 +22082,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22048,20 +22095,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_crypto_tests_iPad Air 2 13.4",
+        "name": "boringssl_crypto_tests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22078,7 +22125,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22091,20 +22138,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_crypto_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_crypto_tests_iPhone X 13.4",
+        "name": "boringssl_crypto_tests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22121,7 +22168,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22134,20 +22181,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_ssl_tests_iPad Air 2 13.4",
+        "name": "boringssl_ssl_tests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22164,7 +22211,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22177,20 +22224,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "boringssl_ssl_tests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "boringssl_ssl_tests_iPhone X 13.4",
+        "name": "boringssl_ssl_tests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22207,7 +22254,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22220,20 +22267,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "components_unittests_iPad Air 2 13.4",
+        "name": "components_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22250,7 +22297,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22263,20 +22310,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "components_unittests_iPhone X 13.4",
+        "name": "components_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22293,7 +22340,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22306,20 +22353,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "crypto_unittests_iPad Air 2 13.4",
+        "name": "crypto_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22336,7 +22383,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22349,20 +22396,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "crypto_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "crypto_unittests_iPhone X 13.4",
+        "name": "crypto_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22379,7 +22426,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22392,20 +22439,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "gfx_unittests_iPad Air 2 13.4",
+        "name": "gfx_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22422,7 +22469,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22435,20 +22482,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "gfx_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "gfx_unittests_iPhone X 13.4",
+        "name": "gfx_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22465,7 +22512,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22478,20 +22525,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "google_apis_unittests_iPad Air 2 13.4",
+        "name": "google_apis_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22508,7 +22555,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22521,20 +22568,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "google_apis_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "google_apis_unittests_iPhone X 13.4",
+        "name": "google_apis_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22551,7 +22598,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22564,20 +22611,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22594,7 +22641,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22607,20 +22654,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_bookmarks_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22637,7 +22684,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22650,20 +22697,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22680,7 +22727,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22694,20 +22741,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_integration_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_integration_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_integration_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22724,7 +22771,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22738,20 +22785,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22768,7 +22815,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22782,20 +22829,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_settings_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_settings_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22812,7 +22859,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22826,20 +22873,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22856,7 +22903,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22869,20 +22916,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_signin_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_signin_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_signin_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22899,7 +22946,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22912,20 +22959,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22942,7 +22989,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22955,20 +23002,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_smoke_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_smoke_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -22985,7 +23032,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -22998,20 +23045,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23028,7 +23075,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23042,20 +23089,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_ui_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_ui_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_ui_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23072,7 +23119,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23086,20 +23133,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_unittests_iPad Air 2 13.4",
+        "name": "ios_chrome_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23116,7 +23163,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23129,20 +23176,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_unittests_iPhone X 13.4",
+        "name": "ios_chrome_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23159,7 +23206,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23172,20 +23219,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_chrome_web_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23202,7 +23249,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23215,20 +23262,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_chrome_web_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_chrome_web_eg2tests_module_iPhone X 13.4",
+        "name": "ios_chrome_web_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23245,7 +23292,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23258,20 +23305,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_components_unittests_iPad Air 2 13.4",
+        "name": "ios_components_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23288,7 +23335,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23301,20 +23348,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_components_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_components_unittests_iPhone X 13.4",
+        "name": "ios_components_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23331,7 +23378,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23344,20 +23391,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_net_unittests_iPad Air 2 13.4",
+        "name": "ios_net_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23374,7 +23421,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23387,20 +23434,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_net_unittests_iPhone X 13.4",
+        "name": "ios_net_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23417,7 +23464,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23430,20 +23477,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_remoting_unittests_iPad Air 2 13.4",
+        "name": "ios_remoting_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23460,7 +23507,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23473,20 +23520,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_remoting_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_remoting_unittests_iPhone X 13.4",
+        "name": "ios_remoting_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23503,7 +23550,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23516,20 +23563,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_showcase_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_showcase_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23546,7 +23593,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23559,20 +23606,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_showcase_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_showcase_eg2tests_module_iPhone X 13.4",
+        "name": "ios_showcase_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23589,7 +23636,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23602,20 +23649,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_testing_unittests_iPad Air 2 13.4",
+        "name": "ios_testing_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23632,7 +23679,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23645,20 +23692,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_testing_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_testing_unittests_iPhone X 13.4",
+        "name": "ios_testing_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23675,7 +23722,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23688,20 +23735,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_inttests_iPad Air 2 13.4",
+        "name": "ios_web_inttests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23718,7 +23765,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23731,20 +23778,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_inttests_iPhone X 13.4",
+        "name": "ios_web_inttests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23761,7 +23808,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23774,20 +23821,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.4",
+        "name": "ios_web_shell_eg2tests_module_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23804,7 +23851,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23817,20 +23864,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_shell_eg2tests_module",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_shell_eg2tests_module_iPhone X 13.4",
+        "name": "ios_web_shell_eg2tests_module_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23847,7 +23894,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23860,20 +23907,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_unittests_iPad Air 2 13.4",
+        "name": "ios_web_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23890,7 +23937,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23903,20 +23950,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_unittests_iPhone X 13.4",
+        "name": "ios_web_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23933,7 +23980,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23946,20 +23993,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_inttests_iPad Air 2 13.4",
+        "name": "ios_web_view_inttests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -23976,7 +24023,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -23989,20 +24036,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_inttests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_inttests_iPhone X 13.4",
+        "name": "ios_web_view_inttests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24019,7 +24066,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24032,20 +24079,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_unittests_iPad Air 2 13.4",
+        "name": "ios_web_view_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24062,7 +24109,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24075,20 +24122,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ios_web_view_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ios_web_view_unittests_iPhone X 13.4",
+        "name": "ios_web_view_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24105,7 +24152,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24118,20 +24165,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "net_unittests_iPad Air 2 13.4",
+        "name": "net_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24148,7 +24195,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24161,20 +24208,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "net_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "net_unittests_iPhone X 13.4",
+        "name": "net_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24191,7 +24238,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24204,20 +24251,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "services_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "services_unittests_iPad Air 2 13.4",
+        "name": "services_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24234,7 +24281,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24247,20 +24294,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "services_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "services_unittests_iPhone X 13.4",
+        "name": "services_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24277,7 +24324,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24290,20 +24337,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "skia_unittests_iPad Air 2 13.4",
+        "name": "skia_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24320,7 +24367,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24333,20 +24380,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "skia_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "skia_unittests_iPhone X 13.4",
+        "name": "skia_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24363,7 +24410,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24376,20 +24423,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "sql_unittests_iPad Air 2 13.4",
+        "name": "sql_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24406,7 +24453,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24419,20 +24466,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "sql_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "sql_unittests_iPhone X 13.4",
+        "name": "sql_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24449,7 +24496,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24462,20 +24509,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ui_base_unittests_iPad Air 2 13.4",
+        "name": "ui_base_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24492,7 +24539,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24505,20 +24552,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "ui_base_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "ui_base_unittests_iPhone X 13.4",
+        "name": "ui_base_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24535,7 +24582,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24548,20 +24595,20 @@
           "--platform",
           "iPad Air 2",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "url_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "url_unittests_iPad Air 2 13.4",
+        "name": "url_unittests_iPad Air 2 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24578,7 +24625,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
@@ -24591,20 +24638,20 @@
           "--platform",
           "iPhone X",
           "--version",
-          "13.4",
+          "13.5",
           "--args-json",
           "{\"test_args\": [\"--run-with-custom-webkit\"]}",
           "--out-dir",
           "${ISOLATED_OUTDIR}",
           "--xcode-build-version",
-          "11e146"
+          "11e608c"
         ],
         "isolate_name": "url_unittests",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "url_unittests_iPhone X 13.4",
+        "name": "url_unittests_iPhone X 13.5",
         "swarming": {
           "can_use_on_swarming_builders": true,
           "cipd_packages": [
@@ -24621,7 +24668,7 @@
           ],
           "named_caches": [
             {
-              "name": "xcode_ios_11e146",
+              "name": "xcode_ios_11e608c",
               "path": "Xcode.app"
             }
           ],
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json
index c0b46213c..472711d 100644
--- a/testing/buildbot/chromium.gpu.fyi.json
+++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -3760,14 +3760,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3784,7 +3784,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -3929,7 +3929,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -3940,7 +3940,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -3962,7 +3962,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -3971,7 +3971,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -3982,7 +3982,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -4004,7 +4004,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -4013,7 +4013,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -4021,7 +4021,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4038,7 +4038,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -4296,14 +4296,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4320,7 +4320,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -4465,7 +4465,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -4476,7 +4476,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -4498,7 +4498,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -4507,7 +4507,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -4518,7 +4518,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -4540,7 +4540,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -4549,7 +4549,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -4557,7 +4557,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4574,7 +4574,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -4817,14 +4817,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4840,7 +4840,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -4981,7 +4981,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -4992,7 +4992,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -5013,7 +5013,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -5022,7 +5022,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -5033,7 +5033,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -5054,7 +5054,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -5090,7 +5090,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -5098,7 +5098,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -5114,7 +5114,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -5404,14 +5404,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -5428,7 +5428,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -5573,7 +5573,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -5584,7 +5584,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -5606,7 +5606,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -5615,7 +5615,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -5626,7 +5626,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -5648,7 +5648,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -5657,7 +5657,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -5665,7 +5665,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -5682,7 +5682,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -6019,14 +6019,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6043,7 +6043,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -6188,7 +6188,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -6199,7 +6199,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -6221,7 +6221,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -6230,7 +6230,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -6241,7 +6241,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -6263,7 +6263,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -6272,7 +6272,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -6280,7 +6280,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6297,7 +6297,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -6586,14 +6586,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6610,7 +6610,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -6755,7 +6755,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -6766,7 +6766,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -6788,7 +6788,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -6797,7 +6797,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -6808,7 +6808,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -6830,7 +6830,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -6839,7 +6839,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -6847,7 +6847,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -6864,7 +6864,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -6945,7 +6945,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -6956,7 +6956,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -6978,7 +6978,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -6987,7 +6987,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -6995,7 +6995,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -7012,7 +7012,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -7417,7 +7417,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -7426,7 +7426,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -7441,7 +7441,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -7450,7 +7450,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -7483,7 +7483,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -7516,7 +7516,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -7549,7 +7549,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--expected-vendor-id",
           "1af4",
           "--expected-device-id",
@@ -7586,7 +7586,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -7599,7 +7599,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -7619,7 +7619,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -7628,7 +7628,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -7641,7 +7641,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -7661,7 +7661,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -7670,7 +7670,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
@@ -7680,7 +7680,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -7695,7 +7695,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -7704,7 +7704,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
         ],
@@ -7737,7 +7737,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json",
           "--remote=127.0.0.1",
           "--remote-ssh-port=9222"
@@ -7810,7 +7810,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -7818,7 +7818,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -7834,7 +7834,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -7846,7 +7846,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -7882,7 +7882,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -7918,7 +7918,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -7954,7 +7954,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --force_high_performance_gpu",
           "--expected-vendor-id",
           "0",
           "--expected-device-id",
@@ -7994,7 +7994,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8006,7 +8006,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8027,7 +8027,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -8039,7 +8039,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8051,7 +8051,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8072,7 +8072,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -8084,7 +8084,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--remote=variable_chromeos_device_hostname"
         ],
@@ -8093,7 +8093,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8109,7 +8109,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/",
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/",
         "trigger_script": {
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
@@ -8121,7 +8121,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
           "--remote=variable_chromeos_device_hostname"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -8157,7 +8157,7 @@
           "--browser=cros-chrome",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating --force_high_performance_gpu",
           "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl_conformance_tests_output.json",
           "--remote=variable_chromeos_device_hostname"
         ],
@@ -8366,14 +8366,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8388,7 +8388,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -8525,7 +8556,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8536,7 +8567,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8556,7 +8587,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -8565,7 +8636,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -8576,7 +8647,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -8596,7 +8667,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -8605,7 +8716,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -8613,7 +8724,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -8628,7 +8739,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -9148,14 +9291,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -9171,7 +9314,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -9312,7 +9487,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9323,7 +9498,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9344,7 +9519,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -9353,7 +9569,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9364,7 +9580,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9385,7 +9601,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -9394,7 +9651,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -9402,7 +9659,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -9418,7 +9675,40 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "1002:6613",
+              "os": "Ubuntu",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 21600,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -9740,14 +10030,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -9762,7 +10052,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -9899,7 +10220,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9910,7 +10231,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9930,7 +10251,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -9939,7 +10300,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -9950,7 +10311,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -9970,7 +10331,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -9979,7 +10380,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -9987,7 +10388,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10002,7 +10403,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:5912-19.0.2",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -10361,14 +10794,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10384,7 +10817,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -10525,7 +10990,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -10536,7 +11001,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -10557,7 +11022,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -10566,7 +11072,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -10577,7 +11083,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -10598,7 +11104,48 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -10607,7 +11154,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -10615,7 +11162,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -10631,7 +11178,40 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "8086:3e92-19.0.8",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "expiration": 14400,
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -11016,14 +11596,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -11038,7 +11618,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -11175,7 +11786,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -11186,7 +11797,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -11206,7 +11817,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -11215,7 +11866,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -11226,7 +11877,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -11246,7 +11897,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -11255,7 +11946,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -11263,7 +11954,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -11278,7 +11969,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -12968,14 +13691,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -12989,7 +13712,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -13122,7 +13845,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -13133,7 +13856,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -13152,7 +13875,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -13161,7 +13884,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -13172,7 +13895,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -13191,7 +13914,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -13200,7 +13923,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -13208,7 +13931,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -13222,7 +13945,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -13494,14 +14217,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -13516,7 +14239,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -13653,7 +14376,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -13664,7 +14387,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -13684,7 +14407,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -13693,7 +14416,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -13704,7 +14427,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -13724,7 +14447,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -13758,7 +14481,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -13766,7 +14489,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -13781,7 +14504,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -14326,7 +15049,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--is-asan"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -14334,7 +15057,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -14354,7 +15077,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -14471,7 +15194,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -14482,7 +15205,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -14507,7 +15230,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -14516,7 +15239,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -14527,7 +15250,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -14552,7 +15275,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -14561,7 +15284,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -14569,7 +15292,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -14589,7 +15312,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -15038,14 +15761,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -15059,7 +15782,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -15192,7 +15915,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -15203,7 +15926,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -15222,7 +15945,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -15231,7 +15954,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -15242,7 +15965,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -15261,7 +15984,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -15294,7 +16017,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -15302,7 +16025,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -15316,7 +16039,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -15717,14 +16440,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -15740,7 +16463,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -15881,7 +16604,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -15892,7 +16615,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -15913,7 +16636,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -15922,7 +16645,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -15933,7 +16656,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -15954,7 +16677,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -15963,7 +16686,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -15971,7 +16694,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -15987,7 +16710,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -16264,14 +16987,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -16287,7 +17010,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -16428,7 +17151,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -16439,7 +17162,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -16460,7 +17183,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -16469,7 +17192,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -16480,7 +17203,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -16501,7 +17224,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -16510,7 +17233,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -16518,7 +17241,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -16534,7 +17257,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -16805,14 +17528,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -16828,7 +17551,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -16969,7 +17692,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -16980,7 +17703,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -17001,7 +17724,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -17010,7 +17733,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -17021,7 +17744,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -17042,7 +17765,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -17077,7 +17800,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -17085,7 +17808,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -17101,7 +17824,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -17542,14 +18265,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -17565,7 +18288,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -17706,7 +18429,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -17717,7 +18440,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -17738,7 +18461,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -17747,7 +18470,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -17758,7 +18481,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -17779,7 +18502,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -17788,7 +18511,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -17796,7 +18519,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -17812,7 +18535,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -18446,14 +19169,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -18469,7 +19192,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -18610,7 +19333,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -18621,7 +19344,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -18642,7 +19365,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -18651,7 +19374,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -18662,7 +19385,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -18683,7 +19406,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -18692,7 +19415,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -18700,7 +19423,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -18716,7 +19439,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -21555,14 +22278,14 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -21577,7 +22300,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -21714,7 +22437,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -21725,7 +22448,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -21745,7 +22468,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -21754,7 +22477,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -21765,7 +22488,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -21785,7 +22508,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -21794,7 +22517,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -21802,7 +22525,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -21817,7 +22540,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -22372,14 +23095,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -22395,7 +23118,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -22538,7 +23261,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -22549,7 +23272,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -22570,7 +23293,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -22579,7 +23302,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -22590,7 +23313,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -22611,7 +23334,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -22679,7 +23402,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -22687,7 +23410,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -22703,7 +23426,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -23261,14 +23984,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -23284,7 +24007,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -23425,7 +24148,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -23436,7 +24159,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -23457,7 +24180,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -23466,7 +24189,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -23477,7 +24200,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -23498,7 +24221,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -23507,7 +24230,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -23515,7 +24238,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -23531,7 +24254,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -24078,14 +24801,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -24100,7 +24823,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -24237,7 +24960,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -24248,7 +24971,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -24268,7 +24991,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -24277,7 +25000,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -24288,7 +25011,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -24308,7 +25031,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -24374,7 +25097,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -24382,7 +25105,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -24397,7 +25120,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -25020,14 +25743,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -25043,7 +25766,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -25184,7 +25907,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -25195,7 +25918,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -25216,7 +25939,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -25225,7 +25948,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -25236,7 +25959,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -25257,7 +25980,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -25325,7 +26048,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -25333,7 +26056,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -25349,7 +26072,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -25950,14 +26673,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -25973,7 +26696,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -26114,7 +26837,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -26125,7 +26848,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -26146,7 +26869,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -26155,7 +26878,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -26166,7 +26889,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -26187,7 +26910,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -26196,7 +26919,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -26204,7 +26927,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -26220,7 +26943,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -26835,14 +27558,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -26857,7 +27580,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -26994,7 +27717,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -27005,7 +27728,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -27025,7 +27748,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -27065,7 +27788,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -27076,7 +27799,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -27096,7 +27819,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -27131,7 +27854,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -27139,7 +27862,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -27154,7 +27877,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -28662,14 +29385,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -28684,7 +29407,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -28821,7 +29544,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -28832,7 +29555,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -28852,7 +29575,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -28892,7 +29615,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -28903,7 +29626,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -28923,7 +29646,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -28957,7 +29680,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -28965,7 +29688,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -28980,7 +29703,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -29683,14 +30406,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -29706,7 +30429,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -29847,7 +30570,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -29858,7 +30581,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -29879,7 +30602,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -29888,7 +30611,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -29899,7 +30622,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -29920,7 +30643,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -29929,7 +30652,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -29937,7 +30660,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -29953,7 +30676,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -30369,14 +31092,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -30392,7 +31115,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -30533,7 +31256,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -30544,7 +31267,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -30565,7 +31288,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -30574,7 +31297,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -30585,7 +31308,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -30606,7 +31329,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -30615,7 +31338,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -30623,7 +31346,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -30639,7 +31362,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -31123,14 +31846,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -31146,7 +31869,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -31287,7 +32010,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -31298,7 +32021,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -31319,7 +32042,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -31328,7 +32051,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -31339,7 +32062,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -31360,7 +32083,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -31369,7 +32092,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -31377,7 +32100,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -31393,7 +32116,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -31970,14 +32693,14 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -31993,7 +32716,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -32134,7 +32857,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -32145,7 +32868,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -32166,7 +32889,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -32175,7 +32898,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -32186,7 +32909,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -32207,7 +32930,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -32216,7 +32939,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -32224,7 +32947,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -32240,7 +32963,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
diff --git a/testing/buildbot/chromium.gpu.json b/testing/buildbot/chromium.gpu.json
index fd26cd114..3ccfdb3 100644
--- a/testing/buildbot/chromium.gpu.json
+++ b/testing/buildbot/chromium.gpu.json
@@ -10,14 +10,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -33,7 +33,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -174,7 +174,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -185,7 +185,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -206,7 +206,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -215,7 +215,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -226,7 +226,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -247,7 +247,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -284,7 +284,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -292,7 +292,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -308,7 +308,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -470,14 +470,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -492,7 +492,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -661,7 +692,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -672,7 +703,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -692,7 +723,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -701,7 +772,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -712,7 +783,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -732,7 +803,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -741,7 +852,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -749,7 +860,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -764,7 +875,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=debug",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -919,14 +1062,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -941,7 +1084,38 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
+      },
+      {
+        "args": [
+          "context_lost",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "context_lost_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -1110,7 +1284,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1121,7 +1295,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1141,7 +1315,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
+      },
+      {
+        "args": [
+          "maps",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "maps_pixel_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -1150,7 +1364,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1161,7 +1375,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1181,7 +1395,47 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
+      },
+      {
+        "args": [
+          "pixel",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test",
+          "--test-machine-name",
+          "${buildername}",
+          "--git-revision=${got_revision}"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "pixel_skia_gold_validating_test",
+        "precommit_args": [
+          "--gerrit-issue=${patch_issue}",
+          "--gerrit-patchset=${patch_set}",
+          "--buildbucket-id=${buildbucket_build_id}"
+        ],
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -1190,7 +1444,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -1198,7 +1452,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1213,7 +1467,39 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
+      },
+      {
+        "args": [
+          "screenshot_sync",
+          "--show-stdout",
+          "--browser=release",
+          "--passthrough",
+          "-v",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
+          "--dont-restore-color-profile-after-test"
+        ],
+        "isolate_name": "telemetry_gpu_integration_test",
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
+        },
+        "name": "screenshot_sync_validating_tests",
+        "should_retry_with_patch": false,
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "containment_type": "AUTO",
+          "dimension_sets": [
+            {
+              "gpu": "10de:1cb3-418.56",
+              "os": "Ubuntu-19.04",
+              "pool": "chromium.tests.gpu.template"
+            }
+          ],
+          "idempotent": false,
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -1362,14 +1648,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1383,7 +1669,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -1516,7 +1802,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1527,7 +1813,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1546,7 +1832,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -1555,7 +1841,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1566,7 +1852,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1585,7 +1871,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -1594,7 +1880,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -1602,7 +1888,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1616,7 +1902,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -1789,14 +2075,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1810,7 +2096,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -1943,7 +2229,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1954,7 +2240,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1973,7 +2259,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -1982,7 +2268,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1993,7 +2279,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2012,7 +2298,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -2045,7 +2331,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -2053,7 +2339,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2067,7 +2353,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -2244,7 +2530,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -2252,7 +2538,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2266,7 +2552,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -2403,7 +2689,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2415,7 +2701,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2434,7 +2720,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -2443,7 +2729,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2455,7 +2741,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2474,7 +2760,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -2508,7 +2794,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -2517,7 +2803,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2531,7 +2817,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -2686,14 +2972,14 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2709,7 +2995,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -2850,7 +3136,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2861,7 +3147,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2882,7 +3168,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -2891,7 +3177,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2902,7 +3188,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2923,7 +3209,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -2932,7 +3218,7 @@
           "--browser=debug",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -2940,7 +3226,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2956,7 +3242,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -3141,14 +3427,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3164,7 +3450,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -3305,7 +3591,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -3316,7 +3602,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -3337,7 +3623,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -3346,7 +3632,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -3357,7 +3643,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -3378,7 +3664,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -3413,7 +3699,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -3421,7 +3707,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3437,7 +3723,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -3626,7 +3912,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -3634,7 +3920,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3650,7 +3936,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -3795,7 +4081,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -3807,7 +4093,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -3828,7 +4114,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -3837,7 +4123,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -3849,7 +4135,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -3870,7 +4156,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -3906,7 +4192,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -3915,7 +4201,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3931,7 +4217,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -4139,14 +4425,14 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --no-sandbox"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle --no-sandbox"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4161,7 +4447,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -4330,7 +4616,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -4341,7 +4627,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -4361,7 +4647,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -4370,7 +4656,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -4381,7 +4667,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -4401,7 +4687,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -4410,7 +4696,7 @@
           "--browser=debug_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -4418,7 +4704,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4433,7 +4719,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -4642,7 +4928,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -4650,7 +4936,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4665,7 +4951,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -4839,7 +5125,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -4851,7 +5137,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -4871,7 +5157,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -4880,7 +5166,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -4892,7 +5178,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -4912,7 +5198,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -4948,7 +5234,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -4957,7 +5243,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -4972,7 +5258,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -5183,7 +5469,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "isolate_profile_data": true,
@@ -5191,7 +5477,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -5206,7 +5492,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -5380,7 +5666,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -5392,7 +5678,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -5412,7 +5698,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -5421,7 +5707,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -5433,7 +5719,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -5453,7 +5739,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -5489,7 +5775,7 @@
           "--browser=release_x64",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -5498,7 +5784,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -5513,7 +5799,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
diff --git a/testing/buildbot/client.v8.fyi.json b/testing/buildbot/client.v8.fyi.json
index c515228..0844f6a 100644
--- a/testing/buildbot/client.v8.fyi.json
+++ b/testing/buildbot/client.v8.fyi.json
@@ -10,14 +10,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -32,7 +32,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -134,7 +134,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -145,7 +145,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -165,7 +165,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -174,7 +174,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -185,7 +185,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -205,7 +205,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -214,7 +214,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -222,7 +222,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -237,7 +237,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -347,14 +347,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -368,7 +368,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -467,7 +467,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -478,7 +478,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -497,7 +497,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -506,7 +506,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -517,7 +517,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -536,7 +536,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -545,7 +545,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -553,7 +553,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -567,7 +567,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -675,14 +675,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -696,7 +696,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -795,7 +795,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -806,7 +806,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -825,7 +825,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -834,7 +834,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -845,7 +845,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -864,7 +864,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -873,7 +873,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -881,7 +881,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -895,7 +895,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -1003,14 +1003,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1023,7 +1023,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -1119,7 +1119,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1130,7 +1130,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1148,7 +1148,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -1157,7 +1157,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1168,7 +1168,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1186,7 +1186,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -1195,7 +1195,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -1203,7 +1203,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1216,7 +1216,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -1669,14 +1669,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1690,7 +1690,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -1789,7 +1789,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1800,7 +1800,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1819,7 +1819,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -1828,7 +1828,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1839,7 +1839,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1858,7 +1858,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -1867,7 +1867,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -1875,7 +1875,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1889,7 +1889,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py
index ff2ae17..673af81 100755
--- a/testing/buildbot/generate_buildbot_json.py
+++ b/testing/buildbot/generate_buildbot_json.py
@@ -833,19 +833,6 @@
 
     browser = ('android-webview-instrumentation'
                if is_android_webview else tester_config['browser_config'])
-
-    # TODO(crbug.com/1090071): This exception should not be here, but is only
-    # meant to test if the watchdog is negatively impacting general CrOS
-    # testing. It should be removed after ~1 day, i.e. June 5th 2020 at the
-    # latest.
-    extra_browser_args = \
-        '--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc'
-    if tester_name in ['ChromeOS FYI Release (amd64-generic)',
-                       'ChromeOS FYI Release (kevin)']:
-      extra_browser_args = (  # pragma: no cover
-        '--extra-browser-args=--disable-gpu-watchdog --enable-logging=stderr '
-        '--js-flags=--expose-gc')
-
     args = [
         test_to_run,
         '--show-stdout',
@@ -855,7 +842,7 @@
         # being expected to fail, but passing.
         '--passthrough',
         '-v',
-        extra_browser_args,
+        '--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc',
     ] + args
     result['args'] = self.maybe_fixup_args_array(self.substitute_gpu_args(
       tester_config, result['swarming'], args))
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl
index aa48c063..7fdf3b2 100644
--- a/testing/buildbot/mixins.pyl
+++ b/testing/buildbot/mixins.pyl
@@ -842,4 +842,20 @@
       ],
     },
   },
+  'xcode_11e608c': {
+    '$mixin_append': {
+      'args': [
+        '--xcode-build-version',
+        '11e608c'
+      ],
+    },
+    'swarming': {
+      'named_caches': [
+        {
+          'name': 'xcode_ios_11e608c',
+          'path': 'Xcode.app',
+        },
+      ],
+    },
+  },
 }
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl
index f5223ab8..6379177 100644
--- a/testing/buildbot/test_suite_exceptions.pyl
+++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -945,7 +945,18 @@
       },
     },
   },
-  'context_lost_tests': {
+  'context_lost_passthrough_tests': {
+    'modifications': {
+      'Win10 x64 Debug (NVIDIA)': {
+        'args': [
+          # TODO(https://crbug.com/1007013): Remove this flag when it's no
+          # longer necessary to figure out why the renderer process is hanging.
+          '--extra-browser-args=--no-sandbox',
+        ],
+      },
+    },
+  },
+  'context_lost_validating_tests': {
     # TODO(https://crbug.com/850107): Remove the Android FYI Release (Pixel 2)
     # exception once there is enough capacity to run these tests.
     'remove_from': [
@@ -958,13 +969,6 @@
           '--is-asan',
         ]
       },
-      'Win10 x64 Debug (NVIDIA)': {
-        'args': [
-          # TODO(https://crbug.com/1007013): Remove this flag when it's no
-          # longer necessary to figure out why the renderer process is hanging.
-          '--extra-browser-args=--no-sandbox',
-        ],
-      },
     },
   },
   'crashpad_tests': {
@@ -1290,7 +1294,28 @@
       },
     },
   },
-  'maps_pixel_test': {
+  'maps_pixel_passthrough_test': {
+    'replacements': {
+      # The V8 builders pass the V8 revision for ${got_revision}, so instead
+      # use ${got_cr_revision}, which is only set on the V8 bots.
+      'Linux V8 FYI Release (NVIDIA)': {
+        'args': {
+          '--git-revision': '${got_cr_revision}',
+        },
+      },
+      'Linux V8 FYI Release - pointer compression (NVIDIA)': {
+        'args': {
+          '--git-revision': '${got_cr_revision}',
+        },
+      },
+      'Win V8 FYI Release (NVIDIA)': {
+        'args': {
+          '--git-revision': '${got_cr_revision}',
+        },
+      },
+    },
+  },
+  'maps_pixel_validating_test': {
     # TODO(https://crbug.com/850107): Remove the Android FYI Release (Pixel 2)
     # exception once there is enough capacity to run these tests.
     'remove_from': [
@@ -1319,11 +1344,6 @@
           '--git-revision': '${got_cr_revision}',
         },
       },
-      'Win V8 FYI Release (NVIDIA)': {
-        'args': {
-          '--git-revision': '${got_cr_revision}',
-        },
-      },
     },
   },
   'media_unittests': {
@@ -1891,7 +1911,28 @@
       },
     },
   },
-  'pixel_skia_gold_test': {
+  'pixel_skia_gold_passthrough_test': {
+    'replacements': {
+      # The V8 builders pass the V8 revision for ${got_revision}, so instead
+      # use ${got_cr_revision}, which is only set on the V8 bots.
+      'Linux V8 FYI Release (NVIDIA)': {
+        'args': {
+          '--git-revision': '${got_cr_revision}',
+        },
+      },
+      'Linux V8 FYI Release - pointer compression (NVIDIA)': {
+        'args': {
+          '--git-revision': '${got_cr_revision}',
+        },
+      },
+      'Win V8 FYI Release (NVIDIA)': {
+        'args': {
+          '--git-revision': '${got_cr_revision}',
+        },
+      },
+    },
+  },
+  'pixel_skia_gold_validating_test': {
     'replacements': {
       # The V8 builders pass the V8 revision for ${got_revision}, so instead
       # use ${got_cr_revision}, which is only set on the V8 bots.
@@ -1915,11 +1956,6 @@
           '--git-revision': '${got_cr_revision}',
         },
       },
-      'Win V8 FYI Release (NVIDIA)': {
-        'args': {
-          '--git-revision': '${got_cr_revision}',
-        },
-      },
     },
   },
   'pixel_test':{
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index fff6377..334550a1 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -583,7 +583,8 @@
           '--stop-ui',
           # Tell libva to do dummy encoding/decoding. For more info, see:
           # https://github.com/intel/libva/blob/master/va/va_fool.c#L47
-          '--env-var', 'LIBVA_DRIVER_NAME', 'i965',
+          '--env-var', 'LIBVA_DRIVERS_PATH', '/usr/local/lib64',
+          '--env-var', 'LIBVA_DRIVER_NAME', 'fake',
           '--env-var', 'LIBVA_FOOL_DECODE', '1',
           '--env-var', 'LIBVA_FOOL_POSTP', '1',
           '--gtest_filter="VaapiTest.*"',
@@ -1238,8 +1239,13 @@
     },
 
     'fuchsia_gpu_telemetry_tests': {
-      'context_lost': {
+      'context_lost_validating': {
         'isolate_name': 'fuchsia_telemetry_gpu_integration_test',
+        'name': 'context_lost_validating_tests',
+        'telemetry_test_name': 'context_lost',
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=validating',
+        ],
       },
       'depth_capture': {
         'isolate_name': 'fuchsia_telemetry_gpu_integration_test',
@@ -2320,6 +2326,80 @@
       },
     },
 
+    'gpu_passthrough_telemetry_tests': {
+      'context_lost_passthrough': {
+        'name': 'context_lost_passthrough_tests',
+        'telemetry_test_name': 'context_lost',
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+      },
+      'depth_capture': {
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+      },
+      'gpu_process': {
+        'name': 'gpu_process_launch_tests',
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+      },
+      'hardware_accelerated_feature': {
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+      },
+      'maps_passthrough': {
+        'name': 'maps_pixel_passthrough_test',
+        'telemetry_test_name': 'maps',
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'mixins': [
+          'chrome-gpu-gold-service-account',
+          'skia_gold_test',
+        ],
+      },
+      'pixel_skia_passthrough': {
+        'name': 'pixel_skia_gold_passthrough_test',
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--test-machine-name',
+          '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+        'mixins': [
+          'chrome-gpu-gold-service-account',
+          'skia_gold_test',
+        ],
+        'telemetry_test_name': 'pixel',
+      },
+      'screenshot_sync_passthrough': {
+        'name': 'screenshot_sync_passthrough_tests',
+        'telemetry_test_name': 'screenshot_sync',
+        'args': [
+          '--dont-restore-color-profile-after-test',
+          '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle',
+        ],
+        'chromeos_args': [
+          '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
+        ],
+      },
+    },
+
     'gpu_skia_renderer_dawn_gtests': {
       'cc_unittests': {
         'linux_args': ['--no-xvfb'],
@@ -2478,11 +2558,16 @@
       },
     },
 
-    'gpu_telemetry_tests': {
-      'context_lost': {
+    'gpu_validating_telemetry_tests': {
+      'context_lost_validating': {
+        'name': 'context_lost_validating_tests',
+        'telemetry_test_name': 'context_lost',
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
+        'args': [
+          '--extra-browser-args=--use-cmd-decoder=validating',
+        ],
       },
       'depth_capture': {
         'chromeos_args': [
@@ -2500,12 +2585,14 @@
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
       },
-      'maps': {
-        'name': 'maps_pixel_test',
+      'maps_validating': {
+        'name': 'maps_pixel_validating_test',
+        'telemetry_test_name': 'maps',
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
           '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=validating',
         ],
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
@@ -2515,12 +2602,13 @@
           'skia_gold_test',
         ],
       },
-      'pixel_skia': {
-        'name': 'pixel_skia_gold_test',
+      'pixel_skia_validating': {
+        'name': 'pixel_skia_gold_validating_test',
         'args': [
           '--dont-restore-color-profile-after-test',
           '--test-machine-name',
           '${buildername}',
+          '--extra-browser-args=--use-cmd-decoder=validating',
         ],
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
@@ -2531,10 +2619,13 @@
         ],
         'telemetry_test_name': 'pixel',
       },
-      'screenshot_sync': {
+      'screenshot_sync_validating': {
+        'name': 'screenshot_sync_validating_tests',
+        'telemetry_test_name': 'screenshot_sync',
         'args': [
           '--dont-restore-color-profile-after-test',
-        ],
+          '--extra-browser-args=--use-cmd-decoder=validating',
+         ],
         'chromeos_args': [
           '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote',
         ],
@@ -3832,6 +3923,8 @@
     'weblayer_gtests': {
       'weblayer_browsertests': {
       },
+      'weblayer_unittests': {
+      },
     },
 
     'weblayer_shell_wpt': {
@@ -3851,11 +3944,6 @@
       },
     },
 
-    'weblayer_unittests': {
-      'weblayer_unittests': {
-      },
-    },
-
     # TODO(crbug.com/888429): Port remaining WebRTC tests to swarming.
     'webrtc_chromium_baremetal_gtests': {
       # Run capture unittests as well since our bots have real webcams.
@@ -4308,7 +4396,6 @@
       'storage_service_gtests',
       'vr_platform_specific_chromium_gtests',
       'weblayer_gtests',
-      'weblayer_unittests',
     ],
 
     'chromium_linux_rel_isolated_scripts': [
@@ -4354,7 +4441,6 @@
       'storage_service_gtests',
       'vr_platform_specific_chromium_gtests',
       'weblayer_gtests',
-      'weblayer_unittests',
       'win_specific_chromium_gtests',
     ],
 
@@ -4375,7 +4461,6 @@
       'non_android_chromium_gtests',
       'vr_platform_specific_chromium_gtests',
       'weblayer_gtests',
-      'weblayer_unittests',
       'win_specific_chromium_gtests',
     ],
 
@@ -4554,15 +4639,23 @@
       'gpu_webgl_conformance_telemetry_tests',
     ],
 
+    'gpu_common_linux_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_validating_telemetry_tests',
+      'gpu_webgl_conformance_telemetry_tests',
+      'gpu_gl_renderer_small_telemetry_tests',
+    ],
+
     'gpu_common_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl_conformance_telemetry_tests',
     ],
 
-    'gpu_common_win_and_linux_telemetry_tests': [
+    'gpu_common_win_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
       'gpu_webgl_conformance_telemetry_tests',
       'gpu_gl_renderer_small_telemetry_tests',
     ],
@@ -4612,7 +4705,7 @@
     ],
 
     'gpu_fyi_android_webgl2_and_gold_telemetry_tests': [
-      'gpu_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl2_conformance_gles_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_validating_telemetry_tests',
     ],
@@ -4643,7 +4736,7 @@
     # have been enabled.
     'gpu_fyi_chromeos_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl_conformance_validating_telemetry_tests',
       # Large amounts of WebGL/WebGL2 tests are failing due to issues that are
       # possibly related to other CrOS issues that are already reported.
@@ -4665,7 +4758,8 @@
 
     'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_validating_telemetry_tests',
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
@@ -4691,7 +4785,8 @@
 
     'gpu_fyi_linux_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl2_conformance_validating_telemetry_tests',
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl_conformance_validating_telemetry_tests',
@@ -4699,7 +4794,8 @@
 
     'gpu_fyi_linux_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl_conformance_validating_telemetry_tests',
     ],
@@ -4735,7 +4831,7 @@
 
     'gpu_fyi_mac_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_validating_telemetry_tests',
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
@@ -4778,7 +4874,7 @@
 
     'gpu_fyi_win_debug_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
       'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl_conformance_telemetry_tests',
@@ -4801,7 +4897,7 @@
 
     'gpu_fyi_win_intel_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_telemetry_tests',
       'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
@@ -4813,7 +4909,7 @@
 
     'gpu_fyi_win_nvidia_amd_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_telemetry_tests',
       'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
       'gpu_webgl_conformance_gl_passthrough_telemetry_tests',
@@ -4833,7 +4929,7 @@
 
     'gpu_fyi_win_release_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_gl_passthrough_telemetry_tests',
       'gpu_webgl2_conformance_telemetry_tests',
       'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests',
@@ -4844,14 +4940,14 @@
 
     'gpu_nexus5x_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl_conformance_gles_passthrough_telemetry_tests',
       'gpu_webgl_conformance_validating_telemetry_tests',
     ],
 
     'gpu_nexus5x_telemetry_tests_v8': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl_conformance_gles_passthrough_telemetry_tests',
       'gpu_webgl_conformance_validating_telemetry_tests',
     ],
@@ -4880,9 +4976,16 @@
       'gpu_skia_renderer_vulkan_telemetry_tests',
     ],
 
-    'gpu_v8_desktop_telemetry_tests': [
+    'gpu_v8_desktop_passthrough_telemetry_tests': [
       'gpu_common_and_optional_telemetry_tests',
-      'gpu_telemetry_tests',
+      'gpu_passthrough_telemetry_tests',
+      'gpu_webgl2_conformance_telemetry_tests',
+      'gpu_webgl_conformance_telemetry_tests',
+    ],
+
+    'gpu_v8_desktop_validating_telemetry_tests': [
+      'gpu_common_and_optional_telemetry_tests',
+      'gpu_validating_telemetry_tests',
       'gpu_webgl2_conformance_telemetry_tests',
       'gpu_webgl_conformance_telemetry_tests',
     ],
@@ -5239,26 +5342,26 @@
     'ios_webkit_tot_tests': {
       'ios_common_tests': {
         'variants': [
-          'SIM_IPHONE_X_13_4',
-          'SIM_IPAD_AIR_2_13_4',
+          'SIM_IPHONE_X_13_5',
+          'SIM_IPAD_AIR_2_13_5',
         ]
       },
       'ios_eg2_cq_tests': {
         'variants': [
-          'SIM_IPHONE_X_13_4',
-          'SIM_IPAD_AIR_2_13_4',
+          'SIM_IPHONE_X_13_5',
+          'SIM_IPAD_AIR_2_13_5',
         ]
       },
       'ios_eg2_tests': {
         'variants': [
-          'SIM_IPHONE_X_13_4',
-          'SIM_IPAD_AIR_2_13_4',
+          'SIM_IPHONE_X_13_5',
+          'SIM_IPAD_AIR_2_13_5',
         ]
       },
       'ios_screen_size_dependent_tests': {
         'variants': [
-          'SIM_IPHONE_X_13_4',
-          'SIM_IPAD_AIR_2_13_4',
+          'SIM_IPHONE_X_13_5',
+          'SIM_IPAD_AIR_2_13_5',
         ]
       },
     },
diff --git a/testing/buildbot/v8.ci.json b/testing/buildbot/v8.ci.json
index ae3522f..08051364 100644
--- a/testing/buildbot/v8.ci.json
+++ b/testing/buildbot/v8.ci.json
@@ -10,14 +10,14 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -32,7 +32,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -134,7 +134,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -145,7 +145,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -165,7 +165,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -174,7 +174,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -185,7 +185,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -205,7 +205,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -214,7 +214,7 @@
           "--browser=android-chromium",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -222,7 +222,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -237,7 +237,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -1494,14 +1494,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1515,7 +1515,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -1614,7 +1614,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1625,7 +1625,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1644,7 +1644,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -1653,7 +1653,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1664,7 +1664,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1683,7 +1683,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -1692,7 +1692,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -1700,7 +1700,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1714,7 +1714,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -1822,14 +1822,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -1843,7 +1843,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -1942,7 +1942,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1953,7 +1953,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -1972,7 +1972,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -1981,7 +1981,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -1992,7 +1992,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2011,7 +2011,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -2020,7 +2020,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -2028,7 +2028,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2042,7 +2042,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
@@ -2150,14 +2150,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2170,7 +2170,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_validating_tests/"
       },
       {
         "args": [
@@ -2266,7 +2266,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2277,7 +2277,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2295,7 +2295,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_validating_test/"
       },
       {
         "args": [
@@ -2304,7 +2304,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2315,7 +2315,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_validating_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2333,7 +2333,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_validating_test/"
       },
       {
         "args": [
@@ -2342,7 +2342,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=validating",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -2350,7 +2350,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_validating_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2363,7 +2363,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_validating_tests/"
       },
       {
         "args": [
@@ -2816,14 +2816,14 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc"
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
         "merge": {
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "context_lost_tests",
+        "name": "context_lost_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -2837,7 +2837,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/context_lost_passthrough_tests/"
       },
       {
         "args": [
@@ -2936,7 +2936,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2947,7 +2947,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "maps_pixel_test",
+        "name": "maps_pixel_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -2966,7 +2966,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/maps_pixel_passthrough_test/"
       },
       {
         "args": [
@@ -2975,7 +2975,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test",
           "--test-machine-name",
           "${buildername}",
@@ -2986,7 +2986,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "pixel_skia_gold_test",
+        "name": "pixel_skia_gold_passthrough_test",
         "precommit_args": [
           "--gerrit-issue=${patch_issue}",
           "--gerrit-patchset=${patch_set}",
@@ -3005,7 +3005,7 @@
           "idempotent": false,
           "service_account": "chrome-gpu-gold@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_test/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/pixel_skia_gold_passthrough_test/"
       },
       {
         "args": [
@@ -3014,7 +3014,7 @@
           "--browser=release",
           "--passthrough",
           "-v",
-          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc",
+          "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-cmd-decoder=passthrough --use-gl=angle",
           "--dont-restore-color-profile-after-test"
         ],
         "isolate_name": "telemetry_gpu_integration_test",
@@ -3022,7 +3022,7 @@
           "args": [],
           "script": "//testing/merge_scripts/standard_isolated_script_merge.py"
         },
-        "name": "screenshot_sync_tests",
+        "name": "screenshot_sync_passthrough_tests",
         "should_retry_with_patch": false,
         "swarming": {
           "can_use_on_swarming_builders": true,
@@ -3036,7 +3036,7 @@
           "idempotent": false,
           "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
         },
-        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_tests/"
+        "test_id_prefix": "ninja://chrome/test:telemetry_gpu_integration_test/screenshot_sync_passthrough_tests/"
       },
       {
         "args": [
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index cd0a77b0..b9f719e 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -59,6 +59,15 @@
         ],
         'identifier': 'iPad Air 2 13.4'
     },
+    'SIM_IPAD_AIR_2_13_5': {
+        'args': [
+            '--platform',
+            'iPad Air 2',
+            '--version',
+            '13.5'
+        ],
+        'identifier': 'iPad Air 2 13.5'
+    },
     'SIM_IPAD_AIR_3RD_GEN_12_4': {
         'args': [
             '--platform',
@@ -185,4 +194,13 @@
         ],
         'identifier': 'iPhone X 13.4'
     },
+    'SIM_IPHONE_X_13_5': {
+        'args': [
+            '--platform',
+            'iPhone X',
+            '--version',
+            '13.5',
+        ],
+        'identifier': 'iPhone X 13.5'
+    },
 }
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index aed9cd3..33acbd5a 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2038,7 +2038,7 @@
           'mac_10.15',
           'mac_toolchain',
           'out_dir_arg',
-          'xcode_11e146'
+          'xcode_11e608c'
         ],
         'test_suites': {
           'isolated_scripts': 'ios_webkit_tot_tests',
@@ -2760,7 +2760,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_desktop_gtests',
-          'gpu_telemetry_tests': 'gpu_common_win_and_linux_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_common_linux_telemetry_tests',
         },
       },
       'Linux Release (NVIDIA)': {
@@ -2771,7 +2771,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_desktop_gtests',
-          'gpu_telemetry_tests': 'gpu_common_win_and_linux_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_common_linux_telemetry_tests',
         },
       },
       'Mac Debug (Intel)': {
@@ -2854,7 +2854,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_win_gtests',
-          'gpu_telemetry_tests': 'gpu_common_win_and_linux_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_common_win_telemetry_tests',
         },
       },
       'Win10 x64 Release (NVIDIA)': {
@@ -2866,7 +2866,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_win_gtests',
-          'gpu_telemetry_tests': 'gpu_common_win_and_linux_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_common_win_telemetry_tests',
           'isolated_scripts': 'rendering_desktop_representative_perf_tests_isolated_scripts',
         },
       },
@@ -2881,7 +2881,7 @@
         ],
         'test_suites': {
           'gtest_tests': 'gpu_win_gtests',
-          'gpu_telemetry_tests': 'gpu_common_win_and_linux_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_common_win_telemetry_tests',
           'isolated_scripts': 'rendering_desktop_representative_perf_tests_isolated_scripts',
         },
       },
@@ -4987,7 +4987,7 @@
           'linux_nvidia_quadro_p400_stable',
         ],
         'test_suites': {
-          'gpu_telemetry_tests': 'gpu_v8_desktop_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_v8_desktop_passthrough_telemetry_tests',
         },
       },
       'Linux V8 FYI Release - pointer compression (NVIDIA)': {
@@ -4997,7 +4997,7 @@
           'linux_nvidia_quadro_p400_stable',
         ],
         'test_suites': {
-          'gpu_telemetry_tests': 'gpu_v8_desktop_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_v8_desktop_passthrough_telemetry_tests',
         },
       },
       'Mac V8 FYI Release (Intel)': {
@@ -5007,7 +5007,7 @@
           'mac_mini_intel_gpu_stable',
         ],
         'test_suites': {
-          'gpu_telemetry_tests': 'gpu_v8_desktop_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_v8_desktop_validating_telemetry_tests',
         },
       },
       'V8 Android GN (dbg)': {
@@ -5134,7 +5134,7 @@
           'win10_nvidia_quadro_p400_stable',
         ],
         'test_suites': {
-          'gpu_telemetry_tests': 'gpu_v8_desktop_telemetry_tests',
+          'gpu_telemetry_tests': 'gpu_v8_desktop_passthrough_telemetry_tests',
         },
       },
     },
diff --git a/testing/merge_scripts/code_coverage/merge_lib.py b/testing/merge_scripts/code_coverage/merge_lib.py
index c219959a..4b6cda3 100644
--- a/testing/merge_scripts/code_coverage/merge_lib.py
+++ b/testing/merge_scripts/code_coverage/merge_lib.py
@@ -23,7 +23,6 @@
 def _call_profdata_tool(profile_input_file_paths,
                         profile_output_file_path,
                         profdata_tool_path,
-                        retries=3,
                         sparse=True):
   """Calls the llvm-profdata tool.
 
@@ -59,34 +58,6 @@
     output = subprocess.check_output(subprocess_cmd, stderr=subprocess.STDOUT)
     logging.info('Merge succeeded with output: %r', output)
   except subprocess.CalledProcessError as error:
-    if len(profile_input_file_paths) > 1 and retries >= 0:
-      logging.warning('Merge failed with error output: %r', error.output)
-
-      # The output of the llvm-profdata command will include the path of
-      # malformed files, such as
-      # `error: /.../default.profraw: Malformed instrumentation profile data`
-      invalid_profiles = [
-          f for f in profile_input_file_paths if f in error.output
-      ]
-
-      if not invalid_profiles:
-        logging.info(
-            'Merge failed, but wasn\'t able to figure out the culprit invalid '
-            'profiles from the output, so skip retry and bail out.')
-        raise error
-
-      valid_profiles = list(
-          set(profile_input_file_paths) - set(invalid_profiles))
-      if valid_profiles:
-        logging.warning(
-            'Following invalid profiles are removed as they were mentioned in '
-            'the merge error output: %r', invalid_profiles)
-        logging.info('Retry merging with the remaining profiles: %r',
-                     valid_profiles)
-        return invalid_profiles + _call_profdata_tool(
-            valid_profiles, profile_output_file_path, profdata_tool_path,
-            retries - 1)
-
     logging.error('Failed to merge profiles, return code (%d), output: %r' %
                   (error.returncode, error.output))
     raise error
diff --git a/testing/merge_scripts/code_coverage/merge_results_test.py b/testing/merge_scripts/code_coverage/merge_results_test.py
index d490b74b..ecb1768 100755
--- a/testing/merge_scripts/code_coverage/merge_results_test.py
+++ b/testing/merge_scripts/code_coverage/merge_results_test.py
@@ -246,50 +246,6 @@
     # The mock method should only apply when merging .profraw files.
     self.assertFalse(mock_validate_and_convert_profraws.called)
 
-  def test_retry_profdata_merge_failures(self):
-    mock_input_dir_walk = [
-        ('/b/some/path', ['0', '1'], ['summary.json']),
-        ('/b/some/path/0', [],
-         ['output.json', 'default-1.profdata', 'default-2.profdata']),
-        ('/b/some/path/1', [],
-         ['output.json', 'default-1.profdata', 'default-2.profdata']),
-    ]
-    with mock.patch.object(os, 'walk') as mock_walk:
-      with mock.patch.object(os, 'remove'):
-        mock_walk.return_value = mock_input_dir_walk
-        with mock.patch.object(subprocess, 'check_output') as mock_exec_cmd:
-          invalid_profiles_msg = (
-              'error: /b/some/path/0/default-1.profdata: Malformed '
-              'instrumentation profile data.')
-
-          # Failed on the first merge, but succeed on the second attempt.
-          mock_exec_cmd.side_effect = [
-              subprocess.CalledProcessError(
-                  returncode=1, cmd='dummy cmd', output=invalid_profiles_msg),
-              None
-          ]
-
-          merger.merge_profiles('/b/some/path', 'output/dir/default.profdata',
-                                '.profdata', 'llvm-profdata')
-
-          self.assertEqual(2, mock_exec_cmd.call_count)
-
-          # Note that in the second call, /b/some/path/0/default-1.profdata is
-          # excluded!
-          self.assertEqual(
-              mock.call(
-                  [
-                      'llvm-profdata',
-                      'merge',
-                      '-o',
-                      'output/dir/default.profdata',
-                      '-sparse=true',
-                      '/b/some/path/0/default-2.profdata',
-                      '/b/some/path/1/default-1.profdata',
-                      '/b/some/path/1/default-2.profdata',
-                  ],
-                  stderr=-2,
-              ), mock_exec_cmd.call_args)
 
   @mock.patch('os.remove')
   def test_mark_invalid_shards(self, mock_rm):
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 67cff2b6..20a97aa2 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -79,6 +79,22 @@
             ]
         }
     ],
+    "AndroidCopyImageAndClipboardImageSuggstions": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "AndroidCopyImageAndClipboardImageSuggstions",
+                    "enable_features": [
+                        "ContextMenuCopyImage",
+                        "OmniboxEnableClipboardProviderImageSuggestions"
+                    ]
+                }
+            ]
+        }
+    ],
     "AndroidDarkSearch": [
         {
             "platforms": [
@@ -1183,6 +1199,27 @@
             ]
         }
     ],
+    "CSSMatchedPropertiesCacheDependencies": [
+        {
+            "platforms": [
+                "android",
+                "android_weblayer",
+                "android_webview",
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "CSSMatchedPropertiesCacheDependencies"
+                    ]
+                }
+            ]
+        }
+    ],
     "CSSOMViewScrollCoordinates": [
         {
             "platforms": [
@@ -5028,6 +5065,81 @@
             ]
         }
     ],
+    "QueryTiles": [
+        {
+            "platforms": [
+                "android"
+            ],
+            "experiments": [
+                {
+                    "name": "EnabledStitch",
+                    "params": {
+                        "base_url": "https://chromeupboarding-pa.googleapis.com",
+                        "experiment_tag": "",
+                        "image_prefetch_mode": "top",
+                        "most_visited_max_rows_normal_screen": "1",
+                        "most_visited_max_rows_small_screen": "1"
+                    },
+                    "enable_features": [
+                        "QueryTiles",
+                        "QueryTilesInOmnibox"
+                    ],
+                    "disable_features": [
+                        "QueryTilesEnableQueryEditing"
+                    ]
+                },
+                {
+                    "name": "EnabledStitchWithNoSearchParam",
+                    "params": {
+                        "base_url": "https://chromeupboarding-pa.googleapis.com",
+                        "experiment_tag": "disableSearchParams : true",
+                        "image_prefetch_mode": "top",
+                        "most_visited_max_rows_normal_screen": "1",
+                        "most_visited_max_rows_small_screen": "1"
+                    },
+                    "enable_features": [
+                        "QueryTiles",
+                        "QueryTilesInOmnibox"
+                    ],
+                    "disable_features": [
+                        "QueryTilesEnableQueryEditing"
+                    ]
+                },
+                {
+                    "name": "EnabledExplore",
+                    "params": {
+                        "base_url": "https://chromeupboarding-pa.googleapis.com",
+                        "experiment_tag": "maxLevels : 1",
+                        "image_prefetch_mode": "top",
+                        "most_visited_max_rows_normal_screen": "1",
+                        "most_visited_max_rows_small_screen": "1"
+                    },
+                    "enable_features": [
+                        "QueryTiles",
+                        "QueryTilesInOmnibox"
+                    ],
+                    "disable_features": [
+                        "QueryTilesEnableQueryEditing"
+                    ]
+                },
+                {
+                    "name": "EnabledStart",
+                    "params": {
+                        "base_url": "https://chromeupboarding-pa.googleapis.com",
+                        "experiment_tag": "maxLevels : 1",
+                        "image_prefetch_mode": "top",
+                        "most_visited_max_rows_normal_screen": "1",
+                        "most_visited_max_rows_small_screen": "1"
+                    },
+                    "enable_features": [
+                        "QueryTiles",
+                        "QueryTilesEnableQueryEditing",
+                        "QueryTilesInOmnibox"
+                    ]
+                }
+            ]
+        }
+    ],
     "QuietNotificationPrompts": [
         {
             "platforms": [
diff --git a/third_party/android_deps/libs/android_arch_core_runtime/android_arch_core_runtime.info b/third_party/android_deps/libs/android_arch_core_runtime/android_arch_core_runtime.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/android_arch_core_runtime/android_arch_core_runtime.info
+++ b/third_party/android_deps/libs/android_arch_core_runtime/android_arch_core_runtime.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_livedata/android_arch_lifecycle_livedata.info b/third_party/android_deps/libs/android_arch_lifecycle_livedata/android_arch_lifecycle_livedata.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_livedata/android_arch_lifecycle_livedata.info
+++ b/third_party/android_deps/libs/android_arch_lifecycle_livedata/android_arch_lifecycle_livedata.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/android_arch_lifecycle_livedata_core.info b/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/android_arch_lifecycle_livedata_core.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/android_arch_lifecycle_livedata_core.info
+++ b/third_party/android_deps/libs/android_arch_lifecycle_livedata_core/android_arch_lifecycle_livedata_core.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info b/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info
+++ b/third_party/android_deps/libs/android_arch_lifecycle_runtime/android_arch_lifecycle_runtime.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/android_arch_lifecycle_viewmodel.info b/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/android_arch_lifecycle_viewmodel.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/android_arch_lifecycle_viewmodel.info
+++ b/third_party/android_deps/libs/android_arch_lifecycle_viewmodel/android_arch_lifecycle_viewmodel.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_activity_activity/androidx_activity_activity.info b/third_party/android_deps/libs/androidx_activity_activity/androidx_activity_activity.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_activity_activity/androidx_activity_activity.info
+++ b/third_party/android_deps/libs/androidx_activity_activity/androidx_activity_activity.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_annotation_annotation_experimental/androidx_annotation_annotation_experimental.info b/third_party/android_deps/libs/androidx_annotation_annotation_experimental/androidx_annotation_annotation_experimental.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_annotation_annotation_experimental/androidx_annotation_annotation_experimental.info
+++ b/third_party/android_deps/libs/androidx_annotation_annotation_experimental/androidx_annotation_annotation_experimental.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_appcompat_appcompat/androidx_appcompat_appcompat.info b/third_party/android_deps/libs/androidx_appcompat_appcompat/androidx_appcompat_appcompat.info
index 80c30c0c..887f70d5 100644
--- a/third_party/android_deps/libs/androidx_appcompat_appcompat/androidx_appcompat_appcompat.info
+++ b/third_party/android_deps/libs/androidx_appcompat_appcompat/androidx_appcompat_appcompat.info
@@ -1,13 +1,500 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/anim/abc_fade_in.xml", "res/anim/abc_fade_out.xml", "res/anim/abc_grow_fade_in_from_bottom.xml", "res/anim/abc_popup_enter.xml", "res/anim/abc_popup_exit.xml", "res/anim/abc_shrink_fade_out_from_bottom.xml", "res/anim/abc_slide_in_bottom.xml", "res/anim/abc_slide_in_top.xml", "res/anim/abc_slide_out_bottom.xml", "res/anim/abc_slide_out_top.xml", "res/anim/abc_tooltip_enter.xml", "res/anim/abc_tooltip_exit.xml", "res/anim/btn_checkbox_to_checked_box_inner_merged_animation.xml", "res/anim/btn_checkbox_to_checked_box_outer_merged_animation.xml", "res/anim/btn_checkbox_to_checked_icon_null_animation.xml", "res/anim/btn_checkbox_to_unchecked_box_inner_merged_animation.xml", "res/anim/btn_checkbox_to_unchecked_check_path_merged_animation.xml", "res/anim/btn_checkbox_to_unchecked_icon_null_animation.xml", "res/anim/btn_radio_to_off_mtrl_dot_group_animation.xml", "res/anim/btn_radio_to_off_mtrl_ring_outer_animation.xml", "res/anim/btn_radio_to_off_mtrl_ring_outer_path_animation.xml", "res/anim/btn_radio_to_on_mtrl_dot_group_animation.xml", "res/anim/btn_radio_to_on_mtrl_ring_outer_animation.xml", "res/anim/btn_radio_to_on_mtrl_ring_outer_path_animation.xml", "res/color/abc_background_cache_hint_selector_material_dark.xml", "res/color/abc_background_cache_hint_selector_material_light.xml", "res/color/abc_btn_colored_borderless_text_material.xml", "res/color/abc_btn_colored_text_material.xml", "res/color/abc_hint_foreground_material_dark.xml", "res/color/abc_hint_foreground_material_light.xml", "res/color/abc_primary_text_disable_only_material_dark.xml", "res/color/abc_primary_text_disable_only_material_light.xml", "res/color/abc_primary_text_material_dark.xml", "res/color/abc_primary_text_material_light.xml", "res/color/abc_search_url_text.xml", "res/color/abc_secondary_text_material_dark.xml", "res/color/abc_secondary_text_material_light.xml", "res/color/abc_tint_btn_checkable.xml", "res/color/abc_tint_default.xml", "res/color/abc_tint_edittext.xml", "res/color/abc_tint_seek_thumb.xml", "res/color/abc_tint_spinner.xml", "res/color/abc_tint_switch_track.xml", "res/color/switch_thumb_material_dark.xml", "res/color/switch_thumb_material_light.xml", "res/color-v21/abc_btn_colored_borderless_text_material.xml", "res/color-v23/abc_btn_colored_borderless_text_material.xml", "res/color-v23/abc_btn_colored_text_material.xml", "res/color-v23/abc_color_highlight_material.xml", "res/color-v23/abc_tint_btn_checkable.xml", "res/color-v23/abc_tint_default.xml", "res/color-v23/abc_tint_edittext.xml", "res/color-v23/abc_tint_seek_thumb.xml", "res/color-v23/abc_tint_spinner.xml", "res/color-v23/abc_tint_switch_track.xml", "res/drawable/abc_btn_borderless_material.xml", "res/drawable/abc_btn_check_material.xml", "res/drawable/abc_btn_check_material_anim.xml", "res/drawable/abc_btn_colored_material.xml", "res/drawable/abc_btn_default_mtrl_shape.xml", "res/drawable/abc_btn_radio_material.xml", "res/drawable/abc_btn_radio_material_anim.xml", "res/drawable/abc_cab_background_internal_bg.xml", "res/drawable/abc_cab_background_top_material.xml", "res/drawable/abc_dialog_material_background.xml", "res/drawable/abc_edit_text_material.xml", "res/drawable/abc_ic_ab_back_material.xml", "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml", "res/drawable/abc_ic_clear_material.xml", "res/drawable/abc_ic_go_search_api_material.xml", "res/drawable/abc_ic_menu_overflow_material.xml", "res/drawable/abc_ic_search_api_material.xml", "res/drawable/abc_ic_voice_search_api_material.xml", "res/drawable/abc_item_background_holo_dark.xml", "res/drawable/abc_item_background_holo_light.xml", "res/drawable/abc_list_divider_material.xml", "res/drawable/abc_list_selector_background_transition_holo_dark.xml", "res/drawable/abc_list_selector_background_transition_holo_light.xml", "res/drawable/abc_list_selector_holo_dark.xml", "res/drawable/abc_list_selector_holo_light.xml", "res/drawable/abc_ratingbar_indicator_material.xml", "res/drawable/abc_ratingbar_material.xml", "res/drawable/abc_ratingbar_small_material.xml", "res/drawable/abc_seekbar_thumb_material.xml", "res/drawable/abc_seekbar_tick_mark_material.xml", "res/drawable/abc_seekbar_track_material.xml", "res/drawable/abc_spinner_textfield_background_material.xml", "res/drawable/abc_switch_thumb_material.xml", "res/drawable/abc_tab_indicator_material.xml", "res/drawable/abc_text_cursor_material.xml", "res/drawable/abc_textfield_search_material.xml", "res/drawable/btn_checkbox_checked_mtrl.xml", "res/drawable/btn_checkbox_checked_to_unchecked_mtrl_animation.xml", "res/drawable/btn_checkbox_unchecked_mtrl.xml", "res/drawable/btn_checkbox_unchecked_to_checked_mtrl_animation.xml", "res/drawable/btn_radio_off_mtrl.xml", "res/drawable/btn_radio_off_to_on_mtrl_animation.xml", "res/drawable/btn_radio_on_mtrl.xml", "res/drawable/btn_radio_on_to_off_mtrl_animation.xml", "res/drawable/tooltip_frame_dark.xml", "res/drawable/tooltip_frame_light.xml", "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_list_focused_holo.9.png", "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-mdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-mdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-mdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-mdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-mdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_list_focused_holo.9.png", "res/drawable-mdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-mdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-mdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-mdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-mdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-v21/abc_action_bar_item_background_material.xml", "res/drawable-v21/abc_btn_colored_material.xml", "res/drawable-v21/abc_dialog_material_background.xml", "res/drawable-v21/abc_edit_text_material.xml", "res/drawable-v21/abc_list_divider_material.xml", "res/drawable-v23/abc_control_background_material.xml", "res/drawable-watch-v20/abc_dialog_material_background.xml", "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xxhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_0.xml", "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_1.xml", "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml", "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml", "res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml", "res/interpolator/btn_radio_to_on_mtrl_animation_interpolator_0.xml", "res/interpolator/fast_out_slow_in.xml", "res/layout/abc_action_bar_title_item.xml", "res/layout/abc_action_bar_up_container.xml", "res/layout/abc_action_menu_item_layout.xml", "res/layout/abc_action_menu_layout.xml", "res/layout/abc_action_mode_bar.xml", "res/layout/abc_action_mode_close_item_material.xml", "res/layout/abc_activity_chooser_view.xml", "res/layout/abc_activity_chooser_view_list_item.xml", "res/layout/abc_alert_dialog_button_bar_material.xml", "res/layout/abc_alert_dialog_material.xml", "res/layout/abc_alert_dialog_title_material.xml", "res/layout/abc_cascading_menu_item_layout.xml", "res/layout/abc_dialog_title_material.xml", "res/layout/abc_expanded_menu_layout.xml", "res/layout/abc_list_menu_item_checkbox.xml", "res/layout/abc_list_menu_item_icon.xml", "res/layout/abc_list_menu_item_layout.xml", "res/layout/abc_list_menu_item_radio.xml", "res/layout/abc_popup_menu_header_item_layout.xml", "res/layout/abc_popup_menu_item_layout.xml", "res/layout/abc_screen_content_include.xml", "res/layout/abc_screen_simple.xml", "res/layout/abc_screen_simple_overlay_action_mode.xml", "res/layout/abc_screen_toolbar.xml", "res/layout/abc_search_dropdown_item_icons_2line.xml", "res/layout/abc_search_view.xml", "res/layout/abc_select_dialog_material.xml", "res/layout/abc_tooltip.xml", "res/layout/select_dialog_item_material.xml", "res/layout/select_dialog_multichoice_material.xml", "res/layout/select_dialog_singlechoice_material.xml", "res/layout/support_simple_spinner_dropdown_item.xml", "res/layout-v26/abc_screen_toolbar.xml", "res/layout-watch-v20/abc_alert_dialog_button_bar_material.xml", "res/layout-watch-v20/abc_alert_dialog_title_material.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-as/values-as.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-h720dp-v13/values-h720dp-v13.xml", "res/values-hdpi-v4/values-hdpi-v4.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-land/values-land.xml", "res/values-large-v4/values-large-v4.xml", "res/values-ldltr-v21/values-ldltr-v21.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-night-v8/values-night-v8.xml", "res/values-nl/values-nl.xml", "res/values-or/values-or.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-port/values-port.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v16/values-v16.xml", "res/values-v17/values-v17.xml", "res/values-v18/values-v18.xml", "res/values-v21/values-v21.xml", "res/values-v22/values-v22.xml", "res/values-v23/values-v23.xml", "res/values-v24/values-v24.xml", "res/values-v25/values-v25.xml", "res/values-v26/values-v26.xml", "res/values-v28/values-v28.xml", "res/values-vi/values-vi.xml", "res/values-watch-v20/values-watch-v20.xml", "res/values-watch-v21/values-watch-v21.xml", "res/values-xlarge-v4/values-xlarge-v4.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/anim/abc_fade_in.xml",
+  "res/anim/abc_fade_out.xml",
+  "res/anim/abc_grow_fade_in_from_bottom.xml",
+  "res/anim/abc_popup_enter.xml",
+  "res/anim/abc_popup_exit.xml",
+  "res/anim/abc_shrink_fade_out_from_bottom.xml",
+  "res/anim/abc_slide_in_bottom.xml",
+  "res/anim/abc_slide_in_top.xml",
+  "res/anim/abc_slide_out_bottom.xml",
+  "res/anim/abc_slide_out_top.xml",
+  "res/anim/abc_tooltip_enter.xml",
+  "res/anim/abc_tooltip_exit.xml",
+  "res/anim/btn_checkbox_to_checked_box_inner_merged_animation.xml",
+  "res/anim/btn_checkbox_to_checked_box_outer_merged_animation.xml",
+  "res/anim/btn_checkbox_to_checked_icon_null_animation.xml",
+  "res/anim/btn_checkbox_to_unchecked_box_inner_merged_animation.xml",
+  "res/anim/btn_checkbox_to_unchecked_check_path_merged_animation.xml",
+  "res/anim/btn_checkbox_to_unchecked_icon_null_animation.xml",
+  "res/anim/btn_radio_to_off_mtrl_dot_group_animation.xml",
+  "res/anim/btn_radio_to_off_mtrl_ring_outer_animation.xml",
+  "res/anim/btn_radio_to_off_mtrl_ring_outer_path_animation.xml",
+  "res/anim/btn_radio_to_on_mtrl_dot_group_animation.xml",
+  "res/anim/btn_radio_to_on_mtrl_ring_outer_animation.xml",
+  "res/anim/btn_radio_to_on_mtrl_ring_outer_path_animation.xml",
+  "res/color/abc_background_cache_hint_selector_material_dark.xml",
+  "res/color/abc_background_cache_hint_selector_material_light.xml",
+  "res/color/abc_btn_colored_borderless_text_material.xml",
+  "res/color/abc_btn_colored_text_material.xml",
+  "res/color/abc_hint_foreground_material_dark.xml",
+  "res/color/abc_hint_foreground_material_light.xml",
+  "res/color/abc_primary_text_disable_only_material_dark.xml",
+  "res/color/abc_primary_text_disable_only_material_light.xml",
+  "res/color/abc_primary_text_material_dark.xml",
+  "res/color/abc_primary_text_material_light.xml",
+  "res/color/abc_search_url_text.xml",
+  "res/color/abc_secondary_text_material_dark.xml",
+  "res/color/abc_secondary_text_material_light.xml",
+  "res/color/abc_tint_btn_checkable.xml",
+  "res/color/abc_tint_default.xml",
+  "res/color/abc_tint_edittext.xml",
+  "res/color/abc_tint_seek_thumb.xml",
+  "res/color/abc_tint_spinner.xml",
+  "res/color/abc_tint_switch_track.xml",
+  "res/color/switch_thumb_material_dark.xml",
+  "res/color/switch_thumb_material_light.xml",
+  "res/color-v21/abc_btn_colored_borderless_text_material.xml",
+  "res/color-v23/abc_btn_colored_borderless_text_material.xml",
+  "res/color-v23/abc_btn_colored_text_material.xml",
+  "res/color-v23/abc_color_highlight_material.xml",
+  "res/color-v23/abc_tint_btn_checkable.xml",
+  "res/color-v23/abc_tint_default.xml",
+  "res/color-v23/abc_tint_edittext.xml",
+  "res/color-v23/abc_tint_seek_thumb.xml",
+  "res/color-v23/abc_tint_spinner.xml",
+  "res/color-v23/abc_tint_switch_track.xml",
+  "res/drawable/abc_btn_borderless_material.xml",
+  "res/drawable/abc_btn_check_material.xml",
+  "res/drawable/abc_btn_check_material_anim.xml",
+  "res/drawable/abc_btn_colored_material.xml",
+  "res/drawable/abc_btn_default_mtrl_shape.xml",
+  "res/drawable/abc_btn_radio_material.xml",
+  "res/drawable/abc_btn_radio_material_anim.xml",
+  "res/drawable/abc_cab_background_internal_bg.xml",
+  "res/drawable/abc_cab_background_top_material.xml",
+  "res/drawable/abc_dialog_material_background.xml",
+  "res/drawable/abc_edit_text_material.xml",
+  "res/drawable/abc_ic_ab_back_material.xml",
+  "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml",
+  "res/drawable/abc_ic_clear_material.xml",
+  "res/drawable/abc_ic_go_search_api_material.xml",
+  "res/drawable/abc_ic_menu_overflow_material.xml",
+  "res/drawable/abc_ic_search_api_material.xml",
+  "res/drawable/abc_ic_voice_search_api_material.xml",
+  "res/drawable/abc_item_background_holo_dark.xml",
+  "res/drawable/abc_item_background_holo_light.xml",
+  "res/drawable/abc_list_divider_material.xml",
+  "res/drawable/abc_list_selector_background_transition_holo_dark.xml",
+  "res/drawable/abc_list_selector_background_transition_holo_light.xml",
+  "res/drawable/abc_list_selector_holo_dark.xml",
+  "res/drawable/abc_list_selector_holo_light.xml",
+  "res/drawable/abc_ratingbar_indicator_material.xml",
+  "res/drawable/abc_ratingbar_material.xml",
+  "res/drawable/abc_ratingbar_small_material.xml",
+  "res/drawable/abc_seekbar_thumb_material.xml",
+  "res/drawable/abc_seekbar_tick_mark_material.xml",
+  "res/drawable/abc_seekbar_track_material.xml",
+  "res/drawable/abc_spinner_textfield_background_material.xml",
+  "res/drawable/abc_switch_thumb_material.xml",
+  "res/drawable/abc_tab_indicator_material.xml",
+  "res/drawable/abc_text_cursor_material.xml",
+  "res/drawable/abc_textfield_search_material.xml",
+  "res/drawable/btn_checkbox_checked_mtrl.xml",
+  "res/drawable/btn_checkbox_checked_to_unchecked_mtrl_animation.xml",
+  "res/drawable/btn_checkbox_unchecked_mtrl.xml",
+  "res/drawable/btn_checkbox_unchecked_to_checked_mtrl_animation.xml",
+  "res/drawable/btn_radio_off_mtrl.xml",
+  "res/drawable/btn_radio_off_to_on_mtrl_animation.xml",
+  "res/drawable/btn_radio_on_mtrl.xml",
+  "res/drawable/btn_radio_on_to_off_mtrl_animation.xml",
+  "res/drawable/tooltip_frame_dark.xml",
+  "res/drawable/tooltip_frame_light.xml",
+  "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-mdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-mdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-mdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-mdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-mdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-mdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-mdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-mdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-mdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-mdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-v21/abc_action_bar_item_background_material.xml",
+  "res/drawable-v21/abc_btn_colored_material.xml",
+  "res/drawable-v21/abc_dialog_material_background.xml",
+  "res/drawable-v21/abc_edit_text_material.xml",
+  "res/drawable-v21/abc_list_divider_material.xml",
+  "res/drawable-v23/abc_control_background_material.xml",
+  "res/drawable-watch-v20/abc_dialog_material_background.xml",
+  "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-xhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-xhdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-xhdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-xhdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-xhdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-xhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-xhdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-xhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-xxhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-xxhdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-xxhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-xxhdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xxxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_0.xml",
+  "res/interpolator/btn_checkbox_checked_mtrl_animation_interpolator_1.xml",
+  "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_0.xml",
+  "res/interpolator/btn_checkbox_unchecked_mtrl_animation_interpolator_1.xml",
+  "res/interpolator/btn_radio_to_off_mtrl_animation_interpolator_0.xml",
+  "res/interpolator/btn_radio_to_on_mtrl_animation_interpolator_0.xml",
+  "res/interpolator/fast_out_slow_in.xml",
+  "res/layout/abc_action_bar_title_item.xml",
+  "res/layout/abc_action_bar_up_container.xml",
+  "res/layout/abc_action_menu_item_layout.xml",
+  "res/layout/abc_action_menu_layout.xml",
+  "res/layout/abc_action_mode_bar.xml",
+  "res/layout/abc_action_mode_close_item_material.xml",
+  "res/layout/abc_activity_chooser_view.xml",
+  "res/layout/abc_activity_chooser_view_list_item.xml",
+  "res/layout/abc_alert_dialog_button_bar_material.xml",
+  "res/layout/abc_alert_dialog_material.xml",
+  "res/layout/abc_alert_dialog_title_material.xml",
+  "res/layout/abc_cascading_menu_item_layout.xml",
+  "res/layout/abc_dialog_title_material.xml",
+  "res/layout/abc_expanded_menu_layout.xml",
+  "res/layout/abc_list_menu_item_checkbox.xml",
+  "res/layout/abc_list_menu_item_icon.xml",
+  "res/layout/abc_list_menu_item_layout.xml",
+  "res/layout/abc_list_menu_item_radio.xml",
+  "res/layout/abc_popup_menu_header_item_layout.xml",
+  "res/layout/abc_popup_menu_item_layout.xml",
+  "res/layout/abc_screen_content_include.xml",
+  "res/layout/abc_screen_simple.xml",
+  "res/layout/abc_screen_simple_overlay_action_mode.xml",
+  "res/layout/abc_screen_toolbar.xml",
+  "res/layout/abc_search_dropdown_item_icons_2line.xml",
+  "res/layout/abc_search_view.xml",
+  "res/layout/abc_select_dialog_material.xml",
+  "res/layout/abc_tooltip.xml",
+  "res/layout/select_dialog_item_material.xml",
+  "res/layout/select_dialog_multichoice_material.xml",
+  "res/layout/select_dialog_singlechoice_material.xml",
+  "res/layout/support_simple_spinner_dropdown_item.xml",
+  "res/layout-v26/abc_screen_toolbar.xml",
+  "res/layout-watch-v20/abc_alert_dialog_button_bar_material.xml",
+  "res/layout-watch-v20/abc_alert_dialog_title_material.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-as/values-as.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-h720dp-v13/values-h720dp-v13.xml",
+  "res/values-hdpi-v4/values-hdpi-v4.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-land/values-land.xml",
+  "res/values-large-v4/values-large-v4.xml",
+  "res/values-ldltr-v21/values-ldltr-v21.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-night-v8/values-night-v8.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-or/values-or.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-port/values-port.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-sw600dp-v13/values-sw600dp-v13.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v16/values-v16.xml",
+  "res/values-v17/values-v17.xml",
+  "res/values-v18/values-v18.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-v22/values-v22.xml",
+  "res/values-v23/values-v23.xml",
+  "res/values-v24/values-v24.xml",
+  "res/values-v25/values-v25.xml",
+  "res/values-v26/values-v26.xml",
+  "res/values-v28/values-v28.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-watch-v20/values-watch-v20.xml",
+  "res/values-watch-v21/values-watch-v21.xml",
+  "res/values-xlarge-v4/values-xlarge-v4.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_appcompat_appcompat_resources/androidx_appcompat_appcompat_resources.info b/third_party/android_deps/libs/androidx_appcompat_appcompat_resources/androidx_appcompat_appcompat_resources.info
index e1bb856..abc23a0 100644
--- a/third_party/android_deps/libs/androidx_appcompat_appcompat_resources/androidx_appcompat_appcompat_resources.info
+++ b/third_party/android_deps/libs/androidx_appcompat_appcompat_resources/androidx_appcompat_appcompat_resources.info
@@ -1,13 +1,16 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable/abc_vector_test.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable/abc_vector_test.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_arch_core_core_runtime/androidx_arch_core_core_runtime.info b/third_party/android_deps/libs/androidx_arch_core_core_runtime/androidx_arch_core_core_runtime.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_arch_core_core_runtime/androidx_arch_core_core_runtime.info
+++ b/third_party/android_deps/libs/androidx_arch_core_core_runtime/androidx_arch_core_core_runtime.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_asynclayoutinflater_asynclayoutinflater/androidx_asynclayoutinflater_asynclayoutinflater.info b/third_party/android_deps/libs/androidx_asynclayoutinflater_asynclayoutinflater/androidx_asynclayoutinflater_asynclayoutinflater.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_asynclayoutinflater_asynclayoutinflater/androidx_asynclayoutinflater_asynclayoutinflater.info
+++ b/third_party/android_deps/libs/androidx_asynclayoutinflater_asynclayoutinflater/androidx_asynclayoutinflater_asynclayoutinflater.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_cardview_cardview/androidx_cardview_cardview.info b/third_party/android_deps/libs/androidx_cardview_cardview/androidx_cardview_cardview.info
index 7e63301..3375863 100644
--- a/third_party/android_deps/libs/androidx_cardview_cardview/androidx_cardview_cardview.info
+++ b/third_party/android_deps/libs/androidx_cardview_cardview/androidx_cardview_cardview.info
@@ -1,13 +1,16 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml", "res/values-v23/values-v23.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml",
+  "res/values-v23/values-v23.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_coordinatorlayout_coordinatorlayout/androidx_coordinatorlayout_coordinatorlayout.info b/third_party/android_deps/libs/androidx_coordinatorlayout_coordinatorlayout/androidx_coordinatorlayout_coordinatorlayout.info
index a25d255..5134f1a 100644
--- a/third_party/android_deps/libs/androidx_coordinatorlayout_coordinatorlayout/androidx_coordinatorlayout_coordinatorlayout.info
+++ b/third_party/android_deps/libs/androidx_coordinatorlayout_coordinatorlayout/androidx_coordinatorlayout_coordinatorlayout.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_core_core/androidx_core_core.info b/third_party/android_deps/libs/androidx_core_core/androidx_core_core.info
index 1ce756d..d9f6d2c5 100644
--- a/third_party/android_deps/libs/androidx_core_core/androidx_core_core.info
+++ b/third_party/android_deps/libs/androidx_core_core/androidx_core_core.info
@@ -1,13 +1,136 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [ "aidl/android/support/v4/os/ResultReceiver.aidl" ]
-assets = [  ]
+aidl = [
+  "aidl/android/support/v4/os/ResultReceiver.aidl"
+]
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable/notification_bg.xml", "res/drawable/notification_bg_low.xml", "res/drawable/notification_icon_background.xml", "res/drawable/notification_tile_bg.xml", "res/drawable-hdpi-v4/notification_bg_low_normal.9.png", "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-hdpi-v4/notification_bg_normal.9.png", "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-mdpi-v4/notification_bg_low_normal.9.png", "res/drawable-mdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-mdpi-v4/notification_bg_normal.9.png", "res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-v21/notification_action_background.xml", "res/drawable-xhdpi-v4/notification_bg_low_normal.9.png", "res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-xhdpi-v4/notification_bg_normal.9.png", "res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png", "res/layout/custom_dialog.xml", "res/layout/notification_action.xml", "res/layout/notification_action_tombstone.xml", "res/layout/notification_template_custom_big.xml", "res/layout/notification_template_icon_group.xml", "res/layout/notification_template_part_chronometer.xml", "res/layout/notification_template_part_time.xml", "res/layout-v16/notification_template_custom_big.xml", "res/layout-v21/notification_action.xml", "res/layout-v21/notification_action_tombstone.xml", "res/layout-v21/notification_template_custom_big.xml", "res/layout-v21/notification_template_icon_group.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-as/values-as.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-or/values-or.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v16/values-v16.xml", "res/values-v21/values-v21.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable/notification_bg.xml",
+  "res/drawable/notification_bg_low.xml",
+  "res/drawable/notification_icon_background.xml",
+  "res/drawable/notification_tile_bg.xml",
+  "res/drawable-hdpi-v4/notification_bg_low_normal.9.png",
+  "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png",
+  "res/drawable-hdpi-v4/notification_bg_normal.9.png",
+  "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png",
+  "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png",
+  "res/drawable-mdpi-v4/notification_bg_low_normal.9.png",
+  "res/drawable-mdpi-v4/notification_bg_low_pressed.9.png",
+  "res/drawable-mdpi-v4/notification_bg_normal.9.png",
+  "res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png",
+  "res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png",
+  "res/drawable-v21/notification_action_background.xml",
+  "res/drawable-xhdpi-v4/notification_bg_low_normal.9.png",
+  "res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png",
+  "res/drawable-xhdpi-v4/notification_bg_normal.9.png",
+  "res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png",
+  "res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png",
+  "res/layout/custom_dialog.xml",
+  "res/layout/notification_action.xml",
+  "res/layout/notification_action_tombstone.xml",
+  "res/layout/notification_template_custom_big.xml",
+  "res/layout/notification_template_icon_group.xml",
+  "res/layout/notification_template_part_chronometer.xml",
+  "res/layout/notification_template_part_time.xml",
+  "res/layout-v16/notification_template_custom_big.xml",
+  "res/layout-v21/notification_action.xml",
+  "res/layout-v21/notification_action_tombstone.xml",
+  "res/layout-v21/notification_template_custom_big.xml",
+  "res/layout-v21/notification_template_icon_group.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-as/values-as.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-or/values-or.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v16/values-v16.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_cursoradapter_cursoradapter/androidx_cursoradapter_cursoradapter.info b/third_party/android_deps/libs/androidx_cursoradapter_cursoradapter/androidx_cursoradapter_cursoradapter.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_cursoradapter_cursoradapter/androidx_cursoradapter_cursoradapter.info
+++ b/third_party/android_deps/libs/androidx_cursoradapter_cursoradapter/androidx_cursoradapter_cursoradapter.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_customview_customview/androidx_customview_customview.info b/third_party/android_deps/libs/androidx_customview_customview/androidx_customview_customview.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_customview_customview/androidx_customview_customview.info
+++ b/third_party/android_deps/libs/androidx_customview_customview/androidx_customview_customview.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_documentfile_documentfile/androidx_documentfile_documentfile.info b/third_party/android_deps/libs/androidx_documentfile_documentfile/androidx_documentfile_documentfile.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_documentfile_documentfile/androidx_documentfile_documentfile.info
+++ b/third_party/android_deps/libs/androidx_documentfile_documentfile/androidx_documentfile_documentfile.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_drawerlayout_drawerlayout/androidx_drawerlayout_drawerlayout.info b/third_party/android_deps/libs/androidx_drawerlayout_drawerlayout/androidx_drawerlayout_drawerlayout.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_drawerlayout_drawerlayout/androidx_drawerlayout_drawerlayout.info
+++ b/third_party/android_deps/libs/androidx_drawerlayout_drawerlayout/androidx_drawerlayout_drawerlayout.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_fragment_fragment/androidx_fragment_fragment.info b/third_party/android_deps/libs/androidx_fragment_fragment/androidx_fragment_fragment.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_fragment_fragment/androidx_fragment_fragment.info
+++ b/third_party/android_deps/libs/androidx_fragment_fragment/androidx_fragment_fragment.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_gridlayout_gridlayout/androidx_gridlayout_gridlayout.info b/third_party/android_deps/libs/androidx_gridlayout_gridlayout/androidx_gridlayout_gridlayout.info
index 28c8330..4a744e7 100644
--- a/third_party/android_deps/libs/androidx_gridlayout_gridlayout/androidx_gridlayout_gridlayout.info
+++ b/third_party/android_deps/libs/androidx_gridlayout_gridlayout/androidx_gridlayout_gridlayout.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_interpolator_interpolator/androidx_interpolator_interpolator.info b/third_party/android_deps/libs/androidx_interpolator_interpolator/androidx_interpolator_interpolator.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_interpolator_interpolator/androidx_interpolator_interpolator.info
+++ b/third_party/android_deps/libs/androidx_interpolator_interpolator/androidx_interpolator_interpolator.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_leanback_leanback/androidx_leanback_leanback.info b/third_party/android_deps/libs/androidx_leanback_leanback/androidx_leanback_leanback.info
index d7f5494..190c417d 100644
--- a/third_party/android_deps/libs/androidx_leanback_leanback/androidx_leanback_leanback.info
+++ b/third_party/android_deps/libs/androidx_leanback_leanback/androidx_leanback_leanback.info
@@ -1,13 +1,300 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/anim/lb_decelerator_2.xml", "res/anim/lb_decelerator_4.xml", "res/animator/lb_guidedactions_item_pressed.xml", "res/animator/lb_guidedactions_item_unpressed.xml", "res/animator/lb_guidedstep_slide_down.xml", "res/animator/lb_guidedstep_slide_up.xml", "res/animator/lb_onboarding_description_enter.xml", "res/animator/lb_onboarding_logo_enter.xml", "res/animator/lb_onboarding_logo_exit.xml", "res/animator/lb_onboarding_page_indicator_enter.xml", "res/animator/lb_onboarding_page_indicator_fade_in.xml", "res/animator/lb_onboarding_page_indicator_fade_out.xml", "res/animator/lb_onboarding_start_button_fade_in.xml", "res/animator/lb_onboarding_start_button_fade_out.xml", "res/animator/lb_onboarding_title_enter.xml", "res/animator/lb_playback_bg_fade_in.xml", "res/animator/lb_playback_bg_fade_out.xml", "res/animator/lb_playback_controls_fade_in.xml", "res/animator/lb_playback_controls_fade_out.xml", "res/animator/lb_playback_description_fade_in.xml", "res/animator/lb_playback_description_fade_out.xml", "res/animator/lb_playback_rows_fade_in.xml", "res/animator/lb_playback_rows_fade_out.xml", "res/animator-v21/lb_onboarding_description_enter.xml", "res/animator-v21/lb_onboarding_logo_enter.xml", "res/animator-v21/lb_onboarding_logo_exit.xml", "res/animator-v21/lb_onboarding_page_indicator_enter.xml", "res/animator-v21/lb_onboarding_title_enter.xml", "res/animator-v21/lb_playback_bg_fade_in.xml", "res/animator-v21/lb_playback_bg_fade_out.xml", "res/animator-v21/lb_playback_description_fade_out.xml", "res/drawable/lb_background.xml", "res/drawable/lb_card_foreground.xml", "res/drawable/lb_control_button_primary.xml", "res/drawable/lb_control_button_secondary.xml", "res/drawable/lb_headers_right_fading.xml", "res/drawable/lb_onboarding_start_button_background.xml", "res/drawable/lb_playback_now_playing_bar.xml", "res/drawable/lb_playback_progress_bar.xml", "res/drawable/lb_search_orb.xml", "res/drawable/lb_speech_orb.xml", "res/drawable-hdpi-v4/lb_action_bg_focused.9.png", "res/drawable-hdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-hdpi-v4/lb_ic_in_app_search.png", "res/drawable-hdpi-v4/lb_ic_sad_cloud.png", "res/drawable-hdpi-v4/lb_ic_search_mic.png", "res/drawable-hdpi-v4/lb_ic_search_mic_out.png", "res/drawable-hdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-mdpi-v4/lb_action_bg_focused.9.png", "res/drawable-mdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-mdpi-v4/lb_ic_in_app_search.png", "res/drawable-mdpi-v4/lb_ic_sad_cloud.png", "res/drawable-mdpi-v4/lb_ic_search_mic.png", "res/drawable-mdpi-v4/lb_ic_search_mic_out.png", "res/drawable-mdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-v21/lb_action_bg.xml", "res/drawable-v21/lb_card_foreground.xml", "res/drawable-v21/lb_control_button_primary.xml", "res/drawable-v21/lb_control_button_secondary.xml", "res/drawable-v21/lb_selectable_item_rounded_rect.xml", "res/drawable-xhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xhdpi-v4/lb_card_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_card_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xhdpi-v4/lb_ic_cc.png", "res/drawable-xhdpi-v4/lb_ic_fast_forward.png", "res/drawable-xhdpi-v4/lb_ic_fast_rewind.png", "res/drawable-xhdpi-v4/lb_ic_guidedactions_item_chevron.png", "res/drawable-xhdpi-v4/lb_ic_hq.png", "res/drawable-xhdpi-v4/lb_ic_in_app_search.png", "res/drawable-xhdpi-v4/lb_ic_loop.png", "res/drawable-xhdpi-v4/lb_ic_loop_one.png", "res/drawable-xhdpi-v4/lb_ic_more.png", "res/drawable-xhdpi-v4/lb_ic_nav_arrow.png", "res/drawable-xhdpi-v4/lb_ic_pause.png", "res/drawable-xhdpi-v4/lb_ic_pip.png", "res/drawable-xhdpi-v4/lb_ic_play.png", "res/drawable-xhdpi-v4/lb_ic_play_fit.png", "res/drawable-xhdpi-v4/lb_ic_playback_loop.png", "res/drawable-xhdpi-v4/lb_ic_replay.png", "res/drawable-xhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xhdpi-v4/lb_ic_search_mic.png", "res/drawable-xhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xhdpi-v4/lb_ic_shuffle.png", "res/drawable-xhdpi-v4/lb_ic_skip_next.png", "res/drawable-xhdpi-v4/lb_ic_skip_previous.png", "res/drawable-xhdpi-v4/lb_ic_stop.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down_outline.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up_outline.png", "res/drawable-xhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_text_dot_one.png", "res/drawable-xhdpi-v4/lb_text_dot_one_small.png", "res/drawable-xhdpi-v4/lb_text_dot_two.png", "res/drawable-xhdpi-v4/lb_text_dot_two_small.png", "res/drawable-xxhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xxhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xxhdpi-v4/lb_ic_in_app_search.png", "res/drawable-xxhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xxhdpi-v4/lb_ic_search_mic.png", "res/drawable-xxhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xxhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/layout/lb_action_1_line.xml", "res/layout/lb_action_2_lines.xml", "res/layout/lb_background_window.xml", "res/layout/lb_browse_fragment.xml", "res/layout/lb_browse_title.xml", "res/layout/lb_control_bar.xml", "res/layout/lb_control_button_primary.xml", "res/layout/lb_control_button_secondary.xml", "res/layout/lb_details_description.xml", "res/layout/lb_details_fragment.xml", "res/layout/lb_details_overview.xml", "res/layout/lb_divider.xml", "res/layout/lb_error_fragment.xml", "res/layout/lb_fullwidth_details_overview.xml", "res/layout/lb_fullwidth_details_overview_logo.xml", "res/layout/lb_guidance.xml", "res/layout/lb_guidedactions.xml", "res/layout/lb_guidedactions_datepicker_item.xml", "res/layout/lb_guidedactions_item.xml", "res/layout/lb_guidedbuttonactions.xml", "res/layout/lb_guidedstep_background.xml", "res/layout/lb_guidedstep_fragment.xml", "res/layout/lb_header.xml", "res/layout/lb_headers_fragment.xml", "res/layout/lb_image_card_view.xml", "res/layout/lb_image_card_view_themed_badge_left.xml", "res/layout/lb_image_card_view_themed_badge_right.xml", "res/layout/lb_image_card_view_themed_content.xml", "res/layout/lb_image_card_view_themed_title.xml", "res/layout/lb_list_row.xml", "res/layout/lb_list_row_hovercard.xml", "res/layout/lb_media_item_number_view_flipper.xml", "res/layout/lb_media_list_header.xml", "res/layout/lb_onboarding_fragment.xml", "res/layout/lb_picker.xml", "res/layout/lb_picker_column.xml", "res/layout/lb_picker_item.xml", "res/layout/lb_picker_separator.xml", "res/layout/lb_playback_controls.xml", "res/layout/lb_playback_controls_row.xml", "res/layout/lb_playback_fragment.xml", "res/layout/lb_playback_now_playing_bars.xml", "res/layout/lb_playback_transport_controls.xml", "res/layout/lb_playback_transport_controls_row.xml", "res/layout/lb_row_container.xml", "res/layout/lb_row_header.xml", "res/layout/lb_row_media_item.xml", "res/layout/lb_row_media_item_action.xml", "res/layout/lb_rows_fragment.xml", "res/layout/lb_search_bar.xml", "res/layout/lb_search_fragment.xml", "res/layout/lb_search_orb.xml", "res/layout/lb_section_header.xml", "res/layout/lb_shadow.xml", "res/layout/lb_speech_orb.xml", "res/layout/lb_title_view.xml", "res/layout/lb_vertical_grid.xml", "res/layout/lb_vertical_grid_fragment.xml", "res/layout/lb_video_surface.xml", "res/layout/video_surface_fragment.xml", "res/raw/lb_voice_failure.ogg", "res/raw/lb_voice_no_input.ogg", "res/raw/lb_voice_open.ogg", "res/raw/lb_voice_success.ogg", "res/transition-v19/lb_browse_headers_in.xml", "res/transition-v19/lb_browse_headers_out.xml", "res/transition-v21/lb_browse_enter_transition.xml", "res/transition-v21/lb_browse_entrance_transition.xml", "res/transition-v21/lb_browse_headers_in.xml", "res/transition-v21/lb_browse_headers_out.xml", "res/transition-v21/lb_browse_return_transition.xml", "res/transition-v21/lb_details_enter_transition.xml", "res/transition-v21/lb_details_return_transition.xml", "res/transition-v21/lb_enter_transition.xml", "res/transition-v21/lb_guidedstep_activity_enter.xml", "res/transition-v21/lb_guidedstep_activity_enter_bottom.xml", "res/transition-v21/lb_return_transition.xml", "res/transition-v21/lb_shared_element_enter_transition.xml", "res/transition-v21/lb_shared_element_return_transition.xml", "res/transition-v21/lb_title_in.xml", "res/transition-v21/lb_title_out.xml", "res/transition-v21/lb_vertical_grid_enter_transition.xml", "res/transition-v21/lb_vertical_grid_entrance_transition.xml", "res/transition-v21/lb_vertical_grid_return_transition.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-as/values-as.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-ldrtl-v17/values-ldrtl-v17.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-or/values-or.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v18/values-v18.xml", "res/values-v19/values-v19.xml", "res/values-v21/values-v21.xml", "res/values-v22/values-v22.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/anim/lb_decelerator_2.xml",
+  "res/anim/lb_decelerator_4.xml",
+  "res/animator/lb_guidedactions_item_pressed.xml",
+  "res/animator/lb_guidedactions_item_unpressed.xml",
+  "res/animator/lb_guidedstep_slide_down.xml",
+  "res/animator/lb_guidedstep_slide_up.xml",
+  "res/animator/lb_onboarding_description_enter.xml",
+  "res/animator/lb_onboarding_logo_enter.xml",
+  "res/animator/lb_onboarding_logo_exit.xml",
+  "res/animator/lb_onboarding_page_indicator_enter.xml",
+  "res/animator/lb_onboarding_page_indicator_fade_in.xml",
+  "res/animator/lb_onboarding_page_indicator_fade_out.xml",
+  "res/animator/lb_onboarding_start_button_fade_in.xml",
+  "res/animator/lb_onboarding_start_button_fade_out.xml",
+  "res/animator/lb_onboarding_title_enter.xml",
+  "res/animator/lb_playback_bg_fade_in.xml",
+  "res/animator/lb_playback_bg_fade_out.xml",
+  "res/animator/lb_playback_controls_fade_in.xml",
+  "res/animator/lb_playback_controls_fade_out.xml",
+  "res/animator/lb_playback_description_fade_in.xml",
+  "res/animator/lb_playback_description_fade_out.xml",
+  "res/animator/lb_playback_rows_fade_in.xml",
+  "res/animator/lb_playback_rows_fade_out.xml",
+  "res/animator-v21/lb_onboarding_description_enter.xml",
+  "res/animator-v21/lb_onboarding_logo_enter.xml",
+  "res/animator-v21/lb_onboarding_logo_exit.xml",
+  "res/animator-v21/lb_onboarding_page_indicator_enter.xml",
+  "res/animator-v21/lb_onboarding_title_enter.xml",
+  "res/animator-v21/lb_playback_bg_fade_in.xml",
+  "res/animator-v21/lb_playback_bg_fade_out.xml",
+  "res/animator-v21/lb_playback_description_fade_out.xml",
+  "res/drawable/lb_background.xml",
+  "res/drawable/lb_card_foreground.xml",
+  "res/drawable/lb_control_button_primary.xml",
+  "res/drawable/lb_control_button_secondary.xml",
+  "res/drawable/lb_headers_right_fading.xml",
+  "res/drawable/lb_onboarding_start_button_background.xml",
+  "res/drawable/lb_playback_now_playing_bar.xml",
+  "res/drawable/lb_playback_progress_bar.xml",
+  "res/drawable/lb_search_orb.xml",
+  "res/drawable/lb_speech_orb.xml",
+  "res/drawable-hdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-hdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-hdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-hdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-hdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-hdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-hdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-hdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-hdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/drawable-mdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-mdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-mdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-mdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-mdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-mdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-mdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-mdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-mdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/drawable-v21/lb_action_bg.xml",
+  "res/drawable-v21/lb_card_foreground.xml",
+  "res/drawable-v21/lb_control_button_primary.xml",
+  "res/drawable-v21/lb_control_button_secondary.xml",
+  "res/drawable-v21/lb_selectable_item_rounded_rect.xml",
+  "res/drawable-xhdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-xhdpi-v4/lb_card_shadow_focused.9.png",
+  "res/drawable-xhdpi-v4/lb_card_shadow_normal.9.png",
+  "res/drawable-xhdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-xhdpi-v4/lb_ic_cc.png",
+  "res/drawable-xhdpi-v4/lb_ic_fast_forward.png",
+  "res/drawable-xhdpi-v4/lb_ic_fast_rewind.png",
+  "res/drawable-xhdpi-v4/lb_ic_guidedactions_item_chevron.png",
+  "res/drawable-xhdpi-v4/lb_ic_hq.png",
+  "res/drawable-xhdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-xhdpi-v4/lb_ic_loop.png",
+  "res/drawable-xhdpi-v4/lb_ic_loop_one.png",
+  "res/drawable-xhdpi-v4/lb_ic_more.png",
+  "res/drawable-xhdpi-v4/lb_ic_nav_arrow.png",
+  "res/drawable-xhdpi-v4/lb_ic_pause.png",
+  "res/drawable-xhdpi-v4/lb_ic_pip.png",
+  "res/drawable-xhdpi-v4/lb_ic_play.png",
+  "res/drawable-xhdpi-v4/lb_ic_play_fit.png",
+  "res/drawable-xhdpi-v4/lb_ic_playback_loop.png",
+  "res/drawable-xhdpi-v4/lb_ic_replay.png",
+  "res/drawable-xhdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-xhdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-xhdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-xhdpi-v4/lb_ic_shuffle.png",
+  "res/drawable-xhdpi-v4/lb_ic_skip_next.png",
+  "res/drawable-xhdpi-v4/lb_ic_skip_previous.png",
+  "res/drawable-xhdpi-v4/lb_ic_stop.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_down.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_down_outline.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_up.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_up_outline.png",
+  "res/drawable-xhdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-xhdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-xhdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_one.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_one_small.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_two.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_two_small.png",
+  "res/drawable-xxhdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-xxhdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-xxhdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-xxhdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-xxhdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-xxhdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-xxhdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/layout/lb_action_1_line.xml",
+  "res/layout/lb_action_2_lines.xml",
+  "res/layout/lb_background_window.xml",
+  "res/layout/lb_browse_fragment.xml",
+  "res/layout/lb_browse_title.xml",
+  "res/layout/lb_control_bar.xml",
+  "res/layout/lb_control_button_primary.xml",
+  "res/layout/lb_control_button_secondary.xml",
+  "res/layout/lb_details_description.xml",
+  "res/layout/lb_details_fragment.xml",
+  "res/layout/lb_details_overview.xml",
+  "res/layout/lb_divider.xml",
+  "res/layout/lb_error_fragment.xml",
+  "res/layout/lb_fullwidth_details_overview.xml",
+  "res/layout/lb_fullwidth_details_overview_logo.xml",
+  "res/layout/lb_guidance.xml",
+  "res/layout/lb_guidedactions.xml",
+  "res/layout/lb_guidedactions_datepicker_item.xml",
+  "res/layout/lb_guidedactions_item.xml",
+  "res/layout/lb_guidedbuttonactions.xml",
+  "res/layout/lb_guidedstep_background.xml",
+  "res/layout/lb_guidedstep_fragment.xml",
+  "res/layout/lb_header.xml",
+  "res/layout/lb_headers_fragment.xml",
+  "res/layout/lb_image_card_view.xml",
+  "res/layout/lb_image_card_view_themed_badge_left.xml",
+  "res/layout/lb_image_card_view_themed_badge_right.xml",
+  "res/layout/lb_image_card_view_themed_content.xml",
+  "res/layout/lb_image_card_view_themed_title.xml",
+  "res/layout/lb_list_row.xml",
+  "res/layout/lb_list_row_hovercard.xml",
+  "res/layout/lb_media_item_number_view_flipper.xml",
+  "res/layout/lb_media_list_header.xml",
+  "res/layout/lb_onboarding_fragment.xml",
+  "res/layout/lb_picker.xml",
+  "res/layout/lb_picker_column.xml",
+  "res/layout/lb_picker_item.xml",
+  "res/layout/lb_picker_separator.xml",
+  "res/layout/lb_playback_controls.xml",
+  "res/layout/lb_playback_controls_row.xml",
+  "res/layout/lb_playback_fragment.xml",
+  "res/layout/lb_playback_now_playing_bars.xml",
+  "res/layout/lb_playback_transport_controls.xml",
+  "res/layout/lb_playback_transport_controls_row.xml",
+  "res/layout/lb_row_container.xml",
+  "res/layout/lb_row_header.xml",
+  "res/layout/lb_row_media_item.xml",
+  "res/layout/lb_row_media_item_action.xml",
+  "res/layout/lb_rows_fragment.xml",
+  "res/layout/lb_search_bar.xml",
+  "res/layout/lb_search_fragment.xml",
+  "res/layout/lb_search_orb.xml",
+  "res/layout/lb_section_header.xml",
+  "res/layout/lb_shadow.xml",
+  "res/layout/lb_speech_orb.xml",
+  "res/layout/lb_title_view.xml",
+  "res/layout/lb_vertical_grid.xml",
+  "res/layout/lb_vertical_grid_fragment.xml",
+  "res/layout/lb_video_surface.xml",
+  "res/layout/video_surface_fragment.xml",
+  "res/raw/lb_voice_failure.ogg",
+  "res/raw/lb_voice_no_input.ogg",
+  "res/raw/lb_voice_open.ogg",
+  "res/raw/lb_voice_success.ogg",
+  "res/transition-v19/lb_browse_headers_in.xml",
+  "res/transition-v19/lb_browse_headers_out.xml",
+  "res/transition-v21/lb_browse_enter_transition.xml",
+  "res/transition-v21/lb_browse_entrance_transition.xml",
+  "res/transition-v21/lb_browse_headers_in.xml",
+  "res/transition-v21/lb_browse_headers_out.xml",
+  "res/transition-v21/lb_browse_return_transition.xml",
+  "res/transition-v21/lb_details_enter_transition.xml",
+  "res/transition-v21/lb_details_return_transition.xml",
+  "res/transition-v21/lb_enter_transition.xml",
+  "res/transition-v21/lb_guidedstep_activity_enter.xml",
+  "res/transition-v21/lb_guidedstep_activity_enter_bottom.xml",
+  "res/transition-v21/lb_return_transition.xml",
+  "res/transition-v21/lb_shared_element_enter_transition.xml",
+  "res/transition-v21/lb_shared_element_return_transition.xml",
+  "res/transition-v21/lb_title_in.xml",
+  "res/transition-v21/lb_title_out.xml",
+  "res/transition-v21/lb_vertical_grid_enter_transition.xml",
+  "res/transition-v21/lb_vertical_grid_entrance_transition.xml",
+  "res/transition-v21/lb_vertical_grid_return_transition.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-as/values-as.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-ldrtl-v17/values-ldrtl-v17.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-or/values-or.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v18/values-v18.xml",
+  "res/values-v19/values-v19.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-v22/values-v22.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_leanback_leanback_preference/androidx_leanback_leanback_preference.info b/third_party/android_deps/libs/androidx_leanback_leanback_preference/androidx_leanback_leanback_preference.info
index 754a696c..500cc24 100644
--- a/third_party/android_deps/libs/androidx_leanback_leanback_preference/androidx_leanback_leanback_preference.info
+++ b/third_party/android_deps/libs/androidx_leanback_leanback_preference/androidx_leanback_leanback_preference.info
@@ -1,13 +1,29 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/color/lb_preference_item_primary_text_color.xml", "res/color/lb_preference_item_secondary_text_color.xml", "res/layout/leanback_list_preference_fragment.xml", "res/layout/leanback_list_preference_item_multi.xml", "res/layout/leanback_list_preference_item_single.xml", "res/layout/leanback_preference.xml", "res/layout/leanback_preference_category.xml", "res/layout/leanback_preference_fragment.xml", "res/layout/leanback_preference_information.xml", "res/layout/leanback_preference_widget_seekbar.xml", "res/layout/leanback_preferences_list.xml", "res/layout/leanback_settings_fragment.xml", "res/layout-v21/leanback_preference_category.xml", "res/layout-v21/leanback_settings_fragment.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/color/lb_preference_item_primary_text_color.xml",
+  "res/color/lb_preference_item_secondary_text_color.xml",
+  "res/layout/leanback_list_preference_fragment.xml",
+  "res/layout/leanback_list_preference_item_multi.xml",
+  "res/layout/leanback_list_preference_item_single.xml",
+  "res/layout/leanback_preference.xml",
+  "res/layout/leanback_preference_category.xml",
+  "res/layout/leanback_preference_fragment.xml",
+  "res/layout/leanback_preference_information.xml",
+  "res/layout/leanback_preference_widget_seekbar.xml",
+  "res/layout/leanback_preferences_list.xml",
+  "res/layout/leanback_settings_fragment.xml",
+  "res/layout-v21/leanback_preference_category.xml",
+  "res/layout-v21/leanback_settings_fragment.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_legacy_legacy_preference_v14/androidx_legacy_legacy_preference_v14.info b/third_party/android_deps/libs/androidx_legacy_legacy_preference_v14/androidx_legacy_legacy_preference_v14.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_legacy_legacy_preference_v14/androidx_legacy_legacy_preference_v14.info
+++ b/third_party/android_deps/libs/androidx_legacy_legacy_preference_v14/androidx_legacy_legacy_preference_v14.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_legacy_legacy_support_core_ui/androidx_legacy_legacy_support_core_ui.info b/third_party/android_deps/libs/androidx_legacy_legacy_support_core_ui/androidx_legacy_legacy_support_core_ui.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_legacy_legacy_support_core_ui/androidx_legacy_legacy_support_core_ui.info
+++ b/third_party/android_deps/libs/androidx_legacy_legacy_support_core_ui/androidx_legacy_legacy_support_core_ui.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_legacy_legacy_support_core_utils/androidx_legacy_legacy_support_core_utils.info b/third_party/android_deps/libs/androidx_legacy_legacy_support_core_utils/androidx_legacy_legacy_support_core_utils.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_legacy_legacy_support_core_utils/androidx_legacy_legacy_support_core_utils.info
+++ b/third_party/android_deps/libs/androidx_legacy_legacy_support_core_utils/androidx_legacy_legacy_support_core_utils.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_legacy_legacy_support_v13/androidx_legacy_legacy_support_v13.info b/third_party/android_deps/libs/androidx_legacy_legacy_support_v13/androidx_legacy_legacy_support_v13.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_legacy_legacy_support_v13/androidx_legacy_legacy_support_v13.info
+++ b/third_party/android_deps/libs/androidx_legacy_legacy_support_v13/androidx_legacy_legacy_support_v13.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_legacy_legacy_support_v4/androidx_legacy_legacy_support_v4.info b/third_party/android_deps/libs/androidx_legacy_legacy_support_v4/androidx_legacy_legacy_support_v4.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_legacy_legacy_support_v4/androidx_legacy_legacy_support_v4.info
+++ b/third_party/android_deps/libs/androidx_legacy_legacy_support_v4/androidx_legacy_legacy_support_v4.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata/androidx_lifecycle_lifecycle_livedata.info b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata/androidx_lifecycle_lifecycle_livedata.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata/androidx_lifecycle_lifecycle_livedata.info
+++ b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata/androidx_lifecycle_lifecycle_livedata.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata_core/androidx_lifecycle_lifecycle_livedata_core.info b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata_core/androidx_lifecycle_lifecycle_livedata_core.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata_core/androidx_lifecycle_lifecycle_livedata_core.info
+++ b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_livedata_core/androidx_lifecycle_lifecycle_livedata_core.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_runtime/androidx_lifecycle_lifecycle_runtime.info b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_runtime/androidx_lifecycle_lifecycle_runtime.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_runtime/androidx_lifecycle_lifecycle_runtime.info
+++ b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_runtime/androidx_lifecycle_lifecycle_runtime.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_viewmodel/androidx_lifecycle_lifecycle_viewmodel.info b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_viewmodel/androidx_lifecycle_lifecycle_viewmodel.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/androidx_lifecycle_lifecycle_viewmodel/androidx_lifecycle_lifecycle_viewmodel.info
+++ b/third_party/android_deps/libs/androidx_lifecycle_lifecycle_viewmodel/androidx_lifecycle_lifecycle_viewmodel.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_loader_loader/androidx_loader_loader.info b/third_party/android_deps/libs/androidx_loader_loader/androidx_loader_loader.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_loader_loader/androidx_loader_loader.info
+++ b/third_party/android_deps/libs/androidx_loader_loader/androidx_loader_loader.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_localbroadcastmanager_localbroadcastmanager/androidx_localbroadcastmanager_localbroadcastmanager.info b/third_party/android_deps/libs/androidx_localbroadcastmanager_localbroadcastmanager/androidx_localbroadcastmanager_localbroadcastmanager.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_localbroadcastmanager_localbroadcastmanager/androidx_localbroadcastmanager_localbroadcastmanager.info
+++ b/third_party/android_deps/libs/androidx_localbroadcastmanager_localbroadcastmanager/androidx_localbroadcastmanager_localbroadcastmanager.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_media_media/androidx_media_media.info b/third_party/android_deps/libs/androidx_media_media/androidx_media_media.info
index 672a388..00257b6 100644
--- a/third_party/android_deps/libs/androidx_media_media/androidx_media_media.info
+++ b/third_party/android_deps/libs/androidx_media_media/androidx_media_media.info
@@ -1,13 +1,33 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [ "aidl/android/support/v4/media/MediaDescriptionCompat.aidl", "aidl/android/support/v4/media/MediaMetadataCompat.aidl", "aidl/android/support/v4/media/RatingCompat.aidl", "aidl/android/support/v4/media/session/MediaSessionCompat.aidl", "aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl", "aidl/android/support/v4/media/session/PlaybackStateCompat.aidl" ]
-assets = [  ]
+aidl = [
+  "aidl/android/support/v4/media/MediaDescriptionCompat.aidl",
+  "aidl/android/support/v4/media/MediaMetadataCompat.aidl",
+  "aidl/android/support/v4/media/RatingCompat.aidl",
+  "aidl/android/support/v4/media/session/MediaSessionCompat.aidl",
+  "aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl",
+  "aidl/android/support/v4/media/session/PlaybackStateCompat.aidl"
+]
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/layout/notification_media_action.xml", "res/layout/notification_media_cancel_action.xml", "res/layout/notification_template_big_media.xml", "res/layout/notification_template_big_media_custom.xml", "res/layout/notification_template_big_media_narrow.xml", "res/layout/notification_template_big_media_narrow_custom.xml", "res/layout/notification_template_lines_media.xml", "res/layout/notification_template_media.xml", "res/layout/notification_template_media_custom.xml", "res/values/values.xml", "res/values-v21/values-v21.xml", "res/values-v24/values-v24.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/layout/notification_media_action.xml",
+  "res/layout/notification_media_cancel_action.xml",
+  "res/layout/notification_template_big_media.xml",
+  "res/layout/notification_template_big_media_custom.xml",
+  "res/layout/notification_template_big_media_narrow.xml",
+  "res/layout/notification_template_big_media_narrow_custom.xml",
+  "res/layout/notification_template_lines_media.xml",
+  "res/layout/notification_template_media.xml",
+  "res/layout/notification_template_media_custom.xml",
+  "res/values/values.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-v24/values-v24.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_mediarouter_mediarouter/androidx_mediarouter_mediarouter.info b/third_party/android_deps/libs/androidx_mediarouter_mediarouter/androidx_mediarouter_mediarouter.info
index e0bb0fd..9532abc 100644
--- a/third_party/android_deps/libs/androidx_mediarouter_mediarouter/androidx_mediarouter_mediarouter.info
+++ b/third_party/android_deps/libs/androidx_mediarouter_mediarouter/androidx_mediarouter_mediarouter.info
@@ -1,13 +1,502 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable/mr_button_connected_dark.xml", "res/drawable/mr_button_connected_light.xml", "res/drawable/mr_button_connecting_dark.xml", "res/drawable/mr_button_connecting_light.xml", "res/drawable/mr_button_dark.xml", "res/drawable/mr_button_light.xml", "res/drawable/mr_dialog_close_dark.xml", "res/drawable/mr_dialog_close_light.xml", "res/drawable/mr_dialog_material_background_dark.xml", "res/drawable/mr_dialog_material_background_light.xml", "res/drawable/mr_group_collapse.xml", "res/drawable/mr_group_expand.xml", "res/drawable/mr_media_pause_dark.xml", "res/drawable/mr_media_pause_light.xml", "res/drawable/mr_media_play_dark.xml", "res/drawable/mr_media_play_light.xml", "res/drawable/mr_media_stop_dark.xml", "res/drawable/mr_media_stop_light.xml", "res/drawable/mr_vol_type_audiotrack_dark.xml", "res/drawable/mr_vol_type_audiotrack_light.xml", "res/drawable-hdpi-v4/ic_audiotrack_dark.png", "res/drawable-hdpi-v4/ic_audiotrack_light.png", "res/drawable-hdpi-v4/ic_dialog_close_dark.png", "res/drawable-hdpi-v4/ic_dialog_close_light.png", "res/drawable-hdpi-v4/ic_media_pause_dark.png", "res/drawable-hdpi-v4/ic_media_pause_light.png", "res/drawable-hdpi-v4/ic_media_play_dark.png", "res/drawable-hdpi-v4/ic_media_play_light.png", "res/drawable-hdpi-v4/ic_media_stop_dark.png", "res/drawable-hdpi-v4/ic_media_stop_light.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-hdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-hdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-hdpi-v4/ic_mr_button_grey.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-hdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-hdpi-v4/ic_vol_type_tv_light.png", "res/drawable-mdpi-v4/ic_audiotrack_dark.png", "res/drawable-mdpi-v4/ic_audiotrack_light.png", "res/drawable-mdpi-v4/ic_dialog_close_dark.png", "res/drawable-mdpi-v4/ic_dialog_close_light.png", "res/drawable-mdpi-v4/ic_media_pause_dark.png", "res/drawable-mdpi-v4/ic_media_pause_light.png", "res/drawable-mdpi-v4/ic_media_play_dark.png", "res/drawable-mdpi-v4/ic_media_play_light.png", "res/drawable-mdpi-v4/ic_media_stop_dark.png", "res/drawable-mdpi-v4/ic_media_stop_light.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-mdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-mdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-mdpi-v4/ic_mr_button_grey.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-mdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-mdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xhdpi-v4/ic_audiotrack_light.png", "res/drawable-xhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xhdpi-v4/ic_dialog_close_light.png", "res/drawable-xhdpi-v4/ic_media_pause_dark.png", "res/drawable-xhdpi-v4/ic_media_pause_light.png", "res/drawable-xhdpi-v4/ic_media_play_dark.png", "res/drawable-xhdpi-v4/ic_media_play_light.png", "res/drawable-xhdpi-v4/ic_media_stop_dark.png", "res/drawable-xhdpi-v4/ic_media_stop_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_23_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_23_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_24_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_24_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_25_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_25_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_26_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_26_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_27_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_27_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_28_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_28_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_29_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_29_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_30_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_30_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xhdpi-v4/ic_mr_button_grey.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xxhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xxhdpi-v4/ic_audiotrack_light.png", "res/drawable-xxhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xxhdpi-v4/ic_dialog_close_light.png", "res/drawable-xxhdpi-v4/ic_media_pause_dark.png", "res/drawable-xxhdpi-v4/ic_media_pause_light.png", "res/drawable-xxhdpi-v4/ic_media_play_dark.png", "res/drawable-xxhdpi-v4/ic_media_play_light.png", "res/drawable-xxhdpi-v4/ic_media_stop_dark.png", "res/drawable-xxhdpi-v4/ic_media_stop_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_grey.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_00.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_01.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_02.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_03.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_04.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_05.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_06.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_07.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_08.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_09.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_10.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_11.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_12.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_13.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_14.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_15.png", "res/drawable-xxxhdpi-v4/ic_group_expand_00.png", "res/drawable-xxxhdpi-v4/ic_group_expand_01.png", "res/drawable-xxxhdpi-v4/ic_group_expand_02.png", "res/drawable-xxxhdpi-v4/ic_group_expand_03.png", "res/drawable-xxxhdpi-v4/ic_group_expand_04.png", "res/drawable-xxxhdpi-v4/ic_group_expand_05.png", "res/drawable-xxxhdpi-v4/ic_group_expand_06.png", "res/drawable-xxxhdpi-v4/ic_group_expand_07.png", "res/drawable-xxxhdpi-v4/ic_group_expand_08.png", "res/drawable-xxxhdpi-v4/ic_group_expand_09.png", "res/drawable-xxxhdpi-v4/ic_group_expand_10.png", "res/drawable-xxxhdpi-v4/ic_group_expand_11.png", "res/drawable-xxxhdpi-v4/ic_group_expand_12.png", "res/drawable-xxxhdpi-v4/ic_group_expand_13.png", "res/drawable-xxxhdpi-v4/ic_group_expand_14.png", "res/drawable-xxxhdpi-v4/ic_group_expand_15.png", "res/drawable-xxxhdpi-v4/ic_mr_button_grey.png", "res/interpolator/mr_fast_out_slow_in.xml", "res/interpolator/mr_linear_out_slow_in.xml", "res/layout/mr_cast_dialog.xml", "res/layout/mr_cast_group_item.xml", "res/layout/mr_cast_group_volume_item.xml", "res/layout/mr_cast_media_metadata.xml", "res/layout/mr_cast_route_item.xml", "res/layout/mr_chooser_dialog.xml", "res/layout/mr_chooser_list_item.xml", "res/layout/mr_controller_material_dialog_b.xml", "res/layout/mr_controller_volume_item.xml", "res/layout/mr_dialog_header_item.xml", "res/layout/mr_picker_dialog.xml", "res/layout/mr_picker_route_item.xml", "res/layout/mr_playback_control.xml", "res/layout/mr_volume_control.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-land/values-land.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-sw720dp-v13/values-sw720dp-v13.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable/mr_button_connected_dark.xml",
+  "res/drawable/mr_button_connected_light.xml",
+  "res/drawable/mr_button_connecting_dark.xml",
+  "res/drawable/mr_button_connecting_light.xml",
+  "res/drawable/mr_button_dark.xml",
+  "res/drawable/mr_button_light.xml",
+  "res/drawable/mr_dialog_close_dark.xml",
+  "res/drawable/mr_dialog_close_light.xml",
+  "res/drawable/mr_dialog_material_background_dark.xml",
+  "res/drawable/mr_dialog_material_background_light.xml",
+  "res/drawable/mr_group_collapse.xml",
+  "res/drawable/mr_group_expand.xml",
+  "res/drawable/mr_media_pause_dark.xml",
+  "res/drawable/mr_media_pause_light.xml",
+  "res/drawable/mr_media_play_dark.xml",
+  "res/drawable/mr_media_play_light.xml",
+  "res/drawable/mr_media_stop_dark.xml",
+  "res/drawable/mr_media_stop_light.xml",
+  "res/drawable/mr_vol_type_audiotrack_dark.xml",
+  "res/drawable/mr_vol_type_audiotrack_light.xml",
+  "res/drawable-hdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-hdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-hdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-hdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-hdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-hdpi-v4/ic_media_pause_light.png",
+  "res/drawable-hdpi-v4/ic_media_play_dark.png",
+  "res/drawable-hdpi-v4/ic_media_play_light.png",
+  "res/drawable-hdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-hdpi-v4/ic_media_stop_light.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-hdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-hdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-hdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-mdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-mdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-mdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-mdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-mdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-mdpi-v4/ic_media_pause_light.png",
+  "res/drawable-mdpi-v4/ic_media_play_dark.png",
+  "res/drawable-mdpi-v4/ic_media_play_light.png",
+  "res/drawable-mdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-mdpi-v4/ic_media_stop_light.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-mdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-mdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-mdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-xhdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-xhdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-xhdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-xhdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-xhdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-xhdpi-v4/ic_media_pause_light.png",
+  "res/drawable-xhdpi-v4/ic_media_play_dark.png",
+  "res/drawable-xhdpi-v4/ic_media_play_light.png",
+  "res/drawable-xhdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-xhdpi-v4/ic_media_stop_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_00_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_00_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_01_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_01_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_02_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_02_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_03_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_03_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_04_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_04_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_05_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_05_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_06_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_06_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_07_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_07_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_08_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_08_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_09_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_09_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_10_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_10_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_11_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_11_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_12_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_12_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_13_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_13_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_14_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_14_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_15_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_15_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_16_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_16_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_17_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_17_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_18_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_18_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_19_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_19_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_20_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_20_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_21_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_21_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_22_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_22_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_23_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_23_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_24_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_24_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_25_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_25_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_26_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_26_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_27_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_27_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_28_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_28_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_29_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_29_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_30_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_30_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-xxhdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-xxhdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-xxhdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-xxhdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-xxhdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-xxhdpi-v4/ic_media_pause_light.png",
+  "res/drawable-xxhdpi-v4/ic_media_play_dark.png",
+  "res/drawable-xxhdpi-v4/ic_media_play_light.png",
+  "res/drawable-xxhdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-xxhdpi-v4/ic_media_stop_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_00.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_01.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_02.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_03.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_04.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_05.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_06.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_07.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_08.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_09.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_10.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_11.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_12.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_13.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_14.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_15.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_00.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_01.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_02.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_03.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_04.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_05.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_06.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_07.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_08.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_09.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_10.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_11.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_12.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_13.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_14.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_15.png",
+  "res/drawable-xxxhdpi-v4/ic_mr_button_grey.png",
+  "res/interpolator/mr_fast_out_slow_in.xml",
+  "res/interpolator/mr_linear_out_slow_in.xml",
+  "res/layout/mr_cast_dialog.xml",
+  "res/layout/mr_cast_group_item.xml",
+  "res/layout/mr_cast_group_volume_item.xml",
+  "res/layout/mr_cast_media_metadata.xml",
+  "res/layout/mr_cast_route_item.xml",
+  "res/layout/mr_chooser_dialog.xml",
+  "res/layout/mr_chooser_list_item.xml",
+  "res/layout/mr_controller_material_dialog_b.xml",
+  "res/layout/mr_controller_volume_item.xml",
+  "res/layout/mr_dialog_header_item.xml",
+  "res/layout/mr_picker_dialog.xml",
+  "res/layout/mr_picker_route_item.xml",
+  "res/layout/mr_playback_control.xml",
+  "res/layout/mr_volume_control.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-land/values-land.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-sw600dp-v13/values-sw600dp-v13.xml",
+  "res/values-sw720dp-v13/values-sw720dp-v13.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_multidex_multidex/androidx_multidex_multidex.info b/third_party/android_deps/libs/androidx_multidex_multidex/androidx_multidex_multidex.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_multidex_multidex/androidx_multidex_multidex.info
+++ b/third_party/android_deps/libs/androidx_multidex_multidex/androidx_multidex_multidex.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_palette_palette/androidx_palette_palette.info b/third_party/android_deps/libs/androidx_palette_palette/androidx_palette_palette.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_palette_palette/androidx_palette_palette.info
+++ b/third_party/android_deps/libs/androidx_palette_palette/androidx_palette_palette.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_preference_preference/androidx_preference_preference.info b/third_party/android_deps/libs/androidx_preference_preference/androidx_preference_preference.info
index 8d5529d..1e68e8c 100644
--- a/third_party/android_deps/libs/androidx_preference_preference/androidx_preference_preference.info
+++ b/third_party/android_deps/libs/androidx_preference_preference/androidx_preference_preference.info
@@ -1,13 +1,138 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable/preference_list_divider_material.xml", "res/drawable-anydpi-v21/ic_arrow_down_24dp.xml", "res/drawable-hdpi-v4/ic_arrow_down_24dp.png", "res/drawable-ldpi-v4/ic_arrow_down_24dp.png", "res/drawable-mdpi-v4/ic_arrow_down_24dp.png", "res/drawable-v21/ic_arrow_down_24dp.xml", "res/drawable-v21/preference_list_divider_material.xml", "res/drawable-xhdpi-v4/ic_arrow_down_24dp.png", "res/drawable-xxhdpi-v4/ic_arrow_down_24dp.png", "res/drawable-xxxhdpi-v4/ic_arrow_down_24dp.png", "res/layout/expand_button.xml", "res/layout/preference.xml", "res/layout/preference_category.xml", "res/layout/preference_category_material.xml", "res/layout/preference_dialog_edittext.xml", "res/layout/preference_dropdown.xml", "res/layout/preference_dropdown_material.xml", "res/layout/preference_information.xml", "res/layout/preference_information_material.xml", "res/layout/preference_list_fragment.xml", "res/layout/preference_material.xml", "res/layout/preference_recyclerview.xml", "res/layout/preference_widget_checkbox.xml", "res/layout/preference_widget_seekbar.xml", "res/layout/preference_widget_seekbar_material.xml", "res/layout/preference_widget_switch.xml", "res/layout/preference_widget_switch_compat.xml", "res/layout-v17/preference_category_material.xml", "res/layout-v17/preference_dropdown_material.xml", "res/layout-v17/preference_information_material.xml", "res/layout-v17/preference_material.xml", "res/layout-v17/preference_widget_seekbar_material.xml", "res/layout-v21/preference_category_material.xml", "res/layout-v21/preference_dropdown_material.xml", "res/layout-v21/preference_information_material.xml", "res/layout-v21/preference_material.xml", "res/layout-v21/preference_widget_seekbar_material.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-sw360dp-v13/values-sw360dp-v13.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v17/values-v17.xml", "res/values-v21/values-v21.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable/preference_list_divider_material.xml",
+  "res/drawable-anydpi-v21/ic_arrow_down_24dp.xml",
+  "res/drawable-hdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-ldpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-mdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-v21/ic_arrow_down_24dp.xml",
+  "res/drawable-v21/preference_list_divider_material.xml",
+  "res/drawable-xhdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-xxhdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-xxxhdpi-v4/ic_arrow_down_24dp.png",
+  "res/layout/expand_button.xml",
+  "res/layout/preference.xml",
+  "res/layout/preference_category.xml",
+  "res/layout/preference_category_material.xml",
+  "res/layout/preference_dialog_edittext.xml",
+  "res/layout/preference_dropdown.xml",
+  "res/layout/preference_dropdown_material.xml",
+  "res/layout/preference_information.xml",
+  "res/layout/preference_information_material.xml",
+  "res/layout/preference_list_fragment.xml",
+  "res/layout/preference_material.xml",
+  "res/layout/preference_recyclerview.xml",
+  "res/layout/preference_widget_checkbox.xml",
+  "res/layout/preference_widget_seekbar.xml",
+  "res/layout/preference_widget_seekbar_material.xml",
+  "res/layout/preference_widget_switch.xml",
+  "res/layout/preference_widget_switch_compat.xml",
+  "res/layout-v17/preference_category_material.xml",
+  "res/layout-v17/preference_dropdown_material.xml",
+  "res/layout-v17/preference_information_material.xml",
+  "res/layout-v17/preference_material.xml",
+  "res/layout-v17/preference_widget_seekbar_material.xml",
+  "res/layout-v21/preference_category_material.xml",
+  "res/layout-v21/preference_dropdown_material.xml",
+  "res/layout-v21/preference_information_material.xml",
+  "res/layout-v21/preference_material.xml",
+  "res/layout-v21/preference_widget_seekbar_material.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-sw360dp-v13/values-sw360dp-v13.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v17/values-v17.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_print_print/androidx_print_print.info b/third_party/android_deps/libs/androidx_print_print/androidx_print_print.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_print_print/androidx_print_print.info
+++ b/third_party/android_deps/libs/androidx_print_print/androidx_print_print.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_recyclerview_recyclerview/androidx_recyclerview_recyclerview.info b/third_party/android_deps/libs/androidx_recyclerview_recyclerview/androidx_recyclerview_recyclerview.info
index a25d255..5134f1a 100644
--- a/third_party/android_deps/libs/androidx_recyclerview_recyclerview/androidx_recyclerview_recyclerview.info
+++ b/third_party/android_deps/libs/androidx_recyclerview_recyclerview/androidx_recyclerview_recyclerview.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_savedstate_savedstate/androidx_savedstate_savedstate.info b/third_party/android_deps/libs/androidx_savedstate_savedstate/androidx_savedstate_savedstate.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/androidx_savedstate_savedstate/androidx_savedstate_savedstate.info
+++ b/third_party/android_deps/libs/androidx_savedstate_savedstate/androidx_savedstate_savedstate.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_slidingpanelayout_slidingpanelayout/androidx_slidingpanelayout_slidingpanelayout.info b/third_party/android_deps/libs/androidx_slidingpanelayout_slidingpanelayout/androidx_slidingpanelayout_slidingpanelayout.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_slidingpanelayout_slidingpanelayout/androidx_slidingpanelayout_slidingpanelayout.info
+++ b/third_party/android_deps/libs/androidx_slidingpanelayout_slidingpanelayout/androidx_slidingpanelayout_slidingpanelayout.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_swiperefreshlayout_swiperefreshlayout/androidx_swiperefreshlayout_swiperefreshlayout.info b/third_party/android_deps/libs/androidx_swiperefreshlayout_swiperefreshlayout/androidx_swiperefreshlayout_swiperefreshlayout.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_swiperefreshlayout_swiperefreshlayout/androidx_swiperefreshlayout_swiperefreshlayout.info
+++ b/third_party/android_deps/libs/androidx_swiperefreshlayout_swiperefreshlayout/androidx_swiperefreshlayout_swiperefreshlayout.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_core/androidx_test_core.info b/third_party/android_deps/libs/androidx_test_core/androidx_test_core.info
index 2307336..be3ad57 100644
--- a/third_party/android_deps/libs/androidx_test_core/androidx_test_core.info
+++ b/third_party/android_deps/libs/androidx_test_core/androidx_test_core.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = false
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_espresso_espresso_contrib/androidx_test_espresso_espresso_contrib.info b/third_party/android_deps/libs/androidx_test_espresso_espresso_contrib/androidx_test_espresso_espresso_contrib.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_test_espresso_espresso_contrib/androidx_test_espresso_espresso_contrib.info
+++ b/third_party/android_deps/libs/androidx_test_espresso_espresso_contrib/androidx_test_espresso_espresso_contrib.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_espresso_espresso_core/androidx_test_espresso_espresso_core.info b/third_party/android_deps/libs/androidx_test_espresso_espresso_core/androidx_test_espresso_espresso_core.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/androidx_test_espresso_espresso_core/androidx_test_espresso_espresso_core.info
+++ b/third_party/android_deps/libs/androidx_test_espresso_espresso_core/androidx_test_espresso_espresso_core.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_espresso_espresso_idling_resource/androidx_test_espresso_espresso_idling_resource.info b/third_party/android_deps/libs/androidx_test_espresso_espresso_idling_resource/androidx_test_espresso_espresso_idling_resource.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_test_espresso_espresso_idling_resource/androidx_test_espresso_espresso_idling_resource.info
+++ b/third_party/android_deps/libs/androidx_test_espresso_espresso_idling_resource/androidx_test_espresso_espresso_idling_resource.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_espresso_espresso_intents/androidx_test_espresso_espresso_intents.info b/third_party/android_deps/libs/androidx_test_espresso_espresso_intents/androidx_test_espresso_espresso_intents.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_test_espresso_espresso_intents/androidx_test_espresso_espresso_intents.info
+++ b/third_party/android_deps/libs/androidx_test_espresso_espresso_intents/androidx_test_espresso_espresso_intents.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_espresso_espresso_web/androidx_test_espresso_espresso_web.info b/third_party/android_deps/libs/androidx_test_espresso_espresso_web/androidx_test_espresso_espresso_web.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_test_espresso_espresso_web/androidx_test_espresso_espresso_web.info
+++ b/third_party/android_deps/libs/androidx_test_espresso_espresso_web/androidx_test_espresso_espresso_web.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_ext_junit/androidx_test_ext_junit.info b/third_party/android_deps/libs/androidx_test_ext_junit/androidx_test_ext_junit.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_test_ext_junit/androidx_test_ext_junit.info
+++ b/third_party/android_deps/libs/androidx_test_ext_junit/androidx_test_ext_junit.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_monitor/androidx_test_monitor.info b/third_party/android_deps/libs/androidx_test_monitor/androidx_test_monitor.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/androidx_test_monitor/androidx_test_monitor.info
+++ b/third_party/android_deps/libs/androidx_test_monitor/androidx_test_monitor.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_rules/androidx_test_rules.info b/third_party/android_deps/libs/androidx_test_rules/androidx_test_rules.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/androidx_test_rules/androidx_test_rules.info
+++ b/third_party/android_deps/libs/androidx_test_rules/androidx_test_rules.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_runner/androidx_test_runner.info b/third_party/android_deps/libs/androidx_test_runner/androidx_test_runner.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/androidx_test_runner/androidx_test_runner.info
+++ b/third_party/android_deps/libs/androidx_test_runner/androidx_test_runner.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_test_uiautomator_uiautomator/androidx_test_uiautomator_uiautomator.info b/third_party/android_deps/libs/androidx_test_uiautomator_uiautomator/androidx_test_uiautomator_uiautomator.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/androidx_test_uiautomator_uiautomator/androidx_test_uiautomator_uiautomator.info
+++ b/third_party/android_deps/libs/androidx_test_uiautomator_uiautomator/androidx_test_uiautomator_uiautomator.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_transition_transition/androidx_transition_transition.info b/third_party/android_deps/libs/androidx_transition_transition/androidx_transition_transition.info
index a25d255..5134f1a 100644
--- a/third_party/android_deps/libs/androidx_transition_transition/androidx_transition_transition.info
+++ b/third_party/android_deps/libs/androidx_transition_transition/androidx_transition_transition.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_tvprovider_tvprovider/androidx_tvprovider_tvprovider.info b/third_party/android_deps/libs/androidx_tvprovider_tvprovider/androidx_tvprovider_tvprovider.info
index 861fc798..adae029 100644
--- a/third_party/android_deps/libs/androidx_tvprovider_tvprovider/androidx_tvprovider_tvprovider.info
+++ b/third_party/android_deps/libs/androidx_tvprovider_tvprovider/androidx_tvprovider_tvprovider.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = false
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable/androidx_vectordrawable_vectordrawable.info b/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable/androidx_vectordrawable_vectordrawable.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable/androidx_vectordrawable_vectordrawable.info
+++ b/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable/androidx_vectordrawable_vectordrawable.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable_animated/androidx_vectordrawable_vectordrawable_animated.info b/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable_animated/androidx_vectordrawable_vectordrawable_animated.info
index 7103bc0..8e7b59d 100644
--- a/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable_animated/androidx_vectordrawable_vectordrawable_animated.info
+++ b/third_party/android_deps/libs/androidx_vectordrawable_vectordrawable_animated/androidx_vectordrawable_vectordrawable_animated.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_versionedparcelable_versionedparcelable/androidx_versionedparcelable_versionedparcelable.info b/third_party/android_deps/libs/androidx_versionedparcelable_versionedparcelable/androidx_versionedparcelable_versionedparcelable.info
index 4e6c39c..b29e3757 100644
--- a/third_party/android_deps/libs/androidx_versionedparcelable_versionedparcelable/androidx_versionedparcelable_versionedparcelable.info
+++ b/third_party/android_deps/libs/androidx_versionedparcelable_versionedparcelable/androidx_versionedparcelable_versionedparcelable.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [ "aidl/androidx/versionedparcelable/ParcelImpl.aidl" ]
-assets = [  ]
+aidl = [
+  "aidl/androidx/versionedparcelable/ParcelImpl.aidl"
+]
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_viewpager2_viewpager2/androidx_viewpager2_viewpager2.info b/third_party/android_deps/libs/androidx_viewpager2_viewpager2/androidx_viewpager2_viewpager2.info
index 28c8330..4a744e7 100644
--- a/third_party/android_deps/libs/androidx_viewpager2_viewpager2/androidx_viewpager2_viewpager2.info
+++ b/third_party/android_deps/libs/androidx_viewpager2_viewpager2/androidx_viewpager2_viewpager2.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/androidx_viewpager_viewpager/androidx_viewpager_viewpager.info b/third_party/android_deps/libs/androidx_viewpager_viewpager/androidx_viewpager_viewpager.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/androidx_viewpager_viewpager/androidx_viewpager_viewpager.info
+++ b/third_party/android_deps/libs/androidx_viewpager_viewpager/androidx_viewpager_viewpager.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_animated_vector_drawable/com_android_support_animated_vector_drawable.info b/third_party/android_deps/libs/com_android_support_animated_vector_drawable/com_android_support_animated_vector_drawable.info
index 7103bc0..8e7b59d 100644
--- a/third_party/android_deps/libs/com_android_support_animated_vector_drawable/com_android_support_animated_vector_drawable.info
+++ b/third_party/android_deps/libs/com_android_support_animated_vector_drawable/com_android_support_animated_vector_drawable.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_appcompat_v7/com_android_support_appcompat_v7.info b/third_party/android_deps/libs/com_android_support_appcompat_v7/com_android_support_appcompat_v7.info
index 6f5ede0..24b6bac 100644
--- a/third_party/android_deps/libs/com_android_support_appcompat_v7/com_android_support_appcompat_v7.info
+++ b/third_party/android_deps/libs/com_android_support_appcompat_v7/com_android_support_appcompat_v7.info
@@ -1,13 +1,472 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/anim/abc_fade_in.xml", "res/anim/abc_fade_out.xml", "res/anim/abc_grow_fade_in_from_bottom.xml", "res/anim/abc_popup_enter.xml", "res/anim/abc_popup_exit.xml", "res/anim/abc_shrink_fade_out_from_bottom.xml", "res/anim/abc_slide_in_bottom.xml", "res/anim/abc_slide_in_top.xml", "res/anim/abc_slide_out_bottom.xml", "res/anim/abc_slide_out_top.xml", "res/anim/abc_tooltip_enter.xml", "res/anim/abc_tooltip_exit.xml", "res/color/abc_background_cache_hint_selector_material_dark.xml", "res/color/abc_background_cache_hint_selector_material_light.xml", "res/color/abc_btn_colored_borderless_text_material.xml", "res/color/abc_btn_colored_text_material.xml", "res/color/abc_hint_foreground_material_dark.xml", "res/color/abc_hint_foreground_material_light.xml", "res/color/abc_primary_text_disable_only_material_dark.xml", "res/color/abc_primary_text_disable_only_material_light.xml", "res/color/abc_primary_text_material_dark.xml", "res/color/abc_primary_text_material_light.xml", "res/color/abc_search_url_text.xml", "res/color/abc_secondary_text_material_dark.xml", "res/color/abc_secondary_text_material_light.xml", "res/color/abc_tint_btn_checkable.xml", "res/color/abc_tint_default.xml", "res/color/abc_tint_edittext.xml", "res/color/abc_tint_seek_thumb.xml", "res/color/abc_tint_spinner.xml", "res/color/abc_tint_switch_track.xml", "res/color/switch_thumb_material_dark.xml", "res/color/switch_thumb_material_light.xml", "res/color-v21/abc_btn_colored_borderless_text_material.xml", "res/color-v23/abc_btn_colored_borderless_text_material.xml", "res/color-v23/abc_btn_colored_text_material.xml", "res/color-v23/abc_color_highlight_material.xml", "res/color-v23/abc_tint_btn_checkable.xml", "res/color-v23/abc_tint_default.xml", "res/color-v23/abc_tint_edittext.xml", "res/color-v23/abc_tint_seek_thumb.xml", "res/color-v23/abc_tint_spinner.xml", "res/color-v23/abc_tint_switch_track.xml", "res/drawable/abc_btn_borderless_material.xml", "res/drawable/abc_btn_check_material.xml", "res/drawable/abc_btn_colored_material.xml", "res/drawable/abc_btn_default_mtrl_shape.xml", "res/drawable/abc_btn_radio_material.xml", "res/drawable/abc_cab_background_internal_bg.xml", "res/drawable/abc_cab_background_top_material.xml", "res/drawable/abc_dialog_material_background.xml", "res/drawable/abc_edit_text_material.xml", "res/drawable/abc_ic_ab_back_material.xml", "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml", "res/drawable/abc_ic_clear_material.xml", "res/drawable/abc_ic_go_search_api_material.xml", "res/drawable/abc_ic_menu_overflow_material.xml", "res/drawable/abc_ic_search_api_material.xml", "res/drawable/abc_ic_voice_search_api_material.xml", "res/drawable/abc_item_background_holo_dark.xml", "res/drawable/abc_item_background_holo_light.xml", "res/drawable/abc_list_divider_material.xml", "res/drawable/abc_list_selector_background_transition_holo_dark.xml", "res/drawable/abc_list_selector_background_transition_holo_light.xml", "res/drawable/abc_list_selector_holo_dark.xml", "res/drawable/abc_list_selector_holo_light.xml", "res/drawable/abc_ratingbar_indicator_material.xml", "res/drawable/abc_ratingbar_material.xml", "res/drawable/abc_ratingbar_small_material.xml", "res/drawable/abc_seekbar_thumb_material.xml", "res/drawable/abc_seekbar_tick_mark_material.xml", "res/drawable/abc_seekbar_track_material.xml", "res/drawable/abc_spinner_textfield_background_material.xml", "res/drawable/abc_switch_thumb_material.xml", "res/drawable/abc_tab_indicator_material.xml", "res/drawable/abc_text_cursor_material.xml", "res/drawable/abc_textfield_search_material.xml", "res/drawable/abc_vector_test.xml", "res/drawable/tooltip_frame_dark.xml", "res/drawable/tooltip_frame_light.xml", "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_list_focused_holo.9.png", "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-mdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-mdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-mdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-mdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-mdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-mdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_list_focused_holo.9.png", "res/drawable-mdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-mdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-mdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-mdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-mdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-mdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-mdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-mdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-v21/abc_action_bar_item_background_material.xml", "res/drawable-v21/abc_btn_colored_material.xml", "res/drawable-v21/abc_dialog_material_background.xml", "res/drawable-v21/abc_edit_text_material.xml", "res/drawable-v21/abc_list_divider_material.xml", "res/drawable-v23/abc_control_background_material.xml", "res/drawable-watch-v20/abc_dialog_material_background.xml", "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxhdpi-v4/abc_list_divider_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_list_focused_holo.9.png", "res/drawable-xxhdpi-v4/abc_list_longpressed_holo.9.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_list_pressed_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_dark.9.png", "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_light.9.png", "res/drawable-xxhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_popup_background_mtrl_mult.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/drawable-xxhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_default_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png", "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_16dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_36dp.png", "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_48dp.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_switch_track_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_light.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png", "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_light.png", "res/layout/abc_action_bar_title_item.xml", "res/layout/abc_action_bar_up_container.xml", "res/layout/abc_action_menu_item_layout.xml", "res/layout/abc_action_menu_layout.xml", "res/layout/abc_action_mode_bar.xml", "res/layout/abc_action_mode_close_item_material.xml", "res/layout/abc_activity_chooser_view.xml", "res/layout/abc_activity_chooser_view_list_item.xml", "res/layout/abc_alert_dialog_button_bar_material.xml", "res/layout/abc_alert_dialog_material.xml", "res/layout/abc_alert_dialog_title_material.xml", "res/layout/abc_cascading_menu_item_layout.xml", "res/layout/abc_dialog_title_material.xml", "res/layout/abc_expanded_menu_layout.xml", "res/layout/abc_list_menu_item_checkbox.xml", "res/layout/abc_list_menu_item_icon.xml", "res/layout/abc_list_menu_item_layout.xml", "res/layout/abc_list_menu_item_radio.xml", "res/layout/abc_popup_menu_header_item_layout.xml", "res/layout/abc_popup_menu_item_layout.xml", "res/layout/abc_screen_content_include.xml", "res/layout/abc_screen_simple.xml", "res/layout/abc_screen_simple_overlay_action_mode.xml", "res/layout/abc_screen_toolbar.xml", "res/layout/abc_search_dropdown_item_icons_2line.xml", "res/layout/abc_search_view.xml", "res/layout/abc_select_dialog_material.xml", "res/layout/abc_tooltip.xml", "res/layout/select_dialog_item_material.xml", "res/layout/select_dialog_multichoice_material.xml", "res/layout/select_dialog_singlechoice_material.xml", "res/layout/support_simple_spinner_dropdown_item.xml", "res/layout-v26/abc_screen_toolbar.xml", "res/layout-watch-v20/abc_alert_dialog_button_bar_material.xml", "res/layout-watch-v20/abc_alert_dialog_title_material.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-as/values-as.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-h720dp-v13/values-h720dp-v13.xml", "res/values-hdpi-v4/values-hdpi-v4.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-land/values-land.xml", "res/values-large-v4/values-large-v4.xml", "res/values-ldltr-v21/values-ldltr-v21.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-night-v8/values-night-v8.xml", "res/values-nl/values-nl.xml", "res/values-or/values-or.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-port/values-port.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v16/values-v16.xml", "res/values-v17/values-v17.xml", "res/values-v18/values-v18.xml", "res/values-v21/values-v21.xml", "res/values-v22/values-v22.xml", "res/values-v23/values-v23.xml", "res/values-v24/values-v24.xml", "res/values-v25/values-v25.xml", "res/values-v26/values-v26.xml", "res/values-v28/values-v28.xml", "res/values-vi/values-vi.xml", "res/values-watch-v20/values-watch-v20.xml", "res/values-watch-v21/values-watch-v21.xml", "res/values-xlarge-v4/values-xlarge-v4.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/anim/abc_fade_in.xml",
+  "res/anim/abc_fade_out.xml",
+  "res/anim/abc_grow_fade_in_from_bottom.xml",
+  "res/anim/abc_popup_enter.xml",
+  "res/anim/abc_popup_exit.xml",
+  "res/anim/abc_shrink_fade_out_from_bottom.xml",
+  "res/anim/abc_slide_in_bottom.xml",
+  "res/anim/abc_slide_in_top.xml",
+  "res/anim/abc_slide_out_bottom.xml",
+  "res/anim/abc_slide_out_top.xml",
+  "res/anim/abc_tooltip_enter.xml",
+  "res/anim/abc_tooltip_exit.xml",
+  "res/color/abc_background_cache_hint_selector_material_dark.xml",
+  "res/color/abc_background_cache_hint_selector_material_light.xml",
+  "res/color/abc_btn_colored_borderless_text_material.xml",
+  "res/color/abc_btn_colored_text_material.xml",
+  "res/color/abc_hint_foreground_material_dark.xml",
+  "res/color/abc_hint_foreground_material_light.xml",
+  "res/color/abc_primary_text_disable_only_material_dark.xml",
+  "res/color/abc_primary_text_disable_only_material_light.xml",
+  "res/color/abc_primary_text_material_dark.xml",
+  "res/color/abc_primary_text_material_light.xml",
+  "res/color/abc_search_url_text.xml",
+  "res/color/abc_secondary_text_material_dark.xml",
+  "res/color/abc_secondary_text_material_light.xml",
+  "res/color/abc_tint_btn_checkable.xml",
+  "res/color/abc_tint_default.xml",
+  "res/color/abc_tint_edittext.xml",
+  "res/color/abc_tint_seek_thumb.xml",
+  "res/color/abc_tint_spinner.xml",
+  "res/color/abc_tint_switch_track.xml",
+  "res/color/switch_thumb_material_dark.xml",
+  "res/color/switch_thumb_material_light.xml",
+  "res/color-v21/abc_btn_colored_borderless_text_material.xml",
+  "res/color-v23/abc_btn_colored_borderless_text_material.xml",
+  "res/color-v23/abc_btn_colored_text_material.xml",
+  "res/color-v23/abc_color_highlight_material.xml",
+  "res/color-v23/abc_tint_btn_checkable.xml",
+  "res/color-v23/abc_tint_default.xml",
+  "res/color-v23/abc_tint_edittext.xml",
+  "res/color-v23/abc_tint_seek_thumb.xml",
+  "res/color-v23/abc_tint_spinner.xml",
+  "res/color-v23/abc_tint_switch_track.xml",
+  "res/drawable/abc_btn_borderless_material.xml",
+  "res/drawable/abc_btn_check_material.xml",
+  "res/drawable/abc_btn_colored_material.xml",
+  "res/drawable/abc_btn_default_mtrl_shape.xml",
+  "res/drawable/abc_btn_radio_material.xml",
+  "res/drawable/abc_cab_background_internal_bg.xml",
+  "res/drawable/abc_cab_background_top_material.xml",
+  "res/drawable/abc_dialog_material_background.xml",
+  "res/drawable/abc_edit_text_material.xml",
+  "res/drawable/abc_ic_ab_back_material.xml",
+  "res/drawable/abc_ic_arrow_drop_right_black_24dp.xml",
+  "res/drawable/abc_ic_clear_material.xml",
+  "res/drawable/abc_ic_go_search_api_material.xml",
+  "res/drawable/abc_ic_menu_overflow_material.xml",
+  "res/drawable/abc_ic_search_api_material.xml",
+  "res/drawable/abc_ic_voice_search_api_material.xml",
+  "res/drawable/abc_item_background_holo_dark.xml",
+  "res/drawable/abc_item_background_holo_light.xml",
+  "res/drawable/abc_list_divider_material.xml",
+  "res/drawable/abc_list_selector_background_transition_holo_dark.xml",
+  "res/drawable/abc_list_selector_background_transition_holo_light.xml",
+  "res/drawable/abc_list_selector_holo_dark.xml",
+  "res/drawable/abc_list_selector_holo_light.xml",
+  "res/drawable/abc_ratingbar_indicator_material.xml",
+  "res/drawable/abc_ratingbar_material.xml",
+  "res/drawable/abc_ratingbar_small_material.xml",
+  "res/drawable/abc_seekbar_thumb_material.xml",
+  "res/drawable/abc_seekbar_tick_mark_material.xml",
+  "res/drawable/abc_seekbar_track_material.xml",
+  "res/drawable/abc_spinner_textfield_background_material.xml",
+  "res/drawable/abc_switch_thumb_material.xml",
+  "res/drawable/abc_tab_indicator_material.xml",
+  "res/drawable/abc_text_cursor_material.xml",
+  "res/drawable/abc_textfield_search_material.xml",
+  "res/drawable/abc_vector_test.xml",
+  "res/drawable/tooltip_frame_dark.xml",
+  "res/drawable/tooltip_frame_light.xml",
+  "res/drawable-hdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-hdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-hdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-hdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-hdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-hdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-hdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-hdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-hdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-hdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-hdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-hdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-hdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-hdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-hdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-hdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-hdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-hdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-hdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-hdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-mdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-mdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-xhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-xhdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-xxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-xxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-ldrtl-xxxhdpi-v17/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-ldrtl-xxxhdpi-v17/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-mdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-mdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-mdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-mdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-mdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-mdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-mdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-mdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-mdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-mdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-mdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-mdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-mdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-mdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-mdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-mdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-mdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-v21/abc_action_bar_item_background_material.xml",
+  "res/drawable-v21/abc_btn_colored_material.xml",
+  "res/drawable-v21/abc_dialog_material_background.xml",
+  "res/drawable-v21/abc_edit_text_material.xml",
+  "res/drawable-v21/abc_list_divider_material.xml",
+  "res/drawable-v23/abc_control_background_material.xml",
+  "res/drawable-watch-v20/abc_dialog_material_background.xml",
+  "res/drawable-xhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-xhdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-xhdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-xhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-xhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-xhdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-xhdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-xhdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-xhdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-xhdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-xhdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-xhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-xhdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-xhdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-xhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_ab_share_pack_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-xxhdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-xxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-xxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-xxhdpi-v4/abc_cab_background_top_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_ic_commit_search_api_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-xxhdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-xxhdpi-v4/abc_list_divider_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_focused_holo.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_longpressed_holo.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_pressed_holo_dark.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_pressed_holo_light.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_dark.9.png",
+  "res/drawable-xxhdpi-v4/abc_list_selector_disabled_holo_light.9.png",
+  "res/drawable-xxhdpi-v4/abc_menu_hardkey_panel_mtrl_mult.9.png",
+  "res/drawable-xxhdpi-v4/abc_popup_background_mtrl_mult.9.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_scrubber_track_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_dark.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_middle_mtrl_light.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-xxhdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_activated_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_default_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_search_activated_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/abc_textfield_search_default_mtrl_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_000.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_check_to_on_mtrl_015.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_000.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_radio_to_on_mtrl_015.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00001.9.png",
+  "res/drawable-xxxhdpi-v4/abc_btn_switch_to_on_mtrl_00012.9.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_copy_mtrl_am_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_cut_mtrl_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_paste_mtrl_am_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_selectall_mtrl_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_menu_share_mtrl_alpha.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_black_16dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_black_36dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_black_48dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_16dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_36dp.png",
+  "res/drawable-xxxhdpi-v4/abc_ic_star_half_black_48dp.png",
+  "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xxxhdpi-v4/abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xxxhdpi-v4/abc_spinner_mtrl_am_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_switch_track_mtrl_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_tab_indicator_mtrl_alpha.9.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_dark.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_left_mtrl_light.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_dark.png",
+  "res/drawable-xxxhdpi-v4/abc_text_select_handle_right_mtrl_light.png",
+  "res/layout/abc_action_bar_title_item.xml",
+  "res/layout/abc_action_bar_up_container.xml",
+  "res/layout/abc_action_menu_item_layout.xml",
+  "res/layout/abc_action_menu_layout.xml",
+  "res/layout/abc_action_mode_bar.xml",
+  "res/layout/abc_action_mode_close_item_material.xml",
+  "res/layout/abc_activity_chooser_view.xml",
+  "res/layout/abc_activity_chooser_view_list_item.xml",
+  "res/layout/abc_alert_dialog_button_bar_material.xml",
+  "res/layout/abc_alert_dialog_material.xml",
+  "res/layout/abc_alert_dialog_title_material.xml",
+  "res/layout/abc_cascading_menu_item_layout.xml",
+  "res/layout/abc_dialog_title_material.xml",
+  "res/layout/abc_expanded_menu_layout.xml",
+  "res/layout/abc_list_menu_item_checkbox.xml",
+  "res/layout/abc_list_menu_item_icon.xml",
+  "res/layout/abc_list_menu_item_layout.xml",
+  "res/layout/abc_list_menu_item_radio.xml",
+  "res/layout/abc_popup_menu_header_item_layout.xml",
+  "res/layout/abc_popup_menu_item_layout.xml",
+  "res/layout/abc_screen_content_include.xml",
+  "res/layout/abc_screen_simple.xml",
+  "res/layout/abc_screen_simple_overlay_action_mode.xml",
+  "res/layout/abc_screen_toolbar.xml",
+  "res/layout/abc_search_dropdown_item_icons_2line.xml",
+  "res/layout/abc_search_view.xml",
+  "res/layout/abc_select_dialog_material.xml",
+  "res/layout/abc_tooltip.xml",
+  "res/layout/select_dialog_item_material.xml",
+  "res/layout/select_dialog_multichoice_material.xml",
+  "res/layout/select_dialog_singlechoice_material.xml",
+  "res/layout/support_simple_spinner_dropdown_item.xml",
+  "res/layout-v26/abc_screen_toolbar.xml",
+  "res/layout-watch-v20/abc_alert_dialog_button_bar_material.xml",
+  "res/layout-watch-v20/abc_alert_dialog_title_material.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-as/values-as.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-h720dp-v13/values-h720dp-v13.xml",
+  "res/values-hdpi-v4/values-hdpi-v4.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-land/values-land.xml",
+  "res/values-large-v4/values-large-v4.xml",
+  "res/values-ldltr-v21/values-ldltr-v21.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-night-v8/values-night-v8.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-or/values-or.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-port/values-port.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-sw600dp-v13/values-sw600dp-v13.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v16/values-v16.xml",
+  "res/values-v17/values-v17.xml",
+  "res/values-v18/values-v18.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-v22/values-v22.xml",
+  "res/values-v23/values-v23.xml",
+  "res/values-v24/values-v24.xml",
+  "res/values-v25/values-v25.xml",
+  "res/values-v26/values-v26.xml",
+  "res/values-v28/values-v28.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-watch-v20/values-watch-v20.xml",
+  "res/values-watch-v21/values-watch-v21.xml",
+  "res/values-xlarge-v4/values-xlarge-v4.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_asynclayoutinflater/com_android_support_asynclayoutinflater.info b/third_party/android_deps/libs/com_android_support_asynclayoutinflater/com_android_support_asynclayoutinflater.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_asynclayoutinflater/com_android_support_asynclayoutinflater.info
+++ b/third_party/android_deps/libs/com_android_support_asynclayoutinflater/com_android_support_asynclayoutinflater.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_cardview_v7/com_android_support_cardview_v7.info b/third_party/android_deps/libs/com_android_support_cardview_v7/com_android_support_cardview_v7.info
index 7e63301..3375863 100644
--- a/third_party/android_deps/libs/com_android_support_cardview_v7/com_android_support_cardview_v7.info
+++ b/third_party/android_deps/libs/com_android_support_cardview_v7/com_android_support_cardview_v7.info
@@ -1,13 +1,16 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml", "res/values-v23/values-v23.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml",
+  "res/values-v23/values-v23.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_coordinatorlayout/com_android_support_coordinatorlayout.info b/third_party/android_deps/libs/com_android_support_coordinatorlayout/com_android_support_coordinatorlayout.info
index a25d255..5134f1a 100644
--- a/third_party/android_deps/libs/com_android_support_coordinatorlayout/com_android_support_coordinatorlayout.info
+++ b/third_party/android_deps/libs/com_android_support_coordinatorlayout/com_android_support_coordinatorlayout.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_cursoradapter/com_android_support_cursoradapter.info b/third_party/android_deps/libs/com_android_support_cursoradapter/com_android_support_cursoradapter.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_android_support_cursoradapter/com_android_support_cursoradapter.info
+++ b/third_party/android_deps/libs/com_android_support_cursoradapter/com_android_support_cursoradapter.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_customview/com_android_support_customview.info b/third_party/android_deps/libs/com_android_support_customview/com_android_support_customview.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_customview/com_android_support_customview.info
+++ b/third_party/android_deps/libs/com_android_support_customview/com_android_support_customview.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_design/com_android_support_design.info b/third_party/android_deps/libs/com_android_support_design/com_android_support_design.info
index f4622af..f7922f8 100644
--- a/third_party/android_deps/libs/com_android_support_design/com_android_support_design.info
+++ b/third_party/android_deps/libs/com_android_support_design/com_android_support_design.info
@@ -1,13 +1,107 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/anim/design_bottom_sheet_slide_in.xml", "res/anim/design_bottom_sheet_slide_out.xml", "res/anim/design_snackbar_in.xml", "res/anim/design_snackbar_out.xml", "res/anim-v21/design_bottom_sheet_slide_in.xml", "res/anim-v21/design_bottom_sheet_slide_out.xml", "res/animator/design_fab_hide_motion_spec.xml", "res/animator/design_fab_show_motion_spec.xml", "res/animator/mtrl_btn_state_list_anim.xml", "res/animator/mtrl_btn_unelevated_state_list_anim.xml", "res/animator/mtrl_chip_state_list_anim.xml", "res/animator/mtrl_fab_hide_motion_spec.xml", "res/animator/mtrl_fab_show_motion_spec.xml", "res/animator/mtrl_fab_transformation_sheet_collapse_spec.xml", "res/animator/mtrl_fab_transformation_sheet_expand_spec.xml", "res/animator-v21/design_appbar_state_list_animator.xml", "res/color/design_error.xml", "res/color/design_tint_password_toggle.xml", "res/color/mtrl_bottom_nav_colored_item_tint.xml", "res/color/mtrl_bottom_nav_item_tint.xml", "res/color/mtrl_btn_bg_color_selector.xml", "res/color/mtrl_btn_ripple_color.xml", "res/color/mtrl_btn_stroke_color_selector.xml", "res/color/mtrl_btn_text_btn_ripple_color.xml", "res/color/mtrl_btn_text_color_selector.xml", "res/color/mtrl_chip_background_color.xml", "res/color/mtrl_chip_close_icon_tint.xml", "res/color/mtrl_chip_ripple_color.xml", "res/color/mtrl_chip_text_color.xml", "res/color/mtrl_fab_ripple_color.xml", "res/color/mtrl_tabs_colored_ripple_color.xml", "res/color/mtrl_tabs_icon_color_selector.xml", "res/color/mtrl_tabs_icon_color_selector_colored.xml", "res/color/mtrl_tabs_legacy_text_color_selector.xml", "res/color/mtrl_tabs_ripple_color.xml", "res/color/mtrl_text_btn_text_color_selector.xml", "res/color-v23/design_tint_password_toggle.xml", "res/drawable/design_bottom_navigation_item_background.xml", "res/drawable/design_fab_background.xml", "res/drawable/design_password_eye.xml", "res/drawable/design_snackbar_background.xml", "res/drawable/ic_mtrl_chip_checked_black.xml", "res/drawable/ic_mtrl_chip_checked_circle.xml", "res/drawable/ic_mtrl_chip_close_circle.xml", "res/drawable/mtrl_snackbar_background.xml", "res/drawable/mtrl_tabs_default_indicator.xml", "res/drawable/navigation_empty_icon.xml", "res/drawable-anydpi-v21/design_ic_visibility.xml", "res/drawable-anydpi-v21/design_ic_visibility_off.xml", "res/drawable-hdpi-v4/design_ic_visibility.png", "res/drawable-hdpi-v4/design_ic_visibility_off.png", "res/drawable-mdpi-v4/design_ic_visibility.png", "res/drawable-mdpi-v4/design_ic_visibility_off.png", "res/drawable-v21/avd_hide_password.xml", "res/drawable-v21/avd_show_password.xml", "res/drawable-v21/design_bottom_navigation_item_background.xml", "res/drawable-v21/design_password_eye.xml", "res/drawable-xhdpi-v4/design_ic_visibility.png", "res/drawable-xhdpi-v4/design_ic_visibility_off.png", "res/drawable-xxhdpi-v4/design_ic_visibility.png", "res/drawable-xxhdpi-v4/design_ic_visibility_off.png", "res/drawable-xxxhdpi-v4/design_ic_visibility.png", "res/drawable-xxxhdpi-v4/design_ic_visibility_off.png", "res/interpolator/mtrl_fast_out_linear_in.xml", "res/interpolator/mtrl_fast_out_slow_in.xml", "res/interpolator/mtrl_linear.xml", "res/interpolator/mtrl_linear_out_slow_in.xml", "res/interpolator-v21/mtrl_fast_out_linear_in.xml", "res/interpolator-v21/mtrl_fast_out_slow_in.xml", "res/interpolator-v21/mtrl_linear_out_slow_in.xml", "res/layout/design_bottom_navigation_item.xml", "res/layout/design_bottom_sheet_dialog.xml", "res/layout/design_layout_snackbar.xml", "res/layout/design_layout_snackbar_include.xml", "res/layout/design_layout_tab_icon.xml", "res/layout/design_layout_tab_text.xml", "res/layout/design_menu_item_action_area.xml", "res/layout/design_navigation_item.xml", "res/layout/design_navigation_item_header.xml", "res/layout/design_navigation_item_separator.xml", "res/layout/design_navigation_item_subheader.xml", "res/layout/design_navigation_menu.xml", "res/layout/design_navigation_menu_item.xml", "res/layout/design_text_input_password_icon.xml", "res/layout/mtrl_layout_snackbar.xml", "res/layout/mtrl_layout_snackbar_include.xml", "res/layout-sw600dp-v13/design_layout_snackbar.xml", "res/layout-sw600dp-v13/mtrl_layout_snackbar.xml", "res/values/values.xml", "res/values-land/values-land.xml", "res/values-large-v4/values-large-v4.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-v21/values-v21.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/anim/design_bottom_sheet_slide_in.xml",
+  "res/anim/design_bottom_sheet_slide_out.xml",
+  "res/anim/design_snackbar_in.xml",
+  "res/anim/design_snackbar_out.xml",
+  "res/anim-v21/design_bottom_sheet_slide_in.xml",
+  "res/anim-v21/design_bottom_sheet_slide_out.xml",
+  "res/animator/design_fab_hide_motion_spec.xml",
+  "res/animator/design_fab_show_motion_spec.xml",
+  "res/animator/mtrl_btn_state_list_anim.xml",
+  "res/animator/mtrl_btn_unelevated_state_list_anim.xml",
+  "res/animator/mtrl_chip_state_list_anim.xml",
+  "res/animator/mtrl_fab_hide_motion_spec.xml",
+  "res/animator/mtrl_fab_show_motion_spec.xml",
+  "res/animator/mtrl_fab_transformation_sheet_collapse_spec.xml",
+  "res/animator/mtrl_fab_transformation_sheet_expand_spec.xml",
+  "res/animator-v21/design_appbar_state_list_animator.xml",
+  "res/color/design_error.xml",
+  "res/color/design_tint_password_toggle.xml",
+  "res/color/mtrl_bottom_nav_colored_item_tint.xml",
+  "res/color/mtrl_bottom_nav_item_tint.xml",
+  "res/color/mtrl_btn_bg_color_selector.xml",
+  "res/color/mtrl_btn_ripple_color.xml",
+  "res/color/mtrl_btn_stroke_color_selector.xml",
+  "res/color/mtrl_btn_text_btn_ripple_color.xml",
+  "res/color/mtrl_btn_text_color_selector.xml",
+  "res/color/mtrl_chip_background_color.xml",
+  "res/color/mtrl_chip_close_icon_tint.xml",
+  "res/color/mtrl_chip_ripple_color.xml",
+  "res/color/mtrl_chip_text_color.xml",
+  "res/color/mtrl_fab_ripple_color.xml",
+  "res/color/mtrl_tabs_colored_ripple_color.xml",
+  "res/color/mtrl_tabs_icon_color_selector.xml",
+  "res/color/mtrl_tabs_icon_color_selector_colored.xml",
+  "res/color/mtrl_tabs_legacy_text_color_selector.xml",
+  "res/color/mtrl_tabs_ripple_color.xml",
+  "res/color/mtrl_text_btn_text_color_selector.xml",
+  "res/color-v23/design_tint_password_toggle.xml",
+  "res/drawable/design_bottom_navigation_item_background.xml",
+  "res/drawable/design_fab_background.xml",
+  "res/drawable/design_password_eye.xml",
+  "res/drawable/design_snackbar_background.xml",
+  "res/drawable/ic_mtrl_chip_checked_black.xml",
+  "res/drawable/ic_mtrl_chip_checked_circle.xml",
+  "res/drawable/ic_mtrl_chip_close_circle.xml",
+  "res/drawable/mtrl_snackbar_background.xml",
+  "res/drawable/mtrl_tabs_default_indicator.xml",
+  "res/drawable/navigation_empty_icon.xml",
+  "res/drawable-anydpi-v21/design_ic_visibility.xml",
+  "res/drawable-anydpi-v21/design_ic_visibility_off.xml",
+  "res/drawable-hdpi-v4/design_ic_visibility.png",
+  "res/drawable-hdpi-v4/design_ic_visibility_off.png",
+  "res/drawable-mdpi-v4/design_ic_visibility.png",
+  "res/drawable-mdpi-v4/design_ic_visibility_off.png",
+  "res/drawable-v21/avd_hide_password.xml",
+  "res/drawable-v21/avd_show_password.xml",
+  "res/drawable-v21/design_bottom_navigation_item_background.xml",
+  "res/drawable-v21/design_password_eye.xml",
+  "res/drawable-xhdpi-v4/design_ic_visibility.png",
+  "res/drawable-xhdpi-v4/design_ic_visibility_off.png",
+  "res/drawable-xxhdpi-v4/design_ic_visibility.png",
+  "res/drawable-xxhdpi-v4/design_ic_visibility_off.png",
+  "res/drawable-xxxhdpi-v4/design_ic_visibility.png",
+  "res/drawable-xxxhdpi-v4/design_ic_visibility_off.png",
+  "res/interpolator/mtrl_fast_out_linear_in.xml",
+  "res/interpolator/mtrl_fast_out_slow_in.xml",
+  "res/interpolator/mtrl_linear.xml",
+  "res/interpolator/mtrl_linear_out_slow_in.xml",
+  "res/interpolator-v21/mtrl_fast_out_linear_in.xml",
+  "res/interpolator-v21/mtrl_fast_out_slow_in.xml",
+  "res/interpolator-v21/mtrl_linear_out_slow_in.xml",
+  "res/layout/design_bottom_navigation_item.xml",
+  "res/layout/design_bottom_sheet_dialog.xml",
+  "res/layout/design_layout_snackbar.xml",
+  "res/layout/design_layout_snackbar_include.xml",
+  "res/layout/design_layout_tab_icon.xml",
+  "res/layout/design_layout_tab_text.xml",
+  "res/layout/design_menu_item_action_area.xml",
+  "res/layout/design_navigation_item.xml",
+  "res/layout/design_navigation_item_header.xml",
+  "res/layout/design_navigation_item_separator.xml",
+  "res/layout/design_navigation_item_subheader.xml",
+  "res/layout/design_navigation_menu.xml",
+  "res/layout/design_navigation_menu_item.xml",
+  "res/layout/design_text_input_password_icon.xml",
+  "res/layout/mtrl_layout_snackbar.xml",
+  "res/layout/mtrl_layout_snackbar_include.xml",
+  "res/layout-sw600dp-v13/design_layout_snackbar.xml",
+  "res/layout-sw600dp-v13/mtrl_layout_snackbar.xml",
+  "res/values/values.xml",
+  "res/values-land/values-land.xml",
+  "res/values-large-v4/values-large-v4.xml",
+  "res/values-sw600dp-v13/values-sw600dp-v13.xml",
+  "res/values-v21/values-v21.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_documentfile/com_android_support_documentfile.info b/third_party/android_deps/libs/com_android_support_documentfile/com_android_support_documentfile.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_android_support_documentfile/com_android_support_documentfile.info
+++ b/third_party/android_deps/libs/com_android_support_documentfile/com_android_support_documentfile.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_drawerlayout/com_android_support_drawerlayout.info b/third_party/android_deps/libs/com_android_support_drawerlayout/com_android_support_drawerlayout.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_drawerlayout/com_android_support_drawerlayout.info
+++ b/third_party/android_deps/libs/com_android_support_drawerlayout/com_android_support_drawerlayout.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_gridlayout_v7/com_android_support_gridlayout_v7.info b/third_party/android_deps/libs/com_android_support_gridlayout_v7/com_android_support_gridlayout_v7.info
index 28c8330..4a744e7 100644
--- a/third_party/android_deps/libs/com_android_support_gridlayout_v7/com_android_support_gridlayout_v7.info
+++ b/third_party/android_deps/libs/com_android_support_gridlayout_v7/com_android_support_gridlayout_v7.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_interpolator/com_android_support_interpolator.info b/third_party/android_deps/libs/com_android_support_interpolator/com_android_support_interpolator.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_android_support_interpolator/com_android_support_interpolator.info
+++ b/third_party/android_deps/libs/com_android_support_interpolator/com_android_support_interpolator.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_leanback_v17/com_android_support_leanback_v17.info b/third_party/android_deps/libs/com_android_support_leanback_v17/com_android_support_leanback_v17.info
index d7f5494..190c417d 100644
--- a/third_party/android_deps/libs/com_android_support_leanback_v17/com_android_support_leanback_v17.info
+++ b/third_party/android_deps/libs/com_android_support_leanback_v17/com_android_support_leanback_v17.info
@@ -1,13 +1,300 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/anim/lb_decelerator_2.xml", "res/anim/lb_decelerator_4.xml", "res/animator/lb_guidedactions_item_pressed.xml", "res/animator/lb_guidedactions_item_unpressed.xml", "res/animator/lb_guidedstep_slide_down.xml", "res/animator/lb_guidedstep_slide_up.xml", "res/animator/lb_onboarding_description_enter.xml", "res/animator/lb_onboarding_logo_enter.xml", "res/animator/lb_onboarding_logo_exit.xml", "res/animator/lb_onboarding_page_indicator_enter.xml", "res/animator/lb_onboarding_page_indicator_fade_in.xml", "res/animator/lb_onboarding_page_indicator_fade_out.xml", "res/animator/lb_onboarding_start_button_fade_in.xml", "res/animator/lb_onboarding_start_button_fade_out.xml", "res/animator/lb_onboarding_title_enter.xml", "res/animator/lb_playback_bg_fade_in.xml", "res/animator/lb_playback_bg_fade_out.xml", "res/animator/lb_playback_controls_fade_in.xml", "res/animator/lb_playback_controls_fade_out.xml", "res/animator/lb_playback_description_fade_in.xml", "res/animator/lb_playback_description_fade_out.xml", "res/animator/lb_playback_rows_fade_in.xml", "res/animator/lb_playback_rows_fade_out.xml", "res/animator-v21/lb_onboarding_description_enter.xml", "res/animator-v21/lb_onboarding_logo_enter.xml", "res/animator-v21/lb_onboarding_logo_exit.xml", "res/animator-v21/lb_onboarding_page_indicator_enter.xml", "res/animator-v21/lb_onboarding_title_enter.xml", "res/animator-v21/lb_playback_bg_fade_in.xml", "res/animator-v21/lb_playback_bg_fade_out.xml", "res/animator-v21/lb_playback_description_fade_out.xml", "res/drawable/lb_background.xml", "res/drawable/lb_card_foreground.xml", "res/drawable/lb_control_button_primary.xml", "res/drawable/lb_control_button_secondary.xml", "res/drawable/lb_headers_right_fading.xml", "res/drawable/lb_onboarding_start_button_background.xml", "res/drawable/lb_playback_now_playing_bar.xml", "res/drawable/lb_playback_progress_bar.xml", "res/drawable/lb_search_orb.xml", "res/drawable/lb_speech_orb.xml", "res/drawable-hdpi-v4/lb_action_bg_focused.9.png", "res/drawable-hdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-hdpi-v4/lb_ic_in_app_search.png", "res/drawable-hdpi-v4/lb_ic_sad_cloud.png", "res/drawable-hdpi-v4/lb_ic_search_mic.png", "res/drawable-hdpi-v4/lb_ic_search_mic_out.png", "res/drawable-hdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-hdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-mdpi-v4/lb_action_bg_focused.9.png", "res/drawable-mdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-mdpi-v4/lb_ic_in_app_search.png", "res/drawable-mdpi-v4/lb_ic_sad_cloud.png", "res/drawable-mdpi-v4/lb_ic_search_mic.png", "res/drawable-mdpi-v4/lb_ic_search_mic_out.png", "res/drawable-mdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-mdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-v21/lb_action_bg.xml", "res/drawable-v21/lb_card_foreground.xml", "res/drawable-v21/lb_control_button_primary.xml", "res/drawable-v21/lb_control_button_secondary.xml", "res/drawable-v21/lb_selectable_item_rounded_rect.xml", "res/drawable-xhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xhdpi-v4/lb_card_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_card_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xhdpi-v4/lb_ic_cc.png", "res/drawable-xhdpi-v4/lb_ic_fast_forward.png", "res/drawable-xhdpi-v4/lb_ic_fast_rewind.png", "res/drawable-xhdpi-v4/lb_ic_guidedactions_item_chevron.png", "res/drawable-xhdpi-v4/lb_ic_hq.png", "res/drawable-xhdpi-v4/lb_ic_in_app_search.png", "res/drawable-xhdpi-v4/lb_ic_loop.png", "res/drawable-xhdpi-v4/lb_ic_loop_one.png", "res/drawable-xhdpi-v4/lb_ic_more.png", "res/drawable-xhdpi-v4/lb_ic_nav_arrow.png", "res/drawable-xhdpi-v4/lb_ic_pause.png", "res/drawable-xhdpi-v4/lb_ic_pip.png", "res/drawable-xhdpi-v4/lb_ic_play.png", "res/drawable-xhdpi-v4/lb_ic_play_fit.png", "res/drawable-xhdpi-v4/lb_ic_playback_loop.png", "res/drawable-xhdpi-v4/lb_ic_replay.png", "res/drawable-xhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xhdpi-v4/lb_ic_search_mic.png", "res/drawable-xhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xhdpi-v4/lb_ic_shuffle.png", "res/drawable-xhdpi-v4/lb_ic_skip_next.png", "res/drawable-xhdpi-v4/lb_ic_skip_previous.png", "res/drawable-xhdpi-v4/lb_ic_stop.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down.png", "res/drawable-xhdpi-v4/lb_ic_thumb_down_outline.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up.png", "res/drawable-xhdpi-v4/lb_ic_thumb_up_outline.png", "res/drawable-xhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/drawable-xhdpi-v4/lb_text_dot_one.png", "res/drawable-xhdpi-v4/lb_text_dot_one_small.png", "res/drawable-xhdpi-v4/lb_text_dot_two.png", "res/drawable-xhdpi-v4/lb_text_dot_two_small.png", "res/drawable-xxhdpi-v4/lb_action_bg_focused.9.png", "res/drawable-xxhdpi-v4/lb_ic_actions_right_arrow.png", "res/drawable-xxhdpi-v4/lb_ic_in_app_search.png", "res/drawable-xxhdpi-v4/lb_ic_sad_cloud.png", "res/drawable-xxhdpi-v4/lb_ic_search_mic.png", "res/drawable-xxhdpi-v4/lb_ic_search_mic_out.png", "res/drawable-xxhdpi-v4/lb_in_app_search_bg.9.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_focused.9.png", "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_normal.9.png", "res/layout/lb_action_1_line.xml", "res/layout/lb_action_2_lines.xml", "res/layout/lb_background_window.xml", "res/layout/lb_browse_fragment.xml", "res/layout/lb_browse_title.xml", "res/layout/lb_control_bar.xml", "res/layout/lb_control_button_primary.xml", "res/layout/lb_control_button_secondary.xml", "res/layout/lb_details_description.xml", "res/layout/lb_details_fragment.xml", "res/layout/lb_details_overview.xml", "res/layout/lb_divider.xml", "res/layout/lb_error_fragment.xml", "res/layout/lb_fullwidth_details_overview.xml", "res/layout/lb_fullwidth_details_overview_logo.xml", "res/layout/lb_guidance.xml", "res/layout/lb_guidedactions.xml", "res/layout/lb_guidedactions_datepicker_item.xml", "res/layout/lb_guidedactions_item.xml", "res/layout/lb_guidedbuttonactions.xml", "res/layout/lb_guidedstep_background.xml", "res/layout/lb_guidedstep_fragment.xml", "res/layout/lb_header.xml", "res/layout/lb_headers_fragment.xml", "res/layout/lb_image_card_view.xml", "res/layout/lb_image_card_view_themed_badge_left.xml", "res/layout/lb_image_card_view_themed_badge_right.xml", "res/layout/lb_image_card_view_themed_content.xml", "res/layout/lb_image_card_view_themed_title.xml", "res/layout/lb_list_row.xml", "res/layout/lb_list_row_hovercard.xml", "res/layout/lb_media_item_number_view_flipper.xml", "res/layout/lb_media_list_header.xml", "res/layout/lb_onboarding_fragment.xml", "res/layout/lb_picker.xml", "res/layout/lb_picker_column.xml", "res/layout/lb_picker_item.xml", "res/layout/lb_picker_separator.xml", "res/layout/lb_playback_controls.xml", "res/layout/lb_playback_controls_row.xml", "res/layout/lb_playback_fragment.xml", "res/layout/lb_playback_now_playing_bars.xml", "res/layout/lb_playback_transport_controls.xml", "res/layout/lb_playback_transport_controls_row.xml", "res/layout/lb_row_container.xml", "res/layout/lb_row_header.xml", "res/layout/lb_row_media_item.xml", "res/layout/lb_row_media_item_action.xml", "res/layout/lb_rows_fragment.xml", "res/layout/lb_search_bar.xml", "res/layout/lb_search_fragment.xml", "res/layout/lb_search_orb.xml", "res/layout/lb_section_header.xml", "res/layout/lb_shadow.xml", "res/layout/lb_speech_orb.xml", "res/layout/lb_title_view.xml", "res/layout/lb_vertical_grid.xml", "res/layout/lb_vertical_grid_fragment.xml", "res/layout/lb_video_surface.xml", "res/layout/video_surface_fragment.xml", "res/raw/lb_voice_failure.ogg", "res/raw/lb_voice_no_input.ogg", "res/raw/lb_voice_open.ogg", "res/raw/lb_voice_success.ogg", "res/transition-v19/lb_browse_headers_in.xml", "res/transition-v19/lb_browse_headers_out.xml", "res/transition-v21/lb_browse_enter_transition.xml", "res/transition-v21/lb_browse_entrance_transition.xml", "res/transition-v21/lb_browse_headers_in.xml", "res/transition-v21/lb_browse_headers_out.xml", "res/transition-v21/lb_browse_return_transition.xml", "res/transition-v21/lb_details_enter_transition.xml", "res/transition-v21/lb_details_return_transition.xml", "res/transition-v21/lb_enter_transition.xml", "res/transition-v21/lb_guidedstep_activity_enter.xml", "res/transition-v21/lb_guidedstep_activity_enter_bottom.xml", "res/transition-v21/lb_return_transition.xml", "res/transition-v21/lb_shared_element_enter_transition.xml", "res/transition-v21/lb_shared_element_return_transition.xml", "res/transition-v21/lb_title_in.xml", "res/transition-v21/lb_title_out.xml", "res/transition-v21/lb_vertical_grid_enter_transition.xml", "res/transition-v21/lb_vertical_grid_entrance_transition.xml", "res/transition-v21/lb_vertical_grid_return_transition.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-as/values-as.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-ldrtl-v17/values-ldrtl-v17.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-or/values-or.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v18/values-v18.xml", "res/values-v19/values-v19.xml", "res/values-v21/values-v21.xml", "res/values-v22/values-v22.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/anim/lb_decelerator_2.xml",
+  "res/anim/lb_decelerator_4.xml",
+  "res/animator/lb_guidedactions_item_pressed.xml",
+  "res/animator/lb_guidedactions_item_unpressed.xml",
+  "res/animator/lb_guidedstep_slide_down.xml",
+  "res/animator/lb_guidedstep_slide_up.xml",
+  "res/animator/lb_onboarding_description_enter.xml",
+  "res/animator/lb_onboarding_logo_enter.xml",
+  "res/animator/lb_onboarding_logo_exit.xml",
+  "res/animator/lb_onboarding_page_indicator_enter.xml",
+  "res/animator/lb_onboarding_page_indicator_fade_in.xml",
+  "res/animator/lb_onboarding_page_indicator_fade_out.xml",
+  "res/animator/lb_onboarding_start_button_fade_in.xml",
+  "res/animator/lb_onboarding_start_button_fade_out.xml",
+  "res/animator/lb_onboarding_title_enter.xml",
+  "res/animator/lb_playback_bg_fade_in.xml",
+  "res/animator/lb_playback_bg_fade_out.xml",
+  "res/animator/lb_playback_controls_fade_in.xml",
+  "res/animator/lb_playback_controls_fade_out.xml",
+  "res/animator/lb_playback_description_fade_in.xml",
+  "res/animator/lb_playback_description_fade_out.xml",
+  "res/animator/lb_playback_rows_fade_in.xml",
+  "res/animator/lb_playback_rows_fade_out.xml",
+  "res/animator-v21/lb_onboarding_description_enter.xml",
+  "res/animator-v21/lb_onboarding_logo_enter.xml",
+  "res/animator-v21/lb_onboarding_logo_exit.xml",
+  "res/animator-v21/lb_onboarding_page_indicator_enter.xml",
+  "res/animator-v21/lb_onboarding_title_enter.xml",
+  "res/animator-v21/lb_playback_bg_fade_in.xml",
+  "res/animator-v21/lb_playback_bg_fade_out.xml",
+  "res/animator-v21/lb_playback_description_fade_out.xml",
+  "res/drawable/lb_background.xml",
+  "res/drawable/lb_card_foreground.xml",
+  "res/drawable/lb_control_button_primary.xml",
+  "res/drawable/lb_control_button_secondary.xml",
+  "res/drawable/lb_headers_right_fading.xml",
+  "res/drawable/lb_onboarding_start_button_background.xml",
+  "res/drawable/lb_playback_now_playing_bar.xml",
+  "res/drawable/lb_playback_progress_bar.xml",
+  "res/drawable/lb_search_orb.xml",
+  "res/drawable/lb_speech_orb.xml",
+  "res/drawable-hdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-hdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-hdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-hdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-hdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-hdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-hdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-hdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-hdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/drawable-mdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-mdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-mdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-mdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-mdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-mdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-mdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-mdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-mdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/drawable-v21/lb_action_bg.xml",
+  "res/drawable-v21/lb_card_foreground.xml",
+  "res/drawable-v21/lb_control_button_primary.xml",
+  "res/drawable-v21/lb_control_button_secondary.xml",
+  "res/drawable-v21/lb_selectable_item_rounded_rect.xml",
+  "res/drawable-xhdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-xhdpi-v4/lb_card_shadow_focused.9.png",
+  "res/drawable-xhdpi-v4/lb_card_shadow_normal.9.png",
+  "res/drawable-xhdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-xhdpi-v4/lb_ic_cc.png",
+  "res/drawable-xhdpi-v4/lb_ic_fast_forward.png",
+  "res/drawable-xhdpi-v4/lb_ic_fast_rewind.png",
+  "res/drawable-xhdpi-v4/lb_ic_guidedactions_item_chevron.png",
+  "res/drawable-xhdpi-v4/lb_ic_hq.png",
+  "res/drawable-xhdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-xhdpi-v4/lb_ic_loop.png",
+  "res/drawable-xhdpi-v4/lb_ic_loop_one.png",
+  "res/drawable-xhdpi-v4/lb_ic_more.png",
+  "res/drawable-xhdpi-v4/lb_ic_nav_arrow.png",
+  "res/drawable-xhdpi-v4/lb_ic_pause.png",
+  "res/drawable-xhdpi-v4/lb_ic_pip.png",
+  "res/drawable-xhdpi-v4/lb_ic_play.png",
+  "res/drawable-xhdpi-v4/lb_ic_play_fit.png",
+  "res/drawable-xhdpi-v4/lb_ic_playback_loop.png",
+  "res/drawable-xhdpi-v4/lb_ic_replay.png",
+  "res/drawable-xhdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-xhdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-xhdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-xhdpi-v4/lb_ic_shuffle.png",
+  "res/drawable-xhdpi-v4/lb_ic_skip_next.png",
+  "res/drawable-xhdpi-v4/lb_ic_skip_previous.png",
+  "res/drawable-xhdpi-v4/lb_ic_stop.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_down.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_down_outline.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_up.png",
+  "res/drawable-xhdpi-v4/lb_ic_thumb_up_outline.png",
+  "res/drawable-xhdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-xhdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-xhdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_one.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_one_small.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_two.png",
+  "res/drawable-xhdpi-v4/lb_text_dot_two_small.png",
+  "res/drawable-xxhdpi-v4/lb_action_bg_focused.9.png",
+  "res/drawable-xxhdpi-v4/lb_ic_actions_right_arrow.png",
+  "res/drawable-xxhdpi-v4/lb_ic_in_app_search.png",
+  "res/drawable-xxhdpi-v4/lb_ic_sad_cloud.png",
+  "res/drawable-xxhdpi-v4/lb_ic_search_mic.png",
+  "res/drawable-xxhdpi-v4/lb_ic_search_mic_out.png",
+  "res/drawable-xxhdpi-v4/lb_in_app_search_bg.9.png",
+  "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_focused.9.png",
+  "res/drawable-xxhdpi-v4/lb_in_app_search_shadow_normal.9.png",
+  "res/layout/lb_action_1_line.xml",
+  "res/layout/lb_action_2_lines.xml",
+  "res/layout/lb_background_window.xml",
+  "res/layout/lb_browse_fragment.xml",
+  "res/layout/lb_browse_title.xml",
+  "res/layout/lb_control_bar.xml",
+  "res/layout/lb_control_button_primary.xml",
+  "res/layout/lb_control_button_secondary.xml",
+  "res/layout/lb_details_description.xml",
+  "res/layout/lb_details_fragment.xml",
+  "res/layout/lb_details_overview.xml",
+  "res/layout/lb_divider.xml",
+  "res/layout/lb_error_fragment.xml",
+  "res/layout/lb_fullwidth_details_overview.xml",
+  "res/layout/lb_fullwidth_details_overview_logo.xml",
+  "res/layout/lb_guidance.xml",
+  "res/layout/lb_guidedactions.xml",
+  "res/layout/lb_guidedactions_datepicker_item.xml",
+  "res/layout/lb_guidedactions_item.xml",
+  "res/layout/lb_guidedbuttonactions.xml",
+  "res/layout/lb_guidedstep_background.xml",
+  "res/layout/lb_guidedstep_fragment.xml",
+  "res/layout/lb_header.xml",
+  "res/layout/lb_headers_fragment.xml",
+  "res/layout/lb_image_card_view.xml",
+  "res/layout/lb_image_card_view_themed_badge_left.xml",
+  "res/layout/lb_image_card_view_themed_badge_right.xml",
+  "res/layout/lb_image_card_view_themed_content.xml",
+  "res/layout/lb_image_card_view_themed_title.xml",
+  "res/layout/lb_list_row.xml",
+  "res/layout/lb_list_row_hovercard.xml",
+  "res/layout/lb_media_item_number_view_flipper.xml",
+  "res/layout/lb_media_list_header.xml",
+  "res/layout/lb_onboarding_fragment.xml",
+  "res/layout/lb_picker.xml",
+  "res/layout/lb_picker_column.xml",
+  "res/layout/lb_picker_item.xml",
+  "res/layout/lb_picker_separator.xml",
+  "res/layout/lb_playback_controls.xml",
+  "res/layout/lb_playback_controls_row.xml",
+  "res/layout/lb_playback_fragment.xml",
+  "res/layout/lb_playback_now_playing_bars.xml",
+  "res/layout/lb_playback_transport_controls.xml",
+  "res/layout/lb_playback_transport_controls_row.xml",
+  "res/layout/lb_row_container.xml",
+  "res/layout/lb_row_header.xml",
+  "res/layout/lb_row_media_item.xml",
+  "res/layout/lb_row_media_item_action.xml",
+  "res/layout/lb_rows_fragment.xml",
+  "res/layout/lb_search_bar.xml",
+  "res/layout/lb_search_fragment.xml",
+  "res/layout/lb_search_orb.xml",
+  "res/layout/lb_section_header.xml",
+  "res/layout/lb_shadow.xml",
+  "res/layout/lb_speech_orb.xml",
+  "res/layout/lb_title_view.xml",
+  "res/layout/lb_vertical_grid.xml",
+  "res/layout/lb_vertical_grid_fragment.xml",
+  "res/layout/lb_video_surface.xml",
+  "res/layout/video_surface_fragment.xml",
+  "res/raw/lb_voice_failure.ogg",
+  "res/raw/lb_voice_no_input.ogg",
+  "res/raw/lb_voice_open.ogg",
+  "res/raw/lb_voice_success.ogg",
+  "res/transition-v19/lb_browse_headers_in.xml",
+  "res/transition-v19/lb_browse_headers_out.xml",
+  "res/transition-v21/lb_browse_enter_transition.xml",
+  "res/transition-v21/lb_browse_entrance_transition.xml",
+  "res/transition-v21/lb_browse_headers_in.xml",
+  "res/transition-v21/lb_browse_headers_out.xml",
+  "res/transition-v21/lb_browse_return_transition.xml",
+  "res/transition-v21/lb_details_enter_transition.xml",
+  "res/transition-v21/lb_details_return_transition.xml",
+  "res/transition-v21/lb_enter_transition.xml",
+  "res/transition-v21/lb_guidedstep_activity_enter.xml",
+  "res/transition-v21/lb_guidedstep_activity_enter_bottom.xml",
+  "res/transition-v21/lb_return_transition.xml",
+  "res/transition-v21/lb_shared_element_enter_transition.xml",
+  "res/transition-v21/lb_shared_element_return_transition.xml",
+  "res/transition-v21/lb_title_in.xml",
+  "res/transition-v21/lb_title_out.xml",
+  "res/transition-v21/lb_vertical_grid_enter_transition.xml",
+  "res/transition-v21/lb_vertical_grid_entrance_transition.xml",
+  "res/transition-v21/lb_vertical_grid_return_transition.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-as/values-as.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-ldrtl-v17/values-ldrtl-v17.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-or/values-or.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v18/values-v18.xml",
+  "res/values-v19/values-v19.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-v22/values-v22.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_loader/com_android_support_loader.info b/third_party/android_deps/libs/com_android_support_loader/com_android_support_loader.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_loader/com_android_support_loader.info
+++ b/third_party/android_deps/libs/com_android_support_loader/com_android_support_loader.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_localbroadcastmanager/com_android_support_localbroadcastmanager.info b/third_party/android_deps/libs/com_android_support_localbroadcastmanager/com_android_support_localbroadcastmanager.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_android_support_localbroadcastmanager/com_android_support_localbroadcastmanager.info
+++ b/third_party/android_deps/libs/com_android_support_localbroadcastmanager/com_android_support_localbroadcastmanager.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_mediarouter_v7/com_android_support_mediarouter_v7.info b/third_party/android_deps/libs/com_android_support_mediarouter_v7/com_android_support_mediarouter_v7.info
index e0bb0fd..9532abc 100644
--- a/third_party/android_deps/libs/com_android_support_mediarouter_v7/com_android_support_mediarouter_v7.info
+++ b/third_party/android_deps/libs/com_android_support_mediarouter_v7/com_android_support_mediarouter_v7.info
@@ -1,13 +1,502 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable/mr_button_connected_dark.xml", "res/drawable/mr_button_connected_light.xml", "res/drawable/mr_button_connecting_dark.xml", "res/drawable/mr_button_connecting_light.xml", "res/drawable/mr_button_dark.xml", "res/drawable/mr_button_light.xml", "res/drawable/mr_dialog_close_dark.xml", "res/drawable/mr_dialog_close_light.xml", "res/drawable/mr_dialog_material_background_dark.xml", "res/drawable/mr_dialog_material_background_light.xml", "res/drawable/mr_group_collapse.xml", "res/drawable/mr_group_expand.xml", "res/drawable/mr_media_pause_dark.xml", "res/drawable/mr_media_pause_light.xml", "res/drawable/mr_media_play_dark.xml", "res/drawable/mr_media_play_light.xml", "res/drawable/mr_media_stop_dark.xml", "res/drawable/mr_media_stop_light.xml", "res/drawable/mr_vol_type_audiotrack_dark.xml", "res/drawable/mr_vol_type_audiotrack_light.xml", "res/drawable-hdpi-v4/ic_audiotrack_dark.png", "res/drawable-hdpi-v4/ic_audiotrack_light.png", "res/drawable-hdpi-v4/ic_dialog_close_dark.png", "res/drawable-hdpi-v4/ic_dialog_close_light.png", "res/drawable-hdpi-v4/ic_media_pause_dark.png", "res/drawable-hdpi-v4/ic_media_pause_light.png", "res/drawable-hdpi-v4/ic_media_play_dark.png", "res/drawable-hdpi-v4/ic_media_play_light.png", "res/drawable-hdpi-v4/ic_media_stop_dark.png", "res/drawable-hdpi-v4/ic_media_stop_light.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-hdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-hdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-hdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-hdpi-v4/ic_mr_button_grey.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-hdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-hdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-hdpi-v4/ic_vol_type_tv_light.png", "res/drawable-mdpi-v4/ic_audiotrack_dark.png", "res/drawable-mdpi-v4/ic_audiotrack_light.png", "res/drawable-mdpi-v4/ic_dialog_close_dark.png", "res/drawable-mdpi-v4/ic_dialog_close_light.png", "res/drawable-mdpi-v4/ic_media_pause_dark.png", "res/drawable-mdpi-v4/ic_media_pause_light.png", "res/drawable-mdpi-v4/ic_media_play_dark.png", "res/drawable-mdpi-v4/ic_media_play_light.png", "res/drawable-mdpi-v4/ic_media_stop_dark.png", "res/drawable-mdpi-v4/ic_media_stop_light.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-mdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-mdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-mdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-mdpi-v4/ic_mr_button_grey.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-mdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-mdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-mdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xhdpi-v4/ic_audiotrack_light.png", "res/drawable-xhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xhdpi-v4/ic_dialog_close_light.png", "res/drawable-xhdpi-v4/ic_media_pause_dark.png", "res/drawable-xhdpi-v4/ic_media_pause_light.png", "res/drawable-xhdpi-v4/ic_media_play_dark.png", "res/drawable-xhdpi-v4/ic_media_play_light.png", "res/drawable-xhdpi-v4/ic_media_stop_dark.png", "res/drawable-xhdpi-v4/ic_media_stop_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_03_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_23_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_23_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_24_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_24_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_25_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_25_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_26_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_26_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_27_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_27_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_28_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_28_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_29_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_29_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_30_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connected_30_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_light.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xhdpi-v4/ic_mr_button_grey.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xxhdpi-v4/ic_audiotrack_dark.png", "res/drawable-xxhdpi-v4/ic_audiotrack_light.png", "res/drawable-xxhdpi-v4/ic_dialog_close_dark.png", "res/drawable-xxhdpi-v4/ic_dialog_close_light.png", "res/drawable-xxhdpi-v4/ic_media_pause_dark.png", "res/drawable-xxhdpi-v4/ic_media_pause_light.png", "res/drawable-xxhdpi-v4/ic_media_play_dark.png", "res/drawable-xxhdpi-v4/ic_media_play_light.png", "res/drawable-xxhdpi-v4/ic_media_stop_dark.png", "res/drawable-xxhdpi-v4/ic_media_stop_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_disabled_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_dark.png", "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_light.png", "res/drawable-xxhdpi-v4/ic_mr_button_grey.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_speaker_light.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_dark.png", "res/drawable-xxhdpi-v4/ic_vol_type_tv_light.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_00.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_01.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_02.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_03.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_04.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_05.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_06.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_07.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_08.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_09.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_10.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_11.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_12.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_13.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_14.png", "res/drawable-xxxhdpi-v4/ic_group_collapse_15.png", "res/drawable-xxxhdpi-v4/ic_group_expand_00.png", "res/drawable-xxxhdpi-v4/ic_group_expand_01.png", "res/drawable-xxxhdpi-v4/ic_group_expand_02.png", "res/drawable-xxxhdpi-v4/ic_group_expand_03.png", "res/drawable-xxxhdpi-v4/ic_group_expand_04.png", "res/drawable-xxxhdpi-v4/ic_group_expand_05.png", "res/drawable-xxxhdpi-v4/ic_group_expand_06.png", "res/drawable-xxxhdpi-v4/ic_group_expand_07.png", "res/drawable-xxxhdpi-v4/ic_group_expand_08.png", "res/drawable-xxxhdpi-v4/ic_group_expand_09.png", "res/drawable-xxxhdpi-v4/ic_group_expand_10.png", "res/drawable-xxxhdpi-v4/ic_group_expand_11.png", "res/drawable-xxxhdpi-v4/ic_group_expand_12.png", "res/drawable-xxxhdpi-v4/ic_group_expand_13.png", "res/drawable-xxxhdpi-v4/ic_group_expand_14.png", "res/drawable-xxxhdpi-v4/ic_group_expand_15.png", "res/drawable-xxxhdpi-v4/ic_mr_button_grey.png", "res/interpolator/mr_fast_out_slow_in.xml", "res/interpolator/mr_linear_out_slow_in.xml", "res/layout/mr_cast_dialog.xml", "res/layout/mr_cast_group_item.xml", "res/layout/mr_cast_group_volume_item.xml", "res/layout/mr_cast_media_metadata.xml", "res/layout/mr_cast_route_item.xml", "res/layout/mr_chooser_dialog.xml", "res/layout/mr_chooser_list_item.xml", "res/layout/mr_controller_material_dialog_b.xml", "res/layout/mr_controller_volume_item.xml", "res/layout/mr_dialog_header_item.xml", "res/layout/mr_picker_dialog.xml", "res/layout/mr_picker_route_item.xml", "res/layout/mr_playback_control.xml", "res/layout/mr_volume_control.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-land/values-land.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-sw720dp-v13/values-sw720dp-v13.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable/mr_button_connected_dark.xml",
+  "res/drawable/mr_button_connected_light.xml",
+  "res/drawable/mr_button_connecting_dark.xml",
+  "res/drawable/mr_button_connecting_light.xml",
+  "res/drawable/mr_button_dark.xml",
+  "res/drawable/mr_button_light.xml",
+  "res/drawable/mr_dialog_close_dark.xml",
+  "res/drawable/mr_dialog_close_light.xml",
+  "res/drawable/mr_dialog_material_background_dark.xml",
+  "res/drawable/mr_dialog_material_background_light.xml",
+  "res/drawable/mr_group_collapse.xml",
+  "res/drawable/mr_group_expand.xml",
+  "res/drawable/mr_media_pause_dark.xml",
+  "res/drawable/mr_media_pause_light.xml",
+  "res/drawable/mr_media_play_dark.xml",
+  "res/drawable/mr_media_play_light.xml",
+  "res/drawable/mr_media_stop_dark.xml",
+  "res/drawable/mr_media_stop_light.xml",
+  "res/drawable/mr_vol_type_audiotrack_dark.xml",
+  "res/drawable/mr_vol_type_audiotrack_light.xml",
+  "res/drawable-hdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-hdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-hdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-hdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-hdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-hdpi-v4/ic_media_pause_light.png",
+  "res/drawable-hdpi-v4/ic_media_play_dark.png",
+  "res/drawable-hdpi-v4/ic_media_play_light.png",
+  "res/drawable-hdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-hdpi-v4/ic_media_stop_light.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-hdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-hdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-hdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-hdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-hdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-mdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-mdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-mdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-mdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-mdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-mdpi-v4/ic_media_pause_light.png",
+  "res/drawable-mdpi-v4/ic_media_play_dark.png",
+  "res/drawable-mdpi-v4/ic_media_play_light.png",
+  "res/drawable-mdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-mdpi-v4/ic_media_stop_light.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-mdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-mdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-mdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-mdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-mdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-xhdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-xhdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-xhdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-xhdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-xhdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-xhdpi-v4/ic_media_pause_light.png",
+  "res/drawable-xhdpi-v4/ic_media_play_dark.png",
+  "res/drawable-xhdpi-v4/ic_media_play_light.png",
+  "res/drawable-xhdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-xhdpi-v4/ic_media_stop_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_00_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_00_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_01_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_01_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_02_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_02_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_03_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_03_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_04_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_04_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_05_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_05_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_06_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_06_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_07_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_07_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_08_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_08_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_09_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_09_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_10_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_10_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_11_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_11_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_12_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_12_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_13_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_13_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_14_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_14_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_15_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_15_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_16_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_16_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_17_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_17_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_18_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_18_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_19_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_19_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_20_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_20_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_21_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_21_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_22_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_22_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_23_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_23_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_24_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_24_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_25_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_25_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_26_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_26_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_27_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_27_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_28_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_28_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_29_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_29_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_30_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connected_30_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_00_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_01_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_02_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_03_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_04_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_05_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_06_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_07_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_08_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_09_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_10_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_11_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_12_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_13_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_14_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_15_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_16_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_17_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_18_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_19_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_20_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_21_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_22_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_23_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_24_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_25_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_26_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_27_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_28_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_29_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_connecting_30_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-xhdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-xhdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-xxhdpi-v4/ic_audiotrack_dark.png",
+  "res/drawable-xxhdpi-v4/ic_audiotrack_light.png",
+  "res/drawable-xxhdpi-v4/ic_dialog_close_dark.png",
+  "res/drawable-xxhdpi-v4/ic_dialog_close_light.png",
+  "res/drawable-xxhdpi-v4/ic_media_pause_dark.png",
+  "res/drawable-xxhdpi-v4/ic_media_pause_light.png",
+  "res/drawable-xxhdpi-v4/ic_media_play_dark.png",
+  "res/drawable-xxhdpi-v4/ic_media_play_light.png",
+  "res/drawable-xxhdpi-v4/ic_media_stop_dark.png",
+  "res/drawable-xxhdpi-v4/ic_media_stop_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_00_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_01_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_02_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_03_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_04_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_05_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_06_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_07_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_08_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_09_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_10_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_11_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_12_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_13_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_14_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_15_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_16_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_17_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_18_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_19_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_20_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_21_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_22_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_23_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_24_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_25_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_26_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_27_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_28_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_29_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connected_30_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_00_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_01_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_02_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_03_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_04_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_05_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_06_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_07_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_08_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_09_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_10_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_11_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_12_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_13_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_14_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_15_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_16_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_17_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_18_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_19_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_20_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_21_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_22_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_23_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_24_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_25_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_26_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_27_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_28_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_29_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_connecting_30_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disabled_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disabled_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_dark.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_disconnected_light.png",
+  "res/drawable-xxhdpi-v4/ic_mr_button_grey.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_dark.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_dark.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_group_light.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_speaker_light.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_tv_dark.png",
+  "res/drawable-xxhdpi-v4/ic_vol_type_tv_light.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_00.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_01.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_02.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_03.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_04.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_05.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_06.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_07.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_08.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_09.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_10.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_11.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_12.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_13.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_14.png",
+  "res/drawable-xxxhdpi-v4/ic_group_collapse_15.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_00.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_01.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_02.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_03.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_04.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_05.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_06.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_07.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_08.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_09.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_10.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_11.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_12.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_13.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_14.png",
+  "res/drawable-xxxhdpi-v4/ic_group_expand_15.png",
+  "res/drawable-xxxhdpi-v4/ic_mr_button_grey.png",
+  "res/interpolator/mr_fast_out_slow_in.xml",
+  "res/interpolator/mr_linear_out_slow_in.xml",
+  "res/layout/mr_cast_dialog.xml",
+  "res/layout/mr_cast_group_item.xml",
+  "res/layout/mr_cast_group_volume_item.xml",
+  "res/layout/mr_cast_media_metadata.xml",
+  "res/layout/mr_cast_route_item.xml",
+  "res/layout/mr_chooser_dialog.xml",
+  "res/layout/mr_chooser_list_item.xml",
+  "res/layout/mr_controller_material_dialog_b.xml",
+  "res/layout/mr_controller_volume_item.xml",
+  "res/layout/mr_dialog_header_item.xml",
+  "res/layout/mr_picker_dialog.xml",
+  "res/layout/mr_picker_route_item.xml",
+  "res/layout/mr_playback_control.xml",
+  "res/layout/mr_volume_control.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-land/values-land.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-sw600dp-v13/values-sw600dp-v13.xml",
+  "res/values-sw720dp-v13/values-sw720dp-v13.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_multidex/com_android_support_multidex.info b/third_party/android_deps/libs/com_android_support_multidex/com_android_support_multidex.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_android_support_multidex/com_android_support_multidex.info
+++ b/third_party/android_deps/libs/com_android_support_multidex/com_android_support_multidex.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_palette_v7/com_android_support_palette_v7.info b/third_party/android_deps/libs/com_android_support_palette_v7/com_android_support_palette_v7.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_palette_v7/com_android_support_palette_v7.info
+++ b/third_party/android_deps/libs/com_android_support_palette_v7/com_android_support_palette_v7.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_preference_leanback_v17/com_android_support_preference_leanback_v17.info b/third_party/android_deps/libs/com_android_support_preference_leanback_v17/com_android_support_preference_leanback_v17.info
index 754a696c..500cc24 100644
--- a/third_party/android_deps/libs/com_android_support_preference_leanback_v17/com_android_support_preference_leanback_v17.info
+++ b/third_party/android_deps/libs/com_android_support_preference_leanback_v17/com_android_support_preference_leanback_v17.info
@@ -1,13 +1,29 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/color/lb_preference_item_primary_text_color.xml", "res/color/lb_preference_item_secondary_text_color.xml", "res/layout/leanback_list_preference_fragment.xml", "res/layout/leanback_list_preference_item_multi.xml", "res/layout/leanback_list_preference_item_single.xml", "res/layout/leanback_preference.xml", "res/layout/leanback_preference_category.xml", "res/layout/leanback_preference_fragment.xml", "res/layout/leanback_preference_information.xml", "res/layout/leanback_preference_widget_seekbar.xml", "res/layout/leanback_preferences_list.xml", "res/layout/leanback_settings_fragment.xml", "res/layout-v21/leanback_preference_category.xml", "res/layout-v21/leanback_settings_fragment.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/color/lb_preference_item_primary_text_color.xml",
+  "res/color/lb_preference_item_secondary_text_color.xml",
+  "res/layout/leanback_list_preference_fragment.xml",
+  "res/layout/leanback_list_preference_item_multi.xml",
+  "res/layout/leanback_list_preference_item_single.xml",
+  "res/layout/leanback_preference.xml",
+  "res/layout/leanback_preference_category.xml",
+  "res/layout/leanback_preference_fragment.xml",
+  "res/layout/leanback_preference_information.xml",
+  "res/layout/leanback_preference_widget_seekbar.xml",
+  "res/layout/leanback_preferences_list.xml",
+  "res/layout/leanback_settings_fragment.xml",
+  "res/layout-v21/leanback_preference_category.xml",
+  "res/layout-v21/leanback_settings_fragment.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_preference_v14/com_android_support_preference_v14.info b/third_party/android_deps/libs/com_android_support_preference_v14/com_android_support_preference_v14.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_preference_v14/com_android_support_preference_v14.info
+++ b/third_party/android_deps/libs/com_android_support_preference_v14/com_android_support_preference_v14.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_preference_v7/com_android_support_preference_v7.info b/third_party/android_deps/libs/com_android_support_preference_v7/com_android_support_preference_v7.info
index 8d5529d..1e68e8c 100644
--- a/third_party/android_deps/libs/com_android_support_preference_v7/com_android_support_preference_v7.info
+++ b/third_party/android_deps/libs/com_android_support_preference_v7/com_android_support_preference_v7.info
@@ -1,13 +1,138 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable/preference_list_divider_material.xml", "res/drawable-anydpi-v21/ic_arrow_down_24dp.xml", "res/drawable-hdpi-v4/ic_arrow_down_24dp.png", "res/drawable-ldpi-v4/ic_arrow_down_24dp.png", "res/drawable-mdpi-v4/ic_arrow_down_24dp.png", "res/drawable-v21/ic_arrow_down_24dp.xml", "res/drawable-v21/preference_list_divider_material.xml", "res/drawable-xhdpi-v4/ic_arrow_down_24dp.png", "res/drawable-xxhdpi-v4/ic_arrow_down_24dp.png", "res/drawable-xxxhdpi-v4/ic_arrow_down_24dp.png", "res/layout/expand_button.xml", "res/layout/preference.xml", "res/layout/preference_category.xml", "res/layout/preference_category_material.xml", "res/layout/preference_dialog_edittext.xml", "res/layout/preference_dropdown.xml", "res/layout/preference_dropdown_material.xml", "res/layout/preference_information.xml", "res/layout/preference_information_material.xml", "res/layout/preference_list_fragment.xml", "res/layout/preference_material.xml", "res/layout/preference_recyclerview.xml", "res/layout/preference_widget_checkbox.xml", "res/layout/preference_widget_seekbar.xml", "res/layout/preference_widget_seekbar_material.xml", "res/layout/preference_widget_switch.xml", "res/layout/preference_widget_switch_compat.xml", "res/layout-v17/preference_category_material.xml", "res/layout-v17/preference_dropdown_material.xml", "res/layout-v17/preference_information_material.xml", "res/layout-v17/preference_material.xml", "res/layout-v17/preference_widget_seekbar_material.xml", "res/layout-v21/preference_category_material.xml", "res/layout-v21/preference_dropdown_material.xml", "res/layout-v21/preference_information_material.xml", "res/layout-v21/preference_material.xml", "res/layout-v21/preference_widget_seekbar_material.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-sw360dp-v13/values-sw360dp-v13.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v17/values-v17.xml", "res/values-v21/values-v21.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable/preference_list_divider_material.xml",
+  "res/drawable-anydpi-v21/ic_arrow_down_24dp.xml",
+  "res/drawable-hdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-ldpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-mdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-v21/ic_arrow_down_24dp.xml",
+  "res/drawable-v21/preference_list_divider_material.xml",
+  "res/drawable-xhdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-xxhdpi-v4/ic_arrow_down_24dp.png",
+  "res/drawable-xxxhdpi-v4/ic_arrow_down_24dp.png",
+  "res/layout/expand_button.xml",
+  "res/layout/preference.xml",
+  "res/layout/preference_category.xml",
+  "res/layout/preference_category_material.xml",
+  "res/layout/preference_dialog_edittext.xml",
+  "res/layout/preference_dropdown.xml",
+  "res/layout/preference_dropdown_material.xml",
+  "res/layout/preference_information.xml",
+  "res/layout/preference_information_material.xml",
+  "res/layout/preference_list_fragment.xml",
+  "res/layout/preference_material.xml",
+  "res/layout/preference_recyclerview.xml",
+  "res/layout/preference_widget_checkbox.xml",
+  "res/layout/preference_widget_seekbar.xml",
+  "res/layout/preference_widget_seekbar_material.xml",
+  "res/layout/preference_widget_switch.xml",
+  "res/layout/preference_widget_switch_compat.xml",
+  "res/layout-v17/preference_category_material.xml",
+  "res/layout-v17/preference_dropdown_material.xml",
+  "res/layout-v17/preference_information_material.xml",
+  "res/layout-v17/preference_material.xml",
+  "res/layout-v17/preference_widget_seekbar_material.xml",
+  "res/layout-v21/preference_category_material.xml",
+  "res/layout-v21/preference_dropdown_material.xml",
+  "res/layout-v21/preference_information_material.xml",
+  "res/layout-v21/preference_material.xml",
+  "res/layout-v21/preference_widget_seekbar_material.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-sw360dp-v13/values-sw360dp-v13.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v17/values-v17.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_print/com_android_support_print.info b/third_party/android_deps/libs/com_android_support_print/com_android_support_print.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_android_support_print/com_android_support_print.info
+++ b/third_party/android_deps/libs/com_android_support_print/com_android_support_print.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_recyclerview_v7/com_android_support_recyclerview_v7.info b/third_party/android_deps/libs/com_android_support_recyclerview_v7/com_android_support_recyclerview_v7.info
index a25d255..5134f1a 100644
--- a/third_party/android_deps/libs/com_android_support_recyclerview_v7/com_android_support_recyclerview_v7.info
+++ b/third_party/android_deps/libs/com_android_support_recyclerview_v7/com_android_support_recyclerview_v7.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_slidingpanelayout/com_android_support_slidingpanelayout.info b/third_party/android_deps/libs/com_android_support_slidingpanelayout/com_android_support_slidingpanelayout.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_slidingpanelayout/com_android_support_slidingpanelayout.info
+++ b/third_party/android_deps/libs/com_android_support_slidingpanelayout/com_android_support_slidingpanelayout.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_compat/com_android_support_support_compat.info b/third_party/android_deps/libs/com_android_support_support_compat/com_android_support_support_compat.info
index 1a74950..7263fd0 100644
--- a/third_party/android_deps/libs/com_android_support_support_compat/com_android_support_support_compat.info
+++ b/third_party/android_deps/libs/com_android_support_support_compat/com_android_support_support_compat.info
@@ -1,13 +1,135 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [ "aidl/android/support/v4/os/ResultReceiver.aidl" ]
-assets = [  ]
+aidl = [
+  "aidl/android/support/v4/os/ResultReceiver.aidl"
+]
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable/notification_bg.xml", "res/drawable/notification_bg_low.xml", "res/drawable/notification_icon_background.xml", "res/drawable/notification_tile_bg.xml", "res/drawable-hdpi-v4/notification_bg_low_normal.9.png", "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-hdpi-v4/notification_bg_normal.9.png", "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-mdpi-v4/notification_bg_low_normal.9.png", "res/drawable-mdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-mdpi-v4/notification_bg_normal.9.png", "res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png", "res/drawable-v21/notification_action_background.xml", "res/drawable-xhdpi-v4/notification_bg_low_normal.9.png", "res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png", "res/drawable-xhdpi-v4/notification_bg_normal.9.png", "res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png", "res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png", "res/layout/notification_action.xml", "res/layout/notification_action_tombstone.xml", "res/layout/notification_template_custom_big.xml", "res/layout/notification_template_icon_group.xml", "res/layout/notification_template_part_chronometer.xml", "res/layout/notification_template_part_time.xml", "res/layout-v16/notification_template_custom_big.xml", "res/layout-v21/notification_action.xml", "res/layout-v21/notification_action_tombstone.xml", "res/layout-v21/notification_template_custom_big.xml", "res/layout-v21/notification_template_icon_group.xml", "res/values/values.xml", "res/values-af/values-af.xml", "res/values-am/values-am.xml", "res/values-ar/values-ar.xml", "res/values-as/values-as.xml", "res/values-az/values-az.xml", "res/values-b+sr+Latn/values-b+sr+Latn.xml", "res/values-be/values-be.xml", "res/values-bg/values-bg.xml", "res/values-bn/values-bn.xml", "res/values-bs/values-bs.xml", "res/values-ca/values-ca.xml", "res/values-cs/values-cs.xml", "res/values-da/values-da.xml", "res/values-de/values-de.xml", "res/values-el/values-el.xml", "res/values-en-rAU/values-en-rAU.xml", "res/values-en-rCA/values-en-rCA.xml", "res/values-en-rGB/values-en-rGB.xml", "res/values-en-rIN/values-en-rIN.xml", "res/values-en-rXC/values-en-rXC.xml", "res/values-es/values-es.xml", "res/values-es-rUS/values-es-rUS.xml", "res/values-et/values-et.xml", "res/values-eu/values-eu.xml", "res/values-fa/values-fa.xml", "res/values-fi/values-fi.xml", "res/values-fr/values-fr.xml", "res/values-fr-rCA/values-fr-rCA.xml", "res/values-gl/values-gl.xml", "res/values-gu/values-gu.xml", "res/values-hi/values-hi.xml", "res/values-hr/values-hr.xml", "res/values-hu/values-hu.xml", "res/values-hy/values-hy.xml", "res/values-in/values-in.xml", "res/values-is/values-is.xml", "res/values-it/values-it.xml", "res/values-iw/values-iw.xml", "res/values-ja/values-ja.xml", "res/values-ka/values-ka.xml", "res/values-kk/values-kk.xml", "res/values-km/values-km.xml", "res/values-kn/values-kn.xml", "res/values-ko/values-ko.xml", "res/values-ky/values-ky.xml", "res/values-lo/values-lo.xml", "res/values-lt/values-lt.xml", "res/values-lv/values-lv.xml", "res/values-mk/values-mk.xml", "res/values-ml/values-ml.xml", "res/values-mn/values-mn.xml", "res/values-mr/values-mr.xml", "res/values-ms/values-ms.xml", "res/values-my/values-my.xml", "res/values-nb/values-nb.xml", "res/values-ne/values-ne.xml", "res/values-nl/values-nl.xml", "res/values-or/values-or.xml", "res/values-pa/values-pa.xml", "res/values-pl/values-pl.xml", "res/values-pt/values-pt.xml", "res/values-pt-rBR/values-pt-rBR.xml", "res/values-pt-rPT/values-pt-rPT.xml", "res/values-ro/values-ro.xml", "res/values-ru/values-ru.xml", "res/values-si/values-si.xml", "res/values-sk/values-sk.xml", "res/values-sl/values-sl.xml", "res/values-sq/values-sq.xml", "res/values-sr/values-sr.xml", "res/values-sv/values-sv.xml", "res/values-sw/values-sw.xml", "res/values-ta/values-ta.xml", "res/values-te/values-te.xml", "res/values-th/values-th.xml", "res/values-tl/values-tl.xml", "res/values-tr/values-tr.xml", "res/values-uk/values-uk.xml", "res/values-ur/values-ur.xml", "res/values-uz/values-uz.xml", "res/values-v16/values-v16.xml", "res/values-v21/values-v21.xml", "res/values-vi/values-vi.xml", "res/values-zh-rCN/values-zh-rCN.xml", "res/values-zh-rHK/values-zh-rHK.xml", "res/values-zh-rTW/values-zh-rTW.xml", "res/values-zu/values-zu.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable/notification_bg.xml",
+  "res/drawable/notification_bg_low.xml",
+  "res/drawable/notification_icon_background.xml",
+  "res/drawable/notification_tile_bg.xml",
+  "res/drawable-hdpi-v4/notification_bg_low_normal.9.png",
+  "res/drawable-hdpi-v4/notification_bg_low_pressed.9.png",
+  "res/drawable-hdpi-v4/notification_bg_normal.9.png",
+  "res/drawable-hdpi-v4/notification_bg_normal_pressed.9.png",
+  "res/drawable-hdpi-v4/notify_panel_notification_icon_bg.png",
+  "res/drawable-mdpi-v4/notification_bg_low_normal.9.png",
+  "res/drawable-mdpi-v4/notification_bg_low_pressed.9.png",
+  "res/drawable-mdpi-v4/notification_bg_normal.9.png",
+  "res/drawable-mdpi-v4/notification_bg_normal_pressed.9.png",
+  "res/drawable-mdpi-v4/notify_panel_notification_icon_bg.png",
+  "res/drawable-v21/notification_action_background.xml",
+  "res/drawable-xhdpi-v4/notification_bg_low_normal.9.png",
+  "res/drawable-xhdpi-v4/notification_bg_low_pressed.9.png",
+  "res/drawable-xhdpi-v4/notification_bg_normal.9.png",
+  "res/drawable-xhdpi-v4/notification_bg_normal_pressed.9.png",
+  "res/drawable-xhdpi-v4/notify_panel_notification_icon_bg.png",
+  "res/layout/notification_action.xml",
+  "res/layout/notification_action_tombstone.xml",
+  "res/layout/notification_template_custom_big.xml",
+  "res/layout/notification_template_icon_group.xml",
+  "res/layout/notification_template_part_chronometer.xml",
+  "res/layout/notification_template_part_time.xml",
+  "res/layout-v16/notification_template_custom_big.xml",
+  "res/layout-v21/notification_action.xml",
+  "res/layout-v21/notification_action_tombstone.xml",
+  "res/layout-v21/notification_template_custom_big.xml",
+  "res/layout-v21/notification_template_icon_group.xml",
+  "res/values/values.xml",
+  "res/values-af/values-af.xml",
+  "res/values-am/values-am.xml",
+  "res/values-ar/values-ar.xml",
+  "res/values-as/values-as.xml",
+  "res/values-az/values-az.xml",
+  "res/values-b+sr+Latn/values-b+sr+Latn.xml",
+  "res/values-be/values-be.xml",
+  "res/values-bg/values-bg.xml",
+  "res/values-bn/values-bn.xml",
+  "res/values-bs/values-bs.xml",
+  "res/values-ca/values-ca.xml",
+  "res/values-cs/values-cs.xml",
+  "res/values-da/values-da.xml",
+  "res/values-de/values-de.xml",
+  "res/values-el/values-el.xml",
+  "res/values-en-rAU/values-en-rAU.xml",
+  "res/values-en-rCA/values-en-rCA.xml",
+  "res/values-en-rGB/values-en-rGB.xml",
+  "res/values-en-rIN/values-en-rIN.xml",
+  "res/values-en-rXC/values-en-rXC.xml",
+  "res/values-es/values-es.xml",
+  "res/values-es-rUS/values-es-rUS.xml",
+  "res/values-et/values-et.xml",
+  "res/values-eu/values-eu.xml",
+  "res/values-fa/values-fa.xml",
+  "res/values-fi/values-fi.xml",
+  "res/values-fr/values-fr.xml",
+  "res/values-fr-rCA/values-fr-rCA.xml",
+  "res/values-gl/values-gl.xml",
+  "res/values-gu/values-gu.xml",
+  "res/values-hi/values-hi.xml",
+  "res/values-hr/values-hr.xml",
+  "res/values-hu/values-hu.xml",
+  "res/values-hy/values-hy.xml",
+  "res/values-in/values-in.xml",
+  "res/values-is/values-is.xml",
+  "res/values-it/values-it.xml",
+  "res/values-iw/values-iw.xml",
+  "res/values-ja/values-ja.xml",
+  "res/values-ka/values-ka.xml",
+  "res/values-kk/values-kk.xml",
+  "res/values-km/values-km.xml",
+  "res/values-kn/values-kn.xml",
+  "res/values-ko/values-ko.xml",
+  "res/values-ky/values-ky.xml",
+  "res/values-lo/values-lo.xml",
+  "res/values-lt/values-lt.xml",
+  "res/values-lv/values-lv.xml",
+  "res/values-mk/values-mk.xml",
+  "res/values-ml/values-ml.xml",
+  "res/values-mn/values-mn.xml",
+  "res/values-mr/values-mr.xml",
+  "res/values-ms/values-ms.xml",
+  "res/values-my/values-my.xml",
+  "res/values-nb/values-nb.xml",
+  "res/values-ne/values-ne.xml",
+  "res/values-nl/values-nl.xml",
+  "res/values-or/values-or.xml",
+  "res/values-pa/values-pa.xml",
+  "res/values-pl/values-pl.xml",
+  "res/values-pt/values-pt.xml",
+  "res/values-pt-rBR/values-pt-rBR.xml",
+  "res/values-pt-rPT/values-pt-rPT.xml",
+  "res/values-ro/values-ro.xml",
+  "res/values-ru/values-ru.xml",
+  "res/values-si/values-si.xml",
+  "res/values-sk/values-sk.xml",
+  "res/values-sl/values-sl.xml",
+  "res/values-sq/values-sq.xml",
+  "res/values-sr/values-sr.xml",
+  "res/values-sv/values-sv.xml",
+  "res/values-sw/values-sw.xml",
+  "res/values-ta/values-ta.xml",
+  "res/values-te/values-te.xml",
+  "res/values-th/values-th.xml",
+  "res/values-tl/values-tl.xml",
+  "res/values-tr/values-tr.xml",
+  "res/values-uk/values-uk.xml",
+  "res/values-ur/values-ur.xml",
+  "res/values-uz/values-uz.xml",
+  "res/values-v16/values-v16.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-vi/values-vi.xml",
+  "res/values-zh-rCN/values-zh-rCN.xml",
+  "res/values-zh-rHK/values-zh-rHK.xml",
+  "res/values-zh-rTW/values-zh-rTW.xml",
+  "res/values-zu/values-zu.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_core_ui/com_android_support_support_core_ui.info b/third_party/android_deps/libs/com_android_support_support_core_ui/com_android_support_support_core_ui.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_support_core_ui/com_android_support_support_core_ui.info
+++ b/third_party/android_deps/libs/com_android_support_support_core_ui/com_android_support_support_core_ui.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_core_utils/com_android_support_support_core_utils.info b/third_party/android_deps/libs/com_android_support_support_core_utils/com_android_support_support_core_utils.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_support_core_utils/com_android_support_support_core_utils.info
+++ b/third_party/android_deps/libs/com_android_support_support_core_utils/com_android_support_support_core_utils.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_fragment/com_android_support_support_fragment.info b/third_party/android_deps/libs/com_android_support_support_fragment/com_android_support_support_fragment.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_support_fragment/com_android_support_support_fragment.info
+++ b/third_party/android_deps/libs/com_android_support_support_fragment/com_android_support_support_fragment.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_media_compat/com_android_support_support_media_compat.info b/third_party/android_deps/libs/com_android_support_support_media_compat/com_android_support_support_media_compat.info
index 672a388..00257b6 100644
--- a/third_party/android_deps/libs/com_android_support_support_media_compat/com_android_support_support_media_compat.info
+++ b/third_party/android_deps/libs/com_android_support_support_media_compat/com_android_support_support_media_compat.info
@@ -1,13 +1,33 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [ "aidl/android/support/v4/media/MediaDescriptionCompat.aidl", "aidl/android/support/v4/media/MediaMetadataCompat.aidl", "aidl/android/support/v4/media/RatingCompat.aidl", "aidl/android/support/v4/media/session/MediaSessionCompat.aidl", "aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl", "aidl/android/support/v4/media/session/PlaybackStateCompat.aidl" ]
-assets = [  ]
+aidl = [
+  "aidl/android/support/v4/media/MediaDescriptionCompat.aidl",
+  "aidl/android/support/v4/media/MediaMetadataCompat.aidl",
+  "aidl/android/support/v4/media/RatingCompat.aidl",
+  "aidl/android/support/v4/media/session/MediaSessionCompat.aidl",
+  "aidl/android/support/v4/media/session/ParcelableVolumeInfo.aidl",
+  "aidl/android/support/v4/media/session/PlaybackStateCompat.aidl"
+]
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/layout/notification_media_action.xml", "res/layout/notification_media_cancel_action.xml", "res/layout/notification_template_big_media.xml", "res/layout/notification_template_big_media_custom.xml", "res/layout/notification_template_big_media_narrow.xml", "res/layout/notification_template_big_media_narrow_custom.xml", "res/layout/notification_template_lines_media.xml", "res/layout/notification_template_media.xml", "res/layout/notification_template_media_custom.xml", "res/values/values.xml", "res/values-v21/values-v21.xml", "res/values-v24/values-v24.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/layout/notification_media_action.xml",
+  "res/layout/notification_media_cancel_action.xml",
+  "res/layout/notification_template_big_media.xml",
+  "res/layout/notification_template_big_media_custom.xml",
+  "res/layout/notification_template_big_media_narrow.xml",
+  "res/layout/notification_template_big_media_narrow_custom.xml",
+  "res/layout/notification_template_lines_media.xml",
+  "res/layout/notification_template_media.xml",
+  "res/layout/notification_template_media_custom.xml",
+  "res/values/values.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-v24/values-v24.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_v13/com_android_support_support_v13.info b/third_party/android_deps/libs/com_android_support_support_v13/com_android_support_support_v13.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_support_v13/com_android_support_support_v13.info
+++ b/third_party/android_deps/libs/com_android_support_support_v13/com_android_support_support_v13.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_v4/com_android_support_support_v4.info b/third_party/android_deps/libs/com_android_support_support_v4/com_android_support_support_v4.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_support_v4/com_android_support_support_v4.info
+++ b/third_party/android_deps/libs/com_android_support_support_v4/com_android_support_support_v4.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_support_vector_drawable/com_android_support_support_vector_drawable.info b/third_party/android_deps/libs/com_android_support_support_vector_drawable/com_android_support_support_vector_drawable.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_support_vector_drawable/com_android_support_support_vector_drawable.info
+++ b/third_party/android_deps/libs/com_android_support_support_vector_drawable/com_android_support_support_vector_drawable.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_swiperefreshlayout/com_android_support_swiperefreshlayout.info b/third_party/android_deps/libs/com_android_support_swiperefreshlayout/com_android_support_swiperefreshlayout.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_swiperefreshlayout/com_android_support_swiperefreshlayout.info
+++ b/third_party/android_deps/libs/com_android_support_swiperefreshlayout/com_android_support_swiperefreshlayout.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_transition/com_android_support_transition.info b/third_party/android_deps/libs/com_android_support_transition/com_android_support_transition.info
index a25d255..5134f1a 100644
--- a/third_party/android_deps/libs/com_android_support_transition/com_android_support_transition.info
+++ b/third_party/android_deps/libs/com_android_support_transition/com_android_support_transition.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_versionedparcelable/com_android_support_versionedparcelable.info b/third_party/android_deps/libs/com_android_support_versionedparcelable/com_android_support_versionedparcelable.info
index 4e6c39c..b29e3757 100644
--- a/third_party/android_deps/libs/com_android_support_versionedparcelable/com_android_support_versionedparcelable.info
+++ b/third_party/android_deps/libs/com_android_support_versionedparcelable/com_android_support_versionedparcelable.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [ "aidl/androidx/versionedparcelable/ParcelImpl.aidl" ]
-assets = [  ]
+aidl = [
+  "aidl/androidx/versionedparcelable/ParcelImpl.aidl"
+]
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_android_support_viewpager/com_android_support_viewpager.info b/third_party/android_deps/libs/com_android_support_viewpager/com_android_support_viewpager.info
index cd54060..801ef60 100644
--- a/third_party/android_deps/libs/com_android_support_viewpager/com_android_support_viewpager.info
+++ b/third_party/android_deps/libs/com_android_support_viewpager/com_android_support_viewpager.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_auth/com_google_android_gms_play_services_auth.info b/third_party/android_deps/libs/com_google_android_gms_play_services_auth/com_google_android_gms_play_services_auth.info
index f9c0cdd8..3f8cde6 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_auth/com_google_android_gms_play_services_auth.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_auth/com_google_android_gms_play_services_auth.info
@@ -1,13 +1,18 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = false
-resources = [ "res/drawable-watch-v20/common_google_signin_btn_text_dark_normal.xml", "res/drawable-watch-v20/common_google_signin_btn_text_disabled.xml", "res/drawable-watch-v20/common_google_signin_btn_text_light_normal.xml", "res/values-watch-v20/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable-watch-v20/common_google_signin_btn_text_dark_normal.xml",
+  "res/drawable-watch-v20/common_google_signin_btn_text_disabled.xml",
+  "res/drawable-watch-v20/common_google_signin_btn_text_light_normal.xml",
+  "res/values-watch-v20/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/com_google_android_gms_play_services_auth_api_phone.info b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/com_google_android_gms_play_services_auth_api_phone.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/com_google_android_gms_play_services_auth_api_phone.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_api_phone/com_google_android_gms_play_services_auth_api_phone.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/com_google_android_gms_play_services_auth_base.info b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/com_google_android_gms_play_services_auth_base.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/com_google_android_gms_play_services_auth_base.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_auth_base/com_google_android_gms_play_services_auth_base.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_base/com_google_android_gms_play_services_base.info b/third_party/android_deps/libs/com_google_android_gms_play_services_base/com_google_android_gms_play_services_base.info
index a289db5..4b4d77a 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_base/com_google_android_gms_play_services_base.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_base/com_google_android_gms_play_services_base.info
@@ -1,13 +1,138 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = false
-resources = [ "res/color/common_google_signin_btn_text_dark.xml", "res/color/common_google_signin_btn_text_light.xml", "res/color/common_google_signin_btn_tint.xml", "res/drawable-hdpi-v4/common_full_open_on_phone.png", "res/drawable-hdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png", "res/drawable-hdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png", "res/drawable-hdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png", "res/drawable-hdpi-v4/common_google_signin_btn_text_light_normal_background.9.png", "res/drawable-hdpi-v4/googleg_disabled_color_18.png", "res/drawable-hdpi-v4/googleg_standard_color_18.png", "res/drawable-mdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png", "res/drawable-mdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png", "res/drawable-mdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png", "res/drawable-mdpi-v4/common_google_signin_btn_text_light_normal_background.9.png", "res/drawable-mdpi-v4/googleg_disabled_color_18.png", "res/drawable-mdpi-v4/googleg_standard_color_18.png", "res/drawable-xhdpi-v4/common_full_open_on_phone.png", "res/drawable-xhdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png", "res/drawable-xhdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png", "res/drawable-xhdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png", "res/drawable-xhdpi-v4/common_google_signin_btn_text_light_normal_background.9.png", "res/drawable-xhdpi-v4/googleg_disabled_color_18.png", "res/drawable-xhdpi-v4/googleg_standard_color_18.png", "res/drawable-xxhdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png", "res/drawable-xxhdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png", "res/drawable-xxhdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png", "res/drawable-xxhdpi-v4/common_google_signin_btn_text_light_normal_background.9.png", "res/drawable-xxhdpi-v4/googleg_disabled_color_18.png", "res/drawable-xxhdpi-v4/googleg_standard_color_18.png", "res/drawable/common_google_signin_btn_icon_dark.xml", "res/drawable/common_google_signin_btn_icon_dark_focused.xml", "res/drawable/common_google_signin_btn_icon_dark_normal.xml", "res/drawable/common_google_signin_btn_icon_disabled.xml", "res/drawable/common_google_signin_btn_icon_light.xml", "res/drawable/common_google_signin_btn_icon_light_focused.xml", "res/drawable/common_google_signin_btn_icon_light_normal.xml", "res/drawable/common_google_signin_btn_text_dark.xml", "res/drawable/common_google_signin_btn_text_dark_focused.xml", "res/drawable/common_google_signin_btn_text_dark_normal.xml", "res/drawable/common_google_signin_btn_text_disabled.xml", "res/drawable/common_google_signin_btn_text_light.xml", "res/drawable/common_google_signin_btn_text_light_focused.xml", "res/drawable/common_google_signin_btn_text_light_normal.xml", "res/values-af/values.xml", "res/values-am/values.xml", "res/values-ar/values.xml", "res/values-as/values.xml", "res/values-az/values.xml", "res/values-b+sr+Latn/values.xml", "res/values-be/values.xml", "res/values-bg/values.xml", "res/values-bn/values.xml", "res/values-bs/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rGB/values.xml", "res/values-es-rUS/values.xml", "res/values-es/values.xml", "res/values-et/values.xml", "res/values-eu/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr/values.xml", "res/values-gl/values.xml", "res/values-gu/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-hy/values.xml", "res/values-in/values.xml", "res/values-is/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ka/values.xml", "res/values-kk/values.xml", "res/values-km/values.xml", "res/values-kn/values.xml", "res/values-ko/values.xml", "res/values-ky/values.xml", "res/values-lo/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-mk/values.xml", "res/values-ml/values.xml", "res/values-mn/values.xml", "res/values-mr/values.xml", "res/values-ms/values.xml", "res/values-my/values.xml", "res/values-nb/values.xml", "res/values-ne/values.xml", "res/values-nl/values.xml", "res/values-or/values.xml", "res/values-pa/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-si/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sq/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-sw/values.xml", "res/values-ta/values.xml", "res/values-te/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-ur/values.xml", "res/values-uz/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rHK/values.xml", "res/values-zh-rTW/values.xml", "res/values-zu/values.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/color/common_google_signin_btn_text_dark.xml",
+  "res/color/common_google_signin_btn_text_light.xml",
+  "res/color/common_google_signin_btn_tint.xml",
+  "res/drawable-hdpi-v4/common_full_open_on_phone.png",
+  "res/drawable-hdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png",
+  "res/drawable-hdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png",
+  "res/drawable-hdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png",
+  "res/drawable-hdpi-v4/common_google_signin_btn_text_light_normal_background.9.png",
+  "res/drawable-hdpi-v4/googleg_disabled_color_18.png",
+  "res/drawable-hdpi-v4/googleg_standard_color_18.png",
+  "res/drawable-mdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png",
+  "res/drawable-mdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png",
+  "res/drawable-mdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png",
+  "res/drawable-mdpi-v4/common_google_signin_btn_text_light_normal_background.9.png",
+  "res/drawable-mdpi-v4/googleg_disabled_color_18.png",
+  "res/drawable-mdpi-v4/googleg_standard_color_18.png",
+  "res/drawable-xhdpi-v4/common_full_open_on_phone.png",
+  "res/drawable-xhdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png",
+  "res/drawable-xhdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png",
+  "res/drawable-xhdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png",
+  "res/drawable-xhdpi-v4/common_google_signin_btn_text_light_normal_background.9.png",
+  "res/drawable-xhdpi-v4/googleg_disabled_color_18.png",
+  "res/drawable-xhdpi-v4/googleg_standard_color_18.png",
+  "res/drawable-xxhdpi-v4/common_google_signin_btn_icon_dark_normal_background.9.png",
+  "res/drawable-xxhdpi-v4/common_google_signin_btn_icon_light_normal_background.9.png",
+  "res/drawable-xxhdpi-v4/common_google_signin_btn_text_dark_normal_background.9.png",
+  "res/drawable-xxhdpi-v4/common_google_signin_btn_text_light_normal_background.9.png",
+  "res/drawable-xxhdpi-v4/googleg_disabled_color_18.png",
+  "res/drawable-xxhdpi-v4/googleg_standard_color_18.png",
+  "res/drawable/common_google_signin_btn_icon_dark.xml",
+  "res/drawable/common_google_signin_btn_icon_dark_focused.xml",
+  "res/drawable/common_google_signin_btn_icon_dark_normal.xml",
+  "res/drawable/common_google_signin_btn_icon_disabled.xml",
+  "res/drawable/common_google_signin_btn_icon_light.xml",
+  "res/drawable/common_google_signin_btn_icon_light_focused.xml",
+  "res/drawable/common_google_signin_btn_icon_light_normal.xml",
+  "res/drawable/common_google_signin_btn_text_dark.xml",
+  "res/drawable/common_google_signin_btn_text_dark_focused.xml",
+  "res/drawable/common_google_signin_btn_text_dark_normal.xml",
+  "res/drawable/common_google_signin_btn_text_disabled.xml",
+  "res/drawable/common_google_signin_btn_text_light.xml",
+  "res/drawable/common_google_signin_btn_text_light_focused.xml",
+  "res/drawable/common_google_signin_btn_text_light_normal.xml",
+  "res/values-af/values.xml",
+  "res/values-am/values.xml",
+  "res/values-ar/values.xml",
+  "res/values-as/values.xml",
+  "res/values-az/values.xml",
+  "res/values-b+sr+Latn/values.xml",
+  "res/values-be/values.xml",
+  "res/values-bg/values.xml",
+  "res/values-bn/values.xml",
+  "res/values-bs/values.xml",
+  "res/values-ca/values.xml",
+  "res/values-cs/values.xml",
+  "res/values-da/values.xml",
+  "res/values-de/values.xml",
+  "res/values-el/values.xml",
+  "res/values-en-rGB/values.xml",
+  "res/values-es-rUS/values.xml",
+  "res/values-es/values.xml",
+  "res/values-et/values.xml",
+  "res/values-eu/values.xml",
+  "res/values-fa/values.xml",
+  "res/values-fi/values.xml",
+  "res/values-fr-rCA/values.xml",
+  "res/values-fr/values.xml",
+  "res/values-gl/values.xml",
+  "res/values-gu/values.xml",
+  "res/values-hi/values.xml",
+  "res/values-hr/values.xml",
+  "res/values-hu/values.xml",
+  "res/values-hy/values.xml",
+  "res/values-in/values.xml",
+  "res/values-is/values.xml",
+  "res/values-it/values.xml",
+  "res/values-iw/values.xml",
+  "res/values-ja/values.xml",
+  "res/values-ka/values.xml",
+  "res/values-kk/values.xml",
+  "res/values-km/values.xml",
+  "res/values-kn/values.xml",
+  "res/values-ko/values.xml",
+  "res/values-ky/values.xml",
+  "res/values-lo/values.xml",
+  "res/values-lt/values.xml",
+  "res/values-lv/values.xml",
+  "res/values-mk/values.xml",
+  "res/values-ml/values.xml",
+  "res/values-mn/values.xml",
+  "res/values-mr/values.xml",
+  "res/values-ms/values.xml",
+  "res/values-my/values.xml",
+  "res/values-nb/values.xml",
+  "res/values-ne/values.xml",
+  "res/values-nl/values.xml",
+  "res/values-or/values.xml",
+  "res/values-pa/values.xml",
+  "res/values-pl/values.xml",
+  "res/values-pt-rBR/values.xml",
+  "res/values-pt-rPT/values.xml",
+  "res/values-ro/values.xml",
+  "res/values-ru/values.xml",
+  "res/values-si/values.xml",
+  "res/values-sk/values.xml",
+  "res/values-sl/values.xml",
+  "res/values-sq/values.xml",
+  "res/values-sr/values.xml",
+  "res/values-sv/values.xml",
+  "res/values-sw/values.xml",
+  "res/values-ta/values.xml",
+  "res/values-te/values.xml",
+  "res/values-th/values.xml",
+  "res/values-tl/values.xml",
+  "res/values-tr/values.xml",
+  "res/values-uk/values.xml",
+  "res/values-ur/values.xml",
+  "res/values-uz/values.xml",
+  "res/values-vi/values.xml",
+  "res/values-zh-rCN/values.xml",
+  "res/values-zh-rHK/values.xml",
+  "res/values-zh-rTW/values.xml",
+  "res/values-zu/values.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_basement/com_google_android_gms_play_services_basement.info b/third_party/android_deps/libs/com_google_android_gms_play_services_basement/com_google_android_gms_play_services_basement.info
index e053dfc..067efb7 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_basement/com_google_android_gms_play_services_basement.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_basement/com_google_android_gms_play_services_basement.info
@@ -1,13 +1,95 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = false
-resources = [ "res/values-af/values.xml", "res/values-am/values.xml", "res/values-ar/values.xml", "res/values-as/values.xml", "res/values-az/values.xml", "res/values-b+sr+Latn/values.xml", "res/values-be/values.xml", "res/values-bg/values.xml", "res/values-bn/values.xml", "res/values-bs/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rGB/values.xml", "res/values-es-rUS/values.xml", "res/values-es/values.xml", "res/values-et/values.xml", "res/values-eu/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr/values.xml", "res/values-gl/values.xml", "res/values-gu/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-hy/values.xml", "res/values-in/values.xml", "res/values-is/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ka/values.xml", "res/values-kk/values.xml", "res/values-km/values.xml", "res/values-kn/values.xml", "res/values-ko/values.xml", "res/values-ky/values.xml", "res/values-lo/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-mk/values.xml", "res/values-ml/values.xml", "res/values-mn/values.xml", "res/values-mr/values.xml", "res/values-ms/values.xml", "res/values-my/values.xml", "res/values-nb/values.xml", "res/values-ne/values.xml", "res/values-nl/values.xml", "res/values-or/values.xml", "res/values-pa/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-si/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sq/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-sw/values.xml", "res/values-ta/values.xml", "res/values-te/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-ur/values.xml", "res/values-uz/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rHK/values.xml", "res/values-zh-rTW/values.xml", "res/values-zu/values.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values-af/values.xml",
+  "res/values-am/values.xml",
+  "res/values-ar/values.xml",
+  "res/values-as/values.xml",
+  "res/values-az/values.xml",
+  "res/values-b+sr+Latn/values.xml",
+  "res/values-be/values.xml",
+  "res/values-bg/values.xml",
+  "res/values-bn/values.xml",
+  "res/values-bs/values.xml",
+  "res/values-ca/values.xml",
+  "res/values-cs/values.xml",
+  "res/values-da/values.xml",
+  "res/values-de/values.xml",
+  "res/values-el/values.xml",
+  "res/values-en-rGB/values.xml",
+  "res/values-es-rUS/values.xml",
+  "res/values-es/values.xml",
+  "res/values-et/values.xml",
+  "res/values-eu/values.xml",
+  "res/values-fa/values.xml",
+  "res/values-fi/values.xml",
+  "res/values-fr-rCA/values.xml",
+  "res/values-fr/values.xml",
+  "res/values-gl/values.xml",
+  "res/values-gu/values.xml",
+  "res/values-hi/values.xml",
+  "res/values-hr/values.xml",
+  "res/values-hu/values.xml",
+  "res/values-hy/values.xml",
+  "res/values-in/values.xml",
+  "res/values-is/values.xml",
+  "res/values-it/values.xml",
+  "res/values-iw/values.xml",
+  "res/values-ja/values.xml",
+  "res/values-ka/values.xml",
+  "res/values-kk/values.xml",
+  "res/values-km/values.xml",
+  "res/values-kn/values.xml",
+  "res/values-ko/values.xml",
+  "res/values-ky/values.xml",
+  "res/values-lo/values.xml",
+  "res/values-lt/values.xml",
+  "res/values-lv/values.xml",
+  "res/values-mk/values.xml",
+  "res/values-ml/values.xml",
+  "res/values-mn/values.xml",
+  "res/values-mr/values.xml",
+  "res/values-ms/values.xml",
+  "res/values-my/values.xml",
+  "res/values-nb/values.xml",
+  "res/values-ne/values.xml",
+  "res/values-nl/values.xml",
+  "res/values-or/values.xml",
+  "res/values-pa/values.xml",
+  "res/values-pl/values.xml",
+  "res/values-pt-rBR/values.xml",
+  "res/values-pt-rPT/values.xml",
+  "res/values-ro/values.xml",
+  "res/values-ru/values.xml",
+  "res/values-si/values.xml",
+  "res/values-sk/values.xml",
+  "res/values-sl/values.xml",
+  "res/values-sq/values.xml",
+  "res/values-sr/values.xml",
+  "res/values-sv/values.xml",
+  "res/values-sw/values.xml",
+  "res/values-ta/values.xml",
+  "res/values-te/values.xml",
+  "res/values-th/values.xml",
+  "res/values-tl/values.xml",
+  "res/values-tr/values.xml",
+  "res/values-uk/values.xml",
+  "res/values-ur/values.xml",
+  "res/values-uz/values.xml",
+  "res/values-vi/values.xml",
+  "res/values-zh-rCN/values.xml",
+  "res/values-zh-rHK/values.xml",
+  "res/values-zh-rTW/values.xml",
+  "res/values-zu/values.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_cast/com_google_android_gms_play_services_cast.info b/third_party/android_deps/libs/com_google_android_gms_play_services_cast/com_google_android_gms_play_services_cast.info
index cbbded39..03b6559 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_cast/com_google_android_gms_play_services_cast.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_cast/com_google_android_gms_play_services_cast.info
@@ -1,13 +1,112 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable-hdpi-v4/cast_ic_notification_0.png", "res/drawable-hdpi-v4/cast_ic_notification_1.png", "res/drawable-hdpi-v4/cast_ic_notification_2.png", "res/drawable-hdpi-v4/cast_ic_notification_on.png", "res/drawable-mdpi-v4/cast_ic_notification_0.png", "res/drawable-mdpi-v4/cast_ic_notification_1.png", "res/drawable-mdpi-v4/cast_ic_notification_2.png", "res/drawable-mdpi-v4/cast_ic_notification_on.png", "res/drawable-xhdpi-v4/cast_ic_notification_0.png", "res/drawable-xhdpi-v4/cast_ic_notification_1.png", "res/drawable-xhdpi-v4/cast_ic_notification_2.png", "res/drawable-xhdpi-v4/cast_ic_notification_on.png", "res/drawable-xxhdpi-v4/cast_ic_notification_0.png", "res/drawable-xxhdpi-v4/cast_ic_notification_1.png", "res/drawable-xxhdpi-v4/cast_ic_notification_2.png", "res/drawable-xxhdpi-v4/cast_ic_notification_on.png", "res/drawable/cast_ic_notification_connecting.xml", "res/values-af/values.xml", "res/values-am/values.xml", "res/values-ar/values.xml", "res/values-as/values.xml", "res/values-az/values.xml", "res/values-b+sr+Latn/values.xml", "res/values-be/values.xml", "res/values-bg/values.xml", "res/values-bn/values.xml", "res/values-bs/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rGB/values.xml", "res/values-es-rUS/values.xml", "res/values-es/values.xml", "res/values-et/values.xml", "res/values-eu/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr/values.xml", "res/values-gl/values.xml", "res/values-gu/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-hy/values.xml", "res/values-in/values.xml", "res/values-is/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ka/values.xml", "res/values-kk/values.xml", "res/values-km/values.xml", "res/values-kn/values.xml", "res/values-ko/values.xml", "res/values-ky/values.xml", "res/values-lo/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-mk/values.xml", "res/values-ml/values.xml", "res/values-mn/values.xml", "res/values-mr/values.xml", "res/values-ms/values.xml", "res/values-my/values.xml", "res/values-nb/values.xml", "res/values-ne/values.xml", "res/values-nl/values.xml", "res/values-or/values.xml", "res/values-pa/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-si/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sq/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-sw/values.xml", "res/values-ta/values.xml", "res/values-te/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-ur/values.xml", "res/values-uz/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rHK/values.xml", "res/values-zh-rTW/values.xml", "res/values-zu/values.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable-hdpi-v4/cast_ic_notification_0.png",
+  "res/drawable-hdpi-v4/cast_ic_notification_1.png",
+  "res/drawable-hdpi-v4/cast_ic_notification_2.png",
+  "res/drawable-hdpi-v4/cast_ic_notification_on.png",
+  "res/drawable-mdpi-v4/cast_ic_notification_0.png",
+  "res/drawable-mdpi-v4/cast_ic_notification_1.png",
+  "res/drawable-mdpi-v4/cast_ic_notification_2.png",
+  "res/drawable-mdpi-v4/cast_ic_notification_on.png",
+  "res/drawable-xhdpi-v4/cast_ic_notification_0.png",
+  "res/drawable-xhdpi-v4/cast_ic_notification_1.png",
+  "res/drawable-xhdpi-v4/cast_ic_notification_2.png",
+  "res/drawable-xhdpi-v4/cast_ic_notification_on.png",
+  "res/drawable-xxhdpi-v4/cast_ic_notification_0.png",
+  "res/drawable-xxhdpi-v4/cast_ic_notification_1.png",
+  "res/drawable-xxhdpi-v4/cast_ic_notification_2.png",
+  "res/drawable-xxhdpi-v4/cast_ic_notification_on.png",
+  "res/drawable/cast_ic_notification_connecting.xml",
+  "res/values-af/values.xml",
+  "res/values-am/values.xml",
+  "res/values-ar/values.xml",
+  "res/values-as/values.xml",
+  "res/values-az/values.xml",
+  "res/values-b+sr+Latn/values.xml",
+  "res/values-be/values.xml",
+  "res/values-bg/values.xml",
+  "res/values-bn/values.xml",
+  "res/values-bs/values.xml",
+  "res/values-ca/values.xml",
+  "res/values-cs/values.xml",
+  "res/values-da/values.xml",
+  "res/values-de/values.xml",
+  "res/values-el/values.xml",
+  "res/values-en-rGB/values.xml",
+  "res/values-es-rUS/values.xml",
+  "res/values-es/values.xml",
+  "res/values-et/values.xml",
+  "res/values-eu/values.xml",
+  "res/values-fa/values.xml",
+  "res/values-fi/values.xml",
+  "res/values-fr-rCA/values.xml",
+  "res/values-fr/values.xml",
+  "res/values-gl/values.xml",
+  "res/values-gu/values.xml",
+  "res/values-hi/values.xml",
+  "res/values-hr/values.xml",
+  "res/values-hu/values.xml",
+  "res/values-hy/values.xml",
+  "res/values-in/values.xml",
+  "res/values-is/values.xml",
+  "res/values-it/values.xml",
+  "res/values-iw/values.xml",
+  "res/values-ja/values.xml",
+  "res/values-ka/values.xml",
+  "res/values-kk/values.xml",
+  "res/values-km/values.xml",
+  "res/values-kn/values.xml",
+  "res/values-ko/values.xml",
+  "res/values-ky/values.xml",
+  "res/values-lo/values.xml",
+  "res/values-lt/values.xml",
+  "res/values-lv/values.xml",
+  "res/values-mk/values.xml",
+  "res/values-ml/values.xml",
+  "res/values-mn/values.xml",
+  "res/values-mr/values.xml",
+  "res/values-ms/values.xml",
+  "res/values-my/values.xml",
+  "res/values-nb/values.xml",
+  "res/values-ne/values.xml",
+  "res/values-nl/values.xml",
+  "res/values-or/values.xml",
+  "res/values-pa/values.xml",
+  "res/values-pl/values.xml",
+  "res/values-pt-rBR/values.xml",
+  "res/values-pt-rPT/values.xml",
+  "res/values-ro/values.xml",
+  "res/values-ru/values.xml",
+  "res/values-si/values.xml",
+  "res/values-sk/values.xml",
+  "res/values-sl/values.xml",
+  "res/values-sq/values.xml",
+  "res/values-sr/values.xml",
+  "res/values-sv/values.xml",
+  "res/values-sw/values.xml",
+  "res/values-ta/values.xml",
+  "res/values-te/values.xml",
+  "res/values-th/values.xml",
+  "res/values-tl/values.xml",
+  "res/values-tr/values.xml",
+  "res/values-uk/values.xml",
+  "res/values-ur/values.xml",
+  "res/values-uz/values.xml",
+  "res/values-vi/values.xml",
+  "res/values-zh-rCN/values.xml",
+  "res/values-zh-rHK/values.xml",
+  "res/values-zh-rTW/values.xml",
+  "res/values-zu/values.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/com_google_android_gms_play_services_cast_framework.info b/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/com_google_android_gms_play_services_cast_framework.info
index a0fd4a65..7c188152 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/com_google_android_gms_play_services_cast_framework.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_cast_framework/com_google_android_gms_play_services_cast_framework.info
@@ -1,13 +1,380 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = false
-resources = [ "res/drawable-hdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-hdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-hdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-hdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-hdpi-v4/cast_ic_stop_circle_filled_grey600.png", "res/drawable-hdpi-v4/cast_ic_stop_circle_filled_white.png", "res/drawable-hdpi-v4/quantum_ic_art_track_grey600_48.png", "res/drawable-hdpi-v4/quantum_ic_bigtop_updates_white_24.png", "res/drawable-hdpi-v4/quantum_ic_cast_connected_white_24.png", "res/drawable-hdpi-v4/quantum_ic_cast_white_36.png", "res/drawable-hdpi-v4/quantum_ic_clear_white_24.png", "res/drawable-hdpi-v4/quantum_ic_closed_caption_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_closed_caption_white_36.png", "res/drawable-hdpi-v4/quantum_ic_forward_10_white_24.png", "res/drawable-hdpi-v4/quantum_ic_forward_30_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_forward_30_white_24.png", "res/drawable-hdpi-v4/quantum_ic_forward_30_white_36.png", "res/drawable-hdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png", "res/drawable-hdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_pause_circle_filled_white_36.png", "res/drawable-hdpi-v4/quantum_ic_pause_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_pause_grey600_48.png", "res/drawable-hdpi-v4/quantum_ic_pause_white_24.png", "res/drawable-hdpi-v4/quantum_ic_play_arrow_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_play_arrow_grey600_48.png", "res/drawable-hdpi-v4/quantum_ic_play_arrow_white_24.png", "res/drawable-hdpi-v4/quantum_ic_play_circle_filled_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_play_circle_filled_white_36.png", "res/drawable-hdpi-v4/quantum_ic_refresh_white_24.png", "res/drawable-hdpi-v4/quantum_ic_replay_10_white_24.png", "res/drawable-hdpi-v4/quantum_ic_replay_30_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_replay_30_white_24.png", "res/drawable-hdpi-v4/quantum_ic_replay_30_white_36.png", "res/drawable-hdpi-v4/quantum_ic_replay_white_24.png", "res/drawable-hdpi-v4/quantum_ic_skip_next_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_skip_next_white_24.png", "res/drawable-hdpi-v4/quantum_ic_skip_next_white_36.png", "res/drawable-hdpi-v4/quantum_ic_skip_previous_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_skip_previous_white_24.png", "res/drawable-hdpi-v4/quantum_ic_skip_previous_white_36.png", "res/drawable-hdpi-v4/quantum_ic_stop_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_stop_grey600_48.png", "res/drawable-hdpi-v4/quantum_ic_stop_white_24.png", "res/drawable-hdpi-v4/quantum_ic_volume_off_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_volume_off_white_36.png", "res/drawable-hdpi-v4/quantum_ic_volume_up_grey600_36.png", "res/drawable-hdpi-v4/quantum_ic_volume_up_white_36.png", "res/drawable-mdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-mdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-mdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-mdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-mdpi-v4/cast_ic_stop_circle_filled_grey600.png", "res/drawable-mdpi-v4/cast_ic_stop_circle_filled_white.png", "res/drawable-mdpi-v4/quantum_ic_art_track_grey600_48.png", "res/drawable-mdpi-v4/quantum_ic_bigtop_updates_white_24.png", "res/drawable-mdpi-v4/quantum_ic_cast_connected_white_24.png", "res/drawable-mdpi-v4/quantum_ic_cast_white_36.png", "res/drawable-mdpi-v4/quantum_ic_clear_white_24.png", "res/drawable-mdpi-v4/quantum_ic_closed_caption_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_closed_caption_white_36.png", "res/drawable-mdpi-v4/quantum_ic_forward_10_white_24.png", "res/drawable-mdpi-v4/quantum_ic_forward_30_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_forward_30_white_24.png", "res/drawable-mdpi-v4/quantum_ic_forward_30_white_36.png", "res/drawable-mdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png", "res/drawable-mdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_pause_circle_filled_white_36.png", "res/drawable-mdpi-v4/quantum_ic_pause_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_pause_grey600_48.png", "res/drawable-mdpi-v4/quantum_ic_pause_white_24.png", "res/drawable-mdpi-v4/quantum_ic_play_arrow_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_play_arrow_grey600_48.png", "res/drawable-mdpi-v4/quantum_ic_play_arrow_white_24.png", "res/drawable-mdpi-v4/quantum_ic_play_circle_filled_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_play_circle_filled_white_36.png", "res/drawable-mdpi-v4/quantum_ic_refresh_white_24.png", "res/drawable-mdpi-v4/quantum_ic_replay_10_white_24.png", "res/drawable-mdpi-v4/quantum_ic_replay_30_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_replay_30_white_24.png", "res/drawable-mdpi-v4/quantum_ic_replay_30_white_36.png", "res/drawable-mdpi-v4/quantum_ic_replay_white_24.png", "res/drawable-mdpi-v4/quantum_ic_skip_next_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_skip_next_white_24.png", "res/drawable-mdpi-v4/quantum_ic_skip_next_white_36.png", "res/drawable-mdpi-v4/quantum_ic_skip_previous_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_skip_previous_white_24.png", "res/drawable-mdpi-v4/quantum_ic_skip_previous_white_36.png", "res/drawable-mdpi-v4/quantum_ic_stop_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_stop_grey600_48.png", "res/drawable-mdpi-v4/quantum_ic_stop_white_24.png", "res/drawable-mdpi-v4/quantum_ic_volume_off_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_volume_off_white_36.png", "res/drawable-mdpi-v4/quantum_ic_volume_up_grey600_36.png", "res/drawable-mdpi-v4/quantum_ic_volume_up_white_36.png", "res/drawable-nodpi-v4/cast_album_art_placeholder.png", "res/drawable-nodpi-v4/cast_album_art_placeholder_large.png", "res/drawable-xhdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xhdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xhdpi-v4/cast_ic_stop_circle_filled_grey600.png", "res/drawable-xhdpi-v4/cast_ic_stop_circle_filled_white.png", "res/drawable-xhdpi-v4/quantum_ic_art_track_grey600_48.png", "res/drawable-xhdpi-v4/quantum_ic_bigtop_updates_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_cast_connected_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_cast_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_clear_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_closed_caption_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_closed_caption_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_forward_10_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_forward_30_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_forward_30_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_forward_30_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_pause_circle_filled_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_pause_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_pause_grey600_48.png", "res/drawable-xhdpi-v4/quantum_ic_pause_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_play_arrow_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_play_arrow_grey600_48.png", "res/drawable-xhdpi-v4/quantum_ic_play_arrow_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_play_circle_filled_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_play_circle_filled_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_refresh_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_replay_10_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_replay_30_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_replay_30_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_replay_30_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_replay_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_skip_next_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_skip_next_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_skip_next_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_skip_previous_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_skip_previous_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_skip_previous_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_stop_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_stop_grey600_48.png", "res/drawable-xhdpi-v4/quantum_ic_stop_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_volume_off_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_volume_off_white_36.png", "res/drawable-xhdpi-v4/quantum_ic_volume_up_grey600_36.png", "res/drawable-xhdpi-v4/quantum_ic_volume_up_white_36.png", "res/drawable-xxhdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png", "res/drawable-xxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxhdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png", "res/drawable-xxhdpi-v4/cast_ic_stop_circle_filled_grey600.png", "res/drawable-xxhdpi-v4/cast_ic_stop_circle_filled_white.png", "res/drawable-xxhdpi-v4/quantum_ic_art_track_grey600_48.png", "res/drawable-xxhdpi-v4/quantum_ic_bigtop_updates_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_cast_connected_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_cast_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_clear_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_closed_caption_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_closed_caption_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_forward_10_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_forward_30_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_forward_30_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_forward_30_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_pause_circle_filled_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_pause_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_pause_grey600_48.png", "res/drawable-xxhdpi-v4/quantum_ic_pause_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_play_arrow_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_play_arrow_grey600_48.png", "res/drawable-xxhdpi-v4/quantum_ic_play_arrow_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_play_circle_filled_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_play_circle_filled_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_refresh_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_replay_10_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_replay_30_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_replay_30_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_replay_30_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_replay_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_skip_next_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_skip_next_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_skip_next_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_skip_previous_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_skip_previous_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_skip_previous_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_stop_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_stop_grey600_48.png", "res/drawable-xxhdpi-v4/quantum_ic_stop_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_volume_off_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_volume_off_white_36.png", "res/drawable-xxhdpi-v4/quantum_ic_volume_up_grey600_36.png", "res/drawable-xxhdpi-v4/quantum_ic_volume_up_white_36.png", "res/drawable-xxxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png", "res/drawable-xxxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png", "res/drawable-xxxhdpi-v4/cast_ic_stop_circle_filled_grey600.png", "res/drawable-xxxhdpi-v4/cast_ic_stop_circle_filled_white.png", "res/drawable-xxxhdpi-v4/quantum_ic_art_track_grey600_48.png", "res/drawable-xxxhdpi-v4/quantum_ic_bigtop_updates_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_cast_connected_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_cast_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_clear_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_closed_caption_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_closed_caption_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_forward_10_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_forward_30_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_forward_30_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_forward_30_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_pause_circle_filled_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_pause_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_pause_grey600_48.png", "res/drawable-xxxhdpi-v4/quantum_ic_pause_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_play_arrow_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_play_arrow_grey600_48.png", "res/drawable-xxxhdpi-v4/quantum_ic_play_arrow_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_play_circle_filled_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_play_circle_filled_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_refresh_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_replay_10_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_replay_30_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_replay_30_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_replay_30_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_replay_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_skip_next_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_skip_next_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_skip_next_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_skip_previous_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_skip_previous_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_skip_previous_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_stop_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_stop_grey600_48.png", "res/drawable-xxxhdpi-v4/quantum_ic_stop_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_volume_off_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_volume_off_white_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_volume_up_grey600_36.png", "res/drawable-xxxhdpi-v4/quantum_ic_volume_up_white_36.png", "res/drawable/cast_expanded_controller_actionbar_bg_gradient_light.xml", "res/drawable/cast_expanded_controller_bg_gradient_light.xml", "res/drawable/cast_expanded_controller_live_indicator_drawable.xml", "res/drawable/cast_expanded_controller_seekbar_thumb.xml", "res/drawable/cast_expanded_controller_seekbar_track.xml", "res/drawable/cast_ic_expanded_controller_closed_caption.xml", "res/drawable/cast_ic_expanded_controller_forward30.xml", "res/drawable/cast_ic_expanded_controller_mute.xml", "res/drawable/cast_ic_expanded_controller_pause.xml", "res/drawable/cast_ic_expanded_controller_play.xml", "res/drawable/cast_ic_expanded_controller_rewind30.xml", "res/drawable/cast_ic_expanded_controller_skip_next.xml", "res/drawable/cast_ic_expanded_controller_skip_previous.xml", "res/drawable/cast_ic_expanded_controller_stop.xml", "res/drawable/cast_ic_mini_controller_closed_caption.xml", "res/drawable/cast_ic_mini_controller_forward30.xml", "res/drawable/cast_ic_mini_controller_mute.xml", "res/drawable/cast_ic_mini_controller_pause.xml", "res/drawable/cast_ic_mini_controller_pause_large.xml", "res/drawable/cast_ic_mini_controller_play.xml", "res/drawable/cast_ic_mini_controller_play_large.xml", "res/drawable/cast_ic_mini_controller_rewind30.xml", "res/drawable/cast_ic_mini_controller_skip_next.xml", "res/drawable/cast_ic_mini_controller_skip_prev.xml", "res/drawable/cast_ic_mini_controller_stop.xml", "res/drawable/cast_ic_mini_controller_stop_large.xml", "res/drawable/cast_ic_notification_disconnect.xml", "res/drawable/cast_ic_notification_forward.xml", "res/drawable/cast_ic_notification_forward10.xml", "res/drawable/cast_ic_notification_forward30.xml", "res/drawable/cast_ic_notification_pause.xml", "res/drawable/cast_ic_notification_play.xml", "res/drawable/cast_ic_notification_rewind.xml", "res/drawable/cast_ic_notification_rewind10.xml", "res/drawable/cast_ic_notification_rewind30.xml", "res/drawable/cast_ic_notification_skip_next.xml", "res/drawable/cast_ic_notification_skip_prev.xml", "res/drawable/cast_ic_notification_small_icon.xml", "res/drawable/cast_ic_notification_stop_live_stream.xml", "res/drawable/cast_mini_controller_gradient_light.xml", "res/drawable/cast_mini_controller_progress_drawable.xml", "res/drawable/cast_skip_ad_label_border.xml", "res/drawable/cast_tooltip_background.xml", "res/layout/cast_expanded_controller_activity.xml", "res/layout/cast_help_text.xml", "res/layout/cast_intro_overlay.xml", "res/layout/cast_mini_controller.xml", "res/layout/cast_tracks_chooser_dialog_layout.xml", "res/layout/cast_tracks_chooser_dialog_row_layout.xml", "res/values-af/values.xml", "res/values-am/values.xml", "res/values-ar/values.xml", "res/values-as/values.xml", "res/values-az/values.xml", "res/values-b+sr+Latn/values.xml", "res/values-be/values.xml", "res/values-bg/values.xml", "res/values-bn/values.xml", "res/values-bs/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rGB/values.xml", "res/values-es-rUS/values.xml", "res/values-es/values.xml", "res/values-et/values.xml", "res/values-eu/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr/values.xml", "res/values-gl/values.xml", "res/values-gu/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-hy/values.xml", "res/values-in/values.xml", "res/values-is/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ka/values.xml", "res/values-kk/values.xml", "res/values-km/values.xml", "res/values-kn/values.xml", "res/values-ko/values.xml", "res/values-ky/values.xml", "res/values-land/values.xml", "res/values-lo/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-mk/values.xml", "res/values-ml/values.xml", "res/values-mn/values.xml", "res/values-mr/values.xml", "res/values-ms/values.xml", "res/values-my/values.xml", "res/values-nb/values.xml", "res/values-ne/values.xml", "res/values-nl/values.xml", "res/values-or/values.xml", "res/values-pa/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-si/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sq/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-sw/values.xml", "res/values-ta/values.xml", "res/values-te/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-ur/values.xml", "res/values-uz/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rHK/values.xml", "res/values-zh-rTW/values.xml", "res/values-zu/values.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable-hdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-hdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-hdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-hdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-hdpi-v4/cast_ic_stop_circle_filled_grey600.png",
+  "res/drawable-hdpi-v4/cast_ic_stop_circle_filled_white.png",
+  "res/drawable-hdpi-v4/quantum_ic_art_track_grey600_48.png",
+  "res/drawable-hdpi-v4/quantum_ic_bigtop_updates_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_cast_connected_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_cast_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_clear_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_closed_caption_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_closed_caption_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_forward_10_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_forward_30_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_forward_30_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_forward_30_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_pause_circle_filled_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_pause_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_pause_grey600_48.png",
+  "res/drawable-hdpi-v4/quantum_ic_pause_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_play_arrow_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_play_arrow_grey600_48.png",
+  "res/drawable-hdpi-v4/quantum_ic_play_arrow_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_play_circle_filled_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_play_circle_filled_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_refresh_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_replay_10_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_replay_30_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_replay_30_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_replay_30_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_replay_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_skip_next_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_skip_next_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_skip_next_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_skip_previous_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_skip_previous_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_skip_previous_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_stop_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_stop_grey600_48.png",
+  "res/drawable-hdpi-v4/quantum_ic_stop_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_volume_off_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_volume_off_white_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_volume_up_grey600_36.png",
+  "res/drawable-hdpi-v4/quantum_ic_volume_up_white_36.png",
+  "res/drawable-mdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-mdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-mdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-mdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-mdpi-v4/cast_ic_stop_circle_filled_grey600.png",
+  "res/drawable-mdpi-v4/cast_ic_stop_circle_filled_white.png",
+  "res/drawable-mdpi-v4/quantum_ic_art_track_grey600_48.png",
+  "res/drawable-mdpi-v4/quantum_ic_bigtop_updates_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_cast_connected_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_cast_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_clear_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_closed_caption_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_closed_caption_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_forward_10_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_forward_30_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_forward_30_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_forward_30_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_pause_circle_filled_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_pause_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_pause_grey600_48.png",
+  "res/drawable-mdpi-v4/quantum_ic_pause_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_play_arrow_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_play_arrow_grey600_48.png",
+  "res/drawable-mdpi-v4/quantum_ic_play_arrow_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_play_circle_filled_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_play_circle_filled_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_refresh_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_replay_10_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_replay_30_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_replay_30_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_replay_30_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_replay_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_skip_next_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_skip_next_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_skip_next_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_skip_previous_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_skip_previous_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_skip_previous_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_stop_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_stop_grey600_48.png",
+  "res/drawable-mdpi-v4/quantum_ic_stop_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_volume_off_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_volume_off_white_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_volume_up_grey600_36.png",
+  "res/drawable-mdpi-v4/quantum_ic_volume_up_white_36.png",
+  "res/drawable-nodpi-v4/cast_album_art_placeholder.png",
+  "res/drawable-nodpi-v4/cast_album_art_placeholder_large.png",
+  "res/drawable-xhdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-xhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xhdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-xhdpi-v4/cast_ic_stop_circle_filled_grey600.png",
+  "res/drawable-xhdpi-v4/cast_ic_stop_circle_filled_white.png",
+  "res/drawable-xhdpi-v4/quantum_ic_art_track_grey600_48.png",
+  "res/drawable-xhdpi-v4/quantum_ic_bigtop_updates_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_cast_connected_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_cast_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_clear_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_closed_caption_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_closed_caption_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_forward_10_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_forward_30_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_forward_30_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_forward_30_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_pause_circle_filled_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_pause_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_pause_grey600_48.png",
+  "res/drawable-xhdpi-v4/quantum_ic_pause_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_play_arrow_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_play_arrow_grey600_48.png",
+  "res/drawable-xhdpi-v4/quantum_ic_play_arrow_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_play_circle_filled_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_play_circle_filled_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_refresh_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_replay_10_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_replay_30_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_replay_30_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_replay_30_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_replay_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_skip_next_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_skip_next_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_skip_next_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_skip_previous_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_skip_previous_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_skip_previous_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_stop_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_stop_grey600_48.png",
+  "res/drawable-xhdpi-v4/quantum_ic_stop_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_volume_off_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_volume_off_white_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_volume_up_grey600_36.png",
+  "res/drawable-xhdpi-v4/quantum_ic_volume_up_white_36.png",
+  "res/drawable-xxhdpi-v4/cast_abc_scrubber_control_off_mtrl_alpha.png",
+  "res/drawable-xxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xxhdpi-v4/cast_abc_scrubber_primary_mtrl_alpha.9.png",
+  "res/drawable-xxhdpi-v4/cast_ic_stop_circle_filled_grey600.png",
+  "res/drawable-xxhdpi-v4/cast_ic_stop_circle_filled_white.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_art_track_grey600_48.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_bigtop_updates_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_cast_connected_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_cast_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_clear_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_closed_caption_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_closed_caption_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_forward_10_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_forward_30_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_forward_30_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_forward_30_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_pause_circle_filled_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_pause_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_pause_grey600_48.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_pause_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_play_arrow_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_play_arrow_grey600_48.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_play_arrow_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_play_circle_filled_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_play_circle_filled_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_refresh_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_replay_10_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_replay_30_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_replay_30_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_replay_30_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_replay_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_skip_next_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_skip_next_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_skip_next_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_skip_previous_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_skip_previous_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_skip_previous_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_stop_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_stop_grey600_48.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_stop_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_volume_off_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_volume_off_white_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_volume_up_grey600_36.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_volume_up_white_36.png",
+  "res/drawable-xxxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_000.png",
+  "res/drawable-xxxhdpi-v4/cast_abc_scrubber_control_to_pressed_mtrl_005.png",
+  "res/drawable-xxxhdpi-v4/cast_ic_stop_circle_filled_grey600.png",
+  "res/drawable-xxxhdpi-v4/cast_ic_stop_circle_filled_white.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_art_track_grey600_48.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_bigtop_updates_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_cast_connected_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_cast_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_clear_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_closed_caption_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_closed_caption_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_forward_10_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_forward_30_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_forward_30_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_forward_30_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_keyboard_arrow_down_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_pause_circle_filled_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_pause_circle_filled_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_pause_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_pause_grey600_48.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_pause_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_play_arrow_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_play_arrow_grey600_48.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_play_arrow_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_play_circle_filled_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_play_circle_filled_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_refresh_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_replay_10_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_replay_30_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_replay_30_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_replay_30_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_replay_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_skip_next_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_skip_next_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_skip_next_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_skip_previous_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_skip_previous_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_skip_previous_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_stop_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_stop_grey600_48.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_stop_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_volume_off_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_volume_off_white_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_volume_up_grey600_36.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_volume_up_white_36.png",
+  "res/drawable/cast_expanded_controller_actionbar_bg_gradient_light.xml",
+  "res/drawable/cast_expanded_controller_bg_gradient_light.xml",
+  "res/drawable/cast_expanded_controller_live_indicator_drawable.xml",
+  "res/drawable/cast_expanded_controller_seekbar_thumb.xml",
+  "res/drawable/cast_expanded_controller_seekbar_track.xml",
+  "res/drawable/cast_ic_expanded_controller_closed_caption.xml",
+  "res/drawable/cast_ic_expanded_controller_forward30.xml",
+  "res/drawable/cast_ic_expanded_controller_mute.xml",
+  "res/drawable/cast_ic_expanded_controller_pause.xml",
+  "res/drawable/cast_ic_expanded_controller_play.xml",
+  "res/drawable/cast_ic_expanded_controller_rewind30.xml",
+  "res/drawable/cast_ic_expanded_controller_skip_next.xml",
+  "res/drawable/cast_ic_expanded_controller_skip_previous.xml",
+  "res/drawable/cast_ic_expanded_controller_stop.xml",
+  "res/drawable/cast_ic_mini_controller_closed_caption.xml",
+  "res/drawable/cast_ic_mini_controller_forward30.xml",
+  "res/drawable/cast_ic_mini_controller_mute.xml",
+  "res/drawable/cast_ic_mini_controller_pause.xml",
+  "res/drawable/cast_ic_mini_controller_pause_large.xml",
+  "res/drawable/cast_ic_mini_controller_play.xml",
+  "res/drawable/cast_ic_mini_controller_play_large.xml",
+  "res/drawable/cast_ic_mini_controller_rewind30.xml",
+  "res/drawable/cast_ic_mini_controller_skip_next.xml",
+  "res/drawable/cast_ic_mini_controller_skip_prev.xml",
+  "res/drawable/cast_ic_mini_controller_stop.xml",
+  "res/drawable/cast_ic_mini_controller_stop_large.xml",
+  "res/drawable/cast_ic_notification_disconnect.xml",
+  "res/drawable/cast_ic_notification_forward.xml",
+  "res/drawable/cast_ic_notification_forward10.xml",
+  "res/drawable/cast_ic_notification_forward30.xml",
+  "res/drawable/cast_ic_notification_pause.xml",
+  "res/drawable/cast_ic_notification_play.xml",
+  "res/drawable/cast_ic_notification_rewind.xml",
+  "res/drawable/cast_ic_notification_rewind10.xml",
+  "res/drawable/cast_ic_notification_rewind30.xml",
+  "res/drawable/cast_ic_notification_skip_next.xml",
+  "res/drawable/cast_ic_notification_skip_prev.xml",
+  "res/drawable/cast_ic_notification_small_icon.xml",
+  "res/drawable/cast_ic_notification_stop_live_stream.xml",
+  "res/drawable/cast_mini_controller_gradient_light.xml",
+  "res/drawable/cast_mini_controller_progress_drawable.xml",
+  "res/drawable/cast_skip_ad_label_border.xml",
+  "res/drawable/cast_tooltip_background.xml",
+  "res/layout/cast_expanded_controller_activity.xml",
+  "res/layout/cast_help_text.xml",
+  "res/layout/cast_intro_overlay.xml",
+  "res/layout/cast_mini_controller.xml",
+  "res/layout/cast_tracks_chooser_dialog_layout.xml",
+  "res/layout/cast_tracks_chooser_dialog_row_layout.xml",
+  "res/values-af/values.xml",
+  "res/values-am/values.xml",
+  "res/values-ar/values.xml",
+  "res/values-as/values.xml",
+  "res/values-az/values.xml",
+  "res/values-b+sr+Latn/values.xml",
+  "res/values-be/values.xml",
+  "res/values-bg/values.xml",
+  "res/values-bn/values.xml",
+  "res/values-bs/values.xml",
+  "res/values-ca/values.xml",
+  "res/values-cs/values.xml",
+  "res/values-da/values.xml",
+  "res/values-de/values.xml",
+  "res/values-el/values.xml",
+  "res/values-en-rGB/values.xml",
+  "res/values-es-rUS/values.xml",
+  "res/values-es/values.xml",
+  "res/values-et/values.xml",
+  "res/values-eu/values.xml",
+  "res/values-fa/values.xml",
+  "res/values-fi/values.xml",
+  "res/values-fr-rCA/values.xml",
+  "res/values-fr/values.xml",
+  "res/values-gl/values.xml",
+  "res/values-gu/values.xml",
+  "res/values-hi/values.xml",
+  "res/values-hr/values.xml",
+  "res/values-hu/values.xml",
+  "res/values-hy/values.xml",
+  "res/values-in/values.xml",
+  "res/values-is/values.xml",
+  "res/values-it/values.xml",
+  "res/values-iw/values.xml",
+  "res/values-ja/values.xml",
+  "res/values-ka/values.xml",
+  "res/values-kk/values.xml",
+  "res/values-km/values.xml",
+  "res/values-kn/values.xml",
+  "res/values-ko/values.xml",
+  "res/values-ky/values.xml",
+  "res/values-land/values.xml",
+  "res/values-lo/values.xml",
+  "res/values-lt/values.xml",
+  "res/values-lv/values.xml",
+  "res/values-mk/values.xml",
+  "res/values-ml/values.xml",
+  "res/values-mn/values.xml",
+  "res/values-mr/values.xml",
+  "res/values-ms/values.xml",
+  "res/values-my/values.xml",
+  "res/values-nb/values.xml",
+  "res/values-ne/values.xml",
+  "res/values-nl/values.xml",
+  "res/values-or/values.xml",
+  "res/values-pa/values.xml",
+  "res/values-pl/values.xml",
+  "res/values-pt-rBR/values.xml",
+  "res/values-pt-rPT/values.xml",
+  "res/values-ro/values.xml",
+  "res/values-ru/values.xml",
+  "res/values-si/values.xml",
+  "res/values-sk/values.xml",
+  "res/values-sl/values.xml",
+  "res/values-sq/values.xml",
+  "res/values-sr/values.xml",
+  "res/values-sv/values.xml",
+  "res/values-sw/values.xml",
+  "res/values-ta/values.xml",
+  "res/values-te/values.xml",
+  "res/values-th/values.xml",
+  "res/values-tl/values.xml",
+  "res/values-tr/values.xml",
+  "res/values-uk/values.xml",
+  "res/values-ur/values.xml",
+  "res/values-uz/values.xml",
+  "res/values-vi/values.xml",
+  "res/values-zh-rCN/values.xml",
+  "res/values-zh-rHK/values.xml",
+  "res/values-zh-rTW/values.xml",
+  "res/values-zu/values.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/com_google_android_gms_play_services_clearcut.info b/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/com_google_android_gms_play_services_clearcut.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/com_google_android_gms_play_services_clearcut.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_clearcut/com_google_android_gms_play_services_clearcut.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_fido/com_google_android_gms_play_services_fido.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_flags/com_google_android_gms_play_services_flags.info b/third_party/android_deps/libs/com_google_android_gms_play_services_flags/com_google_android_gms_play_services_flags.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_flags/com_google_android_gms_play_services_flags.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_flags/com_google_android_gms_play_services_flags.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/com_google_android_gms_play_services_gcm.info b/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/com_google_android_gms_play_services_gcm.info
index e053dfc..067efb7 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/com_google_android_gms_play_services_gcm.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_gcm/com_google_android_gms_play_services_gcm.info
@@ -1,13 +1,95 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = false
-resources = [ "res/values-af/values.xml", "res/values-am/values.xml", "res/values-ar/values.xml", "res/values-as/values.xml", "res/values-az/values.xml", "res/values-b+sr+Latn/values.xml", "res/values-be/values.xml", "res/values-bg/values.xml", "res/values-bn/values.xml", "res/values-bs/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rGB/values.xml", "res/values-es-rUS/values.xml", "res/values-es/values.xml", "res/values-et/values.xml", "res/values-eu/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr/values.xml", "res/values-gl/values.xml", "res/values-gu/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-hy/values.xml", "res/values-in/values.xml", "res/values-is/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ka/values.xml", "res/values-kk/values.xml", "res/values-km/values.xml", "res/values-kn/values.xml", "res/values-ko/values.xml", "res/values-ky/values.xml", "res/values-lo/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-mk/values.xml", "res/values-ml/values.xml", "res/values-mn/values.xml", "res/values-mr/values.xml", "res/values-ms/values.xml", "res/values-my/values.xml", "res/values-nb/values.xml", "res/values-ne/values.xml", "res/values-nl/values.xml", "res/values-or/values.xml", "res/values-pa/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-si/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sq/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-sw/values.xml", "res/values-ta/values.xml", "res/values-te/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-ur/values.xml", "res/values-uz/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rHK/values.xml", "res/values-zh-rTW/values.xml", "res/values-zu/values.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values-af/values.xml",
+  "res/values-am/values.xml",
+  "res/values-ar/values.xml",
+  "res/values-as/values.xml",
+  "res/values-az/values.xml",
+  "res/values-b+sr+Latn/values.xml",
+  "res/values-be/values.xml",
+  "res/values-bg/values.xml",
+  "res/values-bn/values.xml",
+  "res/values-bs/values.xml",
+  "res/values-ca/values.xml",
+  "res/values-cs/values.xml",
+  "res/values-da/values.xml",
+  "res/values-de/values.xml",
+  "res/values-el/values.xml",
+  "res/values-en-rGB/values.xml",
+  "res/values-es-rUS/values.xml",
+  "res/values-es/values.xml",
+  "res/values-et/values.xml",
+  "res/values-eu/values.xml",
+  "res/values-fa/values.xml",
+  "res/values-fi/values.xml",
+  "res/values-fr-rCA/values.xml",
+  "res/values-fr/values.xml",
+  "res/values-gl/values.xml",
+  "res/values-gu/values.xml",
+  "res/values-hi/values.xml",
+  "res/values-hr/values.xml",
+  "res/values-hu/values.xml",
+  "res/values-hy/values.xml",
+  "res/values-in/values.xml",
+  "res/values-is/values.xml",
+  "res/values-it/values.xml",
+  "res/values-iw/values.xml",
+  "res/values-ja/values.xml",
+  "res/values-ka/values.xml",
+  "res/values-kk/values.xml",
+  "res/values-km/values.xml",
+  "res/values-kn/values.xml",
+  "res/values-ko/values.xml",
+  "res/values-ky/values.xml",
+  "res/values-lo/values.xml",
+  "res/values-lt/values.xml",
+  "res/values-lv/values.xml",
+  "res/values-mk/values.xml",
+  "res/values-ml/values.xml",
+  "res/values-mn/values.xml",
+  "res/values-mr/values.xml",
+  "res/values-ms/values.xml",
+  "res/values-my/values.xml",
+  "res/values-nb/values.xml",
+  "res/values-ne/values.xml",
+  "res/values-nl/values.xml",
+  "res/values-or/values.xml",
+  "res/values-pa/values.xml",
+  "res/values-pl/values.xml",
+  "res/values-pt-rBR/values.xml",
+  "res/values-pt-rPT/values.xml",
+  "res/values-ro/values.xml",
+  "res/values-ru/values.xml",
+  "res/values-si/values.xml",
+  "res/values-sk/values.xml",
+  "res/values-sl/values.xml",
+  "res/values-sq/values.xml",
+  "res/values-sr/values.xml",
+  "res/values-sv/values.xml",
+  "res/values-sw/values.xml",
+  "res/values-ta/values.xml",
+  "res/values-te/values.xml",
+  "res/values-th/values.xml",
+  "res/values-tl/values.xml",
+  "res/values-tr/values.xml",
+  "res/values-uk/values.xml",
+  "res/values-ur/values.xml",
+  "res/values-uz/values.xml",
+  "res/values-vi/values.xml",
+  "res/values-zh-rCN/values.xml",
+  "res/values-zh-rHK/values.xml",
+  "res/values-zh-rTW/values.xml",
+  "res/values-zu/values.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_iid/com_google_android_gms_play_services_iid.info b/third_party/android_deps/libs/com_google_android_gms_play_services_iid/com_google_android_gms_play_services_iid.info
index 2307336..be3ad57 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_iid/com_google_android_gms_play_services_iid.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_iid/com_google_android_gms_play_services_iid.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = false
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/com_google_android_gms_play_services_instantapps.info b/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/com_google_android_gms_play_services_instantapps.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/com_google_android_gms_play_services_instantapps.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_instantapps/com_google_android_gms_play_services_instantapps.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_location/com_google_android_gms_play_services_location.info b/third_party/android_deps/libs/com_google_android_gms_play_services_location/com_google_android_gms_play_services_location.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_location/com_google_android_gms_play_services_location.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_location/com_google_android_gms_play_services_location.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/com_google_android_gms_play_services_phenotype.info b/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/com_google_android_gms_play_services_phenotype.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/com_google_android_gms_play_services_phenotype.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_phenotype/com_google_android_gms_play_services_phenotype.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/com_google_android_gms_play_services_places_placereport.info b/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/com_google_android_gms_play_services_places_placereport.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/com_google_android_gms_play_services_places_placereport.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_places_placereport/com_google_android_gms_play_services_places_placereport.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_stats/com_google_android_gms_play_services_stats.info b/third_party/android_deps/libs/com_google_android_gms_play_services_stats/com_google_android_gms_play_services_stats.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_stats/com_google_android_gms_play_services_stats.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_stats/com_google_android_gms_play_services_stats.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/com_google_android_gms_play_services_tasks.info b/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/com_google_android_gms_play_services_tasks.info
index a2ebd4a..da8df19 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/com_google_android_gms_play_services_tasks.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_tasks/com_google_android_gms_play_services_tasks.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_vision/com_google_android_gms_play_services_vision.info b/third_party/android_deps/libs/com_google_android_gms_play_services_vision/com_google_android_gms_play_services_vision.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_vision/com_google_android_gms_play_services_vision.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_vision/com_google_android_gms_play_services_vision.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/com_google_android_gms_play_services_vision_common.info b/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/com_google_android_gms_play_services_vision_common.info
index 0dfcb237..cf6e997b 100644
--- a/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/com_google_android_gms_play_services_vision_common.info
+++ b/third_party/android_deps/libs/com_google_android_gms_play_services_vision_common/com_google_android_gms_play_services_vision_common.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_deps/libs/com_google_android_material_material/com_google_android_material_material.info b/third_party/android_deps/libs/com_google_android_material_material/com_google_android_material_material.info
index 5de81fc4..8865b96 100644
--- a/third_party/android_deps/libs/com_google_android_material_material/com_google_android_material_material.info
+++ b/third_party/android_deps/libs/com_google_android_material_material/com_google_android_material_material.info
@@ -1,13 +1,221 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/anim/design_bottom_sheet_slide_in.xml", "res/anim/design_bottom_sheet_slide_out.xml", "res/anim/design_snackbar_in.xml", "res/anim/design_snackbar_out.xml", "res/anim/mtrl_bottom_sheet_slide_in.xml", "res/anim/mtrl_bottom_sheet_slide_out.xml", "res/anim/mtrl_card_lowers_interpolator.xml", "res/anim-v21/design_bottom_sheet_slide_in.xml", "res/anim-v21/design_bottom_sheet_slide_out.xml", "res/anim-v21/mtrl_bottom_sheet_slide_in.xml", "res/anim-v21/mtrl_bottom_sheet_slide_out.xml", "res/animator/design_fab_hide_motion_spec.xml", "res/animator/design_fab_show_motion_spec.xml", "res/animator/mtrl_btn_state_list_anim.xml", "res/animator/mtrl_btn_unelevated_state_list_anim.xml", "res/animator/mtrl_card_state_list_anim.xml", "res/animator/mtrl_chip_state_list_anim.xml", "res/animator/mtrl_extended_fab_change_size_motion_spec.xml", "res/animator/mtrl_extended_fab_hide_motion_spec.xml", "res/animator/mtrl_extended_fab_show_motion_spec.xml", "res/animator/mtrl_extended_fab_state_list_animator.xml", "res/animator/mtrl_fab_hide_motion_spec.xml", "res/animator/mtrl_fab_show_motion_spec.xml", "res/animator/mtrl_fab_transformation_sheet_collapse_spec.xml", "res/animator/mtrl_fab_transformation_sheet_expand_spec.xml", "res/animator-v21/design_appbar_state_list_animator.xml", "res/color/checkbox_themeable_attribute_color.xml", "res/color/design_box_stroke_color.xml", "res/color/design_error.xml", "res/color/design_icon_tint.xml", "res/color/material_on_background_disabled.xml", "res/color/material_on_background_emphasis_high_type.xml", "res/color/material_on_background_emphasis_medium.xml", "res/color/material_on_primary_disabled.xml", "res/color/material_on_primary_emphasis_high_type.xml", "res/color/material_on_primary_emphasis_medium.xml", "res/color/material_on_surface_disabled.xml", "res/color/material_on_surface_emphasis_high_type.xml", "res/color/material_on_surface_emphasis_medium.xml", "res/color/material_slider_active_tick_marks_color.xml", "res/color/material_slider_active_track_color.xml", "res/color/material_slider_halo_color.xml", "res/color/material_slider_inactive_tick_marks_color.xml", "res/color/material_slider_inactive_track_color.xml", "res/color/material_slider_thumb_color.xml", "res/color/mtrl_bottom_nav_colored_item_tint.xml", "res/color/mtrl_bottom_nav_colored_ripple_color.xml", "res/color/mtrl_bottom_nav_item_tint.xml", "res/color/mtrl_bottom_nav_ripple_color.xml", "res/color/mtrl_btn_bg_color_selector.xml", "res/color/mtrl_btn_ripple_color.xml", "res/color/mtrl_btn_stroke_color_selector.xml", "res/color/mtrl_btn_text_btn_bg_color_selector.xml", "res/color/mtrl_btn_text_btn_ripple_color.xml", "res/color/mtrl_btn_text_color_selector.xml", "res/color/mtrl_calendar_item_stroke_color.xml", "res/color/mtrl_calendar_selected_range.xml", "res/color/mtrl_card_view_foreground.xml", "res/color/mtrl_card_view_ripple.xml", "res/color/mtrl_chip_background_color.xml", "res/color/mtrl_chip_close_icon_tint.xml", "res/color/mtrl_chip_ripple_color.xml", "res/color/mtrl_chip_surface_color.xml", "res/color/mtrl_chip_text_color.xml", "res/color/mtrl_choice_chip_background_color.xml", "res/color/mtrl_choice_chip_ripple_color.xml", "res/color/mtrl_choice_chip_text_color.xml", "res/color/mtrl_error.xml", "res/color/mtrl_fab_bg_color_selector.xml", "res/color/mtrl_fab_icon_text_color_selector.xml", "res/color/mtrl_fab_ripple_color.xml", "res/color/mtrl_filled_background_color.xml", "res/color/mtrl_filled_icon_tint.xml", "res/color/mtrl_filled_stroke_color.xml", "res/color/mtrl_indicator_text_color.xml", "res/color/mtrl_navigation_item_background_color.xml", "res/color/mtrl_navigation_item_icon_tint.xml", "res/color/mtrl_navigation_item_text_color.xml", "res/color/mtrl_on_primary_text_btn_text_color_selector.xml", "res/color/mtrl_outlined_icon_tint.xml", "res/color/mtrl_outlined_stroke_color.xml", "res/color/mtrl_popupmenu_overlay_color.xml", "res/color/mtrl_tabs_colored_ripple_color.xml", "res/color/mtrl_tabs_icon_color_selector.xml", "res/color/mtrl_tabs_icon_color_selector_colored.xml", "res/color/mtrl_tabs_legacy_text_color_selector.xml", "res/color/mtrl_tabs_ripple_color.xml", "res/color/mtrl_text_btn_text_color_selector.xml", "res/color/test_mtrl_calendar_day.xml", "res/color/test_mtrl_calendar_day_selected.xml", "res/drawable/avd_hide_password.xml", "res/drawable/avd_show_password.xml", "res/drawable/design_bottom_navigation_item_background.xml", "res/drawable/design_fab_background.xml", "res/drawable/design_ic_visibility.xml", "res/drawable/design_ic_visibility_off.xml", "res/drawable/design_password_eye.xml", "res/drawable/design_snackbar_background.xml", "res/drawable/ic_mtrl_checked_circle.xml", "res/drawable/ic_mtrl_chip_checked_black.xml", "res/drawable/ic_mtrl_chip_checked_circle.xml", "res/drawable/ic_mtrl_chip_close_circle.xml", "res/drawable/material_ic_calendar_black_24dp.xml", "res/drawable/material_ic_clear_black_24dp.xml", "res/drawable/material_ic_edit_black_24dp.xml", "res/drawable/material_ic_keyboard_arrow_left_black_24dp.xml", "res/drawable/material_ic_keyboard_arrow_right_black_24dp.xml", "res/drawable/material_ic_menu_arrow_down_black_24dp.xml", "res/drawable/material_ic_menu_arrow_up_black_24dp.xml", "res/drawable/mtrl_dialog_background.xml", "res/drawable/mtrl_dropdown_arrow.xml", "res/drawable/mtrl_ic_arrow_drop_down.xml", "res/drawable/mtrl_ic_arrow_drop_up.xml", "res/drawable/mtrl_ic_cancel.xml", "res/drawable/mtrl_ic_error.xml", "res/drawable/mtrl_popupmenu_background.xml", "res/drawable/mtrl_popupmenu_background_dark.xml", "res/drawable/mtrl_tabs_default_indicator.xml", "res/drawable/navigation_empty_icon.xml", "res/drawable/test_custom_background.xml", "res/drawable-v21/design_bottom_navigation_item_background.xml", "res/drawable-v23/mtrl_popupmenu_background_dark.xml", "res/interpolator/mtrl_fast_out_linear_in.xml", "res/interpolator/mtrl_fast_out_slow_in.xml", "res/interpolator/mtrl_linear.xml", "res/interpolator/mtrl_linear_out_slow_in.xml", "res/interpolator-v21/mtrl_fast_out_linear_in.xml", "res/interpolator-v21/mtrl_fast_out_slow_in.xml", "res/interpolator-v21/mtrl_linear_out_slow_in.xml", "res/layout/design_bottom_navigation_item.xml", "res/layout/design_bottom_sheet_dialog.xml", "res/layout/design_layout_snackbar.xml", "res/layout/design_layout_snackbar_include.xml", "res/layout/design_layout_tab_icon.xml", "res/layout/design_layout_tab_text.xml", "res/layout/design_menu_item_action_area.xml", "res/layout/design_navigation_item.xml", "res/layout/design_navigation_item_header.xml", "res/layout/design_navigation_item_separator.xml", "res/layout/design_navigation_item_subheader.xml", "res/layout/design_navigation_menu.xml", "res/layout/design_navigation_menu_item.xml", "res/layout/design_text_input_end_icon.xml", "res/layout/design_text_input_start_icon.xml", "res/layout/mtrl_alert_dialog.xml", "res/layout/mtrl_alert_dialog_actions.xml", "res/layout/mtrl_alert_dialog_title.xml", "res/layout/mtrl_alert_select_dialog_item.xml", "res/layout/mtrl_alert_select_dialog_multichoice.xml", "res/layout/mtrl_alert_select_dialog_singlechoice.xml", "res/layout/mtrl_calendar_day.xml", "res/layout/mtrl_calendar_day_of_week.xml", "res/layout/mtrl_calendar_days_of_week.xml", "res/layout/mtrl_calendar_horizontal.xml", "res/layout/mtrl_calendar_month.xml", "res/layout/mtrl_calendar_month_labeled.xml", "res/layout/mtrl_calendar_month_navigation.xml", "res/layout/mtrl_calendar_months.xml", "res/layout/mtrl_calendar_vertical.xml", "res/layout/mtrl_calendar_year.xml", "res/layout/mtrl_layout_snackbar.xml", "res/layout/mtrl_layout_snackbar_include.xml", "res/layout/mtrl_picker_actions.xml", "res/layout/mtrl_picker_dialog.xml", "res/layout/mtrl_picker_fullscreen.xml", "res/layout/mtrl_picker_header_dialog.xml", "res/layout/mtrl_picker_header_fullscreen.xml", "res/layout/mtrl_picker_header_selection_text.xml", "res/layout/mtrl_picker_header_title_text.xml", "res/layout/mtrl_picker_header_toggle.xml", "res/layout/mtrl_picker_text_input_date.xml", "res/layout/mtrl_picker_text_input_date_range.xml", "res/layout/test_action_chip.xml", "res/layout/test_chip_zero_corner_radius.xml", "res/layout/test_design_checkbox.xml", "res/layout/test_reflow_chipgroup.xml", "res/layout/test_toolbar.xml", "res/layout/test_toolbar_custom_background.xml", "res/layout/test_toolbar_elevation.xml", "res/layout/test_toolbar_surface.xml", "res/layout/text_view_with_line_height_from_appearance.xml", "res/layout/text_view_with_line_height_from_layout.xml", "res/layout/text_view_with_line_height_from_style.xml", "res/layout/text_view_with_theme_line_height.xml", "res/layout/text_view_without_line_height.xml", "res/layout-land/mtrl_picker_header_dialog.xml", "res/layout-sw600dp-v13/design_layout_snackbar.xml", "res/layout-sw600dp-v13/mtrl_layout_snackbar.xml", "res/layout-v26/mtrl_calendar_month.xml", "res/values/values.xml", "res/values-h360dp-land-v13/values-h360dp-land-v13.xml", "res/values-h480dp-land-v13/values-h480dp-land-v13.xml", "res/values-land/values-land.xml", "res/values-large-v4/values-large-v4.xml", "res/values-night-v8/values-night-v8.xml", "res/values-small-v4/values-small-v4.xml", "res/values-sw600dp-v13/values-sw600dp-v13.xml", "res/values-v21/values-v21.xml", "res/values-v23/values-v23.xml", "res/values-v28/values-v28.xml", "res/values-w360dp-port-v13/values-w360dp-port-v13.xml", "res/values-w480dp-port-v13/values-w480dp-port-v13.xml", "res/xml/standalone_badge.xml", "res/xml/standalone_badge_gravity_bottom_end.xml", "res/xml/standalone_badge_gravity_bottom_start.xml", "res/xml/standalone_badge_gravity_top_start.xml", "res/xml/standalone_badge_offset.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/anim/design_bottom_sheet_slide_in.xml",
+  "res/anim/design_bottom_sheet_slide_out.xml",
+  "res/anim/design_snackbar_in.xml",
+  "res/anim/design_snackbar_out.xml",
+  "res/anim/mtrl_bottom_sheet_slide_in.xml",
+  "res/anim/mtrl_bottom_sheet_slide_out.xml",
+  "res/anim/mtrl_card_lowers_interpolator.xml",
+  "res/anim-v21/design_bottom_sheet_slide_in.xml",
+  "res/anim-v21/design_bottom_sheet_slide_out.xml",
+  "res/anim-v21/mtrl_bottom_sheet_slide_in.xml",
+  "res/anim-v21/mtrl_bottom_sheet_slide_out.xml",
+  "res/animator/design_fab_hide_motion_spec.xml",
+  "res/animator/design_fab_show_motion_spec.xml",
+  "res/animator/mtrl_btn_state_list_anim.xml",
+  "res/animator/mtrl_btn_unelevated_state_list_anim.xml",
+  "res/animator/mtrl_card_state_list_anim.xml",
+  "res/animator/mtrl_chip_state_list_anim.xml",
+  "res/animator/mtrl_extended_fab_change_size_motion_spec.xml",
+  "res/animator/mtrl_extended_fab_hide_motion_spec.xml",
+  "res/animator/mtrl_extended_fab_show_motion_spec.xml",
+  "res/animator/mtrl_extended_fab_state_list_animator.xml",
+  "res/animator/mtrl_fab_hide_motion_spec.xml",
+  "res/animator/mtrl_fab_show_motion_spec.xml",
+  "res/animator/mtrl_fab_transformation_sheet_collapse_spec.xml",
+  "res/animator/mtrl_fab_transformation_sheet_expand_spec.xml",
+  "res/animator-v21/design_appbar_state_list_animator.xml",
+  "res/color/checkbox_themeable_attribute_color.xml",
+  "res/color/design_box_stroke_color.xml",
+  "res/color/design_error.xml",
+  "res/color/design_icon_tint.xml",
+  "res/color/material_on_background_disabled.xml",
+  "res/color/material_on_background_emphasis_high_type.xml",
+  "res/color/material_on_background_emphasis_medium.xml",
+  "res/color/material_on_primary_disabled.xml",
+  "res/color/material_on_primary_emphasis_high_type.xml",
+  "res/color/material_on_primary_emphasis_medium.xml",
+  "res/color/material_on_surface_disabled.xml",
+  "res/color/material_on_surface_emphasis_high_type.xml",
+  "res/color/material_on_surface_emphasis_medium.xml",
+  "res/color/material_slider_active_tick_marks_color.xml",
+  "res/color/material_slider_active_track_color.xml",
+  "res/color/material_slider_halo_color.xml",
+  "res/color/material_slider_inactive_tick_marks_color.xml",
+  "res/color/material_slider_inactive_track_color.xml",
+  "res/color/material_slider_thumb_color.xml",
+  "res/color/mtrl_bottom_nav_colored_item_tint.xml",
+  "res/color/mtrl_bottom_nav_colored_ripple_color.xml",
+  "res/color/mtrl_bottom_nav_item_tint.xml",
+  "res/color/mtrl_bottom_nav_ripple_color.xml",
+  "res/color/mtrl_btn_bg_color_selector.xml",
+  "res/color/mtrl_btn_ripple_color.xml",
+  "res/color/mtrl_btn_stroke_color_selector.xml",
+  "res/color/mtrl_btn_text_btn_bg_color_selector.xml",
+  "res/color/mtrl_btn_text_btn_ripple_color.xml",
+  "res/color/mtrl_btn_text_color_selector.xml",
+  "res/color/mtrl_calendar_item_stroke_color.xml",
+  "res/color/mtrl_calendar_selected_range.xml",
+  "res/color/mtrl_card_view_foreground.xml",
+  "res/color/mtrl_card_view_ripple.xml",
+  "res/color/mtrl_chip_background_color.xml",
+  "res/color/mtrl_chip_close_icon_tint.xml",
+  "res/color/mtrl_chip_ripple_color.xml",
+  "res/color/mtrl_chip_surface_color.xml",
+  "res/color/mtrl_chip_text_color.xml",
+  "res/color/mtrl_choice_chip_background_color.xml",
+  "res/color/mtrl_choice_chip_ripple_color.xml",
+  "res/color/mtrl_choice_chip_text_color.xml",
+  "res/color/mtrl_error.xml",
+  "res/color/mtrl_fab_bg_color_selector.xml",
+  "res/color/mtrl_fab_icon_text_color_selector.xml",
+  "res/color/mtrl_fab_ripple_color.xml",
+  "res/color/mtrl_filled_background_color.xml",
+  "res/color/mtrl_filled_icon_tint.xml",
+  "res/color/mtrl_filled_stroke_color.xml",
+  "res/color/mtrl_indicator_text_color.xml",
+  "res/color/mtrl_navigation_item_background_color.xml",
+  "res/color/mtrl_navigation_item_icon_tint.xml",
+  "res/color/mtrl_navigation_item_text_color.xml",
+  "res/color/mtrl_on_primary_text_btn_text_color_selector.xml",
+  "res/color/mtrl_outlined_icon_tint.xml",
+  "res/color/mtrl_outlined_stroke_color.xml",
+  "res/color/mtrl_popupmenu_overlay_color.xml",
+  "res/color/mtrl_tabs_colored_ripple_color.xml",
+  "res/color/mtrl_tabs_icon_color_selector.xml",
+  "res/color/mtrl_tabs_icon_color_selector_colored.xml",
+  "res/color/mtrl_tabs_legacy_text_color_selector.xml",
+  "res/color/mtrl_tabs_ripple_color.xml",
+  "res/color/mtrl_text_btn_text_color_selector.xml",
+  "res/color/test_mtrl_calendar_day.xml",
+  "res/color/test_mtrl_calendar_day_selected.xml",
+  "res/drawable/avd_hide_password.xml",
+  "res/drawable/avd_show_password.xml",
+  "res/drawable/design_bottom_navigation_item_background.xml",
+  "res/drawable/design_fab_background.xml",
+  "res/drawable/design_ic_visibility.xml",
+  "res/drawable/design_ic_visibility_off.xml",
+  "res/drawable/design_password_eye.xml",
+  "res/drawable/design_snackbar_background.xml",
+  "res/drawable/ic_mtrl_checked_circle.xml",
+  "res/drawable/ic_mtrl_chip_checked_black.xml",
+  "res/drawable/ic_mtrl_chip_checked_circle.xml",
+  "res/drawable/ic_mtrl_chip_close_circle.xml",
+  "res/drawable/material_ic_calendar_black_24dp.xml",
+  "res/drawable/material_ic_clear_black_24dp.xml",
+  "res/drawable/material_ic_edit_black_24dp.xml",
+  "res/drawable/material_ic_keyboard_arrow_left_black_24dp.xml",
+  "res/drawable/material_ic_keyboard_arrow_right_black_24dp.xml",
+  "res/drawable/material_ic_menu_arrow_down_black_24dp.xml",
+  "res/drawable/material_ic_menu_arrow_up_black_24dp.xml",
+  "res/drawable/mtrl_dialog_background.xml",
+  "res/drawable/mtrl_dropdown_arrow.xml",
+  "res/drawable/mtrl_ic_arrow_drop_down.xml",
+  "res/drawable/mtrl_ic_arrow_drop_up.xml",
+  "res/drawable/mtrl_ic_cancel.xml",
+  "res/drawable/mtrl_ic_error.xml",
+  "res/drawable/mtrl_popupmenu_background.xml",
+  "res/drawable/mtrl_popupmenu_background_dark.xml",
+  "res/drawable/mtrl_tabs_default_indicator.xml",
+  "res/drawable/navigation_empty_icon.xml",
+  "res/drawable/test_custom_background.xml",
+  "res/drawable-v21/design_bottom_navigation_item_background.xml",
+  "res/drawable-v23/mtrl_popupmenu_background_dark.xml",
+  "res/interpolator/mtrl_fast_out_linear_in.xml",
+  "res/interpolator/mtrl_fast_out_slow_in.xml",
+  "res/interpolator/mtrl_linear.xml",
+  "res/interpolator/mtrl_linear_out_slow_in.xml",
+  "res/interpolator-v21/mtrl_fast_out_linear_in.xml",
+  "res/interpolator-v21/mtrl_fast_out_slow_in.xml",
+  "res/interpolator-v21/mtrl_linear_out_slow_in.xml",
+  "res/layout/design_bottom_navigation_item.xml",
+  "res/layout/design_bottom_sheet_dialog.xml",
+  "res/layout/design_layout_snackbar.xml",
+  "res/layout/design_layout_snackbar_include.xml",
+  "res/layout/design_layout_tab_icon.xml",
+  "res/layout/design_layout_tab_text.xml",
+  "res/layout/design_menu_item_action_area.xml",
+  "res/layout/design_navigation_item.xml",
+  "res/layout/design_navigation_item_header.xml",
+  "res/layout/design_navigation_item_separator.xml",
+  "res/layout/design_navigation_item_subheader.xml",
+  "res/layout/design_navigation_menu.xml",
+  "res/layout/design_navigation_menu_item.xml",
+  "res/layout/design_text_input_end_icon.xml",
+  "res/layout/design_text_input_start_icon.xml",
+  "res/layout/mtrl_alert_dialog.xml",
+  "res/layout/mtrl_alert_dialog_actions.xml",
+  "res/layout/mtrl_alert_dialog_title.xml",
+  "res/layout/mtrl_alert_select_dialog_item.xml",
+  "res/layout/mtrl_alert_select_dialog_multichoice.xml",
+  "res/layout/mtrl_alert_select_dialog_singlechoice.xml",
+  "res/layout/mtrl_calendar_day.xml",
+  "res/layout/mtrl_calendar_day_of_week.xml",
+  "res/layout/mtrl_calendar_days_of_week.xml",
+  "res/layout/mtrl_calendar_horizontal.xml",
+  "res/layout/mtrl_calendar_month.xml",
+  "res/layout/mtrl_calendar_month_labeled.xml",
+  "res/layout/mtrl_calendar_month_navigation.xml",
+  "res/layout/mtrl_calendar_months.xml",
+  "res/layout/mtrl_calendar_vertical.xml",
+  "res/layout/mtrl_calendar_year.xml",
+  "res/layout/mtrl_layout_snackbar.xml",
+  "res/layout/mtrl_layout_snackbar_include.xml",
+  "res/layout/mtrl_picker_actions.xml",
+  "res/layout/mtrl_picker_dialog.xml",
+  "res/layout/mtrl_picker_fullscreen.xml",
+  "res/layout/mtrl_picker_header_dialog.xml",
+  "res/layout/mtrl_picker_header_fullscreen.xml",
+  "res/layout/mtrl_picker_header_selection_text.xml",
+  "res/layout/mtrl_picker_header_title_text.xml",
+  "res/layout/mtrl_picker_header_toggle.xml",
+  "res/layout/mtrl_picker_text_input_date.xml",
+  "res/layout/mtrl_picker_text_input_date_range.xml",
+  "res/layout/test_action_chip.xml",
+  "res/layout/test_chip_zero_corner_radius.xml",
+  "res/layout/test_design_checkbox.xml",
+  "res/layout/test_reflow_chipgroup.xml",
+  "res/layout/test_toolbar.xml",
+  "res/layout/test_toolbar_custom_background.xml",
+  "res/layout/test_toolbar_elevation.xml",
+  "res/layout/test_toolbar_surface.xml",
+  "res/layout/text_view_with_line_height_from_appearance.xml",
+  "res/layout/text_view_with_line_height_from_layout.xml",
+  "res/layout/text_view_with_line_height_from_style.xml",
+  "res/layout/text_view_with_theme_line_height.xml",
+  "res/layout/text_view_without_line_height.xml",
+  "res/layout-land/mtrl_picker_header_dialog.xml",
+  "res/layout-sw600dp-v13/design_layout_snackbar.xml",
+  "res/layout-sw600dp-v13/mtrl_layout_snackbar.xml",
+  "res/layout-v26/mtrl_calendar_month.xml",
+  "res/values/values.xml",
+  "res/values-h360dp-land-v13/values-h360dp-land-v13.xml",
+  "res/values-h480dp-land-v13/values-h480dp-land-v13.xml",
+  "res/values-land/values-land.xml",
+  "res/values-large-v4/values-large-v4.xml",
+  "res/values-night-v8/values-night-v8.xml",
+  "res/values-small-v4/values-small-v4.xml",
+  "res/values-sw600dp-v13/values-sw600dp-v13.xml",
+  "res/values-v21/values-v21.xml",
+  "res/values-v23/values-v23.xml",
+  "res/values-v28/values-v28.xml",
+  "res/values-w360dp-port-v13/values-w360dp-port-v13.xml",
+  "res/values-w480dp-port-v13/values-w480dp-port-v13.xml",
+  "res/xml/standalone_badge.xml",
+  "res/xml/standalone_badge_gravity_bottom_end.xml",
+  "res/xml/standalone_badge_gravity_bottom_start.xml",
+  "res/xml/standalone_badge_gravity_top_start.xml",
+  "res/xml/standalone_badge_offset.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/android_support_test_runner/rules_java.info b/third_party/android_support_test_runner/rules_java.info
index 28c8330..4a744e7 100644
--- a/third_party/android_support_test_runner/rules_java.info
+++ b/third_party/android_support_test_runner/rules_java.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/arcore-android-sdk-client/core-partner_chrome-1.10.0.info b/third_party/arcore-android-sdk-client/core-partner_chrome-1.10.0.info
index 781f29e2..3b68510 100644
--- a/third_party/arcore-android-sdk-client/core-partner_chrome-1.10.0.info
+++ b/third_party/arcore-android-sdk-client/core-partner_chrome-1.10.0.info
@@ -1,14 +1,141 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = true
 has_proguard_flags = true
 has_r_text_file = true
 is_manifest_empty = false
-native_libraries = [ "jni/arm64-v8a/libarcore_sdk_c.so", "jni/arm64-v8a/libarcore_sdk_jni.so", "jni/armeabi-v7a/libarcore_sdk_c.so", "jni/armeabi-v7a/libarcore_sdk_jni.so", "jni/x86/libarcore_sdk_c.so", "jni/x86/libarcore_sdk_jni.so", "jni/x86_64/libarcore_sdk_c.so", "jni/x86_64/libarcore_sdk_jni.so" ]
-resources = [ "res/layout/__arcore_education.xml", "res/raw/keep.xml", "res/values-af/values.xml", "res/values-am/values.xml", "res/values-ar-rEG/values.xml", "res/values-ar-rSA/values.xml", "res/values-az/values.xml", "res/values-b+es+419/values.xml", "res/values-b+sr+Latn/values.xml", "res/values-be/values.xml", "res/values-bg/values.xml", "res/values-bn/values.xml", "res/values-bs/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de-rAT/values.xml", "res/values-de-rCH/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rAU/values.xml", "res/values-en-rCA/values.xml", "res/values-en-rGB/values.xml", "res/values-en-rIE/values.xml", "res/values-en-rSG/values.xml", "res/values-en-rXC/values.xml", "res/values-en-rZA/values.xml", "res/values-es-rAR/values.xml", "res/values-es-rBO/values.xml", "res/values-es-rCL/values.xml", "res/values-es-rCO/values.xml", "res/values-es-rCR/values.xml", "res/values-es-rDO/values.xml", "res/values-es-rEC/values.xml", "res/values-es-rGT/values.xml", "res/values-es-rHN/values.xml", "res/values-es-rMX/values.xml", "res/values-es-rNI/values.xml", "res/values-es-rPA/values.xml", "res/values-es-rPE/values.xml", "res/values-es-rPR/values.xml", "res/values-es-rPY/values.xml", "res/values-es-rSV/values.xml", "res/values-es-rUS/values.xml", "res/values-es-rUY/values.xml", "res/values-es-rVE/values.xml", "res/values-es/values.xml", "res/values-et/values.xml", "res/values-eu/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fil/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr-rCH/values.xml", "res/values-fr/values.xml", "res/values-gl/values.xml", "res/values-gsw/values.xml", "res/values-gu/values.xml", "res/values-he/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-hy/values.xml", "res/values-id/values.xml", "res/values-in/values.xml", "res/values-is/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ka/values.xml", "res/values-kk/values.xml", "res/values-km/values.xml", "res/values-kn/values.xml", "res/values-ko/values.xml", "res/values-ky/values.xml", "res/values-lo/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-mk/values.xml", "res/values-ml/values.xml", "res/values-mn/values.xml", "res/values-mo/values.xml", "res/values-ms/values.xml", "res/values-my/values.xml", "res/values-nb/values.xml", "res/values-ne/values.xml", "res/values-nl/values.xml", "res/values-no/values.xml", "res/values-pa/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-pt/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-si/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sq/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-sw/values.xml", "res/values-ta/values.xml", "res/values-te/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-ur/values.xml", "res/values-uz/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rHK/values.xml", "res/values-zh-rTW/values.xml", "res/values-zh/values.xml", "res/values-zu/values.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+native_libraries = [
+  "jni/arm64-v8a/libarcore_sdk_c.so",
+  "jni/arm64-v8a/libarcore_sdk_jni.so",
+  "jni/armeabi-v7a/libarcore_sdk_c.so",
+  "jni/armeabi-v7a/libarcore_sdk_jni.so",
+  "jni/x86/libarcore_sdk_c.so",
+  "jni/x86/libarcore_sdk_jni.so",
+  "jni/x86_64/libarcore_sdk_c.so",
+  "jni/x86_64/libarcore_sdk_jni.so"
+]
+resources = [
+  "res/layout/__arcore_education.xml",
+  "res/raw/keep.xml",
+  "res/values-af/values.xml",
+  "res/values-am/values.xml",
+  "res/values-ar-rEG/values.xml",
+  "res/values-ar-rSA/values.xml",
+  "res/values-az/values.xml",
+  "res/values-b+es+419/values.xml",
+  "res/values-b+sr+Latn/values.xml",
+  "res/values-be/values.xml",
+  "res/values-bg/values.xml",
+  "res/values-bn/values.xml",
+  "res/values-bs/values.xml",
+  "res/values-ca/values.xml",
+  "res/values-cs/values.xml",
+  "res/values-da/values.xml",
+  "res/values-de-rAT/values.xml",
+  "res/values-de-rCH/values.xml",
+  "res/values-de/values.xml",
+  "res/values-el/values.xml",
+  "res/values-en-rAU/values.xml",
+  "res/values-en-rCA/values.xml",
+  "res/values-en-rGB/values.xml",
+  "res/values-en-rIE/values.xml",
+  "res/values-en-rSG/values.xml",
+  "res/values-en-rXC/values.xml",
+  "res/values-en-rZA/values.xml",
+  "res/values-es-rAR/values.xml",
+  "res/values-es-rBO/values.xml",
+  "res/values-es-rCL/values.xml",
+  "res/values-es-rCO/values.xml",
+  "res/values-es-rCR/values.xml",
+  "res/values-es-rDO/values.xml",
+  "res/values-es-rEC/values.xml",
+  "res/values-es-rGT/values.xml",
+  "res/values-es-rHN/values.xml",
+  "res/values-es-rMX/values.xml",
+  "res/values-es-rNI/values.xml",
+  "res/values-es-rPA/values.xml",
+  "res/values-es-rPE/values.xml",
+  "res/values-es-rPR/values.xml",
+  "res/values-es-rPY/values.xml",
+  "res/values-es-rSV/values.xml",
+  "res/values-es-rUS/values.xml",
+  "res/values-es-rUY/values.xml",
+  "res/values-es-rVE/values.xml",
+  "res/values-es/values.xml",
+  "res/values-et/values.xml",
+  "res/values-eu/values.xml",
+  "res/values-fa/values.xml",
+  "res/values-fi/values.xml",
+  "res/values-fil/values.xml",
+  "res/values-fr-rCA/values.xml",
+  "res/values-fr-rCH/values.xml",
+  "res/values-fr/values.xml",
+  "res/values-gl/values.xml",
+  "res/values-gsw/values.xml",
+  "res/values-gu/values.xml",
+  "res/values-he/values.xml",
+  "res/values-hi/values.xml",
+  "res/values-hr/values.xml",
+  "res/values-hu/values.xml",
+  "res/values-hy/values.xml",
+  "res/values-id/values.xml",
+  "res/values-in/values.xml",
+  "res/values-is/values.xml",
+  "res/values-it/values.xml",
+  "res/values-iw/values.xml",
+  "res/values-ja/values.xml",
+  "res/values-ka/values.xml",
+  "res/values-kk/values.xml",
+  "res/values-km/values.xml",
+  "res/values-kn/values.xml",
+  "res/values-ko/values.xml",
+  "res/values-ky/values.xml",
+  "res/values-lo/values.xml",
+  "res/values-lt/values.xml",
+  "res/values-lv/values.xml",
+  "res/values-mk/values.xml",
+  "res/values-ml/values.xml",
+  "res/values-mn/values.xml",
+  "res/values-mo/values.xml",
+  "res/values-ms/values.xml",
+  "res/values-my/values.xml",
+  "res/values-nb/values.xml",
+  "res/values-ne/values.xml",
+  "res/values-nl/values.xml",
+  "res/values-no/values.xml",
+  "res/values-pa/values.xml",
+  "res/values-pl/values.xml",
+  "res/values-pt-rBR/values.xml",
+  "res/values-pt-rPT/values.xml",
+  "res/values-pt/values.xml",
+  "res/values-ro/values.xml",
+  "res/values-ru/values.xml",
+  "res/values-si/values.xml",
+  "res/values-sk/values.xml",
+  "res/values-sl/values.xml",
+  "res/values-sq/values.xml",
+  "res/values-sr/values.xml",
+  "res/values-sv/values.xml",
+  "res/values-sw/values.xml",
+  "res/values-ta/values.xml",
+  "res/values-te/values.xml",
+  "res/values-th/values.xml",
+  "res/values-tl/values.xml",
+  "res/values-tr/values.xml",
+  "res/values-uk/values.xml",
+  "res/values-ur/values.xml",
+  "res/values-uz/values.xml",
+  "res/values-vi/values.xml",
+  "res/values-zh-rCN/values.xml",
+  "res/values-zh-rHK/values.xml",
+  "res/values-zh-rTW/values.xml",
+  "res/values-zh/values.xml",
+  "res/values-zu/values.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 94ebb5df..14369b8 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -121,6 +121,7 @@
     "service_worker/service_worker_status_code.cc",
     "service_worker/service_worker_type_converters.cc",
     "service_worker/service_worker_utils.cc",
+    "switches.cc",
     "thread_safe_browser_interface_broker_proxy.cc",
     "user_agent/user_agent_metadata.cc",
     "web_package/signed_exchange_consts.cc",
diff --git a/third_party/blink/common/feature_policy/document_policy.cc b/third_party/blink/common/feature_policy/document_policy.cc
index 400e3ba6..eae3df3e 100644
--- a/third_party/blink/common/feature_policy/document_policy.cc
+++ b/third_party/blink/common/feature_policy/document_policy.cc
@@ -153,19 +153,6 @@
   }
 }
 
-bool DocumentPolicy::IsFeatureSupported(
-    mojom::DocumentPolicyFeature feature) const {
-  // TODO(iclelland): Generate this switch block
-  switch (feature) {
-    case mojom::DocumentPolicyFeature::kFontDisplay:
-    case mojom::DocumentPolicyFeature::kUnoptimizedLosslessImages:
-    case mojom::DocumentPolicyFeature::kForceLoadAtTop:
-      return true;
-    default:
-      return false;
-  }
-}
-
 void DocumentPolicy::UpdateFeatureState(const FeatureState& feature_state) {
   for (const auto& feature_and_value : feature_state) {
     internal_feature_state_[static_cast<size_t>(feature_and_value.first)] =
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 21086a0..0fca4a6 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -550,6 +550,12 @@
 const base::FeatureParam<int> kInstallingServiceWorkerOutstandingThrottledLimit{
     &kThrottleInstallingServiceWorker, "limit", 5};
 
+const base::Feature kInputPredictorTypeChoice{
+    "InputPredictorTypeChoice", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kResamplingInputEvents{"ResamplingInputEvents",
+                                           base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kResamplingScrollEvents{"ResamplingScrollEvents",
                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
@@ -598,5 +604,10 @@
 const base::Feature kWebXrMultiGpu{"WebXRMultiGpu",
                                    base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Enables dependency support in blink::MatchedPropertiesCache, which allows
+// caching of previously uncachable objects.
+const base::Feature kCSSMatchedPropertiesCacheDependencies{
+    "CSSMatchedPropertiesCacheDependencies", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/common/switches.cc b/third_party/blink/common/switches.cc
new file mode 100644
index 0000000..fde00dd1
--- /dev/null
+++ b/third_party/blink/common/switches.cc
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/switches.h"
+
+namespace blink {
+namespace switches {
+
+// Allows processing of input before a frame has been committed.
+// TODO(schenney): crbug.com/987626. Used by headless. Look for a way not
+// involving a command line switch.
+const char kAllowPreCommitInput[] = "allow-pre-commit-input";
+
+}  // namespace switches
+}  // namespace blink
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index 95d18e6..03514e6 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -159,6 +159,7 @@
     "service_worker/service_worker_utils.h",
     "sms/sms_receiver_destroyed_reason.h",
     "sms/sms_receiver_outcome.h",
+    "switches.h",
     "user_agent/user_agent_metadata.h",
     "web_cache/web_cache_resource_type_stats.h",
     "web_package/signed_exchange_consts.h",
diff --git a/third_party/blink/public/common/feature_policy/document_policy.h b/third_party/blink/public/common/feature_policy/document_policy.h
index 8974fc79..fe85fbe 100644
--- a/third_party/blink/public/common/feature_policy/document_policy.h
+++ b/third_party/blink/public/common/feature_policy/document_policy.h
@@ -88,11 +88,6 @@
   bool IsFeatureEnabled(mojom::DocumentPolicyFeature feature,
                         const PolicyValue& threshold_value) const;
 
-  // Returns true if the feature is being migrated to document policy
-  // TODO(iclelland): remove this method when those features are fully
-  // migrated to document policy.
-  bool IsFeatureSupported(mojom::DocumentPolicyFeature feature) const;
-
   // Returns the value of the given feature on the given origin.
   PolicyValue GetFeatureValue(mojom::DocumentPolicyFeature feature) const;
 
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index e61a38e..32018fee 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -190,6 +190,16 @@
 BLINK_COMMON_EXPORT extern const base::FeatureParam<int>
     kInstallingServiceWorkerOutstandingThrottledLimit;
 
+// This flag is used to set field parameters to choose predictor we use when
+// kResamplingInputEvents is disabled. It's used for gatherig accuracy metrics
+// on finch and also for choosing predictor type for predictedEvents API without
+// enabling resampling. It does not have any effect when the resampling flag is
+// enabled.
+BLINK_COMMON_EXPORT extern const base::Feature kInputPredictorTypeChoice;
+
+// Enables resampling input events on main thread.
+BLINK_COMMON_EXPORT extern const base::Feature kResamplingInputEvents;
+
 // Enables resampling GestureScroll events on compositor thread.
 BLINK_COMMON_EXPORT extern const base::Feature kResamplingScrollEvents;
 
@@ -248,6 +258,8 @@
     kSkipTouchEventFilterFilteringProcessParamValueBrowserAndRenderer[];
 
 BLINK_COMMON_EXPORT extern const base::Feature kWebXrMultiGpu;
+BLINK_COMMON_EXPORT extern const base::Feature
+    kCSSMatchedPropertiesCacheDependencies;
 
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/public/common/switches.h b/third_party/blink/public/common/switches.h
new file mode 100644
index 0000000..a75bd04
--- /dev/null
+++ b/third_party/blink/public/common/switches.h
@@ -0,0 +1,22 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_SWITCHES_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SWITCHES_H_
+
+#include "third_party/blink/public/common/common_export.h"
+
+namespace blink {
+namespace switches {
+
+// base::Feature should be use instead of switches where possible.
+
+// All switches in alphabetical order. The switches should be documented
+// alongside the definition of their values in the .cc file.
+BLINK_COMMON_EXPORT extern const char kAllowPreCommitInput[];
+
+}  // namespace switches
+}  // namespace blink
+
+#endif  // CONTENT_PUBLIC_COMMON_CONTENT_SWITCHES_H_
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index e3fa78f..e5761e41 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -1025,6 +1025,11 @@
       # Whether this stylesheet is created for STYLE tag by parser. This flag is not set for
       # document.written STYLE tags.
       boolean isInline
+      # Whether this stylesheet is mutable. Inline stylesheets become mutable
+      # after they have been modified via CSSOM API.
+      # <link> element's stylesheets are never mutable. Constructed stylesheets
+      # (new CSSStyleSheet()) are mutable immediately after creation.
+      boolean isMutable
       # Line offset of the stylesheet within the resource (zero based).
       number startLine
       # Column offset of the stylesheet within the resource (zero based).
diff --git a/third_party/blink/public/mojom/app_banner/OWNERS b/third_party/blink/public/mojom/app_banner/OWNERS
index 393b01f..7b66ad53 100644
--- a/third_party/blink/public/mojom/app_banner/OWNERS
+++ b/third_party/blink/public/mojom/app_banner/OWNERS
@@ -1,4 +1,4 @@
-mlamouri@chromium.org
+file://third_party/blink/renderer/modules/app_banner/OWNERS
 
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index ba07b7f..0b2bad2 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -205,6 +205,10 @@
   // Sent by the renderer when the associated frame becomes focused.
   DidFocusFrame();
 
+  // Called to notify the browser process counterpart of this local frame that
+  // |window.focus()| on a page has been invoked in the renderer process.
+  DidCallFocus();
+
   // Notifies the browser process about a new Content Security Policy that needs
   // to be applies to the frame. This message is sent when a frame commits
   // navigation to a new location (reporting accumulated policies from HTTP
@@ -824,8 +828,8 @@
   ZoomToFindInPageRect(gfx.mojom.Rect rect_in_root_frame);
 };
 
-// Implemented in Browser, this interface defines main-frame-specific methods
-// that will be invoked from the renderer process (e.g. WebViewImpl).
+// Implemented in Browser, this interface defines local-main-frame-specific
+// methods that will be invoked from the renderer process (e.g. WebViewImpl).
 interface LocalMainFrameHost {
   // Indicates the scale of the view has changed.
   ScaleFactorChanged(float scale);
@@ -838,4 +842,14 @@
   // browser will share this information with other renderers that have frames
   // in the page.
   TextAutosizerPageInfoChanged(TextAutosizerPageInfo page_info);
+
+  // Asks the browser process to activate the page associated to the main frame.
+  FocusPage();
+};
+
+// Implemented in Browser, this interface defines remote-main-frame-specific
+// methods that will be invoked from the renderer process (e.g. WebViewImpl).
+interface RemoteMainFrameHost {
+  // Asks the browser process to activate the page associated to the main frame.
+  FocusPage();
 };
diff --git a/third_party/blink/public/mojom/input/input_handler.mojom b/third_party/blink/public/mojom/input/input_handler.mojom
index a4f64afa..8864e18d 100644
--- a/third_party/blink/public/mojom/input/input_handler.mojom
+++ b/third_party/blink/public/mojom/input/input_handler.mojom
@@ -239,8 +239,94 @@
           pending_remote<blink.mojom.PointerLockContext>? context);
 };
 
+// This interface provides the input actions associated with the FrameWidget.
+// Other input actions may also be dispatched via the WidgetInputHandler
+// interface. If frame input actions are dispatched the WidgetInputHandler
+// should be fetched via the associated interface request so that input calls
+// remain in order. See https://goo.gl/x4ee8A for more details.
+interface FrameWidgetInputHandler {
+  // Sets the text composition to be between the given start and end offsets in
+  // the currently focused editable field.
+  SetCompositionFromExistingText(
+      int32 start, int32 end, array<ui.mojom.ImeTextSpan> ime_text_spans);
+
+  // Deletes the current selection plus the specified number of characters
+  // before and after the selection or caret.
+  ExtendSelectionAndDelete(int32 before, int32 after);
+
+  // Deletes text before and after the current cursor position, excluding the
+  // selection. The lengths are supplied in Java chars (UTF-16 Code Unit),
+  // not in code points or in glyphs.
+  DeleteSurroundingText(int32 before, int32 after);
+
+  // Deletes text before and after the current cursor position, excluding the
+  // selection. The lengths are supplied in code points, not in Java chars
+  // (UTF-16 Code Unit) or in glyphs. Does nothing if there are one or more
+  // invalid surrogate pairs in the requested range
+  DeleteSurroundingTextInCodePoints(int32 before, int32 after);
+
+  // Selects between the given start and end offsets in the currently focused
+  // editable field.
+  SetEditableSelectionOffsets(int32 start, int32 end);
+
+  // Message payload is the name/value of a WebCore edit command to execute.
+  ExecuteEditCommand(string command, mojo_base.mojom.String16? value);
+
+  // These messages are typically generated from context menus and request the
+  // renderer to apply the specified operation to the current selection.
+  Undo();
+  Redo();
+  Cut();
+  Copy();
+  CopyToFindPboard();
+  Paste();
+  PasteAndMatchStyle();
+  Delete();
+  SelectAll();
+  CollapseSelection();
+
+  // Replaces the selected region or a word around the cursor with the
+  // specified string.
+  Replace(mojo_base.mojom.String16 word);
+
+  // Replaces the misspelling in the selected region with the specified string.
+  ReplaceMisspelling(mojo_base.mojom.String16 word);
+
+  // Requests the renderer to select the region between two points.
+  // Expects a SelectRange_ACK message when finished.
+  SelectRange(gfx.mojom.Point base, gfx.mojom.Point extent);
+
+  // Sent by the browser to ask the renderer to adjust the selection start and
+  // end points by the given amounts. A negative amount moves the selection
+  // towards the beginning of the document, a positive amount moves the
+  // selection towards the end of the document. Will send show selection menu
+  // event when needed.
+  AdjustSelectionByCharacterOffset(
+      int32 start, int32 end, SelectionMenuBehavior behavior);
+
+  // Requests the renderer to select word around caret.
+  // Expects ack with new selection information when finished. |start_adjust|
+  // and |end_adjust| are the start and end offset difference between the
+  // current selection and the previous selection (which is a caret).
+  [EnableIf=is_android]
+  SelectWordAroundCaret()
+      => (bool did_select, int32 start_adjust, int32 end_adjust);
+
+  // Requests the renderer to move the selection extent point to a new position.
+  // Expects a MoveRangeSelectionExtent_ACK message when finished.
+  MoveRangeSelectionExtent(gfx.mojom.Point extent);
+
+  // Tells the renderer to scroll the currently focused node into rect only if
+  // the currently focused node is a Text node (textfield, text area or content
+  // editable divs).
+  ScrollFocusedEditableNodeIntoRect(gfx.mojom.Rect rect);
+
+  // Requests the renderer to move the caret selection toward the point.
+  MoveCaret(gfx.mojom.Point point);
+};
+
 // Interface exposed by the renderer to the browser. This class represents
-// an input interface for an associated Widget object. See FrameInputHandler
+// an input interface for an associated Widget object. See FrameWidgetInputHandler
 // for an interface at the frame level.
 interface WidgetInputHandler {
   // Tells widget focus has been changed.
@@ -321,97 +407,11 @@
       pending_remote<SynchronousCompositorControlHost> control_host,
       pending_associated_remote<SynchronousCompositorHost> host,
       pending_associated_receiver<SynchronousCompositor> compositor_request);
-};
 
-// This interface provides the input actions associated with the RenderFrame.
-// Other input actions may also be dispatched via the WidgetInputHandler
-// interface. If frame input actions are dispatched the WidgetInputHandler
-// should be fetched via the associated interface request so that input calls
-// remain in order. See https://goo.gl/x4ee8A for more details.
-interface FrameInputHandler {
-  // Sets the text composition to be between the given start and end offsets in
-  // the currently focused editable field.
-  SetCompositionFromExistingText(
-      int32 start, int32 end, array<ui.mojom.ImeTextSpan> ime_text_spans);
-
-  // Deletes the current selection plus the specified number of characters
-  // before and after the selection or caret.
-  ExtendSelectionAndDelete(int32 before, int32 after);
-
-  // Deletes text before and after the current cursor position, excluding the
-  // selection. The lengths are supplied in Java chars (UTF-16 Code Unit),
-  // not in code points or in glyphs.
-  DeleteSurroundingText(int32 before, int32 after);
-
-  // Deletes text before and after the current cursor position, excluding the
-  // selection. The lengths are supplied in code points, not in Java chars
-  // (UTF-16 Code Unit) or in glyphs. Does nothing if there are one or more
-  // invalid surrogate pairs in the requested range
-  DeleteSurroundingTextInCodePoints(int32 before, int32 after);
-
-  // Selects between the given start and end offsets in the currently focused
-  // editable field.
-  SetEditableSelectionOffsets(int32 start, int32 end);
-
-  // Message payload is the name/value of a WebCore edit command to execute.
-  ExecuteEditCommand(string command, mojo_base.mojom.String16? value);
-
-  // These messages are typically generated from context menus and request the
-  // renderer to apply the specified operation to the current selection.
-  Undo();
-  Redo();
-  Cut();
-  Copy();
-  CopyToFindPboard();
-  Paste();
-  PasteAndMatchStyle();
-  Delete();
-  SelectAll();
-  CollapseSelection();
-
-  // Replaces the selected region or a word around the cursor with the
-  // specified string.
-  Replace(mojo_base.mojom.String16 word);
-
-  // Replaces the misspelling in the selected region with the specified string.
-  ReplaceMisspelling(mojo_base.mojom.String16 word);
-
-  // Requests the renderer to select the region between two points.
-  // Expects a SelectRange_ACK message when finished.
-  SelectRange(gfx.mojom.Point base, gfx.mojom.Point extent);
-
-  // Sent by the browser to ask the renderer to adjust the selection start and
-  // end points by the given amounts. A negative amount moves the selection
-  // towards the beginning of the document, a positive amount moves the
-  // selection towards the end of the document. Will send show selection menu
-  // event when needed.
-  AdjustSelectionByCharacterOffset(
-      int32 start, int32 end, SelectionMenuBehavior behavior);
-
-  // Requests the renderer to select word around caret.
-  // Expects ack with new selection information when finished. |start_adjust|
-  // and |end_adjust| are the start and end offset difference between the
-  // current selection and the previous selection (which is a caret).
-  [EnableIf=is_android]
-  SelectWordAroundCaret()
-      => (bool did_select, int32 start_adjust, int32 end_adjust);
-
-  // Requests the renderer to move the selection extent point to a new position.
-  // Expects a MoveRangeSelectionExtent_ACK message when finished.
-  MoveRangeSelectionExtent(gfx.mojom.Point extent);
-
-  // Tells the renderer to scroll the currently focused node into rect only if
-  // the currently focused node is a Text node (textfield, text area or content
-  // editable divs).
-  ScrollFocusedEditableNodeIntoRect(gfx.mojom.Rect rect);
-
-  // Requests the renderer to move the caret selection toward the point.
-  MoveCaret(gfx.mojom.Point point);
-
-  // Return an associated WidgetInputHandler interface so that input
-  // messages to the widget associated with this frame can be sent
+  // Return an associated FrameWidgetInputHandler interface so that input
+  // messages to the frame associated with this widget can be sent
   // serially.
-  GetWidgetInputHandler(
-      pending_associated_receiver<WidgetInputHandler> interface_request,
-      pending_remote<WidgetInputHandlerHost> host);
+  GetFrameWidgetInputHandler(
+      pending_associated_receiver<FrameWidgetInputHandler> interface_request);
 };
+
diff --git a/third_party/blink/public/mojom/page/widget.mojom b/third_party/blink/public/mojom/page/widget.mojom
index 29a90ee..382e279 100644
--- a/third_party/blink/public/mojom/page/widget.mojom
+++ b/third_party/blink/public/mojom/page/widget.mojom
@@ -8,6 +8,7 @@
 import "mojo/public/mojom/base/string16.mojom";
 import "mojo/public/mojom/base/text_direction.mojom";
 import "third_party/blink/public/mojom/frame/intrinsic_sizing_info.mojom";
+import "third_party/blink/public/mojom/input/input_handler.mojom";
 import "ui/base/cursor/mojom/cursor.mojom";
 import "ui/gfx/geometry/mojom/geometry.mojom";
 
@@ -39,6 +40,15 @@
 // Implemented in Blink, this interface defines frame-widget-specific methods that
 // will be invoked from the browser process (e.g. blink::WebFrameWidget).
 interface FrameWidget {
+  // Drag-and-drop methods:
+  // |point_in_viewport| is the position of the drag event in the viewport
+  // coordinates.
+  // |screen_point| is the absolute position of the mouse pointer.
+
+  // Notifies the Widget of a drag leave operation.
+  DragTargetDragLeave(gfx.mojom.PointF point_in_viewport,
+                      gfx.mojom.PointF screen_point);
+
   // Notifies the Widget that the system drag and drop operation has ended.
   DragSourceSystemDragEnded();
 
@@ -103,6 +113,10 @@
 
   // Sent by a widget to the browser to notify the end of the autoscroll.
   AutoscrollEnd();
+
+  // Sent once a paint happens after the first non empty layout. In other words,
+  // after the frame widget has painted something.
+  DidFirstVisuallyNonEmptyPaint();
 };
 
 // Implemented in Blink, this interface defines widget-specific methods that
@@ -112,6 +126,14 @@
   // can happen in renderer (abortion of the commit or draw, loss of output
   // surface etc.).
   ForceRedraw() => ();
+
+  // Setup the input channel for this widget. If the widget is a frame,
+  // then it can also obtain a FrameWidgetInputHandler from the
+  // WidgetInputHandler interface.
+  GetWidgetInputHandler(
+    pending_receiver<blink.mojom.WidgetInputHandler> request,
+    pending_remote<blink.mojom.WidgetInputHandlerHost> host);
+
 };
 
 // Implemented in Browser, this interface defines widget-specific methods that
diff --git a/third_party/blink/public/platform/web_string.h b/third_party/blink/public/platform/web_string.h
index ffd1da0..a74c413d 100644
--- a/third_party/blink/public/platform/web_string.h
+++ b/third_party/blink/public/platform/web_string.h
@@ -35,7 +35,6 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/optional.h"
 #include "base/strings/latin1_string_conversions.h"
-#include "base/strings/nullable_string16.h"
 #include "base/strings/string16.h"
 #include "third_party/blink/public/platform/web_common.h"
 
@@ -56,7 +55,6 @@
 // * WebString::FromLatin1(const std::string& latin1)
 // * WebString::FromUTF8(const std::string& utf8)
 // * WebString::FromUTF16(const base::string16& utf16)
-// * WebString::FromUTF16(const base::NullableString16& utf16)
 // * WebString::FromUTF16(const base::Optional<base::string16>& utf16)
 //
 // Similarly, use either of following methods to convert WebString to
@@ -66,7 +64,6 @@
 // * webstring.Latin1()
 // * webstring.Utf8()
 // * webstring.Utf16()
-// * WebString::ToNullableString16(webstring)
 // * WebString::ToOptionalString16(webstring)
 //
 // Note that if you need to convert the UTF8 string converted from WebString
@@ -135,14 +132,8 @@
 
   BLINK_PLATFORM_EXPORT static WebString FromUTF16(const base::string16&);
   BLINK_PLATFORM_EXPORT static WebString FromUTF16(
-      const base::NullableString16&);
-  BLINK_PLATFORM_EXPORT static WebString FromUTF16(
       const base::Optional<base::string16>&);
 
-  static base::NullableString16 ToNullableString16(const WebString& s) {
-    return base::NullableString16(ToOptionalString16(s));
-  }
-
   static base::Optional<base::string16> ToOptionalString16(const WebString& s) {
     return s.IsNull() ? base::nullopt : base::make_optional(s.Utf16());
   }
diff --git a/third_party/blink/public/platform/web_theme_engine.h b/third_party/blink/public/platform/web_theme_engine.h
index bccf63bf..721e50be 100644
--- a/third_party/blink/public/platform/web_theme_engine.h
+++ b/third_party/blink/public/platform/web_theme_engine.h
@@ -148,6 +148,7 @@
     int thumb_x;
     int thumb_y;
     float zoom;
+    bool right_to_left;
   };
 
   // Extra parameters for PartInnerSpinButton
diff --git a/third_party/blink/public/web/web_external_widget_client.h b/third_party/blink/public/web/web_external_widget_client.h
index fb77503..d691ef73 100644
--- a/third_party/blink/public/web/web_external_widget_client.h
+++ b/third_party/blink/public/web/web_external_widget_client.h
@@ -66,6 +66,13 @@
       const gfx::Vector2dF& unused_delta,
       const cc::OverscrollBehavior& overscroll_behavior,
       bool event_processed) {}
+
+  // Connect the Widget Input Handler to the channels provided.
+  virtual void GetWidgetInputHandler(
+      CrossVariantMojoReceiver<mojom::WidgetInputHandlerInterfaceBase>
+          widget_input_receiver,
+      CrossVariantMojoRemote<mojom::WidgetInputHandlerHostInterfaceBase>
+          widget_input_host_remote) {}
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/web/web_remote_frame_client.h b/third_party/blink/public/web/web_remote_frame_client.h
index 29f82cd..99f3495 100644
--- a/third_party/blink/public/web/web_remote_frame_client.h
+++ b/third_party/blink/public/web/web_remote_frame_client.h
@@ -7,6 +7,7 @@
 
 #include "base/optional.h"
 #include "cc/paint/paint_canvas.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
 #include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h"
@@ -49,6 +50,10 @@
   virtual void UpdateRemoteViewportIntersection(
       const ViewportIntersectionState& intersection_state) {}
 
+  // Returns an AssociatedInterfaceProvider the frame can use to request
+  // associated interfaces from the browser.
+  virtual AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() = 0;
+
   // Returns token to be used as a frame id in the devtools protocol.
   // It is derived from the content's devtools_frame_token, is
   // defined by the browser and passed into Blink upon frame creation.
diff --git a/third_party/blink/public/web/web_view.h b/third_party/blink/public/web/web_view.h
index 53faedc..baa1cec0 100644
--- a/third_party/blink/public/web/web_view.h
+++ b/third_party/blink/public/web/web_view.h
@@ -120,6 +120,16 @@
   // detached.
   virtual void DidAttachLocalMainFrame() = 0;
 
+  // Called while the main LocalFrame is being detached. The MainFrameImpl() is
+  // still valid until after this method is called.
+  virtual void DidDetachLocalMainFrame() = 0;
+
+  // Called to inform WebViewImpl that a remote main frame has been attached.
+  virtual void DidAttachRemoteMainFrame() = 0;
+
+  // Called to inform WebViewImpl that a remote main frame has been detached.
+  virtual void DidDetachRemoteMainFrame() = 0;
+
   // Initializes the various client interfaces.
   virtual void SetPrerendererClient(WebPrerendererClient*) = 0;
 
@@ -260,6 +270,9 @@
   // Indicates that view's preferred size changes will be sent to the browser.
   virtual void EnablePreferredSizeChangedMode() = 0;
 
+  // Asks the browser process to activate this web view.
+  virtual void Focus() = 0;
+
   // Sets the ratio as computed by computePageScaleConstraints.
   // TODO(oshima): Remove this once the device scale factor implementation is
   // fully migrated to use zooming mechanism.
diff --git a/third_party/blink/public/web/web_view_client.h b/third_party/blink/public/web/web_view_client.h
index e33c483a..c799a40 100644
--- a/third_party/blink/public/web/web_view_client.h
+++ b/third_party/blink/public/web/web_view_client.h
@@ -146,7 +146,7 @@
   virtual void DidAutoResize(const WebSize& new_size) {}
 
   // Called when the View acquires focus.
-  virtual void DidFocus(WebLocalFrame* calling_frame) {}
+  virtual void DidFocus() {}
 
   // Session history -----------------------------------------------------
 
diff --git a/third_party/blink/public/web/web_widget_client.h b/third_party/blink/public/web/web_widget_client.h
index 993e2b6..a797bdb 100644
--- a/third_party/blink/public/web/web_widget_client.h
+++ b/third_party/blink/public/web/web_widget_client.h
@@ -39,10 +39,12 @@
 #include "cc/trees/layer_tree_host.h"
 #include "components/viz/common/surfaces/frame_sink_id.h"
 #include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "third_party/blink/public/common/input/web_coalesced_input_event.h"
 #include "third_party/blink/public/common/input/web_gesture_event.h"
 #include "third_party/blink/public/common/page/web_drag_operation.h"
-#include "third_party/blink/public/mojom/input/input_handler.mojom-forward.h"
+#include "third_party/blink/public/mojom/input/input_handler.mojom-shared.h"
 #include "third_party/blink/public/mojom/input/pointer_lock_result.mojom-forward.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
 #include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_rect.h"
 #include "third_party/blink/public/platform/web_screen_info.h"
@@ -298,6 +300,13 @@
   // for when handling scrollbars.
   virtual void QueueSyntheticEvent(
       std::unique_ptr<blink::WebCoalescedInputEvent>) {}
+
+  // Connect the Widget Input Handler to the channels provided.
+  virtual void GetWidgetInputHandler(
+      CrossVariantMojoReceiver<mojom::WidgetInputHandlerInterfaceBase>
+          widget_input_receiver,
+      CrossVariantMojoRemote<mojom::WidgetInputHandlerHostInterfaceBase>
+          widget_input_host_remote) {}
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps b/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps
index 77100622a..c37de46 100644
--- a/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps
+++ b/third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps
@@ -1,11 +1,8 @@
 # Generated by running:
 #   build/print_python_deps.py --root third_party/blink/renderer/bindings/scripts --output third_party/blink/renderer/bindings/scripts/build_web_idl_database.pydeps third_party/blink/renderer/bindings/scripts/build_web_idl_database.py
 ../../../../pyjson5/src/json5/__init__.py
-../../../../pyjson5/src/json5/arg_parser.py
-../../../../pyjson5/src/json5/host.py
 ../../../../pyjson5/src/json5/lib.py
 ../../../../pyjson5/src/json5/parser.py
-../../../../pyjson5/src/json5/tool.py
 ../../../../pyjson5/src/json5/version.py
 ../../build/scripts/blinkbuild/__init__.py
 ../../build/scripts/blinkbuild/name_style_converter.py
diff --git a/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps b/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps
index 8546f9e..6e4c701 100644
--- a/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps
+++ b/third_party/blink/renderer/bindings/scripts/collect_idl_files.pydeps
@@ -8,11 +8,8 @@
 ../../../../ply/lex.py
 ../../../../ply/yacc.py
 ../../../../pyjson5/src/json5/__init__.py
-../../../../pyjson5/src/json5/arg_parser.py
-../../../../pyjson5/src/json5/host.py
 ../../../../pyjson5/src/json5/lib.py
 ../../../../pyjson5/src/json5/parser.py
-../../../../pyjson5/src/json5/tool.py
 ../../../../pyjson5/src/json5/version.py
 ../../build/scripts/blinkbuild/__init__.py
 ../../build/scripts/blinkbuild/name_style_converter.py
diff --git a/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps b/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
index 9c2c686..8f86db1 100644
--- a/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
+++ b/third_party/blink/renderer/bindings/scripts/generate_bindings.pydeps
@@ -20,11 +20,8 @@
 ../../../../markupsafe/_compat.py
 ../../../../markupsafe/_native.py
 ../../../../pyjson5/src/json5/__init__.py
-../../../../pyjson5/src/json5/arg_parser.py
-../../../../pyjson5/src/json5/host.py
 ../../../../pyjson5/src/json5/lib.py
 ../../../../pyjson5/src/json5/parser.py
-../../../../pyjson5/src/json5/tool.py
 ../../../../pyjson5/src/json5/version.py
 ../../build/scripts/blinkbuild/__init__.py
 ../../build/scripts/blinkbuild/name_style_converter.py
diff --git a/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps b/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps
index 1d9e7f3b..7e87841 100644
--- a/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps
+++ b/third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps
@@ -1,11 +1,8 @@
 # Generated by running:
 #   build/print_python_deps.py --root third_party/blink/renderer/bindings/scripts --output third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.pydeps third_party/blink/renderer/bindings/scripts/generate_high_entropy_list.py
 ../../../../pyjson5/src/json5/__init__.py
-../../../../pyjson5/src/json5/arg_parser.py
-../../../../pyjson5/src/json5/host.py
 ../../../../pyjson5/src/json5/lib.py
 ../../../../pyjson5/src/json5/parser.py
-../../../../pyjson5/src/json5/tool.py
 ../../../../pyjson5/src/json5/version.py
 ../../build/scripts/blinkbuild/__init__.py
 ../../build/scripts/blinkbuild/name_style_converter.py
diff --git a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
index a5d107d..f21aa67b 100644
--- a/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
+++ b/third_party/blink/renderer/core/animation/css_interpolation_types_map.cc
@@ -60,7 +60,7 @@
     const PropertyRegistry* registry,
     const Document& document)
     : registry_(registry) {
-  allow_all_animations_ = document.GetExecutionContext()->IsFeatureEnabled(
+  allow_all_animations_ = document.IsFeatureEnabled(
       blink::mojom::blink::DocumentPolicyFeature::kLayoutAnimations);
 }
 
diff --git a/third_party/blink/renderer/core/css/parser/css_proto_converter.cc b/third_party/blink/renderer/core/css/parser/css_proto_converter.cc
index 50fa9146..3068cc2f2 100644
--- a/third_party/blink/renderer/core/css/parser/css_proto_converter.cc
+++ b/third_party/blink/renderer/core/css/parser/css_proto_converter.cc
@@ -1517,6 +1517,7 @@
     "overscroll-behavior-block",
     "overscroll-behavior-x",
     "overscroll-behavior-y",
+    "animation-timeline",
     "INVALID_PROPERTY",
 };
 
diff --git a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
index 7b409db..fe4732c 100644
--- a/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
+++ b/third_party/blink/renderer/core/css/resolver/matched_properties_cache.cc
@@ -61,8 +61,9 @@
   this->computed_style = ComputedStyle::Clone(style);
   this->parent_computed_style = ComputedStyle::Clone(parent_style);
 
-  DCHECK(RuntimeEnabledFeatures::MPCDependenciesEnabled() ||
-         dependencies.IsEmpty());
+  DCHECK(
+      RuntimeEnabledFeatures::CSSMatchedPropertiesCacheDependenciesEnabled() ||
+      dependencies.IsEmpty());
   if (dependencies.size()) {
     DCHECK(dependencies.size() <= MatchedPropertiesCache::kMaxDependencies);
     // Plus one for g_null_atom.
@@ -219,7 +220,7 @@
     return false;
   if (style.TextAutosizingMultiplier() != 1)
     return false;
-  if (!RuntimeEnabledFeatures::MPCDependenciesEnabled()) {
+  if (!RuntimeEnabledFeatures::CSSMatchedPropertiesCacheDependenciesEnabled()) {
     if (style.GetWritingMode() !=
             ComputedStyleInitialValues::InitialWritingMode() ||
         style.Direction() != ComputedStyleInitialValues::InitialDirection()) {
@@ -245,7 +246,7 @@
   if (!IsStyleCacheable(style))
     return false;
 
-  if (!RuntimeEnabledFeatures::MPCDependenciesEnabled()) {
+  if (!RuntimeEnabledFeatures::CSSMatchedPropertiesCacheDependenciesEnabled()) {
     // The cache assumes static knowledge about which properties are inherited.
     // Without a flat tree parent, StyleBuilder::ApplyProperty will not
     // SetChildHasExplicitInheritance on the parent style.
diff --git a/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc b/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
index 047d869..52609df 100644
--- a/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/matched_properties_cache_test.cc
@@ -82,10 +82,12 @@
 
 using TestCache = MatchedPropertiesCacheTestCache;
 
-class MatchedPropertiesCacheTest : public PageTestBase,
-                                   private ScopedMPCDependenciesForTest {
+class MatchedPropertiesCacheTest
+    : public PageTestBase,
+      private ScopedCSSMatchedPropertiesCacheDependenciesForTest {
  public:
-  MatchedPropertiesCacheTest() : ScopedMPCDependenciesForTest(true) {}
+  MatchedPropertiesCacheTest()
+      : ScopedCSSMatchedPropertiesCacheDependenciesForTest(true) {}
 
   scoped_refptr<ComputedStyle> CreateStyle() {
     return StyleResolver::InitialStyleForElement(GetDocument());
@@ -455,7 +457,7 @@
 
 TEST_F(MatchedPropertiesCacheTest,
        ExplicitlyInheritedNotCacheableWithoutFeature) {
-  ScopedMPCDependenciesForTest scoped_feature(false);
+  ScopedCSSMatchedPropertiesCacheDependenciesForTest scoped_feature(false);
 
   TestCache cache(GetDocument());
 
@@ -472,7 +474,7 @@
 
 TEST_F(MatchedPropertiesCacheTest,
        VarInNonInheritedPropertyNotCachableWithoutFeature) {
-  ScopedMPCDependenciesForTest scoped_feature(false);
+  ScopedCSSMatchedPropertiesCacheDependenciesForTest scoped_feature(false);
 
   TestCache cache(GetDocument());
 
@@ -489,7 +491,7 @@
 }
 
 TEST_F(MatchedPropertiesCacheTest, WritingModeNotCacheableWithoutFeature) {
-  ScopedMPCDependenciesForTest scoped_feature(false);
+  ScopedCSSMatchedPropertiesCacheDependenciesForTest scoped_feature(false);
 
   ASSERT_NE(WritingMode::kVerticalRl,
             ComputedStyleInitialValues::InitialWritingMode());
@@ -508,7 +510,7 @@
 }
 
 TEST_F(MatchedPropertiesCacheTest, DirectionNotCacheableWithoutFeature) {
-  ScopedMPCDependenciesForTest scoped_feature(false);
+  ScopedCSSMatchedPropertiesCacheDependenciesForTest scoped_feature(false);
 
   ASSERT_NE(TextDirection::kRtl,
             ComputedStyleInitialValues::InitialDirection());
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
index 61cdbe4..03c46ca 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade_test.cc
@@ -269,15 +269,16 @@
   CascadeResolver::AutoLock lock_;
 };
 
-class StyleCascadeTest : public PageTestBase,
-                         private ScopedCSSCascadeForTest,
-                         private ScopedCSSRevertForTest,
-                         private ScopedMPCDependenciesForTest {
+class StyleCascadeTest
+    : public PageTestBase,
+      private ScopedCSSCascadeForTest,
+      private ScopedCSSRevertForTest,
+      private ScopedCSSMatchedPropertiesCacheDependenciesForTest {
  public:
   StyleCascadeTest()
       : ScopedCSSCascadeForTest(true),
         ScopedCSSRevertForTest(true),
-        ScopedMPCDependenciesForTest(true) {}
+        ScopedCSSMatchedPropertiesCacheDependenciesForTest(true) {}
 
   CSSStyleSheet* CreateSheet(const String& css_text) {
     auto* init = MakeGarbageCollected<CSSStyleSheetInit>();
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
index f4cf7d7..37e9e56 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.cc
@@ -240,7 +240,7 @@
 }
 
 void StyleResolverState::MarkDependency(const CSSProperty& property) {
-  if (!RuntimeEnabledFeatures::MPCDependenciesEnabled())
+  if (!RuntimeEnabledFeatures::CSSMatchedPropertiesCacheDependenciesEnabled())
     return;
   has_incomparable_dependency_ |= !property.IsComputedValueComparable();
   dependencies_.insert(property.GetCSSPropertyName());
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_state_test.cc
index 2406789..97ae034 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_state_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state_test.cc
@@ -9,10 +9,12 @@
 
 namespace blink {
 
-class StyleResolverStateTest : public PageTestBase,
-                               private ScopedMPCDependenciesForTest {
+class StyleResolverStateTest
+    : public PageTestBase,
+      private ScopedCSSMatchedPropertiesCacheDependenciesForTest {
  public:
-  StyleResolverStateTest() : ScopedMPCDependenciesForTest(true) {}
+  StyleResolverStateTest()
+      : ScopedCSSMatchedPropertiesCacheDependenciesForTest(true) {}
 };
 
 TEST_F(StyleResolverStateTest, Dependencies) {
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
index 2f1d2b6..30aef02d 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -262,7 +262,7 @@
 }
 
 TEST_F(StyleResolverTest, CachedExplicitInheritanceFlags) {
-  ScopedMPCDependenciesForTest scoped_feature(true);
+  ScopedCSSMatchedPropertiesCacheDependenciesForTest scoped_feature(true);
 
   GetDocument().documentElement()->setInnerHTML(R"HTML(
     <style>
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
index c3dfbf0..07669857 100644
--- a/third_party/blink/renderer/core/css/style_engine.cc
+++ b/third_party/blink/renderer/core/css/style_engine.cc
@@ -75,6 +75,7 @@
 #include "third_party/blink/renderer/core/html/imports/html_imports_controller.h"
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/core/layout/layout_theme.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/page/page_popup_controller.h"
@@ -127,6 +128,7 @@
   }
   if (Platform::Current() && Platform::Current()->ThemeEngine())
     forced_colors_ = Platform::Current()->ThemeEngine()->GetForcedColors();
+  UpdateForcedBackgroundColor();
 }
 
 StyleEngine::~StyleEngine() = default;
@@ -942,6 +944,7 @@
 }
 
 void StyleEngine::PlatformColorsChanged() {
+  UpdateForcedBackgroundColor();
   if (resolver_)
     resolver_->InvalidateMatchedPropertiesCache();
   MarkAllElementsForStyleRecalc(StyleChangeReasonForTracing::Create(
@@ -2121,10 +2124,14 @@
   }
   if (GetDocument().Printing())
     preferred_color_scheme_ = PreferredColorScheme::kLight;
+
+  bool color_scheme_changed = false;
   if (forced_colors_ != old_forced_colors ||
-      preferred_color_scheme_ != old_preferred_color_scheme)
+      preferred_color_scheme_ != old_preferred_color_scheme) {
     PlatformColorsChanged();
-  UpdateColorSchemeBackground();
+    color_scheme_changed = true;
+  }
+  UpdateColorSchemeBackground(color_scheme_changed);
 }
 
 void StyleEngine::ColorSchemeChanged() {
@@ -2140,26 +2147,44 @@
   UpdateColorScheme();
 }
 
-void StyleEngine::UpdateColorSchemeBackground() {
+void StyleEngine::UpdateColorSchemeBackground(bool color_scheme_changed) {
   LocalFrameView* view = GetDocument().View();
   if (!view)
     return;
 
-  bool use_dark_background = false;
+  bool use_color_adjust_background = false;
+  use_dark_background_ = false;
 
-  if (forced_colors_ != ForcedColors::kActive) {
+  if (forced_colors_ != ForcedColors::kNone) {
+    use_color_adjust_background = true;
+  } else {
     const ComputedStyle* style = nullptr;
     if (auto* root_element = GetDocument().documentElement())
       style = root_element->GetComputedStyle();
     if (style) {
       if (style->UsedColorSchemeForInitialColors() == WebColorScheme::kDark)
-        use_dark_background = true;
+        use_dark_background_ = true;
     } else if (SupportsDarkColorScheme()) {
-      use_dark_background = true;
+      use_dark_background_ = true;
     }
   }
 
-  view->SetUseDarkSchemeBackground(use_dark_background);
+  use_color_adjust_background |= use_dark_background_;
+  view->SetUseColorAdjustBackground(use_color_adjust_background,
+                                    color_scheme_changed);
+}
+
+void StyleEngine::UpdateForcedBackgroundColor() {
+  forced_background_color_ = LayoutTheme::GetTheme().SystemColor(
+      CSSValueID::kCanvas, WebColorScheme::kLight);
+}
+
+Color StyleEngine::ColorAdjustBackgroundColor() const {
+  if (use_dark_background_ && forced_colors_ == ForcedColors::kNone)
+    return Color::kBlack;
+
+  DCHECK(forced_colors_ != ForcedColors::kNone);
+  return ForcedBackgroundColor();
 }
 
 void StyleEngine::MarkAllElementsForStyleRecalc(
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
index a93f7960..f540899 100644
--- a/third_party/blink/renderer/core/css/style_engine.h
+++ b/third_party/blink/renderer/core/css/style_engine.h
@@ -382,7 +382,9 @@
     return preferred_color_scheme_;
   }
   ForcedColors GetForcedColors() const { return forced_colors_; }
-  void UpdateColorSchemeBackground();
+  void UpdateColorSchemeBackground(bool color_scheme_changed = false);
+  Color ForcedBackgroundColor() const { return forced_background_color_; }
+  Color ColorAdjustBackgroundColor() const;
 
   void Trace(Visitor*) const override;
   const char* NameInHeapSnapshot() const override { return "StyleEngine"; }
@@ -492,6 +494,7 @@
 
   void UpdateColorScheme();
   bool SupportsDarkColorScheme();
+  void UpdateForcedBackgroundColor();
 
   void ViewportDefiningElementDidChange();
   void PropagateWritingModeAndDirectionToHTMLRoot();
@@ -606,9 +609,11 @@
   // kNoPreference to avoid dark styling to be applied before auto darkening.
   PreferredColorScheme preferred_color_scheme_ =
       PreferredColorScheme::kNoPreference;
+  bool use_dark_background_ = false;
 
   // Forced colors is set in WebThemeEngine.
   ForcedColors forced_colors_ = ForcedColors::kNone;
+  Color forced_background_color_;
 
   friend class NodeTest;
   friend class StyleEngineTest;
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index 1a4a601e..0cb97b5 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/renderer/core/html/html_span_element.h"
 #include "third_party/blink/renderer/core/html/html_style_element.h"
 #include "third_party/blink/renderer/core/layout/layout_text_fragment.h"
+#include "third_party/blink/renderer/core/layout/layout_theme.h"
 #include "third_party/blink/renderer/core/page/viewport_description.h"
 #include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
@@ -2126,6 +2127,14 @@
   UpdateAllLifecyclePhases();
 
   EXPECT_EQ(Color::kBlack, GetDocument().View()->BaseBackgroundColor());
+
+  color_scheme_helper.SetForcedColors(GetDocument(), ForcedColors::kActive);
+  UpdateAllLifecyclePhases();
+  Color system_background_color = LayoutTheme::GetTheme().SystemColor(
+      CSSValueID::kCanvas, WebColorScheme::kLight);
+
+  EXPECT_EQ(system_background_color,
+            GetDocument().View()->BaseBackgroundColor());
 }
 
 TEST_F(StyleEngineTest, ColorSchemeOverride) {
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
index 07c8dc9..cf905d34 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context_test.cc
@@ -1849,6 +1849,52 @@
   EXPECT_FALSE(child_layer->NeedsVisualOverflowRecalc());
 }
 
+TEST_F(DisplayLockContextRenderingTest, FloatChildLocked) {
+  SetHtmlInnerHTML(R"HTML(
+    <style>
+      .hidden { content-visibility: hidden }
+      #floating { float: left; width: 100px; height: 100px }
+    </style>
+    <div id=lockable style="width: 200px; height: 50px; position: absolute">
+      <div id=floating></div>
+    </div>
+  )HTML");
+
+  auto* lockable = GetDocument().getElementById("lockable");
+  auto* lockable_box = lockable->GetLayoutBox();
+  auto* floating = GetDocument().getElementById("floating");
+  EXPECT_EQ(LayoutRect(0, 0, 200, 100), lockable_box->VisualOverflowRect());
+  EXPECT_EQ(LayoutRect(0, 0, 200, 100), lockable_box->LayoutOverflowRect());
+
+  lockable->classList().Add("hidden");
+  UpdateAllLifecyclePhasesForTest();
+
+  // Verify that the display lock knows that the descendant dependent flags
+  // update was blocked.
+  ASSERT_TRUE(lockable->GetDisplayLockContext());
+  EXPECT_TRUE(DescendantDependentFlagUpdateWasBlocked(
+      lockable->GetDisplayLockContext()));
+  EXPECT_EQ(LayoutRect(0, 0, 200, 50), lockable_box->VisualOverflowRect());
+  EXPECT_EQ(LayoutRect(0, 0, 200, 50), lockable_box->LayoutOverflowRect());
+
+  floating->setAttribute(html_names::kStyleAttr, "height: 200px");
+  // The following should not crash/DCHECK.
+  UpdateAllLifecyclePhasesForTest();
+
+  ASSERT_TRUE(lockable->GetDisplayLockContext());
+  EXPECT_TRUE(DescendantDependentFlagUpdateWasBlocked(
+      lockable->GetDisplayLockContext()));
+  EXPECT_EQ(LayoutRect(0, 0, 200, 50), lockable_box->VisualOverflowRect());
+  EXPECT_EQ(LayoutRect(0, 0, 200, 50), lockable_box->LayoutOverflowRect());
+
+  // After unlocking, we should process the pending visual overflow recalc.
+  lockable->classList().Remove("hidden");
+  UpdateAllLifecyclePhasesForTest();
+
+  EXPECT_EQ(LayoutRect(0, 0, 200, 200), lockable_box->VisualOverflowRect());
+  EXPECT_EQ(LayoutRect(0, 0, 200, 200), lockable_box->LayoutOverflowRect());
+}
+
 TEST_F(DisplayLockContextRenderingTest,
        VisualOverflowCalculateOnChildPaintLayerInForcedLock) {
   SetHtmlInnerHTML(R"HTML(
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 08804b3..92502f8 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1069,10 +1069,6 @@
   return GetExecutionContext()->GetPublicURLManager();
 }
 
-ContentSecurityPolicyDelegate& Document::GetContentSecurityPolicyDelegate() {
-  return GetExecutionContext()->GetContentSecurityPolicyDelegate();
-}
-
 SecureContextMode Document::GetSecureContextMode() const {
   return GetSecurityContext().GetSecureContextMode();
 }
@@ -1101,6 +1097,32 @@
   GetSecurityContext().SetSecureContextModeForTesting(mode);
 }
 
+bool Document::IsFeatureEnabled(mojom::blink::FeaturePolicyFeature feature,
+                                ReportOptions report_on_failure,
+                                const String& message) const {
+  return GetExecutionContext() && GetExecutionContext()->IsFeatureEnabled(
+                                      feature, report_on_failure, message);
+}
+
+bool Document::IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature,
+                                ReportOptions report_option,
+                                const String& message,
+                                const String& source_file) const {
+  return GetExecutionContext() &&
+         GetExecutionContext()->IsFeatureEnabled(feature, report_option,
+                                                 message, source_file);
+}
+
+bool Document::IsFeatureEnabled(mojom::blink::DocumentPolicyFeature feature,
+                                PolicyValue threshold_value,
+                                ReportOptions report_option,
+                                const String& message,
+                                const String& source_file) const {
+  return GetExecutionContext() &&
+         GetExecutionContext()->IsFeatureEnabled(
+             feature, threshold_value, report_option, message, source_file);
+}
+
 String Document::addressSpaceForBindings(ScriptState* script_state) const {
   // "public" is the lowest-privilege value.
   if (!script_state->ContextIsValid())
@@ -5961,18 +5983,18 @@
                          ExceptionState& exception_state) {
   UseCounter::Count(*this, WebFeature::kDocumentSetDomain);
 
-  if (!dom_window_) {
-    exception_state.ThrowSecurityError(
-        "A browsing context is required to set a domain.");
+  const String feature_policy_error =
+      "Setting `document.domain` is disabled by Feature Policy.";
+  if (!IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kDocumentDomain,
+                        ReportOptions::kReportOnFailure,
+                        feature_policy_error)) {
+    exception_state.ThrowSecurityError(feature_policy_error);
     return;
   }
 
-  const String feature_policy_error =
-      "Setting `document.domain` is disabled by Feature Policy.";
-  if (!GetExecutionContext()->IsFeatureEnabled(
-          mojom::blink::FeaturePolicyFeature::kDocumentDomain,
-          ReportOptions::kReportOnFailure, feature_policy_error)) {
-    exception_state.ThrowSecurityError(feature_policy_error);
+  if (!dom_window_) {
+    exception_state.ThrowSecurityError(
+        "A browsing context is required to set a domain.");
     return;
   }
 
@@ -7171,9 +7193,9 @@
   if (!RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) {
     return true;
   }
-  if (!GetFrame() || GetExecutionContext()->IsFeatureEnabled(
-                         mojom::blink::FeaturePolicyFeature::kDocumentWrite,
-                         ReportOptions::kReportOnFailure)) {
+  if (!GetFrame() ||
+      IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kDocumentWrite,
+                       ReportOptions::kReportOnFailure)) {
     return true;
   }
 
@@ -7222,7 +7244,7 @@
 void Document::InitContentSecurityPolicy(ContentSecurityPolicy* csp) {
   GetSecurityContext().SetContentSecurityPolicy(csp);
   GetContentSecurityPolicy()->BindToDelegate(
-      GetContentSecurityPolicyDelegate());
+      GetExecutionContext()->GetContentSecurityPolicyDelegate());
 }
 
 void Document::InitSecurityContext(const DocumentInit& initializer) {
@@ -7261,7 +7283,7 @@
 void Document::BindContentSecurityPolicy() {
   DCHECK(!GetContentSecurityPolicy()->IsBound());
   GetContentSecurityPolicy()->BindToDelegate(
-      GetContentSecurityPolicyDelegate());
+      GetExecutionContext()->GetContentSecurityPolicyDelegate());
 }
 
 bool Document::AllowInlineEventHandler(Node* node,
@@ -8408,7 +8430,7 @@
   CountUse(uma_type);
   if (!RuntimeEnabledFeatures::BlockingFocusWithoutUserActivationEnabled())
     return true;
-  return GetExecutionContext()->IsFeatureEnabled(
+  return IsFeatureEnabled(
       mojom::blink::FeaturePolicyFeature::kFocusWithoutUserActivation);
 }
 
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index f38add6..345d759 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -350,7 +350,6 @@
   network::mojom::blink::WebSandboxFlags GetSandboxFlags() const;
   bool IsSandboxed(network::mojom::blink::WebSandboxFlags mask) const;
   PublicURLManager& GetPublicURLManager();
-  ContentSecurityPolicyDelegate& GetContentSecurityPolicyDelegate();
   SecureContextMode GetSecureContextMode() const;
   bool IsSecureContext() const;
   bool IsSecureContext(String& error_message) const;
@@ -358,6 +357,21 @@
   void SetReferrerPolicy(network::mojom::ReferrerPolicy);
   Agent* GetAgent() const;
   OriginTrialContext* GetOriginTrialContext() const;
+  bool IsFeatureEnabled(
+      mojom::blink::FeaturePolicyFeature,
+      ReportOptions report_on_failure = ReportOptions::kDoNotReport,
+      const String& message = g_empty_string) const;
+  bool IsFeatureEnabled(
+      mojom::blink::DocumentPolicyFeature,
+      ReportOptions report_option = ReportOptions::kDoNotReport,
+      const String& message = g_empty_string,
+      const String& source_file = g_empty_string) const;
+  bool IsFeatureEnabled(
+      mojom::blink::DocumentPolicyFeature,
+      PolicyValue threshold_value,
+      ReportOptions report_option = ReportOptions::kDoNotReport,
+      const String& message = g_empty_string,
+      const String& source_file = g_empty_string) const;
 
   String addressSpaceForBindings(ScriptState*) const;
 
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index dc55e6a..52a3c1d 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -210,7 +210,7 @@
   DispatchEventPostProcess(activation_target,
                            pre_dispatch_event_handler_result);
   if (eventTiming)
-    eventTiming->DidDispatchEvent(*event_);
+    eventTiming->DidDispatchEvent(*event_, node_->GetDocument());
 
   return EventTarget::GetDispatchEventResult(*event_);
 }
diff --git a/third_party/blink/renderer/core/dom/node_traversal.h b/third_party/blink/renderer/core/dom/node_traversal.h
index 3dd5e07..764f7ac7 100644
--- a/third_party/blink/renderer/core/dom/node_traversal.h
+++ b/third_party/blink/renderer/core/dom/node_traversal.h
@@ -62,8 +62,7 @@
 
   // Like next, but skips children and starts with the next sibling.
   CORE_EXPORT static Node* NextSkippingChildren(const Node&);
-  CORE_EXPORT static Node* NextSkippingChildren(const Node&,
-                                                const Node* stay_within);
+  static Node* NextSkippingChildren(const Node&, const Node* stay_within);
 
   static Node* FirstWithin(const Node& current) { return current.firstChild(); }
 
@@ -75,9 +74,8 @@
   static Node* Previous(const Node&, const Node* stay_within = nullptr);
 
   // Like previous, but skips children and starts with the next sibling.
-  CORE_EXPORT static Node* PreviousSkippingChildren(
-      const Node&,
-      const Node* stay_within = nullptr);
+  static Node* PreviousSkippingChildren(const Node&,
+                                        const Node* stay_within = nullptr);
 
   // Like next, but visits parents after their children.
   static Node* NextPostOrder(const Node&, const Node* stay_within = nullptr);
@@ -87,10 +85,12 @@
                                  const Node* stay_within = nullptr);
 
   // Pre-order traversal including the pseudo-elements.
-  static Node* PreviousIncludingPseudo(const Node&,
-                                       const Node* stay_within = nullptr);
-  static Node* NextIncludingPseudo(const Node&,
-                                   const Node* stay_within = nullptr);
+  CORE_EXPORT static Node* PreviousIncludingPseudo(
+      const Node&,
+      const Node* stay_within = nullptr);
+  CORE_EXPORT static Node* NextIncludingPseudo(
+      const Node&,
+      const Node* stay_within = nullptr);
   static Node* NextIncludingPseudoSkippingChildren(
       const Node&,
       const Node* stay_within = nullptr);
diff --git a/third_party/blink/renderer/core/editing/visible_units_line_test.cc b/third_party/blink/renderer/core/editing/visible_units_line_test.cc
index 1e6bf18..c1dfc5a 100644
--- a/third_party/blink/renderer/core/editing/visible_units_line_test.cc
+++ b/third_party/blink/renderer/core/editing/visible_units_line_test.cc
@@ -51,6 +51,20 @@
   static bool LayoutNGEnabled() {
     return RuntimeEnabledFeatures::LayoutNGEnabled();
   }
+
+  std::string TestEndOfLine(const std::string& input) {
+    const Position& caret = SetCaretTextToBody(input);
+    const Position& result =
+        EndOfLine(CreateVisiblePosition(caret)).DeepEquivalent();
+    return GetCaretTextFromBody(result);
+  }
+
+  std::string TestLogicalEndOfLine(const std::string& input) {
+    const Position& caret = SetCaretTextToBody(input);
+    const Position& result =
+        LogicalEndOfLine(CreateVisiblePosition(caret)).DeepEquivalent();
+    return GetCaretTextFromBody(result);
+  }
 };
 
 class ParameterizedVisibleUnitsLineTest
@@ -649,6 +663,139 @@
       StartOfLine(CreateVisiblePositionInFlatTree(*seven, 1)).DeepEquivalent());
 }
 
+TEST_P(ParameterizedVisibleUnitsLineTest, EndOfLineWithSoftLineWrap3) {
+  LoadAhem();
+  InsertStyleElement(
+      "div {"
+      "font: 10px/1 Ahem; width: 3ch; word-break: break-all; }");
+
+  EXPECT_EQ("<div>abc|def</div>", TestEndOfLine("<div>|abcdef</div>"));
+  EXPECT_EQ(
+      "<div dir=\"rtl\"><bdo dir=\"rtl\">abc|def</bdo></div>",
+      TestEndOfLine("<div dir=\"rtl\"><bdo dir=\"rtl\">|abcdef</bdo></div>"));
+
+  // Note: Both legacy and NG layout don't have text boxes for spaces cause
+  // soft line wrap.
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestEndOfLine("<div>|abc def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestEndOfLine("<div>ab|c def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestEndOfLine("<div>abc| def ghi</div>"));
+  EXPECT_EQ("<div>abc def| ghi</div>",
+            TestEndOfLine("<div>abc |def ghi</div>"));
+
+  EXPECT_EQ("<div dir=\"rtl\"><bdo dir=\"rtl\">abc| def ghi</bdo></div>",
+            TestEndOfLine(
+                "<div dir=\"rtl\"><bdo dir=\"rtl\">|abc def ghi</bdo></div>"));
+  EXPECT_EQ("<div dir=\"rtl\"><bdo dir=\"rtl\">abc| def ghi</bdo></div>",
+            TestEndOfLine(
+                "<div dir=\"rtl\"><bdo dir=\"rtl\">ab|c def ghi</bdo></div>"));
+  EXPECT_EQ("<div dir=\"rtl\"><bdo dir=\"rtl\">abc| def ghi</bdo></div>",
+            TestEndOfLine(
+                "<div dir=\"rtl\"><bdo dir=\"rtl\">abc| def ghi</bdo></div>"));
+  EXPECT_EQ("<div dir=\"rtl\"><bdo dir=\"rtl\">abc def| ghi</bdo></div>",
+            TestEndOfLine(
+                "<div dir=\"rtl\"><bdo dir=\"rtl\">abc |def ghi</bdo></div>"));
+
+  // On content editable, caret is after a space.
+  // Note: Legacy layout has text boxes at end of line for space cause soft line
+  // wrap for editable text, e.g.
+  //   LayoutText {#text} at (10,9) size 18x32
+  //     text run at (10,9) width 18: "abc"
+  //     text run at (28,9) width 0: " "
+  //     text run at (10,19) width 18: "def"
+  //     text run at (28,19) width 0: " "
+  //     text run at (10,29) width 18: "ghi"
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestEndOfLine("<div contenteditable>|abc def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestEndOfLine("<div contenteditable>ab|c def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestEndOfLine("<div contenteditable>abc| def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc def |ghi</div>",
+            TestEndOfLine("<div contenteditable>abc |def ghi</div>"));
+}
+
+TEST_P(ParameterizedVisibleUnitsLineTest, EndOfLineWithSoftLineWrap4) {
+  LoadAhem();
+  InsertStyleElement("div { font: 10px/1 Ahem; width: 4ch; }");
+
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestEndOfLine("<div>|abc def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestEndOfLine("<div>ab|c def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestEndOfLine("<div>abc| def ghi</div>"));
+  EXPECT_EQ("<div>abc def| ghi</div>",
+            TestEndOfLine("<div>abc |def ghi</div>"));
+
+  // On content editable, caret is after a space.
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestEndOfLine("<div contenteditable>|abc def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestEndOfLine("<div contenteditable>ab|c def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestEndOfLine("<div contenteditable>abc| def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc def |ghi</div>",
+            TestEndOfLine("<div contenteditable>abc |def ghi</div>"));
+}
+
+TEST_P(ParameterizedVisibleUnitsLineTest, LogicalEndOfLineWithSoftLineWrap3) {
+  LoadAhem();
+  InsertStyleElement(
+      "div {"
+      "font: 10px/1 Ahem; width: 3ch; word-break: break-all; }");
+
+  EXPECT_EQ("<div>abc|def</div>", TestLogicalEndOfLine("<div>|abcdef</div>"));
+  EXPECT_EQ("<div dir=\"rtl\"><bdo dir=\"rtl\">abc|def</bdo></div>",
+            TestLogicalEndOfLine(
+                "<div dir=\"rtl\"><bdo dir=\"rtl\">|abcdef</bdo></div>"));
+
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestLogicalEndOfLine("<div>|abc def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestLogicalEndOfLine("<div>ab|c def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestLogicalEndOfLine("<div>abc| def ghi</div>"));
+  EXPECT_EQ("<div>abc def| ghi</div>",
+            TestLogicalEndOfLine("<div>abc |def ghi</div>"));
+
+  // On content editable, caret is after a space.
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>|abc def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>ab|c def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>abc| def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc def |ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>abc |def ghi</div>"));
+}
+
+TEST_P(ParameterizedVisibleUnitsLineTest, LogicalEndOfLineWithSoftLineWrap4) {
+  LoadAhem();
+  InsertStyleElement("div { font: 10px/1 Ahem; width: 4ch; }");
+
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestLogicalEndOfLine("<div>|abc def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestLogicalEndOfLine("<div>ab|c def ghi</div>"));
+  EXPECT_EQ("<div>abc| def ghi</div>",
+            TestLogicalEndOfLine("<div>abc| def ghi</div>"));
+  EXPECT_EQ("<div>abc def| ghi</div>",
+            TestLogicalEndOfLine("<div>abc |def ghi</div>"));
+
+  // On content editable, caret is after a space.
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>|abc def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>ab|c def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc |def ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>abc| def ghi</div>"));
+  EXPECT_EQ("<div contenteditable>abc def |ghi</div>",
+            TestLogicalEndOfLine("<div contenteditable>abc |def ghi</div>"));
+}
+
 TEST_P(ParameterizedVisibleUnitsLineTest, InSameLineSkippingEmptyEditableDiv) {
   // This test records the InSameLine() results in
   // editing/selection/skip-over-contenteditable.html
@@ -680,8 +827,6 @@
   PositionWithAffinity position1(selection.Base());
   PositionWithAffinity position2(selection.Extent());
   // "Same line" is restricted by editability boundaries.
-  // TODO(editing-dev): Make sure this test doesn't fail when we stop wrapping
-  // inline contenteditables with inline blocks.
   EXPECT_FALSE(InSameLine(position1, position2));
 }
 
diff --git a/third_party/blink/renderer/core/exported/web_external_widget_impl.cc b/third_party/blink/renderer/core/exported/web_external_widget_impl.cc
index c139c683..e66acc0 100644
--- a/third_party/blink/renderer/core/exported/web_external_widget_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_external_widget_impl.cc
@@ -6,6 +6,7 @@
 
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/ukm_manager.h"
+#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
 #include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
 #include "third_party/blink/renderer/platform/widget/widget_base.h"
 
@@ -168,4 +169,10 @@
 void WebExternalWidgetImpl::QueueSyntheticEvent(
     std::unique_ptr<blink::WebCoalescedInputEvent>) {}
 
+void WebExternalWidgetImpl::GetWidgetInputHandler(
+    mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+    mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) {
+  client_->GetWidgetInputHandler(std::move(request), std::move(host));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_external_widget_impl.h b/third_party/blink/renderer/core/exported/web_external_widget_impl.h
index a0f27130..781dc22 100644
--- a/third_party/blink/renderer/core/exported/web_external_widget_impl.h
+++ b/third_party/blink/renderer/core/exported/web_external_widget_impl.h
@@ -78,6 +78,9 @@
   void DidHandleKeyEvent() override;
   void QueueSyntheticEvent(
       std::unique_ptr<blink::WebCoalescedInputEvent>) override;
+  void GetWidgetInputHandler(
+      mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+      mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) override;
 
  private:
   WebExternalWidgetClient* const client_;
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 c586f6d8..ac9d12c 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -10595,7 +10595,7 @@
             ->MainFrameImpl();
     web_view_helper_.Resize(WebSize(640, 480));
     remote_frame_host_.Init(
-        remote_frame_client_.GetAssociatedInterfaceProvider());
+        remote_frame_client_.GetRemoteAssociatedInterfaces());
     web_remote_frame_ = frame_test_helpers::CreateRemote(&remote_frame_client_);
   }
 
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 471ee20..6a53be7 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
@@ -34,6 +34,7 @@
 #include "cc/animation/animation_host.h"
 #include "cc/layers/picture_layer.h"
 #include "cc/trees/ukm_manager.h"
+#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
 #include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
 #include "third_party/blink/public/platform/web_float_rect.h"
 #include "third_party/blink/public/web/web_view_client.h"
@@ -549,6 +550,12 @@
   WidgetClient()->QueueSyntheticEvent(std::move(event));
 }
 
+void WebPagePopupImpl::GetWidgetInputHandler(
+    mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+    mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) {
+  WidgetClient()->GetWidgetInputHandler(std::move(request), std::move(host));
+}
+
 WebInputEventResult WebPagePopupImpl::HandleCharEvent(
     const WebKeyboardEvent& event) {
   if (suppress_next_keypress_event_) {
diff --git a/third_party/blink/renderer/core/exported/web_page_popup_impl.h b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
index 67a41cd..ba8db2a 100644
--- a/third_party/blink/renderer/core/exported/web_page_popup_impl.h
+++ b/third_party/blink/renderer/core/exported/web_page_popup_impl.h
@@ -132,6 +132,9 @@
   void DidHandleKeyEvent() override;
   void QueueSyntheticEvent(
       std::unique_ptr<blink::WebCoalescedInputEvent>) override;
+  void GetWidgetInputHandler(
+      mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+      mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) override;
 
   // WebWidget implementation.
   // NOTE: The WebWidget may still be used after requesting the popup to be
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 a1cfb38..94fb986 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -1593,27 +1593,27 @@
 
   if (LocalFrameView* view = MainFrameImpl()->GetFrameView()) {
     LocalFrame* frame = MainFrameImpl()->GetFrame();
-    WebWidgetClient* client =
-        WebLocalFrameImpl::FromFrame(frame)->FrameWidgetImpl()->Client();
+    WebFrameWidgetBase* frame_widget =
+        WebLocalFrameImpl::FromFrame(frame)->LocalRootFrameWidget();
 
     if (should_dispatch_first_visually_non_empty_layout_ &&
         view->IsVisuallyNonEmpty()) {
       should_dispatch_first_visually_non_empty_layout_ = false;
       // TODO(esprehn): Move users of this callback to something
       // better, the heuristic for "visually non-empty" is bad.
-      client->DidMeaningfulLayout(WebMeaningfulLayout::kVisuallyNonEmpty);
+      frame_widget->DidMeaningfulLayout(WebMeaningfulLayout::kVisuallyNonEmpty);
     }
 
     if (should_dispatch_first_layout_after_finished_parsing_ &&
         frame->GetDocument()->HasFinishedParsing()) {
       should_dispatch_first_layout_after_finished_parsing_ = false;
-      client->DidMeaningfulLayout(WebMeaningfulLayout::kFinishedParsing);
+      frame_widget->DidMeaningfulLayout(WebMeaningfulLayout::kFinishedParsing);
     }
 
     if (should_dispatch_first_layout_after_finished_loading_ &&
         frame->GetDocument()->IsLoadCompleted()) {
       should_dispatch_first_layout_after_finished_loading_ = false;
-      client->DidMeaningfulLayout(WebMeaningfulLayout::kFinishedLoading);
+      frame_widget->DidMeaningfulLayout(WebMeaningfulLayout::kFinishedLoading);
     }
   }
 }
@@ -2005,6 +2005,16 @@
   }
 }
 
+void WebViewImpl::DidAttachRemoteMainFrame() {
+  DCHECK(!MainFrameImpl());
+
+  RemoteFrame* remote_frame = DynamicTo<RemoteFrame>(GetPage()->MainFrame());
+  DCHECK(remote_frame);
+
+  remote_frame->GetRemoteAssociatedInterfaces()->GetInterface(
+      remote_main_frame_host_remote_.BindNewEndpointAndPassReceiver());
+}
+
 void WebViewImpl::DidDetachLocalMainFrame() {
   // The WebWidgetClient that generated the |scoped_defer_main_frame_update_|
   // for a local main frame is going away.
@@ -2012,6 +2022,10 @@
   local_main_frame_host_remote_.reset();
 }
 
+void WebViewImpl::DidDetachRemoteMainFrame() {
+  remote_main_frame_host_remote_.reset();
+}
+
 WebLocalFrame* WebViewImpl::FocusedFrame() {
   Frame* frame = FocusedCoreFrame();
   // TODO(yabinh): focusedCoreFrame() should always return a local frame, and
@@ -2733,6 +2747,16 @@
   UpdatePreferredSize();
 }
 
+void WebViewImpl::Focus() {
+  if (GetPage()->MainFrame()->IsLocalFrame()) {
+    DCHECK(local_main_frame_host_remote_);
+    local_main_frame_host_remote_->FocusPage();
+  } else {
+    DCHECK(remote_main_frame_host_remote_);
+    remote_main_frame_host_remote_->FocusPage();
+  }
+}
+
 float WebViewImpl::DefaultMinimumPageScaleFactor() const {
   return GetPageScaleConstraintsSet().DefaultConstraints().minimum_scale;
 }
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h
index 4ee975c..e212443 100644
--- a/third_party/blink/renderer/core/exported/web_view_impl.h
+++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -125,6 +125,9 @@
 
   // WebView methods:
   void DidAttachLocalMainFrame() override;
+  void DidDetachLocalMainFrame() override;
+  void DidAttachRemoteMainFrame() override;
+  void DidDetachRemoteMainFrame() override;
   void SetPrerendererClient(WebPrerendererClient*) override;
   WebSettings* GetSettings() override;
   WebString PageEncoding() const override;
@@ -174,6 +177,7 @@
   WebSize ContentsPreferredMinimumSize() override;
   void UpdatePreferredSize() override;
   void EnablePreferredSizeChangedMode() override;
+  void Focus() override;
   void SetDeviceScaleFactor(float) override;
   void SetZoomFactorForDeviceScaleFactor(float) override;
   float ZoomFactorForDeviceScaleFactor() override {
@@ -447,10 +451,6 @@
   ViewData& AsView() { return as_view_; }
   const ViewData& AsView() const { return as_view_; }
 
-  // Called while the main LocalFrame is being detached. The MainFrameImpl() is
-  // still valid until after this method is called.
-  void DidDetachLocalMainFrame();
-
   // These are temporary methods to allow WebViewFrameWidget to delegate to
   // WebViewImpl. We expect to eventually move these out.
   void SetSuppressFrameRequestsWorkaroundFor704763Only(bool);
@@ -716,6 +716,11 @@
   mojo::AssociatedRemote<mojom::blink::LocalMainFrameHost>
       local_main_frame_host_remote_;
 
+  // Handle to the remote main frame host. Only valid when the MainFrame is
+  // remote.
+  mojo::AssociatedRemote<mojom::blink::RemoteMainFrameHost>
+      remote_main_frame_host_remote_;
+
   // Set when a measurement begins, reset when the measurement is taken.
   base::Optional<base::TimeTicks> update_layers_start_time_;
 
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index fefb2721..cbd6c1b3 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -590,6 +590,19 @@
   web_view->SetBaseBackgroundColor(SK_ColorBLUE);
   EXPECT_EQ(Color::kBlack, frame_view->BaseBackgroundColor());
 
+  color_scheme_helper.SetForcedColors(*(web_view->GetPage()),
+                                      ForcedColors::kActive);
+  UpdateAllLifecyclePhases();
+
+  Color system_background_color = LayoutTheme::GetTheme().SystemColor(
+      CSSValueID::kCanvas, WebColorScheme::kLight);
+  EXPECT_EQ(system_background_color, frame_view->BaseBackgroundColor());
+
+  color_scheme_helper.SetForcedColors(*(web_view->GetPage()),
+                                      ForcedColors::kNone);
+  UpdateAllLifecyclePhases();
+  EXPECT_EQ(Color::kBlack, frame_view->BaseBackgroundColor());
+
   color_scheme_helper.SetPreferredColorScheme(PreferredColorScheme::kLight);
   UpdateAllLifecyclePhases();
   EXPECT_EQ(Color(0, 0, 255), frame_view->BaseBackgroundColor());
@@ -3634,7 +3647,7 @@
   }
 
   // WebWidgetClient methods
-  void DidFocus(WebLocalFrame*) override { did_focus_called_ = true; }
+  void DidFocus() override { did_focus_called_ = true; }
 
   bool DidFocusCalled() const { return did_focus_called_; }
   WebView* CreatedWebView() const { return web_view_helper_.GetWebView(); }
@@ -4046,6 +4059,7 @@
   void AutoscrollStart(const gfx::PointF& position) override {}
   void AutoscrollFling(const gfx::Vector2dF& position) override {}
   void AutoscrollEnd() override {}
+  void DidFirstVisuallyNonEmptyPaint() override {}
 
  private:
   mojo::AssociatedReceiver<mojom::blink::FrameWidgetHost>
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
index 07986bf..a5be54a 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
@@ -9,7 +9,6 @@
 
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
@@ -879,23 +878,23 @@
       "Blink.UseCounter.FeaturePolicy.PotentialViolation";
   auto dummy_page_holder_ = std::make_unique<DummyPageHolder>();
   // Probing feature state should not count.
-  dummy_page_holder_->GetFrame().DomWindow()->IsFeatureEnabled(
+  dummy_page_holder_->GetDocument().IsFeatureEnabled(
       mojom::blink::FeaturePolicyFeature::kPayment);
   tester.ExpectTotalCount(histogram_name, 0);
   // Checking the feature state with reporting intent should record a potential
   // violation.
-  dummy_page_holder_->GetFrame().DomWindow()->IsFeatureEnabled(
+  dummy_page_holder_->GetDocument().IsFeatureEnabled(
       mojom::blink::FeaturePolicyFeature::kPayment,
       ReportOptions::kReportOnFailure);
   tester.ExpectTotalCount(histogram_name, 1);
   // The potential violation for an already recorded violation does not count
   // again.
-  dummy_page_holder_->GetFrame().DomWindow()->IsFeatureEnabled(
+  dummy_page_holder_->GetDocument().IsFeatureEnabled(
       mojom::blink::FeaturePolicyFeature::kPayment,
       ReportOptions::kReportOnFailure);
   tester.ExpectTotalCount(histogram_name, 1);
   // Sanity check: check some other feature to increase the count.
-  dummy_page_holder_->GetFrame().DomWindow()->IsFeatureEnabled(
+  dummy_page_holder_->GetDocument().IsFeatureEnabled(
       mojom::blink::FeaturePolicyFeature::kFullscreen,
       ReportOptions::kReportOnFailure);
   tester.ExpectTotalCount(histogram_name, 2);
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
index 16a0ff5..06a76156 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -1138,7 +1138,7 @@
   // |delegate_|.
   ContentSecurityPolicyDelegate* relevant_delegate =
       context_frame
-          ? &context_frame->GetDocument()->GetContentSecurityPolicyDelegate()
+          ? &context_frame->DomWindow()->GetContentSecurityPolicyDelegate()
           : delegate_.Get();
   DCHECK(relevant_delegate);
   GatherSecurityPolicyViolationEventData(
@@ -1219,7 +1219,7 @@
     bool is_frame_ancestors_violation = !!context_frame;
     ContentSecurityPolicyDelegate* relevant_delegate =
         is_frame_ancestors_violation
-            ? &context_frame->GetDocument()->GetContentSecurityPolicyDelegate()
+            ? &context_frame->DomWindow()->GetContentSecurityPolicyDelegate()
             : delegate_.Get();
     DCHECK(relevant_delegate);
 
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
index e81d8eaf..bacbd16c 100644
--- a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
+++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/document_init.h"
 #include "third_party/blink/renderer/core/frame/csp/csp_directive_list.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/html/html_script_element.h"
 #include "third_party/blink/renderer/core/testing/dummy_page_holder.h"
 #include "third_party/blink/renderer/core/testing/null_execution_context.h"
@@ -85,7 +86,7 @@
     security_context.SetSecurityOriginForTesting(secure_origin);
 
     csp->BindToDelegate(
-        dummy->GetDocument().GetContentSecurityPolicyDelegate());
+        dummy->GetFrame().DomWindow()->GetContentSecurityPolicyDelegate());
     EXPECT_EQ(test.expected_policy,
               security_context.GetInsecureRequestPolicy());
     bool expect_upgrade =
@@ -414,8 +415,8 @@
 
   // We need document for HTMLScriptElement tests.
   auto dummy = std::make_unique<DummyPageHolder>();
-  auto& document = dummy->GetDocument();
-  document.GetSecurityContext().SetSecurityOriginForTesting(secure_origin);
+  auto* window = dummy->GetFrame().DomWindow();
+  window->GetSecurityContext().SetSecurityOriginForTesting(secure_origin);
 
   for (const auto& test : cases) {
     SCOPED_TRACE(testing::Message() << "Policy: `" << test.policy
@@ -423,12 +424,12 @@
 
     unsigned expected_reports = test.allowed ? 0u : 1u;
     auto* element = MakeGarbageCollected<HTMLScriptElement>(
-        document, CreateElementFlags::ByParser());
+        *window->document(), CreateElementFlags::ByParser());
 
     // Enforce 'script-src'
     Persistent<ContentSecurityPolicy> policy =
         MakeGarbageCollected<ContentSecurityPolicy>();
-    policy->BindToDelegate(document.GetContentSecurityPolicyDelegate());
+    policy->BindToDelegate(window->GetContentSecurityPolicyDelegate());
     policy->DidReceiveHeader(String("script-src ") + test.policy,
                              ContentSecurityPolicyType::kEnforce,
                              ContentSecurityPolicySource::kHTTP);
@@ -440,7 +441,7 @@
 
     // Enforce 'style-src'
     policy = MakeGarbageCollected<ContentSecurityPolicy>();
-    policy->BindToDelegate(document.GetContentSecurityPolicyDelegate());
+    policy->BindToDelegate(window->GetContentSecurityPolicyDelegate());
     policy->DidReceiveHeader(String("style-src ") + test.policy,
                              ContentSecurityPolicyType::kEnforce,
                              ContentSecurityPolicySource::kHTTP);
@@ -452,7 +453,7 @@
 
     // Report 'script-src'
     policy = MakeGarbageCollected<ContentSecurityPolicy>();
-    policy->BindToDelegate(document.GetContentSecurityPolicyDelegate());
+    policy->BindToDelegate(window->GetContentSecurityPolicyDelegate());
     policy->DidReceiveHeader(String("script-src ") + test.policy,
                              ContentSecurityPolicyType::kReport,
                              ContentSecurityPolicySource::kHTTP);
@@ -463,7 +464,7 @@
 
     // Report 'style-src'
     policy = MakeGarbageCollected<ContentSecurityPolicy>();
-    policy->BindToDelegate(document.GetContentSecurityPolicyDelegate());
+    policy->BindToDelegate(window->GetContentSecurityPolicyDelegate());
     policy->DidReceiveHeader(String("style-src ") + test.policy,
                              ContentSecurityPolicyType::kReport,
                              ContentSecurityPolicySource::kHTTP);
@@ -1436,7 +1437,7 @@
                           ContentSecurityPolicySource::kHTTP);
     auto dummy = std::make_unique<DummyPageHolder>();
     csp->BindToDelegate(
-        dummy->GetDocument().GetContentSecurityPolicyDelegate());
+        dummy->GetFrame().DomWindow()->GetContentSecurityPolicyDelegate());
 
     EXPECT_EQ(test.expected_object,
               dummy->GetDocument().IsUseCounted(
@@ -1462,7 +1463,7 @@
                           ContentSecurityPolicySource::kHTTP);
     auto dummy = std::make_unique<DummyPageHolder>();
     csp->BindToDelegate(
-        dummy->GetDocument().GetContentSecurityPolicyDelegate());
+        dummy->GetFrame().DomWindow()->GetContentSecurityPolicyDelegate());
 
     EXPECT_EQ(test.expected_object,
               dummy->GetDocument().IsUseCounted(
@@ -1512,7 +1513,7 @@
                           ContentSecurityPolicySource::kHTTP);
     auto dummy = std::make_unique<DummyPageHolder>();
     csp->BindToDelegate(
-        dummy->GetDocument().GetContentSecurityPolicyDelegate());
+        dummy->GetFrame().DomWindow()->GetContentSecurityPolicyDelegate());
 
     EXPECT_EQ(test.expected,
               dummy->GetDocument().IsUseCounted(
@@ -1528,7 +1529,7 @@
                           ContentSecurityPolicySource::kHTTP);
     auto dummy = std::make_unique<DummyPageHolder>();
     csp->BindToDelegate(
-        dummy->GetDocument().GetContentSecurityPolicyDelegate());
+        dummy->GetFrame().DomWindow()->GetContentSecurityPolicyDelegate());
 
     EXPECT_EQ(test.expected,
               dummy->GetDocument().IsUseCounted(
diff --git a/third_party/blink/renderer/core/frame/csp/string_list_directive.cc b/third_party/blink/renderer/core/frame/csp/string_list_directive.cc
index 7c552648..b297741 100644
--- a/third_party/blink/renderer/core/frame/csp/string_list_directive.cc
+++ b/third_party/blink/renderer/core/frame/csp/string_list_directive.cc
@@ -58,18 +58,23 @@
     allow_any_ = true;
     return false;
   }
+  if (src == "'none'") {
+    if (list_.size() > 1) {
+      Policy()->ReportInvalidSourceExpression(GetName(), src);
+    }
+    return false;
+  }
   return IsPolicyName(src);
 }
 
-bool StringListDirective::Allows(const String& string_piece,
-                                 bool is_duplicate) {
+bool StringListDirective::Allows(const String& value, bool is_duplicate) {
   if (is_duplicate && !allow_duplicates_)
     return false;
-  if (is_duplicate && string_piece == "default")
+  if (is_duplicate && value == "default")
     return false;
-  if (!IsPolicyName(string_piece))
+  if (!IsPolicyName(value))
     return false;
-  return allow_any_ || list_.Contains(string_piece);
+  return allow_any_ || list_.Contains(value);
 }
 
 void StringListDirective::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/frame/csp/string_list_directive_test.cc b/third_party/blink/renderer/core/frame/csp/string_list_directive_test.cc
index 4d59a0a..7800b9c 100644
--- a/third_party/blink/renderer/core/frame/csp/string_list_directive_test.cc
+++ b/third_party/blink/renderer/core/frame/csp/string_list_directive_test.cc
@@ -5,10 +5,20 @@
 #include "third_party/blink/renderer/core/frame/csp/string_list_directive.h"
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
 
 namespace blink {
 
-TEST(StringListDirectiveTest, TestAllowLists) {
+class StringListDirectiveTest : public testing::Test {
+ public:
+  StringListDirectiveTest()
+      : csp_(MakeGarbageCollected<ContentSecurityPolicy>()) {}
+
+ protected:
+  Persistent<ContentSecurityPolicy> csp_;
+};
+
+TEST_F(StringListDirectiveTest, TestAllowLists) {
   struct {
     const char* directive;
     const char* should_be_allowed;
@@ -25,11 +35,15 @@
       {"'allow-duplicates' bla", "bla", "blub", true},
       {"'allow-duplicates'", "", "bla blub", true},
       {"'allow-duplicates' bla blubb", "bla blubb", "blubber", true},
+      {"'none'", "", "default none abc", false},
+      {"'none' default", "default", "none abc", false},
+      {"* 'none'", "default none abc", "", false},
+      {"'allow-duplicates' 'none'", "", "default none abc", true},
   };
 
   for (const auto& test_case : test_cases) {
     StringListDirective directive("trusted-types", test_case.directive,
-                                  nullptr);
+                                  csp_.Get());
 
     Vector<String> allowed;
     String(test_case.should_be_allowed).Split(' ', allowed);
diff --git a/third_party/blink/renderer/core/frame/dom_window.cc b/third_party/blink/renderer/core/frame/dom_window.cc
index da734c80..4d761b46 100644
--- a/third_party/blink/renderer/core/frame/dom_window.cc
+++ b/third_party/blink/renderer/core/frame/dom_window.cc
@@ -361,10 +361,11 @@
 }
 
 void DOMWindow::focus(v8::Isolate* isolate) {
-  if (!GetFrame())
+  Frame* frame = GetFrame();
+  if (!frame)
     return;
 
-  Page* page = GetFrame()->GetPage();
+  Page* page = frame->GetPage();
   if (!page)
     return;
 
@@ -388,9 +389,9 @@
   }
 
   // If we're a top level window, bring the window to the front.
-  if (GetFrame()->IsMainFrame() && allow_focus) {
-    page->GetChromeClient().Focus(incumbent_window->GetFrame());
-  } else if (auto* local_frame = DynamicTo<LocalFrame>(GetFrame())) {
+  if (frame->IsMainFrame() && allow_focus) {
+    frame->FocusPage(incumbent_window->GetFrame());
+  } else if (auto* local_frame = DynamicTo<LocalFrame>(frame)) {
     // We are depending on user activation twice since IsFocusAllowed() will
     // check for activation. This should be addressed in
     // https://crbug.com/959815.
diff --git a/third_party/blink/renderer/core/frame/event_handler_registry.cc b/third_party/blink/renderer/core/frame/event_handler_registry.cc
index d4cf5c68..140feb3c 100644
--- a/third_party/blink/renderer/core/frame/event_handler_registry.cc
+++ b/third_party/blink/renderer/core/frame/event_handler_registry.cc
@@ -248,6 +248,11 @@
     bool has_active_handlers) {
   LocalFrame* frame = GetLocalFrameForTarget(target);
 
+  // TODO(keishi): Added for crbug.com/1090687. Change to CHECK once bug is
+  // fixed.
+  if (!GetPage())
+    return;
+
   switch (handler_class) {
     case kScrollEvent:
       GetPage()->GetChromeClient().SetHasScrollEventHandlers(
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc
index 66ced5c..c23749ca 100644
--- a/third_party/blink/renderer/core/frame/frame.cc
+++ b/third_party/blink/renderer/core/frame/frame.cc
@@ -393,6 +393,23 @@
   form_submit_navigation_task_.Cancel();
 }
 
+void Frame::FocusPage(LocalFrame* originating_frame) {
+  // We only allow focus to move to the |frame|'s page when the request comes
+  // from a user gesture. (See https://bugs.webkit.org/show_bug.cgi?id=33389.)
+  if (originating_frame &&
+      LocalFrame::HasTransientUserActivation(originating_frame)) {
+    // Ask the broswer process to focus the page.
+    GetPage()->GetChromeClient().FocusPage();
+
+    // Tattle on the frame that called |window.focus()|.
+    originating_frame->GetLocalFrameHostRemote().DidCallFocus();
+  }
+
+  // Always report the attempt to focus the page to the Chrome client for
+  // testing purposes (i.e. see WebViewTest.FocusExistingFrameOnNavigate()).
+  GetPage()->GetChromeClient().DidFocusPage();
+}
+
 STATIC_ASSERT_ENUM(FrameDetachType::kRemove,
                    WebLocalFrameClient::DetachType::kRemove);
 STATIC_ASSERT_ENUM(FrameDetachType::kSwap,
diff --git a/third_party/blink/renderer/core/frame/frame.h b/third_party/blink/renderer/core/frame/frame.h
index 32ede18..fdd0f83 100644
--- a/third_party/blink/renderer/core/frame/frame.h
+++ b/third_party/blink/renderer/core/frame/frame.h
@@ -291,6 +291,11 @@
                               FormSubmission* form_submission);
   void CancelFormSubmission();
 
+  // Asks the browser process to activate the page associated to the current
+  // Frame, reporting |originating_frame| as the local frame originating this
+  // request.
+  void FocusPage(LocalFrame* originating_frame);
+
   // Called when the focus controller changes the focus to this frame.
   virtual void DidFocus() = 0;
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index fb1e9fdf..0c3004e 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -316,7 +316,7 @@
   auto* frame = MakeGarbageCollected<WebRemoteFrameImpl>(
       mojom::blink::TreeScopeType::kDocument, client,
       InterfaceRegistry::GetEmptyInterfaceRegistry(),
-      client->GetAssociatedInterfaceProvider(),
+      client->GetRemoteAssociatedInterfaces(),
       base::UnguessableToken::Create());
   client->Bind(frame, std::move(owned_client));
   return frame;
@@ -389,8 +389,8 @@
       mojom::blink::TreeScopeType::kDocument, name, FramePolicy(),
       mojom::blink::FrameOwnerElementType::kIframe, client,
       InterfaceRegistry::GetEmptyInterfaceRegistry(),
-      client->GetAssociatedInterfaceProvider(),
-      base::UnguessableToken::Create(), nullptr));
+      client->GetRemoteAssociatedInterfaces(), base::UnguessableToken::Create(),
+      nullptr));
   client->Bind(frame, std::move(owned_client));
   if (!security_origin)
     security_origin = SecurityOrigin::CreateUniqueOpaque();
@@ -532,7 +532,7 @@
   WebRemoteFrameImpl* frame = WebRemoteFrameImpl::CreateMainFrame(
       web_view_, web_remote_frame_client,
       InterfaceRegistry::GetEmptyInterfaceRegistry(),
-      web_remote_frame_client->GetAssociatedInterfaceProvider(),
+      web_remote_frame_client->GetRemoteAssociatedInterfaces(),
       base::UnguessableToken::Create(), opener);
   web_remote_frame_client->Bind(frame,
                                 std::move(owned_web_remote_frame_client));
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 230c8371..58079e4b 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -454,8 +454,7 @@
 
   // WebRemoteFrameClient:
   void FrameDetached(DetachType) override;
-
-  AssociatedInterfaceProvider* GetAssociatedInterfaceProvider() {
+  AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override {
     return associated_interface_provider_.get();
   }
 
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index e68a1ab..84adce2 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/features.h"
+#include "third_party/blink/public/common/input/web_input_event_attribution.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/ad_tagging/ad_frame.mojom-blink.h"
 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
@@ -77,6 +78,7 @@
 #include "third_party/blink/renderer/core/dom/document_init.h"
 #include "third_party/blink/renderer/core/dom/document_parser.h"
 #include "third_party/blink/renderer/core/dom/document_type.h"
+#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/dom/ignore_opens_during_unload_count_incrementer.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
@@ -143,6 +145,7 @@
 #include "third_party/blink/renderer/core/page/page.h"
 #include "third_party/blink/renderer/core/page/plugin_data.h"
 #include "third_party/blink/renderer/core/page/plugin_script_forbidden_scope.h"
+#include "third_party/blink/renderer/core/page/pointer_lock_controller.h"
 #include "third_party/blink/renderer/core/page/scrolling/scrolling_coordinator.h"
 #include "third_party/blink/renderer/core/paint/compositing/graphics_layer_tree_as_text.h"
 #include "third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h"
@@ -645,6 +648,52 @@
   return first_url_cross_origin_to_parent_;
 }
 
+bool LocalFrame::CanAccessEvent(
+    const WebInputEventAttribution& attribution) const {
+  switch (attribution.type()) {
+    case WebInputEventAttribution::kTargetedFrame: {
+      auto* frame_document = GetDocument();
+      if (!frame_document)
+        return false;
+
+      // FIXME(acomminos): In the presence of a pointer lock, bail out. We
+      // currently do not propagate which frame had the lock at the time of
+      // event dispatch in the compositor. See https://crbug.com/1092617.
+      if (auto* page = frame_document->GetPage()) {
+        auto& pointer_lock_controller = page->GetPointerLockController();
+        if (pointer_lock_controller.GetElement()) {
+          return false;
+        }
+      }
+
+      auto* frame_origin =
+          frame_document->GetSecurityContext().GetSecurityOrigin();
+
+      cc::ElementId element_id = attribution.target_frame_id();
+      if (!element_id)
+        return false;
+
+      DOMNodeId target_document_id =
+          DOMNodeIdFromCompositorElementId(element_id);
+      Document* target_document =
+          DynamicTo<Document>(DOMNodeIds::NodeForId(target_document_id));
+      if (!target_document || !target_document->IsActive())
+        return false;
+
+      const auto* target_document_origin = target_document->GetSecurityOrigin();
+      if (!target_document_origin)
+        return false;
+
+      return frame_origin->CanAccess(target_document_origin);
+    }
+    case WebInputEventAttribution::kFocusedFrame:
+      return GetPage() ? GetPage()->GetFocusController().FocusedFrame() == this
+                       : false;
+    case WebInputEventAttribution::kUnknown:
+      return false;
+  }
+}
+
 void LocalFrame::Reload(WebFrameLoadType load_type) {
   DCHECK(IsReloadLoadType(load_type));
   if (!loader_.GetDocumentLoader()->GetHistoryItem())
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index e0c837d..c27baf7 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -128,6 +128,7 @@
 class TextSuggestionController;
 class VirtualKeyboardOverlayChangedObserver;
 class WebContentSettingsClient;
+class WebInputEventAttribution;
 class WebPluginContainerImpl;
 class WebPrescientNetworking;
 class WebURLLoaderFactory;
@@ -612,6 +613,11 @@
   // parent frame.
   base::Optional<String> FirstUrlCrossOriginToParent() const;
 
+  // Return true if the frame is able to access an event with the given
+  // attribution (i.e. the event is targeted for an origin that the frame may
+  // access).
+  bool CanAccessEvent(const WebInputEventAttribution&) const;
+
  private:
   friend class FrameNavigationDisabler;
   FRIEND_TEST_ALL_PREFIXES(LocalFrameTest, CharacterIndexAtPointWithPinchZoom);
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 8e2c4a5..a1dd266 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -1744,9 +1744,10 @@
 }
 
 Color LocalFrameView::BaseBackgroundColor() const {
-  if (use_dark_scheme_background_ &&
+  if (use_color_adjust_background_ &&
       base_background_color_ != Color::kTransparent) {
-    return Color::kBlack;
+    DCHECK(frame_->GetDocument());
+    return frame_->GetDocument()->GetStyleEngine().ColorAdjustBackgroundColor();
   }
   return base_background_color_;
 }
@@ -1772,11 +1773,12 @@
     GetPage()->Animator().ScheduleVisualUpdate(frame_.Get());
 }
 
-void LocalFrameView::SetUseDarkSchemeBackground(bool dark_scheme) {
-  if (use_dark_scheme_background_ == dark_scheme)
+void LocalFrameView::SetUseColorAdjustBackground(bool color_adjust,
+                                                 bool color_scheme_changed) {
+  if (use_color_adjust_background_ == color_adjust && !color_scheme_changed)
     return;
 
-  use_dark_scheme_background_ = dark_scheme;
+  use_color_adjust_background_ = color_adjust;
   if (auto* layout_view = GetLayoutView())
     layout_view->SetBackgroundNeedsFullPaintInvalidation();
 }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h
index 967ed525..e9c1166 100644
--- a/third_party/blink/renderer/core/frame/local_frame_view.h
+++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -253,7 +253,8 @@
   Color BaseBackgroundColor() const;
   void SetBaseBackgroundColor(const Color&);
   void UpdateBaseBackgroundColorRecursively(const Color&);
-  void SetUseDarkSchemeBackground(bool dark_scheme);
+  void SetUseColorAdjustBackground(bool color_adjust,
+                                   bool color_scheme_changed);
 
   void AdjustViewSize();
   void AdjustViewSizeAndLayout();
@@ -872,7 +873,7 @@
   TaskRunnerTimer<LocalFrameView> update_plugins_timer_;
 
   bool first_layout_;
-  bool use_dark_scheme_background_ = false;
+  bool use_color_adjust_background_ = false;
   Color base_background_color_;
   IntSize last_viewport_size_;
   float last_zoom_factor_;
diff --git a/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc b/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
index d7f8506..db0f416 100644
--- a/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
+++ b/third_party/blink/renderer/core/frame/overlay_interstitial_ad_detector.cc
@@ -11,7 +11,7 @@
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
-#include "third_party/blink/renderer/core/paint/first_meaningful_paint_detector.h"
+#include "third_party/blink/renderer/core/paint/paint_timing.h"
 #include "third_party/blink/renderer/core/scroll/scrollable_area.h"
 
 namespace blink {
@@ -68,101 +68,106 @@
   DCHECK(main_frame->GetDocument());
   DCHECK(main_frame->ContentLayoutObject());
 
+  // Skip any measurement before the FCP.
+  if (PaintTiming::From(*main_frame->GetDocument())
+          .FirstContentfulPaint()
+          .is_null()) {
+    return;
+  }
+
   base::Time current_time = base::Time::Now();
+  if (started_detection_ && current_time < last_detection_time_ + kFireInterval)
+    return;
 
-  if (!started_detection_ ||
-      current_time - last_detection_time_ >= kFireInterval) {
-    IntSize main_frame_size = main_frame->GetMainFrameViewportSize();
+  TRACE_EVENT0("blink,benchmark",
+               "OverlayInterstitialAdDetector::MaybeFireDetection");
 
-    if (started_detection_ &&
-        main_frame_size != last_detection_main_frame_size_) {
-      // Reset the candidate when the the viewport size has changed. Changing
-      // the viewport size could influence the layout and may trick the detector
-      // into believing that an element appeared and was dismissed, but what
-      // could have happened is that the element no longer covers the center,
-      // but still exists (e.g. a sticky ad at the top).
-      candidate_id_ = kInvalidDOMNodeId;
+  started_detection_ = true;
+  last_detection_time_ = current_time;
+
+  IntSize main_frame_size = main_frame->GetMainFrameViewportSize();
+  last_detection_main_frame_size_ = main_frame_size;
+
+  if (main_frame_size != last_detection_main_frame_size_) {
+    // Reset the candidate when the the viewport size has changed. Changing
+    // the viewport size could influence the layout and may trick the detector
+    // into believing that an element appeared and was dismissed, but what
+    // could have happened is that the element no longer covers the center,
+    // but still exists (e.g. a sticky ad at the top).
+    candidate_id_ = kInvalidDOMNodeId;
+  }
+
+  HitTestLocation location(DoublePoint(main_frame_size.Width() / 2.0,
+                                       main_frame_size.Height() / 2.0));
+  HitTestResult result;
+  main_frame->ContentLayoutObject()->HitTestNoLifecycleUpdate(location, result);
+
+  Element* element = result.InnerElement();
+  if (!element)
+    return;
+
+  DOMNodeId element_id = DOMNodeIds::IdForNode(element);
+
+  // Skip considering the overlay for a pop-up candidate if we haven't seen or
+  // have just seen the first meaningful paint. If we have just seen the first
+  // meaningful paint, however, we would consider future overlays for pop-up
+  // candidates.
+  if (!main_content_has_loaded_) {
+    if (!PaintTiming::From(*main_frame->GetDocument())
+             .FirstMeaningfulPaint()
+             .is_null()) {
+      main_content_has_loaded_ = true;
     }
 
-    HitTestLocation location(DoublePoint(main_frame_size.Width() / 2.0,
-                                         main_frame_size.Height() / 2.0));
-    HitTestResult result;
-    main_frame->ContentLayoutObject()->HitTestNoLifecycleUpdate(location,
-                                                                result);
-    started_detection_ = true;
+    last_unqualified_element_id_ = element_id;
+    return;
+  }
 
-    last_detection_time_ = current_time;
-    last_detection_main_frame_size_ = main_frame_size;
+  bool is_new_element = (element_id != candidate_id_);
 
-    Element* element = result.InnerElement();
-    if (!element)
-      return;
-
-    DOMNodeId element_id = DOMNodeIds::IdForNode(element);
-
-    bool is_new_element = (element_id != candidate_id_);
-
-    if (is_new_element && candidate_id_ != kInvalidDOMNodeId) {
-      // If the main frame scrolling offset hasn't changed since the candidate's
-      // appearance, we consider it to be a overlay interstitial; otherwise, we
-      // skip that candidate because it could be a parallax/scroller ad.
-      if (main_frame->GetMainFrameScrollOffset().Y() ==
-          candidate_start_main_frame_scroll_offset_) {
-        OnPopupAdDetected(main_frame);
-        return;
-      }
-      last_unqualified_element_id_ = candidate_id_;
-      candidate_id_ = kInvalidDOMNodeId;
-    }
-
-    if (!is_new_element)
-      return;
-
-    if (element_id == last_unqualified_element_id_)
-      return;
-
-    if (!element->GetLayoutObject())
-      return;
-
-    // Skip considering the overlay for a pop-up candidate if we haven't seen or
-    // have just seen the first meaningful paint. If we have just seen the first
-    // meaningful paint, however, we would consider future overlays for pop-up
-    // candidates.
-    if (!main_content_has_loaded_) {
-      if (FirstMeaningfulPaintDetector::From(*(main_frame->GetDocument()))
-              .SeenFirstMeaningfulPaint()) {
-        main_content_has_loaded_ = true;
-      }
-      last_unqualified_element_id_ = element_id;
+  if (is_new_element && candidate_id_ != kInvalidDOMNodeId) {
+    // If the main frame scrolling offset hasn't changed since the candidate's
+    // appearance, we consider it to be a overlay interstitial; otherwise, we
+    // skip that candidate because it could be a parallax/scroller ad.
+    if (main_frame->GetMainFrameScrollOffset().Y() ==
+        candidate_start_main_frame_scroll_offset_) {
+      OnPopupAdDetected(main_frame);
       return;
     }
+    last_unqualified_element_id_ = candidate_id_;
+    candidate_id_ = kInvalidDOMNodeId;
+  }
 
-    IntRect overlay_rect =
-        element->GetLayoutObject()->AbsoluteBoundingBoxRect();
+  if (!is_new_element)
+    return;
 
-    bool is_large =
-        !overlay_rect.IsEmpty() &&
-        (overlay_rect.Size().Area() >
-         main_frame_size.Area() * kLargeAdSizeToViewportSizeThreshold);
+  if (element_id == last_unqualified_element_id_)
+    return;
 
-    bool has_gesture = LocalFrame::HasTransientUserActivation(main_frame);
+  if (!element->GetLayoutObject())
+    return;
 
-    if (!has_gesture && is_large && IsOverlayAdCandidate(element)) {
-      // If main page is not scrollable, immediately determinine the overlay
-      // to be a popup. There's is no need to check any state at the dismissal
-      // time.
-      if (!main_frame->GetDocument()
-               ->GetLayoutView()
-               ->HasScrollableOverflowY()) {
-        OnPopupAdDetected(main_frame);
-        return;
-      }
-      candidate_id_ = element_id;
-      candidate_start_main_frame_scroll_offset_ =
-          main_frame->GetMainFrameScrollOffset().Y();
-    } else {
-      last_unqualified_element_id_ = element_id;
+  IntRect overlay_rect = element->GetLayoutObject()->AbsoluteBoundingBoxRect();
+
+  bool is_large =
+      (overlay_rect.Size().Area() >
+       main_frame_size.Area() * kLargeAdSizeToViewportSizeThreshold);
+
+  bool has_gesture = LocalFrame::HasTransientUserActivation(main_frame);
+
+  if (!has_gesture && is_large && IsOverlayAdCandidate(element)) {
+    // If main page is not scrollable, immediately determinine the overlay
+    // to be a popup. There's is no need to check any state at the dismissal
+    // time.
+    if (!main_frame->GetDocument()->GetLayoutView()->HasScrollableOverflowY()) {
+      OnPopupAdDetected(main_frame);
+      return;
     }
+    candidate_id_ = element_id;
+    candidate_start_main_frame_scroll_offset_ =
+        main_frame->GetMainFrameScrollOffset().Y();
+  } else {
+    last_unqualified_element_id_ = element_id;
   }
 }
 
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index ca86c50..4967552d 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -349,6 +349,11 @@
   return *remote_frame_host_remote_.get();
 }
 
+AssociatedInterfaceProvider* RemoteFrame::GetRemoteAssociatedInterfaces() {
+  DCHECK(Client());
+  return Client()->GetRemoteAssociatedInterfaces();
+}
+
 RemoteFrameClient* RemoteFrame::Client() const {
   return static_cast<RemoteFrameClient*>(Frame::Client());
 }
diff --git a/third_party/blink/renderer/core/frame/remote_frame.h b/third_party/blink/renderer/core/frame/remote_frame.h
index 3ef68af8..bcfe0bc 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.h
+++ b/third_party/blink/renderer/core/frame/remote_frame.h
@@ -90,6 +90,8 @@
 
   mojom::blink::RemoteFrameHost& GetRemoteFrameHostRemote();
 
+  AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces();
+
   RemoteFrameView* View() const override;
 
   RemoteFrameClient* Client() const;
diff --git a/third_party/blink/renderer/core/frame/remote_frame_client.h b/third_party/blink/renderer/core/frame/remote_frame_client.h
index c38e6a79..4addd8d 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_client.h
+++ b/third_party/blink/renderer/core/frame/remote_frame_client.h
@@ -20,6 +20,7 @@
 }
 
 namespace blink {
+class AssociatedInterfaceProvider;
 class IntRect;
 class ResourceRequest;
 class WebLocalFrame;
@@ -49,6 +50,8 @@
       const ViewportIntersectionState& intersection_state) = 0;
 
   virtual uint32_t Print(const IntRect&, cc::PaintCanvas*) const = 0;
+
+  virtual AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc b/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
index fc313973..f989b4b 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame_client_impl.cc
@@ -7,8 +7,10 @@
 #include <memory>
 #include <utility>
 
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
 #include "third_party/blink/public/web/web_remote_frame_client.h"
+#include "third_party/blink/public/web/web_view.h"
 #include "third_party/blink/renderer/core/events/keyboard_event.h"
 #include "third_party/blink/renderer/core/events/mouse_event.h"
 #include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
@@ -57,8 +59,14 @@
 
   client->FrameDetached(static_cast<WebRemoteFrameClient::DetachType>(type));
 
-  if (type == FrameDetachType::kRemove)
-    web_frame_->DetachFromParent();
+  if (web_frame_->Parent()) {
+    if (type == FrameDetachType::kRemove)
+      web_frame_->DetachFromParent();
+  } else if (web_frame_->View()) {
+    // If the RemoteFrame being detached is also the main frame in the renderer
+    // process, we need to notify the webview to allow it to clean things up.
+    web_frame_->View()->DidDetachRemoteMainFrame();
+  }
 
   // Clear our reference to RemoteFrame at the very end, in case the client
   // refers to it.
@@ -137,4 +145,9 @@
   return web_frame_->Client()->Print(rect, canvas);
 }
 
+AssociatedInterfaceProvider*
+RemoteFrameClientImpl::GetRemoteAssociatedInterfaces() {
+  return web_frame_->Client()->GetRemoteAssociatedInterfaces();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/remote_frame_client_impl.h b/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
index a5003764..c3c2837 100644
--- a/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
+++ b/third_party/blink/renderer/core/frame/remote_frame_client_impl.h
@@ -46,6 +46,7 @@
   void UpdateRemoteViewportIntersection(
       const ViewportIntersectionState& intersection_state) override;
   uint32_t Print(const IntRect&, cc::PaintCanvas*) const override;
+  AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override;
 
   WebRemoteFrameImpl* GetWebFrame() const { return web_frame_; }
 
diff --git a/third_party/blink/renderer/core/frame/scheduling.cc b/third_party/blink/renderer/core/frame/scheduling.cc
index 3bb1f24..dbd3e25 100644
--- a/third_party/blink/renderer/core/frame/scheduling.cc
+++ b/third_party/blink/renderer/core/frame/scheduling.cc
@@ -26,9 +26,11 @@
   auto info = scheduler->GetPendingUserInputInfo(
       options ? options->includeContinuous() : false);
 
-  // TODO(acomminos): Attribution first requires a reverse mapping between
-  // cc::ElementId instances and their underlying Document* objects.
-  (void)info;
+  for (const auto& attribution : info) {
+    if (frame->CanAccessEvent(attribution)) {
+      return true;
+    }
+  }
   return false;
 }
 
diff --git a/third_party/blink/renderer/core/frame/sticky_ad_detector.cc b/third_party/blink/renderer/core/frame/sticky_ad_detector.cc
index 3f18db6..0748d35 100644
--- a/third_party/blink/renderer/core/frame/sticky_ad_detector.cc
+++ b/third_party/blink/renderer/core/frame/sticky_ad_detector.cc
@@ -11,6 +11,7 @@
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/layout/layout_object_inlines.h"
 #include "third_party/blink/renderer/core/layout/layout_view.h"
+#include "third_party/blink/renderer/core/paint/paint_timing.h"
 #include "third_party/blink/renderer/core/scroll/scrollable_area.h"
 
 #include <cstdlib>
@@ -57,10 +58,18 @@
   DCHECK(main_frame->GetDocument());
   DCHECK(main_frame->ContentLayoutObject());
 
+  // Skip any measurement before the FCP.
+  if (PaintTiming::From(*main_frame->GetDocument())
+          .FirstContentfulPaint()
+          .is_null()) {
+    return;
+  }
+
   base::Time current_time = base::Time::Now();
   if (last_detection_time_.has_value() &&
-      current_time < last_detection_time_.value() + kFireInterval)
+      current_time < last_detection_time_.value() + kFireInterval) {
     return;
+  }
 
   TRACE_EVENT0("blink,benchmark", "StickyAdDetector::MaybeFireDetection");
 
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 49d79a4..5611e810 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
@@ -14,6 +14,7 @@
 #include "cc/trees/layer_tree_host.h"
 #include "cc/trees/swap_promise.h"
 #include "cc/trees/ukm_manager.h"
+#include "third_party/blink/public/mojom/input/input_handler.mojom-blink.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/scheduler/web_render_widget_scheduling_state.h"
 #include "third_party/blink/public/web/web_autofill_client.h"
@@ -185,11 +186,11 @@
     const gfx::PointF& screen_point) {
   DCHECK(current_drag_data_);
 
-  // TODO(paulmeyer): It shouldn't be possible for |m_currentDragData| to be
+  // TODO(paulmeyer): It shouldn't be possible for |current_drag_data_| to be
   // null here, but this is somehow happening (rarely). This suggests that in
   // some cases drag-leave is happening before drag-enter, which should be
   // impossible. This needs to be investigated further. Once fixed, the extra
-  // check for |!m_currentDragData| should be removed. (crbug.com/671152)
+  // check for |!current_drag_data_| should be removed. (crbug.com/671152)
   if (IgnoreInputEvents() || !current_drag_data_) {
     CancelDrag();
     return;
@@ -746,6 +747,12 @@
   return controller->TextInputType();
 }
 
+void WebFrameWidgetBase::GetWidgetInputHandler(
+    mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+    mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) {
+  Client()->GetWidgetInputHandler(std::move(request), std::move(host));
+}
+
 void WebFrameWidgetBase::ApplyViewportChangesForTesting(
     const ApplyViewportChangesArgs& args) {
   widget_base_->ApplyViewportChanges(args);
@@ -790,6 +797,24 @@
   GetAssociatedFrameWidgetHost()->AutoscrollEnd();
 }
 
+void WebFrameWidgetBase::DidMeaningfulLayout(WebMeaningfulLayout layout_type) {
+  if (layout_type == blink::WebMeaningfulLayout::kVisuallyNonEmpty) {
+    NotifySwapAndPresentationTime(
+        base::NullCallback(),
+        WTF::Bind(&WebFrameWidgetBase::PresentationCallbackForMeaningfulLayout,
+                  WrapPersistent(this)));
+  }
+
+  if (client_)
+    client_->DidMeaningfulLayout(layout_type);
+}
+
+void WebFrameWidgetBase::PresentationCallbackForMeaningfulLayout(
+    blink::WebSwapResult,
+    base::TimeTicks) {
+  GetAssociatedFrameWidgetHost()->DidFirstVisuallyNonEmptyPaint();
+}
+
 void WebFrameWidgetBase::RequestAnimationAfterDelay(
     const base::TimeDelta& delay) {
   DCHECK(request_animation_after_delay_timer_.get());
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
index 0a02857..dfd127bd 100644
--- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -85,6 +85,9 @@
   void AutoscrollFling(const gfx::Vector2dF& position);
   void AutoscrollEnd();
 
+  // Notifies RenderWidgetHostImpl that the frame widget has painted something.
+  void DidMeaningfulLayout(WebMeaningfulLayout layout_type);
+
   // Creates or returns cached mutator dispatcher. This usually requires a
   // round trip to the compositor. The returned WeakPtr must only be
   // dereferenced on the output |mutator_task_runner|.
@@ -143,8 +146,6 @@
                                       const gfx::PointF& screen_point,
                                       WebDragOperationsMask operations_allowed,
                                       int modifiers) override;
-  void DragTargetDragLeave(const gfx::PointF& point_in_viewport,
-                           const gfx::PointF& screen_point) override;
   void DragTargetDrop(const WebDragData&,
                       const gfx::PointF& point_in_viewport,
                       const gfx::PointF& screen_point,
@@ -233,9 +234,14 @@
   void QueueSyntheticEvent(
       std::unique_ptr<blink::WebCoalescedInputEvent>) override;
   WebTextInputType GetTextInputType() override;
+  void GetWidgetInputHandler(
+      mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+      mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) override;
   void ScheduleAnimationForWebTests() override;
 
   // mojom::blink::FrameWidget methods.
+  void DragTargetDragLeave(const gfx::PointF& point_in_viewport,
+                           const gfx::PointF& screen_point) override;
   void DragSourceSystemDragEnded() override;
   void SetBackgroundOpaque(bool opaque) override;
 
@@ -389,6 +395,8 @@
  private:
   void CancelDrag();
   void RequestAnimationAfterDelayTimerFired(TimerBase*);
+  void PresentationCallbackForMeaningfulLayout(blink::WebSwapResult,
+                                               base::TimeTicks);
 
   static bool ignore_input_events_;
 
diff --git a/third_party/blink/renderer/core/fullscreen/fullscreen.cc b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
index e4a1f3567..843cfffc 100644
--- a/third_party/blink/renderer/core/fullscreen/fullscreen.cc
+++ b/third_party/blink/renderer/core/fullscreen/fullscreen.cc
@@ -220,7 +220,7 @@
 
   // 2. If Feature Policy is enabled, return the policy for "fullscreen"
   // feature.
-  return document.GetExecutionContext()->IsFeatureEnabled(
+  return document.IsFeatureEnabled(
       mojom::blink::FeaturePolicyFeature::kFullscreen, report_on_failure);
 }
 
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 eec0ce2c..8131064 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
@@ -1548,6 +1548,7 @@
 void HTMLCanvasElement::ReplaceExisting2dLayerBridge(
     std::unique_ptr<Canvas2DLayerBridge> new_layer_bridge) {
   scoped_refptr<StaticBitmapImage> image;
+  std::unique_ptr<Canvas2DLayerBridge> old_layer_bridge;
   if (canvas2d_bridge_) {
     image = canvas2d_bridge_->NewImageSnapshot(kPreferNoAcceleration);
     // image can be null if allocation failed in which case we should just
@@ -1555,15 +1556,32 @@
     // functional.
     if (!image)
       return;
+    old_layer_bridge = std::move(canvas2d_bridge_);
+    // Removing connection between old_layer_bridge and CanvasResourceHost;
+    // otherwise, the CanvasResourceHost checks for the old one before
+    // assigning the new canvas layer bridge.
+    old_layer_bridge->SetCanvasResourceHost(nullptr);
   }
   ReplaceResourceProvider(nullptr);
   canvas2d_bridge_ = std::move(new_layer_bridge);
   canvas2d_bridge_->SetCanvasResourceHost(this);
 
+  // If PaintCanvas cannot be get from the new layer bridge, revert the
+  // replacement.
   cc::PaintCanvas* canvas = canvas2d_bridge_->GetPaintCanvas();
-  // Paint canvas automatically has the clip re-applied. Since image already
-  // contains clip, it needs to be drawn before the clip stack is re-applied.
-  // Remove clip from canvas and restore it after the image is drawn.
+  if (!canvas) {
+    if (old_layer_bridge) {
+      canvas2d_bridge_ = std::move(old_layer_bridge);
+      canvas2d_bridge_->SetCanvasResourceHost(this);
+    }
+    return;
+  }
+
+  // After validating paint canvas on new layer bridge, removes the clip from
+  // the canvas. Since clips is automatically applied to paint canvas, the image
+  // already contains clip and the image needs to be drawn before the clip stack
+  // is re-applied, it needs to remove clip from canvas and restore it after the
+  // image is drawn.
   canvas->restoreToCount(1);
   canvas->save();
 
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.cc b/third_party/blink/renderer/core/html/forms/html_option_element.cc
index bce8b9e..c69ab0b 100644
--- a/third_party/blink/renderer/core/html/forms/html_option_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_option_element.cc
@@ -26,8 +26,10 @@
 
 #include "third_party/blink/renderer/core/html/forms/html_option_element.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h"
 #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h"
 #include "third_party/blink/renderer/core/dom/document.h"
+#include "third_party/blink/renderer/core/dom/mutation_observer.h"
 #include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/dom/node_traversal.h"
 #include "third_party/blink/renderer/core/dom/shadow_root.h"
@@ -44,6 +46,37 @@
 
 namespace blink {
 
+class OptionTextObserver : public MutationObserver::Delegate {
+ public:
+  explicit OptionTextObserver(HTMLOptionElement& option)
+      : option_(option), observer_(MutationObserver::Create(this)) {
+    MutationObserverInit* init = MutationObserverInit::Create();
+    init->setCharacterData(true);
+    init->setChildList(true);
+    init->setSubtree(true);
+    observer_->observe(option_, init, ASSERT_NO_EXCEPTION);
+  }
+
+  ExecutionContext* GetExecutionContext() const override {
+    return option_->GetExecutionContext();
+  }
+
+  void Deliver(const MutationRecordVector& records,
+               MutationObserver&) override {
+    option_->DidChangeTextContent();
+  }
+
+  void Trace(Visitor* visitor) const override {
+    visitor->Trace(option_);
+    visitor->Trace(observer_);
+    MutationObserver::Delegate::Trace(visitor);
+  }
+
+ private:
+  Member<HTMLOptionElement> option_;
+  Member<MutationObserver> observer_;
+};
+
 HTMLOptionElement::HTMLOptionElement(Document& document)
     : HTMLElement(html_names::kOptionTag, document), is_selected_(false) {
   EnsureUserAgentShadowRoot();
@@ -81,6 +114,11 @@
   return element;
 }
 
+void HTMLOptionElement::Trace(Visitor* visitor) const {
+  visitor->Trace(text_observer_);
+  HTMLElement::Trace(visitor);
+}
+
 bool HTMLOptionElement::SupportsFocus() const {
   HTMLSelectElement* select = OwnerSelectElement();
   if (select && select->UsesMenuList())
@@ -280,6 +318,15 @@
 
 void HTMLOptionElement::ChildrenChanged(const ChildrenChange& change) {
   HTMLElement::ChildrenChanged(change);
+  DidChangeTextContent();
+
+  // If an element is inserted, We need to use MutationObserver to detect
+  // textContent changes.
+  if (change.type == ChildrenChangeType::kElementInserted && !text_observer_)
+    text_observer_ = MakeGarbageCollected<OptionTextObserver>(*this);
+}
+
+void HTMLOptionElement::DidChangeTextContent() {
   if (HTMLDataListElement* data_list = OwnerDataListElement())
     data_list->OptionElementChildrenChanged();
   else if (HTMLSelectElement* select = OwnerSelectElement())
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.h b/third_party/blink/renderer/core/html/forms/html_option_element.h
index 87e6b6a6..06a62d3 100644
--- a/third_party/blink/renderer/core/html/forms/html_option_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_option_element.h
@@ -33,6 +33,7 @@
 class ExceptionState;
 class HTMLDataListElement;
 class HTMLSelectElement;
+class OptionTextObserver;
 
 class CORE_EXPORT HTMLOptionElement final : public HTMLElement {
   DEFINE_WRAPPERTYPEINFO();
@@ -53,6 +54,7 @@
                                                    ExceptionState&);
 
   explicit HTMLOptionElement(Document&);
+  void Trace(Visitor* visitor) const override;
 
   // A text to be shown to users.  The difference from |label()| is |label()|
   // returns an empty string if |label| content attribute is empty.
@@ -101,6 +103,9 @@
   void SetMultiSelectFocusedState(bool);
   bool IsMultiSelectFocused() const;
 
+  // Callback for OptionTextObserver.
+  void DidChangeTextContent();
+
  private:
   ~HTMLOptionElement() override;
 
@@ -117,6 +122,8 @@
 
   void UpdateLabel();
 
+  Member<OptionTextObserver> text_observer_;
+
   // Represents 'selectedness'.
   // https://html.spec.whatwg.org/C/#concept-option-selectedness
   bool is_selected_;
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
index 5316549..37e8a0d 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -497,14 +497,13 @@
           network::mojom::blink::TrustTokenOperationType::kSigning;
 
   if (operation_requires_feature_policy &&
-      (!GetExecutionContext()->IsFeatureEnabled(
+      (!GetDocument().IsFeatureEnabled(
           mojom::blink::FeaturePolicyFeature::kTrustTokenRedemption))) {
-    GetExecutionContext()->AddConsoleMessage(
-        MakeGarbageCollected<ConsoleMessage>(
-            mojom::blink::ConsoleMessageSource::kOther,
-            mojom::blink::ConsoleMessageLevel::kError,
-            "Trust Tokens: Attempted redemption or signing without the "
-            "trust-token-redemption Feature Policy feature present."));
+    GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+        mojom::blink::ConsoleMessageSource::kOther,
+        mojom::blink::ConsoleMessageLevel::kError,
+        "Trust Tokens: Attempted redemption or signing without the "
+        "trust-token-redemption Feature Policy feature present."));
     return nullptr;
   }
 
diff --git a/third_party/blink/renderer/core/html/html_image_element.cc b/third_party/blink/renderer/core/html/html_image_element.cc
index eb821c28..010b716 100644
--- a/third_party/blink/renderer/core/html/html_image_element.cc
+++ b/third_party/blink/renderer/core/html/html_image_element.cc
@@ -104,7 +104,7 @@
       is_fallback_image_(false),
       is_default_overridden_intrinsic_size_(
           !document.IsImageDocument() &&
-          !GetExecutionContext()->IsFeatureEnabled(
+          !document.IsFeatureEnabled(
               mojom::blink::DocumentPolicyFeature::kUnsizedMedia)),
       is_legacy_format_or_unoptimized_image_(false),
       referrer_policy_(network::mojom::ReferrerPolicy::kDefault) {
diff --git a/third_party/blink/renderer/core/html/html_template_element.cc b/third_party/blink/renderer/core/html/html_template_element.cc
index 13b4401..2cbed91 100644
--- a/third_party/blink/renderer/core/html/html_template_element.cc
+++ b/third_party/blink/renderer/core/html/html_template_element.cc
@@ -66,7 +66,7 @@
 void HTMLTemplateElement::CloneNonAttributePropertiesFrom(
     const Element& source,
     CloneChildrenFlag flag) {
-  if (flag == CloneChildrenFlag::kSkip)
+  if (flag == CloneChildrenFlag::kSkip || !GetExecutionContext())
     return;
   DCHECK_NE(flag, CloneChildrenFlag::kCloneWithShadows);
   auto& html_template_element = To<HTMLTemplateElement>(source);
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
index c169dbcb..bd1d889 100644
--- a/third_party/blink/renderer/core/html/media/autoplay_policy.cc
+++ b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
@@ -89,8 +89,7 @@
     return false;
 
   bool feature_policy_enabled =
-      document.GetExecutionContext()->IsFeatureEnabled(
-          mojom::blink::FeaturePolicyFeature::kAutoplay);
+      document.IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kAutoplay);
 
   for (Frame* frame = document.GetFrame(); frame;
        frame = frame->Tree().Parent()) {
@@ -362,11 +361,11 @@
 
   autoplay_initiated_ = true;
 
+  const Document& document = element_->GetDocument();
   bool feature_policy_enabled =
-      element_->GetExecutionContext()->IsFeatureEnabled(
-          mojom::blink::FeaturePolicyFeature::kAutoplay);
+      document.IsFeatureEnabled(mojom::blink::FeaturePolicyFeature::kAutoplay);
 
-  for (Frame* frame = element_->GetDocument().GetFrame(); frame;
+  for (Frame* frame = document.GetFrame(); frame;
        frame = frame->Tree().Parent()) {
     if (frame->HasStickyUserActivation() ||
         frame->HadStickyUserActivationBeforeNavigation()) {
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index af31686..f647aaef 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -87,7 +87,7 @@
       is_effectively_fullscreen_(false),
       is_default_overridden_intrinsic_size_(
           !document.IsMediaDocument() &&
-          !GetExecutionContext()->IsFeatureEnabled(
+          !document.IsFeatureEnabled(
               mojom::blink::DocumentPolicyFeature::kUnsizedMedia)),
       video_has_played_(false),
       mostly_filling_viewport_(false) {
diff --git a/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc b/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc
index b358da20..eb358a1 100644
--- a/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc
+++ b/third_party/blink/renderer/core/html/media/media_element_parser_helpers.cc
@@ -18,7 +18,7 @@
   bool is_unsized = !style.LogicalWidth().IsSpecified() &&
                     !style.LogicalHeight().IsSpecified();
   if (is_unsized) {
-    layout_object->GetDocument().GetExecutionContext()->IsFeatureEnabled(
+    layout_object->GetDocument().IsFeatureEnabled(
         mojom::blink::DocumentPolicyFeature::kUnsizedMedia,
         send_report ? ReportOptions::kReportOnFailure
                     : ReportOptions::kDoNotReport);
diff --git a/third_party/blink/renderer/core/html/resources/forced_colors.css b/third_party/blink/renderer/core/html/resources/forced_colors.css
index 6b45ae9..47b2e5f 100644
--- a/third_party/blink/renderer/core/html/resources/forced_colors.css
+++ b/third_party/blink/renderer/core/html/resources/forced_colors.css
@@ -20,10 +20,6 @@
     fill: currentColor;
   }
 
-  body {
-    background-color: Canvas;
-  }
-
   :focus {
     outline-color: Highlight;
   }
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index 90dc3ff..644f7c6 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -1268,7 +1268,7 @@
 void InspectorOverlayAgent::SetInspectTool(InspectTool* inspect_tool) {
   LocalFrameView* view = frame_impl_->GetFrameView();
   LocalFrame* frame = GetFrame();
-  if (!view || !frame)
+  if (!view || !frame || !enabled_.Get())
     return;
 
   if (inspect_tool_)
diff --git a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
index 342e219..591330a 100644
--- a/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_style_sheet.cc
@@ -1524,6 +1524,7 @@
           .setTitle(style_sheet->title())
           .setFrameId(frame ? IdentifiersFactory::FrameId(frame) : "")
           .setIsInline(style_sheet->IsInline() && !StartsAtZero())
+          .setIsMutable(style_sheet->Contents()->IsMutable())
           .setStartLine(start.line_.ZeroBasedInt())
           .setStartColumn(start.column_.ZeroBasedInt())
           .setLength(text_length)
diff --git a/third_party/blink/renderer/core/layout/BUILD.gn b/third_party/blink/renderer/core/layout/BUILD.gn
index bad1fb28..7589be90 100644
--- a/third_party/blink/renderer/core/layout/BUILD.gn
+++ b/third_party/blink/renderer/core/layout/BUILD.gn
@@ -63,6 +63,8 @@
     "geometry/physical_size.h",
     "geometry/transform_state.cc",
     "geometry/transform_state.h",
+    "geometry/writing_mode_converter.cc",
+    "geometry/writing_mode_converter.h",
     "grid.cc",
     "grid.h",
     "grid_baseline_alignment.cc",
@@ -145,6 +147,8 @@
     "layout_list_item.h",
     "layout_list_marker.cc",
     "layout_list_marker.h",
+    "layout_list_marker_image.cc",
+    "layout_list_marker_image.h",
     "layout_media.cc",
     "layout_media.h",
     "layout_multi_column_flow_thread.cc",
@@ -426,8 +430,6 @@
     "ng/list/layout_ng_inside_list_marker.h",
     "ng/list/layout_ng_list_item.cc",
     "ng/list/layout_ng_list_item.h",
-    "ng/list/layout_ng_list_marker_image.cc",
-    "ng/list/layout_ng_list_marker_image.h",
     "ng/list/layout_ng_outside_list_marker.cc",
     "ng/list/layout_ng_outside_list_marker.h",
     "ng/list/list_marker.cc",
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_offset.cc b/third_party/blink/renderer/core/layout/geometry/logical_offset.cc
index 5d3cbbb..90ed61b 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_offset.cc
+++ b/third_party/blink/renderer/core/layout/geometry/logical_offset.cc
@@ -7,44 +7,24 @@
 #include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
+#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
-PhysicalOffset LogicalOffset::ConvertToPhysical(WritingMode mode,
+PhysicalOffset LogicalOffset::ConvertToPhysical(
+    WritingDirectionMode writing_direction,
+    PhysicalSize outer_size,
+    PhysicalSize inner_size) const {
+  return WritingModeConverter(writing_direction, outer_size)
+      .ToPhysical(*this, inner_size);
+}
+
+PhysicalOffset LogicalOffset::ConvertToPhysical(WritingMode writing_mode,
                                                 TextDirection direction,
                                                 PhysicalSize outer_size,
                                                 PhysicalSize inner_size) const {
-  switch (mode) {
-    case WritingMode::kHorizontalTb:
-      if (direction == TextDirection::kLtr)
-        return PhysicalOffset(inline_offset, block_offset);
-      return PhysicalOffset(outer_size.width - inline_offset - inner_size.width,
-                            block_offset);
-    case WritingMode::kVerticalRl:
-    case WritingMode::kSidewaysRl:
-      if (direction == TextDirection::kLtr) {
-        return PhysicalOffset(
-            outer_size.width - block_offset - inner_size.width, inline_offset);
-      }
-      return PhysicalOffset(
-          outer_size.width - block_offset - inner_size.width,
-          outer_size.height - inline_offset - inner_size.height);
-    case WritingMode::kVerticalLr:
-      if (direction == TextDirection::kLtr)
-        return PhysicalOffset(block_offset, inline_offset);
-      return PhysicalOffset(
-          block_offset, outer_size.height - inline_offset - inner_size.height);
-    case WritingMode::kSidewaysLr:
-      if (direction == TextDirection::kLtr) {
-        return PhysicalOffset(block_offset, outer_size.height - inline_offset -
-                                                inner_size.height);
-      }
-      return PhysicalOffset(block_offset, inline_offset);
-    default:
-      NOTREACHED();
-      return PhysicalOffset();
-  }
+  return ConvertToPhysical({writing_mode, direction}, outer_size, inner_size);
 }
 
 String LogicalOffset::ToString() const {
diff --git a/third_party/blink/renderer/core/layout/geometry/logical_offset.h b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
index ae0a241f..aa737fd1 100644
--- a/third_party/blink/renderer/core/layout/geometry/logical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/logical_offset.h
@@ -7,8 +7,7 @@
 
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
-#include "third_party/blink/renderer/platform/text/text_direction.h"
-#include "third_party/blink/renderer/platform/text/writing_mode.h"
+#include "third_party/blink/renderer/platform/text/writing_direction_mode.h"
 
 namespace blink {
 
@@ -38,8 +37,11 @@
   // the same point.
   // @param outer_size the size of the rect (typically a fragment).
   // @param inner_size the size of the inner rect (typically a child fragment).
-  PhysicalOffset ConvertToPhysical(WritingMode,
-                                   TextDirection,
+  PhysicalOffset ConvertToPhysical(WritingDirectionMode writing_direction,
+                                   PhysicalSize outer_size,
+                                   PhysicalSize inner_size) const;
+  PhysicalOffset ConvertToPhysical(WritingMode writing_mode,
+                                   TextDirection direction,
                                    PhysicalSize outer_size,
                                    PhysicalSize inner_size) const;
 
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_offset.cc b/third_party/blink/renderer/core/layout/geometry/physical_offset.cc
index d2c6d16..a151cae 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_offset.cc
+++ b/third_party/blink/renderer/core/layout/geometry/physical_offset.cc
@@ -6,39 +6,26 @@
 
 #include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
+#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
 #include "third_party/blink/renderer/platform/geometry/layout_point.h"
 #include "third_party/blink/renderer/platform/geometry/layout_size.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
-LogicalOffset PhysicalOffset::ConvertToLogical(WritingMode mode,
+LogicalOffset PhysicalOffset::ConvertToLogical(
+    WritingDirectionMode writing_direction,
+    PhysicalSize outer_size,
+    PhysicalSize inner_size) const {
+  return WritingModeConverter(writing_direction, outer_size)
+      .ToLogical(*this, inner_size);
+}
+
+LogicalOffset PhysicalOffset::ConvertToLogical(WritingMode writing_mode,
                                                TextDirection direction,
                                                PhysicalSize outer_size,
                                                PhysicalSize inner_size) const {
-  switch (mode) {
-    case WritingMode::kHorizontalTb:
-      if (direction == TextDirection::kLtr)
-        return LogicalOffset(left, top);
-      return LogicalOffset(outer_size.width - left - inner_size.width, top);
-    case WritingMode::kVerticalRl:
-    case WritingMode::kSidewaysRl:
-      if (direction == TextDirection::kLtr)
-        return LogicalOffset(top, outer_size.width - left - inner_size.width);
-      return LogicalOffset(outer_size.height - top - inner_size.height,
-                           outer_size.width - left - inner_size.width);
-    case WritingMode::kVerticalLr:
-      if (direction == TextDirection::kLtr)
-        return LogicalOffset(top, left);
-      return LogicalOffset(outer_size.height - top - inner_size.height, left);
-    case WritingMode::kSidewaysLr:
-      if (direction == TextDirection::kLtr)
-        return LogicalOffset(outer_size.height - top - inner_size.height, left);
-      return LogicalOffset(top, left);
-    default:
-      NOTREACHED();
-      return LogicalOffset();
-  }
+  return ConvertToLogical({writing_mode, direction}, outer_size, inner_size);
 }
 
 String PhysicalOffset::ToString() const {
diff --git a/third_party/blink/renderer/core/layout/geometry/physical_offset.h b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
index 0983ccf4..a2e93b6e 100644
--- a/third_party/blink/renderer/core/layout/geometry/physical_offset.h
+++ b/third_party/blink/renderer/core/layout/geometry/physical_offset.h
@@ -9,8 +9,7 @@
 #include "third_party/blink/renderer/platform/geometry/layout_point.h"
 #include "third_party/blink/renderer/platform/geometry/layout_size.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
-#include "third_party/blink/renderer/platform/text/text_direction.h"
-#include "third_party/blink/renderer/platform/text/writing_mode.h"
+#include "third_party/blink/renderer/platform/text/writing_direction_mode.h"
 
 namespace blink {
 
@@ -38,8 +37,11 @@
   // https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical
   // @param outer_size the size of the rect (typically a fragment).
   // @param inner_size the size of the inner rect (typically a child fragment).
-  LogicalOffset ConvertToLogical(WritingMode,
-                                 TextDirection,
+  LogicalOffset ConvertToLogical(WritingDirectionMode writing_direction,
+                                 PhysicalSize outer_size,
+                                 PhysicalSize inner_size) const;
+  LogicalOffset ConvertToLogical(WritingMode writing_mode,
+                                 TextDirection direction,
                                  PhysicalSize outer_size,
                                  PhysicalSize inner_size) const;
 
diff --git a/third_party/blink/renderer/core/layout/geometry/writing_mode_converter.cc b/third_party/blink/renderer/core/layout/geometry/writing_mode_converter.cc
new file mode 100644
index 0000000..d0fbabd8
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/geometry/writing_mode_converter.cc
@@ -0,0 +1,80 @@
+// 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 "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
+
+namespace blink {
+
+LogicalOffset WritingModeConverter::SlowToLogical(
+    const PhysicalOffset& offset,
+    const PhysicalSize& inner_size) const {
+  switch (GetWritingMode()) {
+    case WritingMode::kHorizontalTb:
+      DCHECK(!IsLtr());  // LTR is in the fast code path.
+      return LogicalOffset(outer_size_.width - offset.left - inner_size.width,
+                           offset.top);
+    case WritingMode::kVerticalRl:
+    case WritingMode::kSidewaysRl:
+      if (IsLtr()) {
+        return LogicalOffset(
+            offset.top, outer_size_.width - offset.left - inner_size.width);
+      }
+      return LogicalOffset(outer_size_.height - offset.top - inner_size.height,
+                           outer_size_.width - offset.left - inner_size.width);
+    case WritingMode::kVerticalLr:
+      if (IsLtr())
+        return LogicalOffset(offset.top, offset.left);
+      return LogicalOffset(outer_size_.height - offset.top - inner_size.height,
+                           offset.left);
+    case WritingMode::kSidewaysLr:
+      if (IsLtr()) {
+        return LogicalOffset(
+            outer_size_.height - offset.top - inner_size.height, offset.left);
+      }
+      return LogicalOffset(offset.top, offset.left);
+    default:
+      NOTREACHED();
+      return LogicalOffset();
+  }
+}
+
+PhysicalOffset WritingModeConverter::SlowToPhysical(
+    const LogicalOffset& offset,
+    const PhysicalSize& inner_size) const {
+  switch (GetWritingMode()) {
+    case WritingMode::kHorizontalTb:
+      DCHECK(!IsLtr());  // LTR is in the fast code path.
+      return PhysicalOffset(
+          outer_size_.width - offset.inline_offset - inner_size.width,
+          offset.block_offset);
+    case WritingMode::kVerticalRl:
+    case WritingMode::kSidewaysRl:
+      if (IsLtr()) {
+        return PhysicalOffset(
+            outer_size_.width - offset.block_offset - inner_size.width,
+            offset.inline_offset);
+      }
+      return PhysicalOffset(
+          outer_size_.width - offset.block_offset - inner_size.width,
+          outer_size_.height - offset.inline_offset - inner_size.height);
+    case WritingMode::kVerticalLr:
+      if (IsLtr())
+        return PhysicalOffset(offset.block_offset, offset.inline_offset);
+      return PhysicalOffset(
+          offset.block_offset,
+          outer_size_.height - offset.inline_offset - inner_size.height);
+    case WritingMode::kSidewaysLr:
+      if (IsLtr()) {
+        return PhysicalOffset(
+            offset.block_offset,
+            outer_size_.height - offset.inline_offset - inner_size.height);
+      }
+      return PhysicalOffset(offset.block_offset, offset.inline_offset);
+    default:
+      NOTREACHED();
+      return PhysicalOffset();
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h b/third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h
new file mode 100644
index 0000000..0972edc
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h
@@ -0,0 +1,88 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_WRITING_MODE_CONVERTER_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_WRITING_MODE_CONVERTER_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
+#include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
+#include "third_party/blink/renderer/core/layout/geometry/physical_size.h"
+#include "third_party/blink/renderer/platform/text/writing_direction_mode.h"
+
+namespace blink {
+
+// This class represents CSS property values to convert between logical and
+// physical coordinate systems. See:
+// https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical
+class CORE_EXPORT WritingModeConverter {
+  STACK_ALLOCATED();
+
+ public:
+  // @param writing_direction |WritingMode| and |TextDirection|.
+  // @param outer_size the size of the rect (typically a fragment). Some
+  // combinations of |WritingMode| and |TextDirection| require the size of the
+  // container to make the offset relative to the right or the bottom edges.
+  WritingModeConverter(WritingDirectionMode writing_direction,
+                       const PhysicalSize& outer_size)
+      : writing_direction_(writing_direction), outer_size_(outer_size) {}
+
+  // Construct without |outer_size|. Caller should call |SetOuterSize| before
+  // conversions.
+  explicit WritingModeConverter(WritingDirectionMode writing_direction)
+      : writing_direction_(writing_direction) {}
+
+  // Conversion properties and utilities.
+  WritingDirectionMode GetWritingDirection() const {
+    return writing_direction_;
+  }
+  WritingMode GetWritingMode() const {
+    return writing_direction_.GetWritingMode();
+  }
+  TextDirection Direction() const { return writing_direction_.Direction(); }
+  bool IsLtr() const { return writing_direction_.IsLtr(); }
+
+  void SetOuterSize(const PhysicalSize& outer_size) {
+    outer_size_ = outer_size;
+  }
+
+  // |LogicalOffset| and |PhysicalOffset| conversions.
+  // PhysicalOffset will be the physical top left point of the rectangle
+  // described by offset + inner_size. Setting inner_size to 0,0 will return
+  // the same point.
+  // @param inner_size the size of the inner rect (typically a child fragment).
+  LogicalOffset ToLogical(const PhysicalOffset& offset,
+                          const PhysicalSize& inner_size) const;
+  PhysicalOffset ToPhysical(const LogicalOffset& offset,
+                            const PhysicalSize& inner_size) const;
+
+ private:
+  LogicalOffset SlowToLogical(const PhysicalOffset& offset,
+                              const PhysicalSize& inner_size) const;
+  PhysicalOffset SlowToPhysical(const LogicalOffset& offset,
+                                const PhysicalSize& inner_size) const;
+
+  WritingDirectionMode writing_direction_;
+  PhysicalSize outer_size_;
+};
+
+inline LogicalOffset WritingModeConverter::ToLogical(
+    const PhysicalOffset& offset,
+    const PhysicalSize& inner_size) const {
+  if (writing_direction_.IsHorizontalLtr())
+    return LogicalOffset(offset.left, offset.top);
+  return SlowToLogical(offset, inner_size);
+}
+
+inline PhysicalOffset WritingModeConverter::ToPhysical(
+    const LogicalOffset& offset,
+    const PhysicalSize& inner_size) const {
+  if (writing_direction_.IsHorizontalLtr())
+    return PhysicalOffset(offset.inline_offset, offset.block_offset);
+  return SlowToPhysical(offset, inner_size);
+}
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_GEOMETRY_WRITING_MODE_CONVERTER_H_
diff --git a/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc b/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc
index ba95fca6..956e4731 100644
--- a/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/grid_track_sizing_algorithm.cc
@@ -798,7 +798,9 @@
   DCHECK(GridLayoutUtils::IsOrthogonalChild(*GetLayoutGrid(), child));
 
   return child.LogicalHeight() +
-         GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child);
+         GridLayoutUtils::MarginLogicalHeightForChild(*GetLayoutGrid(), child) +
+         algorithm_.BaselineOffsetForChild(child,
+                                           GridAxisForDirection(Direction()));
 }
 
 bool IndefiniteSizeStrategy::IsComputingSizeContainment() const {
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index 9ef1f4d..2739c22 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -442,6 +442,9 @@
   if (PrePaintBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren))
     return;
 
+  // TODO(crbug.com/1086968): Change to DCHECK after diagnosing the bug.
+  CHECK(!NeedsLayout());
+
   if (ChildrenInline())
     To<LayoutBlockFlow>(this)->AddVisualOverflowFromInlineChildren();
   else
@@ -459,6 +462,9 @@
 }
 
 void LayoutBlock::ComputeVisualOverflow(bool) {
+  // TODO(crbug.com/1086968): Change to DCHECK after diagnosing the bug.
+  CHECK(!SelfNeedsLayout());
+
   LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
   ClearVisualOverflow();
   AddVisualOverflowFromChildren();
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 f19fd8a..3cf5e7a 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -2385,9 +2385,13 @@
 }
 
 void LayoutBlockFlow::AddVisualOverflowFromFloats() {
-  if (!floating_objects_)
+  if (PrePaintBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren) ||
+      !floating_objects_)
     return;
 
+  // TODO(crbug.com/1086968): Change to DCHECK after diagnosing the bug.
+  CHECK(!NeedsLayout());
+
   for (auto& floating_object : floating_objects_->Set()) {
     if (floating_object->IsDescendant()) {
       AddVisualOverflowFromChild(
@@ -2400,7 +2404,11 @@
 
 void LayoutBlockFlow::AddVisualOverflowFromFloats(
     const NGPhysicalContainerFragment& fragment) {
+  // TODO(crbug.com/1086968): Change to DCHECK after diagnosing the bug.
+  CHECK(!NeedsLayout());
+  DCHECK(!PrePaintBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren));
   DCHECK(fragment.HasFloatingDescendantsForPaint());
+
   for (const NGLink& child : fragment.Children()) {
     if (child->HasSelfPaintingLayer())
       continue;
@@ -2420,7 +2428,8 @@
 }
 
 void LayoutBlockFlow::AddLayoutOverflowFromFloats() {
-  if (!floating_objects_)
+  if (LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren) ||
+      !floating_objects_)
     return;
 
   for (auto& floating_object : floating_objects_->Set()) {
@@ -2445,6 +2454,9 @@
 
 void LayoutBlockFlow::ComputeVisualOverflow(
     bool recompute_floats) {
+  // TODO(crbug.com/1086968): Change to DCHECK after diagnosing the bug.
+  CHECK(!SelfNeedsLayout());
+
   LayoutRect previous_visual_overflow_rect = VisualOverflowRect();
   ClearVisualOverflow();
   AddVisualOverflowFromChildren();
@@ -2456,6 +2468,7 @@
       (recompute_floats || CreatesNewFormattingContext() ||
        HasSelfPaintingLayer()))
     AddVisualOverflowFromFloats();
+
   if (VisualOverflowRect() != previous_visual_overflow_rect) {
     InvalidateIntersectionObserverCachedRects();
     SetShouldCheckForPaintInvalidation();
@@ -4642,13 +4655,8 @@
     }
   }
 
-  bool move_caret_to_boundary =
-      GetDocument()
-          .GetFrame()
-          ->GetEditor()
-          .Behavior()
-          .ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
-
+  const bool move_caret_to_boundary =
+      ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
   if (!move_caret_to_boundary && !closest_box && last_root_box_with_children) {
     // y coordinate is below last root line box, pretend we hit it
     closest_box =
@@ -4712,6 +4720,15 @@
   return CreatePositionWithAffinity(0);
 }
 
+bool LayoutBlockFlow::ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom()
+    const {
+  return GetDocument()
+      .GetFrame()
+      ->GetEditor()
+      .Behavior()
+      .ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
+}
+
 #if DCHECK_IS_ON()
 
 void LayoutBlockFlow::ShowLineTreeAndMark(const InlineBox* marked_box1,
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.h b/third_party/blink/renderer/core/layout/layout_block_flow.h
index 45f4ca5..f9086de 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.h
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.h
@@ -436,6 +436,7 @@
   PositionWithAffinity PositionForPoint(const PhysicalOffset&) const override;
   PositionWithAffinity PositionForPoint(const LayoutObject& offset_parent,
                                         const PhysicalOffset& offset) const;
+  bool ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom() const;
 
   LayoutUnit LowestFloatLogicalBottom(EClear = EClear::kBoth) const;
 
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
index 3a102d8..b01936d 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow_line.cc
@@ -2403,6 +2403,10 @@
 }
 
 void LayoutBlockFlow::AddVisualOverflowFromInlineChildren() {
+  // TODO(crbug.com/1086968): Change to DCHECK after diagnosing the bug.
+  CHECK(!NeedsLayout());
+  DCHECK(!PrePaintBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren));
+
   if (const NGPaintFragment* paint_fragment = PaintFragment()) {
     for (const NGPaintFragment* child : paint_fragment->Children()) {
       if (child->HasSelfPaintingLayer())
@@ -2465,6 +2469,8 @@
 }
 
 void LayoutBlockFlow::AddLayoutOverflowFromInlineChildren() {
+  DCHECK(!LayoutBlockedByDisplayLock(DisplayLockLifecycleTarget::kChildren));
+
   LayoutUnit end_padding = HasOverflowClip() ? PaddingEnd() : LayoutUnit();
   // FIXME: Need to find another way to do this, since scrollbars could show
   // when we don't want them to.
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc
index 325cf499..4436e4c8 100644
--- a/third_party/blink/renderer/core/layout/layout_box.cc
+++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -266,13 +266,10 @@
 LayoutBox::~LayoutBox() = default;
 
 PaintLayerType LayoutBox::LayerTypeRequired() const {
-  // hasAutoZIndex only returns true if the element is positioned or a flex-item
-  // since position:static elements that are not flex-items get their z-index
-  // coerced to auto.
-  if (IsPositioned() || CreatesGroup() || HasTransformRelatedProperty() ||
-      HasHiddenBackface() || HasReflection() ||
+  // TODO(pdr): IsStacked() includes many of the same checks as CreatesGroup()
+  // and these can be unified to do fewer redundant checks.
+  if (IsStacked() || CreatesGroup() || HasHiddenBackface() ||
       (StyleRef().SpecifiesColumns() && !CanTraversePhysicalFragments()) ||
-      IsStackingContext() || StyleRef().ShouldCompositeForCurrentAnimations() ||
       IsEffectiveRootScroller())
     return kNormalPaintLayer;
 
diff --git a/third_party/blink/renderer/core/layout/layout_image.cc b/third_party/blink/renderer/core/layout/layout_image.cc
index 3f48074c..eff5e034 100644
--- a/third_party/blink/renderer/core/layout/layout_image.cc
+++ b/third_party/blink/renderer/core/layout/layout_image.cc
@@ -116,7 +116,7 @@
 
   // If error occurred, image marker should be replaced by a LayoutText.
   // NotifyOfSubtreeChange to make list item updating its marker content.
-  if (IsLayoutNGListMarkerImage() && image_resource_->ErrorOccurred())
+  if (IsListMarkerImage() && image_resource_->ErrorOccurred())
     NotifyOfSubtreeChange();
 
   // Per the spec, we let the server-sent header override srcset/other sources
@@ -380,7 +380,7 @@
     // Our intrinsicSize is empty if we're laying out generated images with
     // relative width/height. Figure out the right intrinsic size to use.
     if (intrinsic_sizing_info.size.IsEmpty() &&
-        !image_resource_->HasIntrinsicSize() && !IsLayoutNGListMarkerImage()) {
+        !image_resource_->HasIntrinsicSize() && !IsListMarkerImage()) {
       if (HasOverrideContainingBlockContentLogicalWidth() &&
           HasOverrideContainingBlockContentLogicalHeight()) {
         intrinsic_sizing_info.size.SetWidth(
diff --git a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
index 9e78085..db5476d 100644
--- a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
+++ b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
@@ -28,8 +28,8 @@
 
 #include "third_party/blink/renderer/core/layout/layout_image_resource_style_image.h"
 
+#include "third_party/blink/renderer/core/layout/layout_list_marker_image.h"
 #include "third_party/blink/renderer/core/layout/layout_replaced.h"
-#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h"
 #include "third_party/blink/renderer/core/style/style_fetched_image.h"
 
 namespace blink {
@@ -72,8 +72,8 @@
 FloatSize LayoutImageResourceStyleImage::ImageSize(float multiplier) const {
   // TODO(davve): Find out the correct default object size in this context.
   LayoutSize default_size =
-      layout_object_->IsLayoutNGListMarkerImage()
-          ? ToLayoutNGListMarkerImage(layout_object_)->DefaultSize()
+      layout_object_->IsListMarkerImage()
+          ? ToLayoutListMarkerImage(layout_object_)->DefaultSize()
           : LayoutSize(LayoutReplaced::kDefaultWidth,
                        LayoutReplaced::kDefaultHeight);
   return ImageSizeWithDefaultSize(multiplier, default_size);
diff --git a/third_party/blink/renderer/core/layout/layout_inline_test.cc b/third_party/blink/renderer/core/layout/layout_inline_test.cc
index f2af84a..21dc245 100644
--- a/third_party/blink/renderer/core/layout/layout_inline_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_inline_test.cc
@@ -111,14 +111,6 @@
       ToLayoutInline(GetLayoutObjectByElementId("lotsOfBoxes"));
   ASSERT_TRUE(lots_of_boxes);
 
-  if (RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
-    NGInlineCursor cursor;
-    cursor.MoveTo(*lots_of_boxes);
-    ASSERT_TRUE(cursor);
-    EXPECT_EQ(lots_of_boxes, cursor.Current().GetLayoutObject());
-    return;
-  }
-
   HitTestRequest hit_request(HitTestRequest::kTouchEvent |
                              HitTestRequest::kListBased);
 
@@ -149,9 +141,10 @@
   }
 
   const auto* div = To<LayoutBlockFlow>(lots_of_boxes->Parent());
-  for (const NGPaintFragment* line : div->PaintFragment()->Children()) {
-    DCHECK(line->PhysicalFragment().IsLineBox());
-    NGInlineCursor line_cursor(*line);
+  NGInlineCursor cursor(*div);
+  for (cursor.MoveToFirstLine(); cursor; cursor.MoveToNextLine()) {
+    DCHECK(cursor.Current().IsLineBox());
+    NGInlineCursor line_cursor = cursor.CursorForDescendants();
     bool hit_outcome = lots_of_boxes->HitTestCulledInline(
         hit_result, location, hit_offset, &line_cursor);
     EXPECT_FALSE(hit_outcome);
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc b/third_party/blink/renderer/core/layout/layout_list_marker_image.cc
similarity index 72%
rename from third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
rename to third_party/blink/renderer/core/layout/layout_list_marker_image.cc
index fa06cf0..ae1b5fb8 100644
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.cc
+++ b/third_party/blink/renderer/core/layout/layout_list_marker_image.cc
@@ -1,8 +1,8 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
+// Copyright 2020 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h"
+#include "third_party/blink/renderer/core/layout/layout_list_marker_image.h"
 
 #include "third_party/blink/renderer/core/layout/intrinsic_sizing_info.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_item.h"
@@ -10,26 +10,25 @@
 
 namespace blink {
 
-LayoutNGListMarkerImage::LayoutNGListMarkerImage(Element* element)
+LayoutListMarkerImage::LayoutListMarkerImage(Element* element)
     : LayoutImage(element) {}
 
-LayoutNGListMarkerImage* LayoutNGListMarkerImage::CreateAnonymous(
+LayoutListMarkerImage* LayoutListMarkerImage::CreateAnonymous(
     Document* document) {
-  LayoutNGListMarkerImage* object = new LayoutNGListMarkerImage(nullptr);
+  LayoutListMarkerImage* object = new LayoutListMarkerImage(nullptr);
   object->SetDocumentForAnonymous(document);
   return object;
 }
 
-bool LayoutNGListMarkerImage::IsOfType(LayoutObjectType type) const {
-  return type == kLayoutObjectNGListMarkerImage || LayoutImage::IsOfType(type);
+bool LayoutListMarkerImage::IsOfType(LayoutObjectType type) const {
+  return type == kLayoutObjectListMarkerImage || LayoutImage::IsOfType(type);
 }
 
-LayoutSize LayoutNGListMarkerImage::DefaultSize() const {
+LayoutSize LayoutListMarkerImage::DefaultSize() const {
   const SimpleFontData* font_data = Style()->GetFont().PrimaryFont();
   DCHECK(font_data);
   if (!font_data)
     return LayoutSize(kDefaultWidth, kDefaultHeight);
-
   LayoutUnit bullet_width =
       font_data->GetFontMetrics().Ascent() / LayoutUnit(2);
   return LayoutSize(bullet_width, bullet_width);
@@ -38,7 +37,7 @@
 // Because ImageResource() is always LayoutImageResourceStyleImage. So we could
 // use StyleImage::ImageSize to determine the concrete object size with
 // default object size(ascent/2 x ascent/2).
-void LayoutNGListMarkerImage::ComputeIntrinsicSizingInfoByDefaultSize(
+void LayoutListMarkerImage::ComputeIntrinsicSizingInfoByDefaultSize(
     IntrinsicSizingInfo& intrinsic_sizing_info) const {
   FloatSize concrete_size = ImageResource()->ImageSizeWithDefaultSize(
       Style()->EffectiveZoom(), DefaultSize());
@@ -51,7 +50,7 @@
   intrinsic_sizing_info.has_height = true;
 }
 
-void LayoutNGListMarkerImage::ComputeIntrinsicSizingInfo(
+void LayoutListMarkerImage::ComputeIntrinsicSizingInfo(
     IntrinsicSizingInfo& intrinsic_sizing_info) const {
   LayoutImage::ComputeIntrinsicSizingInfo(intrinsic_sizing_info);
 
diff --git a/third_party/blink/renderer/core/layout/layout_list_marker_image.h b/third_party/blink/renderer/core/layout/layout_list_marker_image.h
new file mode 100644
index 0000000..878cde8
--- /dev/null
+++ b/third_party/blink/renderer/core/layout/layout_list_marker_image.h
@@ -0,0 +1,36 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_LIST_MARKER_IMAGE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_LIST_MARKER_IMAGE_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/layout/layout_image.h"
+
+namespace blink {
+
+class Document;
+
+class CORE_EXPORT LayoutListMarkerImage final : public LayoutImage {
+ public:
+  explicit LayoutListMarkerImage(Element*);
+  static LayoutListMarkerImage* CreateAnonymous(Document*);
+
+  bool IsLayoutNGObject() const override {
+    return IsLayoutNGObjectForListMarkerImage();
+  }
+  LayoutSize DefaultSize() const;
+
+ private:
+  bool IsOfType(LayoutObjectType) const override;
+
+  void ComputeIntrinsicSizingInfoByDefaultSize(IntrinsicSizingInfo&) const;
+  void ComputeIntrinsicSizingInfo(IntrinsicSizingInfo&) const final;
+};
+
+DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutListMarkerImage, IsListMarkerImage());
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_LIST_MARKER_IMAGE_H_
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index b3d876ec..1bd7786 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -688,9 +688,6 @@
   bool IsLayoutNGInsideListMarker() const {
     return IsOfType(kLayoutObjectNGInsideListMarker);
   }
-  bool IsLayoutNGListMarkerImage() const {
-    return IsOfType(kLayoutObjectNGListMarkerImage);
-  }
   bool IsLayoutNGOutsideListMarker() const {
     return IsOfType(kLayoutObjectNGOutsideListMarker);
   }
@@ -703,6 +700,9 @@
     return IsOfType(kLayoutObjectLayoutNGTableCol);
   }
   bool IsListItem() const { return IsOfType(kLayoutObjectListItem); }
+  bool IsListMarkerImage() const {
+    return IsOfType(kLayoutObjectListMarkerImage);
+  }
   bool IsMathML() const { return IsOfType(kLayoutObjectMathML); }
   bool IsMathMLRoot() const { return IsOfType(kLayoutObjectMathMLRoot); }
   bool IsMedia() const { return IsOfType(kLayoutObjectMedia); }
@@ -1177,6 +1177,8 @@
   bool ShouldClipOverflow() const { return bitfields_.ShouldClipOverflow(); }
   bool HasClipRelatedProperty() const;
 
+  // Not returning StyleRef().HasTransformRelatedProperty() because some objects
+  // ignore the transform-related styles (e.g. LayoutInline, LayoutSVGBlock).
   bool HasTransformRelatedProperty() const {
     return bitfields_.HasTransformRelatedProperty();
   }
@@ -1192,8 +1194,8 @@
 
   // Returns |true| if any property that renders using filter operations is
   // used (including, but not limited to, 'filter' and 'box-reflect').
-  // Not calling style()->hasFilterInducingProperty because some objects force
-  // to ignore reflection style (e.g. LayoutInline).
+  // Not calling StyleRef().HasFilterInducingProperty() because some objects
+  // ignore reflection style (e.g. LayoutInline, LayoutSVGBlock).
   bool HasFilterInducingProperty() const {
     return StyleRef().HasNonInitialFilter() || HasReflection();
   }
@@ -1993,6 +1995,8 @@
            !IsLayoutNGOutsideListMarker() && !IsOutsideListMarker();
   }
 
+  // Not returning StyleRef().BoxReflect() because some objects ignore the
+  // reflection style (e.g. LayoutInline, LayoutSVGBlock).
   bool HasReflection() const { return bitfields_.HasReflection(); }
 
   // The current selection state for an object.  For blocks, the state refers to
@@ -2600,6 +2604,15 @@
     node_ = document;
   }
 
+  bool IsLayoutNGObjectForListMarkerImage() const {
+    DCHECK(IsListMarkerImage());
+    return bitfields_.IsLayoutNGObjectForListMarkerImage();
+  }
+  void SetIsLayoutNGObjectForListMarkerImage(bool b) {
+    DCHECK(IsListMarkerImage());
+    bitfields_.SetIsLayoutNGObjectForListMarkerImage(b);
+  }
+
  protected:
   enum LayoutObjectType {
     kLayoutObjectBr,
@@ -2615,6 +2628,7 @@
     kLayoutObjectLayoutTableCol,
     kLayoutObjectLayoutNGTableCol,
     kLayoutObjectListItem,
+    kLayoutObjectListMarkerImage,
     kLayoutObjectMathML,
     kLayoutObjectMathMLRoot,
     kLayoutObjectMedia,
@@ -2626,7 +2640,6 @@
     kLayoutObjectNGListItem,
     kLayoutObjectNGInsideListMarker,
     kLayoutObjectNGOutsideListMarker,
-    kLayoutObjectNGListMarkerImage,
     kLayoutObjectNGProgress,
     kLayoutObjectNGText,
     kLayoutObjectOutsideListMarker,
@@ -3170,8 +3183,9 @@
     // control clips or contain: paint.
     ADD_BOOLEAN_BITFIELD(should_clip_overflow_, ShouldClipOverflow);
 
-    // This boolean is the cached value from
-    // ComputedStyle::hasTransformRelatedProperty.
+    // The cached value from ComputedStyle::HasTransformRelatedProperty for
+    // objects that do not ignore transform-related styles (e.g. not
+    // LayoutInline, LayoutSVGBlock).
     ADD_BOOLEAN_BITFIELD(has_transform_related_property_,
                          HasTransformRelatedProperty);
     ADD_BOOLEAN_BITFIELD(has_reflection_, HasReflection);
@@ -3282,6 +3296,10 @@
     // True at start of |Destroy()| before calling |WillBeDestroyed()|.
     ADD_BOOLEAN_BITFIELD(being_destroyed_, BeingDestroyed);
 
+    // From LayoutListMarkerImage
+    ADD_BOOLEAN_BITFIELD(is_layout_ng_object_for_list_marker_image,
+                         IsLayoutNGObjectForListMarkerImage);
+
    private:
     // This is the cached 'position' value of this object
     // (see ComputedStyle::position).
diff --git a/third_party/blink/renderer/core/layout/layout_view_test.cc b/third_party/blink/renderer/core/layout/layout_view_test.cc
index e41c964..ce2abae 100644
--- a/third_party/blink/renderer/core/layout/layout_view_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_view_test.cc
@@ -135,10 +135,6 @@
  protected:
   bool LayoutNG() { return RuntimeEnabledFeatures::LayoutNGEnabled(); }
   bool IsAndroidOrWindowsEditingBehavior() {
-    // TODO(crbug.com/971414): For now LayoutNG always uses Android/Windows
-    // behavior for ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom().
-    if (LayoutNG())
-      return true;
     return GetParam().editing_behavior == kEditingAndroidBehavior ||
            GetParam().editing_behavior == kEditingWindowsBehavior;
   }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
index 93fd958b..7b34558 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h"
 
+#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h"
@@ -159,7 +160,9 @@
   // This is needed because the container size may be different, in that case,
   // the physical offsets are different when `writing-mode: vertial-rl`.
   DCHECK(!is_converted_to_physical_);
-  const WritingMode line_writing_mode = ToLineWritingMode(writing_mode_);
+  const WritingModeConverter converter(GetWritingDirection(), container_size);
+  WritingModeConverter line_converter(
+      {ToLineWritingMode(GetWritingMode()), TextDirection::kLtr});
 
   const NGFragmentItem* const end_item =
       stop_at_dirty ? items.EndOfReusableItems() : nullptr;
@@ -174,8 +177,7 @@
     DCHECK(!item.IsDirty());
 
     const LogicalOffset item_offset =
-        item.OffsetInContainerBlock().ConvertToLogical(
-            writing_mode_, direction_, container_size, item.Size());
+        converter.ToLogical(item.OffsetInContainerBlock(), item.Size());
 
     if (item.Type() == NGFragmentItem::kLine) {
       DCHECK(item.LineBoxFragment());
@@ -189,14 +191,15 @@
       items_.emplace_back(item_offset,
                           std::move(const_cast<NGFragmentItem&>(item)));
       const PhysicalRect line_box_bounds = item.RectInContainerBlock();
+      line_converter.SetOuterSize(line_box_bounds.size);
       for (NGInlineCursor line = cursor.CursorForDescendants(); line;
            line.MoveToNext()) {
         const NGFragmentItem& line_child = *line.Current().Item();
         DCHECK(line_child.CanReuse());
         items_.emplace_back(
-            (line_child.OffsetInContainerBlock() - line_box_bounds.offset)
-                .ConvertToLogical(line_writing_mode, TextDirection::kLtr,
-                                  line_box_bounds.size, line_child.Size()),
+            line_converter.ToLogical(
+                line_child.OffsetInContainerBlock() - line_box_bounds.offset,
+                line_child.Size()),
             std::move(const_cast<NGFragmentItem&>(line_child)));
       }
       cursor.MoveToNextSkippingChildren();
@@ -235,14 +238,16 @@
   if (is_converted_to_physical_)
     return;
 
+  const WritingModeConverter converter(GetWritingDirection(), outer_size);
   // Children of lines have line-relative offsets. Use line-writing mode to
-  // convert their logical offsets.
-  const WritingMode line_writing_mode = ToLineWritingMode(writing_mode_);
+  // convert their logical offsets. Use `kLtr` because inline items are after
+  // bidi-reoder, and that their offset is visual, not logical.
+  WritingModeConverter line_converter(
+      {ToLineWritingMode(GetWritingMode()), TextDirection::kLtr});
 
   for (ItemWithOffset* iter = items_.begin(); iter != items_.end(); ++iter) {
     NGFragmentItem* item = &iter->item;
-    item->SetOffset(iter->offset.ConvertToPhysical(writing_mode_, direction_,
-                                                   outer_size, item->Size()));
+    item->SetOffset(converter.ToPhysical(iter->offset, item->Size()));
 
     // Transform children of lines separately from children of the block,
     // because they may have different directions from the block. To do
@@ -252,16 +257,14 @@
       DCHECK(descendants_count);
       if (descendants_count) {
         const PhysicalRect line_box_bounds = item->RectInContainerBlock();
+        line_converter.SetOuterSize(line_box_bounds.size);
         while (--descendants_count) {
           ++iter;
           DCHECK_NE(iter, items_.end());
           item = &iter->item;
-          // Use `kLtr` because inline items are after bidi-reoder, and that
-          // their offset is visual, not logical.
-          item->SetOffset(iter->offset.ConvertToPhysical(
-                              line_writing_mode, TextDirection::kLtr,
-                              line_box_bounds.size, item->Size()) +
-                          line_box_bounds.offset);
+          item->SetOffset(
+              line_converter.ToPhysical(iter->offset, item->Size()) +
+              line_box_bounds.offset);
         }
       }
     }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
index 8859aa2..bba8ab9 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_fragment_items_builder.h
@@ -27,6 +27,9 @@
                          WritingMode writing_mode,
                          TextDirection direction);
 
+  WritingDirectionMode GetWritingDirection() const {
+    return {writing_mode_, direction_};
+  }
   WritingMode GetWritingMode() const { return writing_mode_; }
   TextDirection Direction() const { return direction_; }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
index 62206b6..700dde8 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.cc
@@ -741,18 +741,45 @@
     MoveToNextItem();
   }
 
+  // At here, |point| is not inside any line in |this|:
+  //   |closest_line_before|
+  //   |point|
+  //   |closest_line_after|
   if (closest_line_after) {
     MoveTo(closest_line_after);
-    if (const PositionWithAffinity child_position =
-            PositionForPointInInlineBox(point))
+    // Note: |move_caret_to_boundary| is true for Mac and Unix.
+    const bool move_caret_to_boundary =
+        To<LayoutBlockFlow>(Current().GetLayoutObject())
+            ->ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
+    if (move_caret_to_boundary) {
+      // Tests[1-3] reach here.
+      // [1] editing/selection/click-in-margins-inside-editable-div.html
+      // [2] fast/writing-mode/flipped-blocks-hit-test-line-edges.html
+      // [3] All/LayoutViewHitTestTest.HitTestHorizontal/4
+      if (auto first_position = PositionForStartOfLine())
+        return PositionWithAffinity(first_position.GetPosition());
+    } else if (const PositionWithAffinity child_position =
+                   PositionForPointInInlineBox(point))
       return child_position;
   }
 
   if (closest_line_before) {
     MoveTo(closest_line_before);
-    if (const PositionWithAffinity child_position =
-            PositionForPointInInlineBox(point))
+    // Note: |move_caret_to_boundary| is true for Mac and Unix.
+    const bool move_caret_to_boundary =
+        To<LayoutBlockFlow>(Current().GetLayoutObject())
+            ->ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
+    if (move_caret_to_boundary) {
+      // Tests[1-3] reach here.
+      // [1] editing/selection/click-in-margins-inside-editable-div.html
+      // [2] fast/writing-mode/flipped-blocks-hit-test-line-edges.html
+      // [3] All/LayoutViewHitTestTest.HitTestHorizontal/4
+      if (auto last_position = PositionForEndOfLine())
+        return PositionWithAffinity(last_position.GetPosition());
+    } else if (const PositionWithAffinity child_position =
+                   PositionForPointInInlineBox(point)) {
       return child_position;
+    }
   }
 
   return PositionWithAffinity();
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 92ef98f4..e04b056 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
@@ -140,13 +140,16 @@
     return end_offsets;
   }
 
-  void TestFirstLineIsDirty(LayoutBlockFlow* block_flow, bool expected) {
+  void TestAnyItrermsAreDirty(LayoutBlockFlow* block_flow, bool expected) {
     const NGFragmentItems* items = block_flow->FragmentItems();
     items->DirtyLinesFromNeedsLayout(block_flow);
-    const NGFragmentItem* end_reusable_item = items->EndOfReusableItems();
-    NGInlineCursor cursor(*items);
-    cursor.MoveToFirstLine();
-    EXPECT_EQ(cursor.Current().Item() == end_reusable_item, expected);
+    // Check |NGFragmentItem::IsDirty| directly without using
+    // |EndOfReusableItems|. This is different from the line cache logic, but
+    // some items may not be reusable even if |!IsDirty()|.
+    const bool is_any_items_dirty =
+        std::any_of(items->Items().begin(), items->Items().end(),
+                    [](const NGFragmentItem& item) { return item.IsDirty(); });
+    EXPECT_EQ(is_any_items_dirty, expected);
   }
 
   scoped_refptr<const ComputedStyle> style_;
@@ -636,8 +639,8 @@
 
   if (data.is_line_dirty &&
       RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
-    TestFirstLineIsDirty(To<LayoutBlockFlow>(container->GetLayoutObject()),
-                         *data.is_line_dirty);
+    TestAnyItrermsAreDirty(To<LayoutBlockFlow>(container->GetLayoutObject()),
+                           *data.is_line_dirty);
   }
 
   ForceLayout();  // Ensure running layout does not crash.
@@ -1035,9 +1038,11 @@
   // Keep the text fragment to compare later.
   Element* inner_span = GetElementById("inner_span");
   Node* text = inner_span->firstChild();
-  scoped_refptr<NGPaintFragment> text_fragment_before_split =
-      text->GetLayoutObject()->FirstInlineFragment();
-  EXPECT_NE(text_fragment_before_split.get(), nullptr);
+  NGInlineCursor before_split;
+  before_split.MoveTo(*text->GetLayoutObject());
+  EXPECT_TRUE(before_split);
+  scoped_refptr<const NGPaintFragment> text_fragment_before_split =
+      before_split.Current().PaintFragment();
 
   // Append <div> to <span>. causing SplitFlow().
   Element* outer_span = GetElementById("outer_span");
@@ -1053,23 +1058,32 @@
   // destroyed, and should not be accessible.
   GetDocument().UpdateStyleAndLayoutTree();
   EXPECT_FALSE(text->GetLayoutObject()->IsInLayoutNGInlineFormattingContext());
-  scoped_refptr<NGPaintFragment> text_fragment_before_layout =
-      text->GetLayoutObject()->FirstInlineFragment();
-  EXPECT_EQ(text_fragment_before_layout, nullptr);
+  EXPECT_FALSE(text->GetLayoutObject()->HasInlineFragments());
 
   // Update layout. There should be a different instance of the text fragment.
   UpdateAllLifecyclePhasesForTest();
-  scoped_refptr<NGPaintFragment> text_fragment_after_layout =
-      text->GetLayoutObject()->FirstInlineFragment();
-  EXPECT_NE(text_fragment_before_split, text_fragment_after_layout);
+  NGInlineCursor after_layout;
+  after_layout.MoveTo(*text->GetLayoutObject());
+  EXPECT_TRUE(after_layout);
+  if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+    EXPECT_NE(text_fragment_before_split.get(),
+              after_layout.Current().PaintFragment());
+  }
 
   // Check it is the one owned by the new root inline formatting context.
   LayoutBlock* anonymous_block =
       inner_span->GetLayoutObject()->ContainingBlock();
   EXPECT_TRUE(anonymous_block->IsAnonymous());
-  const NGPaintFragment* block_fragment = anonymous_block->PaintFragment();
-  const NGPaintFragment* line_box_fragment = block_fragment->FirstChild();
-  EXPECT_EQ(line_box_fragment->FirstChild(), text_fragment_after_layout);
+  NGInlineCursor anonymous_block_cursor(*To<LayoutBlockFlow>(anonymous_block));
+  anonymous_block_cursor.MoveToFirstLine();
+  anonymous_block_cursor.MoveToFirstChild();
+  EXPECT_TRUE(anonymous_block_cursor);
+  EXPECT_EQ(anonymous_block_cursor.Current().GetLayoutObject(),
+            text->GetLayoutObject());
+  if (!RuntimeEnabledFeatures::LayoutNGFragmentItemEnabled()) {
+    EXPECT_EQ(anonymous_block_cursor.Current().PaintFragment(),
+              after_layout.Current().PaintFragment());
+  }
 }
 
 TEST_F(NGInlineNodeTest, AddChildToSVGRoot) {
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h b/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
deleted file mode 100644
index b8a2031..0000000
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h
+++ /dev/null
@@ -1,35 +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 THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LIST_LAYOUT_NG_LIST_MARKER_IMAGE_H_
-#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LIST_LAYOUT_NG_LIST_MARKER_IMAGE_H_
-
-#include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/layout/layout_image.h"
-
-namespace blink {
-
-class Document;
-
-class CORE_EXPORT LayoutNGListMarkerImage final : public LayoutImage {
- public:
-  explicit LayoutNGListMarkerImage(Element*);
-  static LayoutNGListMarkerImage* CreateAnonymous(Document*);
-
-  bool IsLayoutNGObject() const override { return true; }
-  LayoutSize DefaultSize() const;
-
- private:
-  bool IsOfType(LayoutObjectType) const override;
-
-  void ComputeIntrinsicSizingInfoByDefaultSize(IntrinsicSizingInfo&) const;
-  void ComputeIntrinsicSizingInfo(IntrinsicSizingInfo&) const final;
-};
-
-DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutNGListMarkerImage,
-                                IsLayoutNGListMarkerImage());
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_LIST_LAYOUT_NG_LIST_MARKER_IMAGE_H_
diff --git a/third_party/blink/renderer/core/layout/ng/list/list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/list_marker.cc
index 9f00e95..c33ac41 100644
--- a/third_party/blink/renderer/core/layout/ng/list/list_marker.cc
+++ b/third_party/blink/renderer/core/layout/ng/list/list_marker.cc
@@ -5,9 +5,9 @@
 #include "third_party/blink/renderer/core/layout/ng/list/list_marker.h"
 
 #include "third_party/blink/renderer/core/layout/layout_image_resource_style_image.h"
+#include "third_party/blink/renderer/core/layout/layout_list_marker_image.h"
 #include "third_party/blink/renderer/core/layout/list_marker_text.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_inside_list_marker.h"
-#include "third_party/blink/renderer/core/layout/ng/list/layout_ng_list_marker_image.h"
 #include "third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.h"
 
 namespace blink {
@@ -209,8 +209,9 @@
       }
     }
     if (!child) {
-      LayoutNGListMarkerImage* image =
-          LayoutNGListMarkerImage::CreateAnonymous(&marker.GetDocument());
+      LayoutListMarkerImage* image =
+          LayoutListMarkerImage::CreateAnonymous(&marker.GetDocument());
+      image->SetIsLayoutNGObjectForListMarkerImage(true);
       scoped_refptr<ComputedStyle> image_style =
           ComputedStyle::CreateAnonymousStyleWithDisplay(marker.StyleRef(),
                                                          EDisplay::kInline);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index 722f296..e678497 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -2161,9 +2161,9 @@
       BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit();
   LayoutUnit space_left = FragmentainerSpaceAvailable();
   LayoutUnit block_size;
-  if (container_builder_.BoxType() == NGPhysicalFragment::kColumnBox &&
+  if (container_builder_.IsFragmentainerBoxType() &&
       ConstraintSpace().HasKnownFragmentainerBlockSize()) {
-    // We're building column fragments, and we know the column size. Just use
+    // We're building fragmentainers, and we know their block-size. Just use
     // that. Calculating the size the regular way would cause some problems with
     // overflow. For one, we don't want to produce a break token if there's no
     // child content that requires it.
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
index d7d16d2..2ffda42ba 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -247,6 +247,9 @@
   void SetBoxType(NGPhysicalFragment::NGBoxType box_type) {
     box_type_ = box_type;
   }
+  bool IsFragmentainerBoxType() const {
+    return BoxType() == NGPhysicalFragment::kColumnBox;
+  }
   void SetIsFieldsetContainer() { is_fieldset_container_ = true; }
   void SetIsLegacyLayoutRoot() { is_legacy_layout_root_ = true; }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc b/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
index 6275cba..8d9dbb5 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.cc
@@ -97,7 +97,7 @@
                current_.link_.fragment->GetLayoutObject());
     current_.break_token_for_fragmentainer_only_ = false;
   } else if (is_fragmentation_context_root_ && previous_fragment) {
-    if (previous_fragment->IsColumnBox()) {
+    if (previous_fragment->IsFragmentainerBox()) {
       // The outgoing break token from one fragmentainer is the incoming break
       // token to the next one. This is also true when there are column spanners
       // between two columns (fragmentainers); the outgoing break token from the
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h b/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
index c4927f0a..5f295d91 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragment_child_iterator.h
@@ -89,7 +89,7 @@
         // be used by a subsequent fragmentainer. Other fragment types (such as
         // column spanners) need to ignore it.
         if (break_token_for_fragmentainer_only_ &&
-            !link_.fragment->IsColumnBox())
+            !link_.fragment->IsFragmentainerBox())
           return nullptr;
       }
       return block_break_token_;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
index 1a9230f..4a45afa 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/layout/ng/ng_physical_container_fragment.h"
 
+#include "third_party/blink/renderer/core/layout/geometry/writing_mode_converter.h"
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
 #include "third_party/blink/renderer/core/layout/layout_inline.h"
 #include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_cursor.h"
@@ -71,11 +72,12 @@
   // Because flexible arrays need to be the last member in a class, we need to
   // have the buffer passed as a constructor argument and have the actual
   // storage be part of the subclass.
+  const WritingModeConverter converter(
+      {block_or_line_writing_mode, builder->Direction()}, size);
   wtf_size_t i = 0;
   for (auto& child : builder->children_) {
-    buffer[i].offset = child.offset.ConvertToPhysical(
-        block_or_line_writing_mode, builder->Direction(), size,
-        child.fragment->Size());
+    buffer[i].offset =
+        converter.ToPhysical(child.offset, child.fragment->Size());
     // Call the move constructor to move without |AddRef|. Fragments in
     // |builder| are not used after |this| was constructed.
     static_assert(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
index 4a13cc05..1dc4eb0 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.cc
@@ -224,7 +224,7 @@
       is_legacy_layout_root_(false),
       is_painted_atomically_(false),
       has_baseline_(false) {
-  DCHECK(builder->layout_object_);
+  CHECK(builder->layout_object_);
 }
 
 NGPhysicalFragment::NGPhysicalFragment(LayoutObject* layout_object,
@@ -243,7 +243,7 @@
       is_legacy_layout_root_(false),
       is_painted_atomically_(false),
       has_baseline_(false) {
-  DCHECK(layout_object);
+  CHECK(layout_object);
 }
 
 // Keep the implementation of the destructor here, to avoid dependencies on
@@ -295,7 +295,7 @@
   // to set.
   if (IsLineBox())
     return false;
-  if (IsColumnBox())
+  if (IsFragmentainerBox())
     return true;
   const LayoutBlock* container = layout_object_->ContainingBlock();
   if (!container)
diff --git a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
index 0bf49c56..68a8794b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_physical_fragment.h
@@ -98,6 +98,7 @@
   bool IsColumnBox() const {
     return IsBox() && BoxType() == NGBoxType::kColumnBox;
   }
+  bool IsFragmentainerBox() const { return IsColumnBox(); }
   // An atomic inline is represented as a kFragmentBox, such as inline block and
   // replaced elements.
   bool IsAtomicInline() const {
@@ -133,7 +134,7 @@
   //
   // [1] https://www.w3.org/TR/css-display-3/#box-tree
   // [2] https://www.w3.org/TR/css-break-3/#fragmentation-container
-  bool IsCSSBox() const { return !IsLineBox() && !IsColumnBox(); }
+  bool IsCSSBox() const { return !IsLineBox() && !IsFragmentainerBox(); }
 
   bool IsBlockFlow() const;
   bool IsAnonymousBlock() const {
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.cc b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
index c02d712d..1d4fbf0 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_resources.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
@@ -599,14 +599,20 @@
                                            const ComputedStyle* style) {
   if (!style)
     return;
-  SVGResourceClient* client = element.GetSVGResourceClient();
+  SVGElementResourceClient* client = element.GetSVGResourceClient();
   if (!client)
     return;
   if (auto* old_reference_clip =
           DynamicTo<ReferenceClipPathOperation>(style->ClipPath()))
     old_reference_clip->RemoveClient(*client);
-  if (style->HasFilter())
+  if (style->HasFilter()) {
     style->Filter().RemoveClient(*client);
+    if (client->ClearFilterData()) {
+      LayoutObject* layout_object = element.GetLayoutObject();
+      LayoutSVGResourceContainer::MarkClientForInvalidation(
+          *layout_object, SVGResourceClient::kPaintInvalidation);
+    }
+  }
   if (StyleSVGResource* masker_resource = style->SvgStyle().MaskerResource())
     masker_resource->RemoveClient(*client);
 }
diff --git a/third_party/blink/renderer/core/loader/document_loader_test.cc b/third_party/blink/renderer/core/loader/document_loader_test.cc
index d359aa8..c680b907 100644
--- a/third_party/blink/renderer/core/loader/document_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/document_loader_test.cc
@@ -255,9 +255,9 @@
   iframe_resource.Finish();
 
   auto* child_frame = To<WebLocalFrameImpl>(MainFrame().FirstChild());
-  auto* child_window = child_frame->GetFrame()->DomWindow();
+  auto* child_document = child_frame->GetFrame()->GetDocument();
 
-  EXPECT_TRUE(child_window->IsFeatureEnabled(
+  EXPECT_TRUE(child_document->IsFeatureEnabled(
       blink::mojom::blink::FeaturePolicyFeature::kPayment));
 }
 // When runtime feature DocumentPolicy is not enabled, specifying
@@ -286,7 +286,7 @@
 
   iframe_resource.Finish();
   auto* child_frame = To<WebLocalFrameImpl>(MainFrame().FirstChild());
-  auto* child_window = child_frame->GetFrame()->DomWindow();
+  auto* child_document = child_frame->GetFrame()->GetDocument();
   auto& console_messages = static_cast<frame_test_helpers::TestWebFrameClient*>(
                                child_frame->Client())
                                ->ConsoleMessages();
@@ -295,24 +295,24 @@
   // violation blocking document load.
   EXPECT_TRUE(console_messages.IsEmpty());
 
-  EXPECT_EQ(child_window->Url(), KURL("https://example.com/foo.html"));
+  EXPECT_EQ(child_document->Url(), KURL("https://example.com/foo.html"));
 
-  EXPECT_FALSE(child_window->document()->IsUseCounted(
+  EXPECT_FALSE(child_document->IsUseCounted(
       mojom::WebFeature::kDocumentPolicyCausedPageUnload));
 
   // Unoptimized-lossless-images should still be allowed in main document.
-  EXPECT_TRUE(Window().IsFeatureEnabled(
+  EXPECT_TRUE(GetDocument().IsFeatureEnabled(
       mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
       PolicyValue(2.0)));
-  EXPECT_TRUE(Window().IsFeatureEnabled(
+  EXPECT_TRUE(GetDocument().IsFeatureEnabled(
       mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
       PolicyValue(1.0)));
 
   // Unoptimized-lossless-images should still be allowed in child document.
-  EXPECT_TRUE(child_window->IsFeatureEnabled(
+  EXPECT_TRUE(child_document->IsFeatureEnabled(
       mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
       PolicyValue(2.0)));
-  EXPECT_TRUE(child_window->IsFeatureEnabled(
+  EXPECT_TRUE(child_document->IsFeatureEnabled(
       mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
       PolicyValue(1.0)));
 }
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index 7f060db..a3797ca 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -35,6 +35,7 @@
 #include "cc/paint/paint_canvas.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/common/input/web_menu_source_type.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
@@ -93,7 +94,8 @@
   void ChromeDestroyed() override {}
   void SetWindowRect(const IntRect&, LocalFrame&) override {}
   IntRect RootWindowRect(LocalFrame&) override { return IntRect(); }
-  void Focus(LocalFrame*) override {}
+  void FocusPage() override {}
+  void DidFocusPage() override {}
   bool CanTakeFocus(mojom::blink::FocusType) override { return false; }
   void TakeFocus(mojom::blink::FocusType) override {}
   void Show(NavigationPolicy) override {}
@@ -419,6 +421,9 @@
   uint32_t Print(const IntRect& rect, cc::PaintCanvas* canvas) const override {
     return 0;
   }
+  AssociatedInterfaceProvider* GetRemoteAssociatedInterfaces() override {
+    return AssociatedInterfaceProvider::GetEmptyAssociatedInterfaceProvider();
+  }
 
   // FrameClient implementation.
   bool InShadowTree() const override { return false; }
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 1a357cc..efcb6e2 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -1038,7 +1038,7 @@
   if (url.GetPath() != kWellKnownConversionRegsitrationPath)
     return false;
 
-  if (!document_->domWindow()->IsFeatureEnabled(
+  if (!document_->IsFeatureEnabled(
           mojom::blink::FeaturePolicyFeature::kConversionMeasurement)) {
     String message =
         "The 'conversion-measurement' feature policy must be enabled to "
diff --git a/third_party/blink/renderer/core/loader/interactive_detector.cc b/third_party/blink/renderer/core/loader/interactive_detector.cc
index 282074c..3dea8d41 100644
--- a/third_party/blink/renderer/core/loader/interactive_detector.cc
+++ b/third_party/blink/renderer/core/loader/interactive_detector.cc
@@ -224,7 +224,6 @@
     event_timestamp = event_platform_timestamp;
   }
 
-  pending_pointerdown_delay_ = base::TimeDelta();
   pending_pointerdown_timestamp_ = base::TimeTicks();
   bool interactive_timing_metrics_changed = false;
 
@@ -260,12 +259,6 @@
     g_num_long_input_events++;
   }
 
-  // Record input delay UKM.
-  ukm::SourceId source_id = GetSupplementable()->UkmSourceID();
-  DCHECK_NE(source_id, ukm::kInvalidSourceId);
-  ukm::builders::InputEvent(source_id)
-      .SetInteractiveTiming_InputDelay(delay.InMilliseconds())
-      .Record(GetUkmRecorder());
   if (GetSupplementable()->Loader()) {
     GetSupplementable()->Loader()->DidObserveInputDelay(delay);
   }
@@ -610,4 +603,49 @@
     ukm::UkmRecorder* test_ukm_recorder) {
   ukm_recorder_ = test_ukm_recorder;
 }
+
+void InteractiveDetector::RecordInputEventTimingUKM(
+    const Event& event,
+    base::TimeTicks event_timestamp,
+    base::TimeTicks processing_start,
+    base::TimeTicks processing_end) {
+  DCHECK(event.isTrusted());
+
+  // This only happens sometimes on tests unrelated to InteractiveDetector. It
+  // is safe to ignore events that are not properly initialized.
+  if (event_timestamp.is_null())
+    return;
+
+  // We can't report a pointerDown until the pointerUp, in case it turns into a
+  // scroll.
+  if (event.type() == event_type_names::kPointerdown) {
+    pending_pointerdown_processing_time_ = processing_end - processing_start;
+    return;
+  }
+
+  base::TimeDelta input_delay;
+  base::TimeDelta processing_time;
+  if (event.type() == event_type_names::kPointerup) {
+    // PointerUp by itself is not considered a significant input.
+    if (!pending_pointerdown_processing_time_)
+      return;
+
+    input_delay = pending_pointerdown_delay_;
+    processing_time = pending_pointerdown_processing_time_.value();
+  } else {
+    processing_time = processing_end - processing_start;
+    input_delay = processing_start - event_timestamp;
+  }
+  pending_pointerdown_delay_ = base::TimeDelta();
+  pending_pointerdown_processing_time_ = base::nullopt;
+
+  // Record InputDelay and Input Event Processing Time UKM.
+  ukm::SourceId source_id = GetSupplementable()->UkmSourceID();
+  DCHECK_NE(source_id, ukm::kInvalidSourceId);
+  ukm::builders::InputEvent(source_id)
+      .SetInteractiveTiming_InputDelay(input_delay.InMilliseconds())
+      .SetInteractiveTiming_ProcessingTime(processing_time.InMilliseconds())
+      .Record(GetUkmRecorder());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/interactive_detector.h b/third_party/blink/renderer/core/loader/interactive_detector.h
index bf45a6a1..e0f90959 100644
--- a/third_party/blink/renderer/core/loader/interactive_detector.h
+++ b/third_party/blink/renderer/core/loader/interactive_detector.h
@@ -120,6 +120,11 @@
 
   void SetUkmRecorderForTesting(ukm::UkmRecorder* test_ukm_recorder);
 
+  void RecordInputEventTimingUKM(const Event& event,
+                                 base::TimeTicks event_timestamp,
+                                 base::TimeTicks processing_start,
+                                 base::TimeTicks processing_end);
+
  private:
   friend class InteractiveDetectorTest;
 
@@ -202,6 +207,10 @@
   void OnLongTaskDetected(base::TimeTicks start_time,
                           base::TimeTicks end_time) override;
 
+  // The duration of event handlers processing the event for the previous
+  // pointer down.
+  base::Optional<base::TimeDelta> pending_pointerdown_processing_time_;
+
   // The duration between the hardware timestamp and when we received the event
   // for the previous pointer down. Only non-zero if we've received a pointer
   // down event, and haven't yet reported the first input delay.
diff --git a/third_party/blink/renderer/core/loader/interactive_detector_test.cc b/third_party/blink/renderer/core/loader/interactive_detector_test.cc
index 4bfb1c4..c21a684b 100644
--- a/third_party/blink/renderer/core/loader/interactive_detector_test.cc
+++ b/third_party/blink/renderer/core/loader/interactive_detector_test.cc
@@ -567,23 +567,28 @@
 }
 
 TEST_F(InteractiveDetectorTest, RecordInputDelayUKM) {
-  base::TimeDelta delay = base::TimeDelta::FromMilliseconds(10);
+  base::TimeDelta delay = base::TimeDelta::FromMilliseconds(20);
+  base::TimeDelta processing_time = base::TimeDelta::FromMilliseconds(10);
   Event event;
   event.SetTrusted(true);
   event.SetType(event_type_names::kClick);
   base::TimeTicks processing_start = Now() + delay;
   base::TimeTicks event_platform_timestamp = Now();
+  base::TimeTicks processing_end = processing_start + processing_time;
 
   ukm::TestAutoSetUkmRecorder test_ukm_recorder;
   GetDetector()->SetUkmRecorderForTesting(&test_ukm_recorder);
-  GetDetector()->HandleForInputDelay(event, event_platform_timestamp,
-                                     processing_start);
+  GetDetector()->RecordInputEventTimingUKM(event, event_platform_timestamp,
+                                           processing_start, processing_end);
   auto entries = test_ukm_recorder.GetEntriesByName(InputEvent::kEntryName);
   EXPECT_EQ(1ul, entries.size());
   auto* entry = entries[0];
   test_ukm_recorder.ExpectEntryMetric(
       entry, InputEvent::kInteractiveTiming_InputDelayName,
       delay.InMilliseconds());
+  test_ukm_recorder.ExpectEntryMetric(
+      entry, InputEvent::kInteractiveTiming_ProcessingTimeName,
+      processing_time.InMilliseconds());
 }
 
 // In tests for Total Blocking Time (TBT) we call SetTimeToInteractive() instead
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h
index 3fe9b69..7079dcd 100644
--- a/third_party/blink/renderer/core/page/chrome_client.h
+++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -148,7 +148,8 @@
   // part of.
   virtual IntRect RootWindowRect(LocalFrame&) = 0;
 
-  virtual void Focus(LocalFrame*) = 0;
+  virtual void FocusPage() = 0;
+  virtual void DidFocusPage() = 0;
 
   virtual bool CanTakeFocus(mojom::blink::FocusType) = 0;
   virtual void TakeFocus(mojom::blink::FocusType) = 0;
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index 79972a73..db2154e 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -200,11 +200,13 @@
   return IntRect(client->WindowRect());
 }
 
-void ChromeClientImpl::Focus(LocalFrame* calling_frame) {
-  if (web_view_->Client()) {
-    web_view_->Client()->DidFocus(
-        calling_frame ? WebLocalFrameImpl::FromFrame(calling_frame) : nullptr);
-  }
+void ChromeClientImpl::FocusPage() {
+  web_view_->Focus();
+}
+
+void ChromeClientImpl::DidFocusPage() {
+  if (web_view_->Client())
+    web_view_->Client()->DidFocus();
 }
 
 bool ChromeClientImpl::CanTakeFocus(mojom::blink::FocusType) {
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h
index e9d36b7..46641a94 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.h
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -68,7 +68,8 @@
   void ChromeDestroyed() override;
   void SetWindowRect(const IntRect&, LocalFrame&) override;
   IntRect RootWindowRect(LocalFrame&) override;
-  void Focus(LocalFrame*) override;
+  void FocusPage() override;
+  void DidFocusPage() override;
   bool CanTakeFocus(mojom::blink::FocusType) override;
   void TakeFocus(mojom::blink::FocusType) override;
   void SetKeyboardFocusURL(Element* new_focus_element) override;
diff --git a/third_party/blink/renderer/core/page/drag_data.cc b/third_party/blink/renderer/core/page/drag_data.cc
index 69e381d..b50ffd8 100644
--- a/third_party/blink/renderer/core/page/drag_data.cc
+++ b/third_party/blink/renderer/core/page/drag_data.cc
@@ -41,13 +41,11 @@
 DragData::DragData(DataObject* data,
                    const FloatPoint& client_position,
                    const FloatPoint& global_position,
-                   DragOperation source_operation_mask,
-                   DragApplicationFlags flags)
+                   DragOperation source_operation_mask)
     : client_position_(client_position),
       global_position_(global_position),
       platform_drag_data_(data),
-      dragging_source_operation_mask_(source_operation_mask),
-      application_flags_(flags) {}
+      dragging_source_operation_mask_(source_operation_mask) {}
 
 bool DragData::ContainsHTML() const {
   return platform_drag_data_->Types().Contains(kMimeTypeTextHTML);
diff --git a/third_party/blink/renderer/core/page/drag_data.h b/third_party/blink/renderer/core/page/drag_data.h
index e5974913..5918a35 100644
--- a/third_party/blink/renderer/core/page/drag_data.h
+++ b/third_party/blink/renderer/core/page/drag_data.h
@@ -40,14 +40,6 @@
 class DocumentFragment;
 class LocalFrame;
 
-enum DragApplicationFlags {
-  kDragApplicationNone = 0,
-  kDragApplicationIsModal = 1,
-  kDragApplicationIsSource = 2,
-  kDragApplicationHasAttachedSheet = 4,
-  kDragApplicationIsCopyKeyDown = 8
-};
-
 class CORE_EXPORT DragData {
   STACK_ALLOCATED();
 
@@ -59,11 +51,9 @@
   DragData(DataObject*,
            const FloatPoint& client_position,
            const FloatPoint& global_position,
-           DragOperation,
-           DragApplicationFlags = kDragApplicationNone);
+           DragOperation);
   const FloatPoint& ClientPosition() const { return client_position_; }
   const FloatPoint& GlobalPosition() const { return global_position_; }
-  DragApplicationFlags Flags() const { return application_flags_; }
   DataObject* PlatformData() const { return platform_drag_data_; }
   DragOperation DraggingSourceOperationMask() const {
     return dragging_source_operation_mask_;
@@ -89,7 +79,6 @@
   const FloatPoint global_position_;
   DataObject* const platform_drag_data_;
   const DragOperation dragging_source_operation_mask_;
-  const DragApplicationFlags application_flags_;
 
   bool ContainsHTML() const;
 };
diff --git a/third_party/blink/renderer/core/page/frame_tree.cc b/third_party/blink/renderer/core/page/frame_tree.cc
index 983f00a..848f917 100644
--- a/third_party/blink/renderer/core/page/frame_tree.cc
+++ b/third_party/blink/renderer/core/page/frame_tree.cc
@@ -217,7 +217,8 @@
 
   if (frame && !new_window) {
     if (frame->GetPage() != current_frame->GetPage())
-      frame->GetPage()->GetChromeClient().Focus(current_frame);
+      frame->FocusPage(current_frame);
+
     // Focusing can fire onblur, so check for detach.
     if (!frame->GetPage())
       frame = nullptr;
diff --git a/third_party/blink/renderer/core/paint/image_painter.cc b/third_party/blink/renderer/core/paint/image_painter.cc
index 036cff6..6436abe 100644
--- a/third_party/blink/renderer/core/paint/image_painter.cc
+++ b/third_party/blink/renderer/core/paint/image_painter.cc
@@ -9,7 +9,6 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/editing/frame_selection.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/html/html_area_element.h"
 #include "third_party/blink/renderer/core/html/html_image_element.h"
@@ -61,7 +60,7 @@
   const String& image_url =
       cached_image ? cached_image->Url().GetString() : g_empty_string;
 
-  return !layout_image.GetDocument().domWindow()->IsFeatureEnabled(
+  return !layout_image.GetDocument().IsFeatureEnabled(
       mojom::blink::DocumentPolicyFeature::kOversizedImages,
       blink::PolicyValue(
           std::max(downscale_ratio_width, downscale_ratio_height),
diff --git a/third_party/blink/renderer/core/paint/line_box_list_painter.cc b/third_party/blink/renderer/core/paint/line_box_list_painter.cc
index 7717975..46b375c 100644
--- a/third_party/blink/renderer/core/paint/line_box_list_painter.cc
+++ b/third_party/blink/renderer/core/paint/line_box_list_painter.cc
@@ -163,7 +163,8 @@
 
   DrawingRecorder recorder(paint_info.context, layout_object,
                            DisplayItem::kForcedColorsModeBackplate);
-  Color backplate_color = style.ForcedBackplateColor();
+  Color backplate_color =
+      layout_object.GetDocument().GetStyleEngine().ForcedBackgroundColor();
   const auto& backplates = GetBackplates(paint_offset);
   for (const auto backplate : backplates)
     paint_info.context.FillRect(FloatRect(backplate), backplate_color);
diff --git a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
index 99f42a2..45c0243 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_box_fragment_painter.cc
@@ -675,7 +675,7 @@
         // that assumes that we have a LayoutObject (and FragmentData).
         PhysicalOffset child_offset = paint_offset + child.offset;
 
-        if (box_child_fragment.IsColumnBox()) {
+        if (box_child_fragment.IsFragmentainerBox()) {
           // This is a fragmentainer, and when node inside a fragmentation
           // context paints multiple block fragments, we need to distinguish
           // between them somehow, for paint caching to work. Therefore,
@@ -823,7 +823,7 @@
       continue;
     }
 
-    if (child_container->IsColumnBox()) {
+    if (child_container->IsFragmentainerBox()) {
       // This is a fragmentainer, and when node inside a fragmentation context
       // paints multiple block fragments, we need to distinguish between them
       // somehow, for paint caching to work. Therefore, establish a display item
@@ -1475,7 +1475,11 @@
 
   DrawingRecorder recorder(paint_info.context, GetDisplayItemClient(),
                            DisplayItem::kForcedColorsModeBackplate);
-  Color backplate_color = style.ForcedBackplateColor();
+  Color backplate_color = PhysicalFragment()
+                              .GetLayoutObject()
+                              ->GetDocument()
+                              .GetStyleEngine()
+                              .ForcedBackgroundColor();
   const auto& backplates = BuildBackplate(line_boxes, paint_offset);
   for (const auto backplate : backplates)
     paint_info.context.FillRect(FloatRect(backplate), backplate_color);
diff --git a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
index aabbc25..d1b1cc9 100644
--- a/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
+++ b/third_party/blink/renderer/core/paint/ng/ng_paint_fragment.cc
@@ -458,7 +458,7 @@
       }
     }
     if (fragment.IsLineBox() || fragment.IsInlineBox() ||
-        fragment.IsColumnBox()) {
+        fragment.IsFragmentainerBox()) {
       child->ClearAssociationWithLayoutObject();
     } else {
       DCHECK(fragment.IsText() || fragment.IsFormattingContextRoot());
@@ -949,16 +949,45 @@
     }
   }
 
+  // Note: |move_caret_to_boundary| is true for Mac and Unix.
+  const bool move_caret_to_boundary =
+      To<LayoutBlockFlow>(GetLayoutObject())
+          ->ShouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
+
+  // At here, |point| is not inside any line in |this|:
+  //   |closest_line_before|
+  //   |point|
+  //   |closest_line_after|
   if (closest_line_after) {
-    if (auto child_position =
-            PositionForPointInChild(*closest_line_after, point))
+    if (move_caret_to_boundary) {
+      // Tests[1-3] reach here.
+      // [1] editing/selection/click-in-margins-inside-editable-div.html
+      // [2] fast/writing-mode/flipped-blocks-hit-test-line-edges.html
+      // [3] All/LayoutViewHitTestTest.HitTestHorizontal/4
+      NGInlineCursor line_box(*this);
+      line_box.MoveTo(*closest_line_after);
+      if (auto first_position = line_box.PositionForStartOfLine())
+        return PositionWithAffinity(first_position.GetPosition());
+    } else if (auto child_position =
+                   PositionForPointInChild(*closest_line_after, point)) {
       return child_position.value();
+    }
   }
 
   if (closest_line_before) {
-    if (auto child_position =
-            PositionForPointInChild(*closest_line_before, point))
+    if (move_caret_to_boundary) {
+      // Tests[1-3] reach here.
+      // [1] editing/selection/click-in-margins-inside-editable-div.html
+      // [2] fast/writing-mode/flipped-blocks-hit-test-line-edges.html
+      // [3] All/LayoutViewHitTestTest.HitTestHorizontal/4
+      NGInlineCursor line_box(*this);
+      line_box.MoveTo(*closest_line_before);
+      if (auto last_position = line_box.PositionForEndOfLine())
+        return PositionWithAffinity(last_position.GetPosition());
+    } else if (auto child_position =
+                   PositionForPointInChild(*closest_line_before, point)) {
       return child_position.value();
+    }
   }
 
   // TODO(xiaochengh): Looking at only the closest lines may not be enough,
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
index 18e6d7a..ab5cc756 100644
--- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
+++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -547,9 +547,9 @@
         continue;
       }
     } else if (!object) {
-      // A column doesn't paint anything itself. Just include its offset and
-      // descend into children.
-      DCHECK((*iterator)->BoxFragment()->IsColumnBox());
+      // A fragmentainer doesn't paint anything itself. Just include its offset
+      // and descend into children.
+      DCHECK((*iterator)->BoxFragment()->IsFragmentainerBox());
       PhysicalOffset offset = (*iterator)->Link().offset;
       PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext*
           fragment_context = nullptr;
diff --git a/third_party/blink/renderer/core/paint/theme_painter_default.cc b/third_party/blink/renderer/core/paint/theme_painter_default.cc
index 9da24a1c..5910864 100644
--- a/third_party/blink/renderer/core/paint/theme_painter_default.cc
+++ b/third_party/blink/renderer/core/paint/theme_painter_default.cc
@@ -350,20 +350,32 @@
   auto* input = DynamicTo<HTMLInputElement>(o.GetNode());
   extra_params.slider.thumb_x = 0;
   extra_params.slider.thumb_y = 0;
+  extra_params.slider.right_to_left = !o.StyleRef().IsLeftToRightDirection();
   if (input) {
     Element* thumb_element = input->UserAgentShadowRoot()
                                  ? input->UserAgentShadowRoot()->getElementById(
                                        shadow_element_names::SliderThumb())
                                  : nullptr;
     LayoutBox* thumb = thumb_element ? thumb_element->GetLayoutBox() : nullptr;
+    LayoutBox* input_box = input->GetLayoutBox();
     if (thumb) {
       IntRect thumb_rect = PixelSnappedIntRect(thumb->FrameRect());
       if (features::IsFormControlsRefreshEnabled()) {
-        extra_params.slider.thumb_x = thumb_rect.X();
-        extra_params.slider.thumb_y = thumb_rect.Y();
+        extra_params.slider.thumb_x = thumb_rect.X() +
+                                      input_box->PaddingLeft().ToInt() +
+                                      input_box->BorderLeft().ToInt();
+        extra_params.slider.thumb_y = thumb_rect.Y() +
+                                      input_box->PaddingTop().ToInt() +
+                                      input_box->BorderTop().ToInt();
       } else {
-        extra_params.slider.thumb_x = thumb_rect.X() / zoom_level;
-        extra_params.slider.thumb_y = thumb_rect.Y() / zoom_level;
+        extra_params.slider.thumb_x =
+            (thumb_rect.X() + input_box->PaddingLeft().ToInt() +
+             input_box->BorderLeft().ToInt()) /
+            zoom_level;
+        extra_params.slider.thumb_y =
+            (thumb_rect.Y() + input_box->PaddingTop().ToInt() +
+             input_box->BorderTop().ToInt()) /
+            zoom_level;
       }
     }
   }
diff --git a/third_party/blink/renderer/core/script/script_loader.cc b/third_party/blink/renderer/core/script/script_loader.cc
index 4871aa3..ddaefa49 100644
--- a/third_party/blink/renderer/core/script/script_loader.cc
+++ b/third_party/blink/renderer/core/script/script_loader.cc
@@ -253,7 +253,7 @@
 bool ShouldBlockSyncScriptForFeaturePolicy(const ScriptElementBase* element,
                                            mojom::ScriptType script_type,
                                            bool parser_inserted) {
-  if (element->GetExecutionContext()->IsFeatureEnabled(
+  if (element->GetDocument().IsFeatureEnabled(
           mojom::blink::FeaturePolicyFeature::kSyncScript)) {
     return false;
   }
diff --git a/third_party/blink/renderer/core/style/computed_style.h b/third_party/blink/renderer/core/style/computed_style.h
index f17ae36..d026ca5 100644
--- a/third_party/blink/renderer/core/style/computed_style.h
+++ b/third_party/blink/renderer/core/style/computed_style.h
@@ -2617,11 +2617,6 @@
     return DarkColorScheme() ? Color::kWhite : Color::kBlack;
   }
 
-  Color ForcedBackplateColor() const {
-    return LayoutTheme::GetTheme().SystemColor(CSSValueID::kCanvas,
-                                               WebColorScheme::kLight);
-  }
-
   bool GeneratesMarkerImage() const {
     return Display() == EDisplay::kListItem && ListStyleImage() &&
            !ListStyleImage()->ErrorOccurred();
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
index 3c01d58c..90968931 100644
--- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc
+++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -853,6 +853,11 @@
           default_settings.GetDefaultFontSize());
       page->GetSettings().SetDefaultFixedFontSize(
           default_settings.GetDefaultFixedFontSize());
+
+      // Also copy the preferred-color-scheme to ensure a responsiveness to
+      // dark/light color schemes.
+      page->GetSettings().SetPreferredColorScheme(
+          default_settings.GetPreferredColorScheme());
     }
   }
 
diff --git a/third_party/blink/renderer/core/svg/svg_image_element.cc b/third_party/blink/renderer/core/svg/svg_image_element.cc
index 6b316ff..46dc7ec0 100644
--- a/third_party/blink/renderer/core/svg/svg_image_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_image_element.cc
@@ -36,9 +36,8 @@
 SVGImageElement::SVGImageElement(Document& document)
     : SVGGraphicsElement(svg_names::kImageTag, document),
       SVGURIReference(this),
-      is_default_overridden_intrinsic_size_(
-          !GetExecutionContext()->IsFeatureEnabled(
-              mojom::blink::DocumentPolicyFeature::kUnsizedMedia)),
+      is_default_overridden_intrinsic_size_(!document.IsFeatureEnabled(
+          mojom::blink::DocumentPolicyFeature::kUnsizedMedia)),
       x_(MakeGarbageCollected<SVGAnimatedLength>(
           this,
           svg_names::kXAttr,
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
index 909fc5ec0..f31f2d49b 100644
--- a/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
+++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.cc
@@ -62,6 +62,8 @@
 
 void FakeLocalFrameHost::DidFocusFrame() {}
 
+void FakeLocalFrameHost::DidCallFocus() {}
+
 void FakeLocalFrameHost::EnforceInsecureRequestPolicy(
     mojom::InsecureRequestPolicy policy_bitmap) {}
 
diff --git a/third_party/blink/renderer/core/testing/fake_local_frame_host.h b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
index 57df70c..773e4b5b 100644
--- a/third_party/blink/renderer/core/testing/fake_local_frame_host.h
+++ b/third_party/blink/renderer/core/testing/fake_local_frame_host.h
@@ -48,6 +48,7 @@
   void DidFailLoadWithError(const ::blink::KURL& url,
                             int32_t error_code) override;
   void DidFocusFrame() override;
+  void DidCallFocus() override;
   void EnforceInsecureRequestPolicy(
       mojom::InsecureRequestPolicy policy_bitmap) override;
   void EnforceInsecureNavigationsSet(const WTF::Vector<uint32_t>& set) override;
diff --git a/third_party/blink/renderer/core/timing/event_timing.cc b/third_party/blink/renderer/core/timing/event_timing.cc
index 4ced914..3b3b1fa 100644
--- a/third_party/blink/renderer/core/timing/event_timing.cc
+++ b/third_party/blink/renderer/core/timing/event_timing.cc
@@ -68,10 +68,12 @@
 
 EventTiming::EventTiming(base::TimeTicks processing_start,
                          base::TimeTicks event_timestamp,
-                         WindowPerformance* performance)
+                         WindowPerformance* performance,
+                         bool should_log_event)
     : processing_start_(processing_start),
       event_timestamp_(event_timestamp),
-      performance_(performance) {}
+      performance_(performance),
+      should_log_event_(should_log_event) {}
 
 // static
 std::unique_ptr<EventTiming> EventTiming::Create(LocalDOMWindow* window,
@@ -92,6 +94,7 @@
                     : event.PlatformTimeStamp();
 
   base::TimeTicks processing_start = Now();
+
   if (should_log_event) {
     InteractiveDetector* interactive_detector =
         InteractiveDetector::From(*window->document());
@@ -103,15 +106,24 @@
 
   return should_report_for_event_timing
              ? std::make_unique<EventTiming>(processing_start, event_timestamp,
-                                             performance)
+                                             performance, should_log_event)
              : nullptr;
 }
 
-void EventTiming::DidDispatchEvent(const Event& event) {
+void EventTiming::DidDispatchEvent(const Event& event, Document& document) {
   Node* target = event.target() ? event.target()->ToNode() : nullptr;
+  base::TimeTicks processing_end = Now();
   performance_->RegisterEventTiming(event.type(), event_timestamp_,
-                                    processing_start_, Now(),
+                                    processing_start_, processing_end,
                                     event.cancelable(), target);
+  if (should_log_event_) {
+    InteractiveDetector* interactive_detector =
+        InteractiveDetector::From(document);
+    if (interactive_detector) {
+      interactive_detector->RecordInputEventTimingUKM(
+          event, event_timestamp_, processing_start_, processing_end);
+    }
+  }
 }
 
 // static
diff --git a/third_party/blink/renderer/core/timing/event_timing.h b/third_party/blink/renderer/core/timing/event_timing.h
index a6d7eef4..dc8c16d 100644
--- a/third_party/blink/renderer/core/timing/event_timing.h
+++ b/third_party/blink/renderer/core/timing/event_timing.h
@@ -30,10 +30,11 @@
 
   explicit EventTiming(base::TimeTicks processing_start,
                        base::TimeTicks event_timestamp,
-                       WindowPerformance* performance);
+                       WindowPerformance* performance,
+                       bool should_log);
 
   // Notifies the Performance object that the event has been dispatched.
-  void DidDispatchEvent(const Event&);
+  void DidDispatchEvent(const Event&, Document& document);
 
   // The caller owns the |clock| which must outlive the EventTiming.
   static void SetTickClockForTesting(const base::TickClock* clock);
@@ -45,6 +46,9 @@
   base::TimeTicks event_timestamp_;
 
   Persistent<WindowPerformance> performance_;
+
+  bool should_log_event_;
+
   DISALLOW_COPY_AND_ASSIGN(EventTiming);
 };
 
diff --git a/third_party/blink/renderer/core/xml/xslt_processor.cc b/third_party/blink/renderer/core/xml/xslt_processor.cc
index 8108945..1549d0a 100644
--- a/third_party/blink/renderer/core/xml/xslt_processor.cc
+++ b/third_party/blink/renderer/core/xml/xslt_processor.cc
@@ -68,6 +68,9 @@
     const String& source_mime_type,
     Node* source_node,
     LocalFrame* frame) {
+  if (!source_node->GetExecutionContext())
+    return nullptr;
+
   KURL url = NullURL();
   Document* owner_document = &source_node->GetDocument();
   if (owner_document == source_node)
diff --git a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
index 838751238..6c34c81 100644
--- a/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
+++ b/third_party/blink/renderer/core/xmlhttprequest/xml_http_request.cc
@@ -741,7 +741,7 @@
 
   if (!async_) {
     if (GetExecutionContext()->IsDocument() &&
-        !GetExecutionContext()->IsFeatureEnabled(
+        !GetDocument()->IsFeatureEnabled(
             mojom::blink::FeaturePolicyFeature::kSyncXHR,
             ReportOptions::kReportOnFailure,
             "Synchronous requests are disabled by Feature Policy.")) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index f1b099c0..3591fa4 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -1338,8 +1338,8 @@
 
   // For consistency between the forward and backward directions, try to always
   // return leaf nodes.
-  if (result && result->ChildCount())
-    return result->DeepestFirstChild();
+  if (result && result->ChildCountIncludingIgnored())
+    return result->DeepestFirstChildIncludingIgnored();
   return result;
 }
 
@@ -1453,8 +1453,8 @@
 
   // For consistency between the forward and backward directions, try to always
   // return leaf nodes.
-  if (result && result->ChildCount())
-    return result->DeepestLastChild();
+  if (result && result->ChildCountIncludingIgnored())
+    return result->DeepestLastChildIncludingIgnored();
   return result;
 }
 
@@ -2891,7 +2891,7 @@
   if (!parent)
     return nullptr;
 
-  for (const auto& child : parent->Children()) {
+  for (const auto& child : parent->ChildrenIncludingIgnored()) {
     if (child->GetBoundsInFrameCoordinates().Contains(point))
       return child.Get();
   }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc b/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc
index 1f2409fe4..82a5489b 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list.cc
@@ -65,7 +65,7 @@
   // There's no reason to clear our AXMenuListPopup child. If we get a
   // call to clearChildren, it's because the options might have changed,
   // so call it on our popup.
-  DCHECK(children_.size() == 1);
+  DCHECK_EQ(ChildCountIncludingIgnored(), 1);
   children_[0]->ClearChildren();
 }
 
@@ -111,7 +111,7 @@
       (GetNode() && !GetNode()->IsFinishedParsingChildren());
 
   if (HasChildren()) {
-    const auto& child_objects = Children();
+    const auto& child_objects = ChildrenIncludingIgnored();
     if (!child_objects.IsEmpty()) {
       DCHECK_EQ(child_objects.size(), 1ul);
       DCHECK(IsA<AXMenuListPopup>(child_objects[0].Get()));
@@ -126,18 +126,18 @@
 }
 
 void AXMenuList::DidShowPopup() {
-  if (Children().size() != 1)
+  if (ChildCountIncludingIgnored() != 1)
     return;
 
-  auto* popup = To<AXMenuListPopup>(Children()[0].Get());
+  auto* popup = To<AXMenuListPopup>(ChildAtIncludingIgnored(0));
   popup->DidShow();
 }
 
 void AXMenuList::DidHidePopup() {
-  if (Children().size() != 1)
+  if (ChildCountIncludingIgnored() != 1)
     return;
 
-  auto* popup = To<AXMenuListPopup>(Children()[0].Get());
+  auto* popup = To<AXMenuListPopup>(ChildAtIncludingIgnored(0));
   popup->DidHide();
 
   if (GetNode() && GetNode()->IsFocused())
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc b/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc
index f7e85a2a..1cb62290 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list_option.cc
@@ -86,7 +86,7 @@
     return select_ax_object;
 
   if (menu_list->HasChildren()) {
-    const auto& child_objects = menu_list->Children();
+    const auto& child_objects = menu_list->ChildrenIncludingIgnored();
     if (child_objects.IsEmpty())
       return nullptr;
     DCHECK_EQ(child_objects.size(), 1UL);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc b/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc
index 5598635..c8e5fe81 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_menu_list_popup.cc
@@ -176,7 +176,7 @@
   if (parent_ && !parent_->IsFocused())
     return nullptr;
 
-  if (active_index_ < 0 || active_index_ >= static_cast<int>(Children().size()))
+  if (active_index_ < 0 || active_index_ >= ChildCountIncludingIgnored())
     return nullptr;
 
   return children_[active_index_].Get();
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index 2ae1edf..0414894 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -1750,7 +1750,7 @@
   // radio buttons.
   AXObject* parent = ParentObject();
   if (parent && parent->RoleValue() == ax::mojom::blink::Role::kRadioGroup) {
-    for (AXObject* child : parent->Children()) {
+    for (AXObject* child : parent->ChildrenIncludingIgnored()) {
       DCHECK(child);
       if (child->RoleValue() == ax::mojom::blink::Role::kRadioButton &&
           child->AccessibilityIsIncludedInTree()) {
@@ -2805,7 +2805,7 @@
       if (AXObject* child_object =
               AXObjectCache().Get(child.GetLayoutObject())) {
         if (!child_object->AccessibilityIsIncludedInTree()) {
-          const auto& children = child_object->Children();
+          const auto& children = child_object->ChildrenIncludingIgnored();
           child_object = children.size() ? children.back().Get() : nullptr;
         }
         if (child_object)
@@ -2874,7 +2874,7 @@
   root->SetParent(this);
 
   if (!root->AccessibilityIsIncludedInTree()) {
-    for (const auto& child : root->Children())
+    for (const auto& child : root->ChildrenIncludingIgnored())
       children_.push_back(child);
   } else {
     children_.push_back(root);
@@ -2982,7 +2982,7 @@
   child->ClearChildren();
 
   if (!child->AccessibilityIsIncludedInTree()) {
-    const auto& children = child->Children();
+    const auto& children = child->ChildrenIncludingIgnored();
     wtf_size_t length = children.size();
     for (wtf_size_t i = 0; i < length; ++i)
       children_.insert(index + i, children[i]);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
index f0ce26b..a8b27ac 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -1845,7 +1845,8 @@
       // Otherwise it's only a subwidget if it's in a grid or treegrid,
       // not in a table.
       return std::any_of(
-          AncestorsBegin(), AncestorsEnd(), [](const AXObject& ancestor) {
+          UnignoredAncestorsBegin(), UnignoredAncestorsEnd(),
+          [](const AXObject& ancestor) {
             return ancestor.RoleValue() == ax::mojom::blink::Role::kGrid ||
                    ancestor.RoleValue() == ax::mojom::blink::Role::kTreeGrid;
           });
@@ -1879,7 +1880,7 @@
 
 String AXObject::ComputedName() const {
   ax::mojom::blink::NameFrom name_from;
-  AXObject::AXObjectVector name_objects;
+  AXObjectVector name_objects;
   return GetName(name_from, &name_objects);
 }
 
@@ -2391,7 +2392,8 @@
   if (!ParentObjectIncludedInTree())
     return 0;
 
-  const AXObjectVector& siblings = ParentObjectIncludedInTree()->Children();
+  const AXObjectVector& siblings =
+      ParentObjectIncludedInTree()->ChildrenIncludingIgnored();
   wtf_size_t index = siblings.Find(this);
   DCHECK(index != kNotFound);
   return (index == kNotFound) ? 0 : static_cast<int>(index);
@@ -2617,14 +2619,14 @@
   return const_cast<AXObject*>(this);
 }
 
-AXObject::AncestorsIterator AXObject::AncestorsBegin() const {
+AXObject::AncestorsIterator AXObject::UnignoredAncestorsBegin() const {
   AXObject* parent = ParentObjectUnignored();
   if (parent)
     return AXObject::AncestorsIterator(*parent);
-  return AncestorsEnd();
+  return UnignoredAncestorsEnd();
 }
 
-AXObject::AncestorsIterator AXObject::AncestorsEnd() const {
+AXObject::AncestorsIterator AXObject::UnignoredAncestorsEnd() const {
   return AXObject::AncestorsIterator();
 }
 
@@ -2632,46 +2634,109 @@
   return InOrderTraversalIterator(*this);
 }
 
-int AXObject::ChildCount() const {
-  return HasIndirectChildren() ? 0 : static_cast<int>(Children().size());
+int AXObject::ChildCountIncludingIgnored() const {
+  return HasIndirectChildren() ? 0 : int{ChildrenIncludingIgnored().size()};
 }
 
-const AXObject::AXObjectVector& AXObject::Children() const {
-  return const_cast<AXObject*>(this)->Children();
+AXObject* AXObject::ChildAtIncludingIgnored(int index) const {
+  // We need to use "ChildCountIncludingIgnored()" and
+  // "ChildrenIncludingIgnored()" instead of using the "children_" member
+  // directly, because we might need to update children and check for the
+  // presence of indirect children.
+  if (index < 0 || index >= ChildCountIncludingIgnored())
+    return nullptr;
+  return ChildrenIncludingIgnored()[index];
 }
 
-const AXObject::AXObjectVector& AXObject::Children() {
+const AXObject::AXObjectVector& AXObject::ChildrenIncludingIgnored() const {
+  return const_cast<AXObject*>(this)->ChildrenIncludingIgnored();
+}
+
+const AXObject::AXObjectVector& AXObject::ChildrenIncludingIgnored() {
   UpdateChildrenIfNecessary();
-
   return children_;
 }
 
-AXObject* AXObject::FirstChild() const {
-  return ChildCount() ? *Children().begin() : nullptr;
+const AXObject::AXObjectVector AXObject::UnignoredChildren() const {
+  return const_cast<AXObject*>(this)->UnignoredChildren();
 }
 
-AXObject* AXObject::LastChild() const {
-  return ChildCount() ? *(Children().end() - 1) : nullptr;
+const AXObject::AXObjectVector AXObject::UnignoredChildren() {
+  if (!AccessibilityIsIncludedInTree()) {
+    NOTREACHED() << "We don't support finding the unignored children of "
+                    "objects excluded from the accessibility tree.";
+    return {};
+  }
+
+  UpdateChildrenIfNecessary();
+
+  // Capture only descendants that are not accessibility ignored, and that are
+  // one level deeper than the current object after flattening any accessibility
+  // ignored descendants.
+  //
+  // For example :
+  // ++A
+  // ++++B
+  // ++++C IGNORED
+  // ++++++F
+  // ++++D
+  // ++++++G
+  // ++++E IGNORED
+  // ++++++H IGNORED
+  // ++++++++J
+  // ++++++I
+  //
+  // Objects [B, F, D, I, J] will be returned, since after flattening all
+  // ignored objects ,those are the ones that are one level deep.
+
+  AXObjectVector unignored_children;
+  AXObject* child = FirstChildIncludingIgnored();
+  while (child && child != this) {
+    if (child->AccessibilityIsIgnored()) {
+      child = child->NextInPreOrderIncludingIgnored(this);
+      continue;
+    }
+
+    unignored_children.push_back(child);
+    for (; child != this; child = child->ParentObjectIncludedInTree()) {
+      if (AXObject* sibling = child->NextSiblingIncludingIgnored()) {
+        child = sibling;
+        break;
+      }
+    }
+  }
+
+  return unignored_children;
 }
 
-AXObject* AXObject::DeepestFirstChild() const {
-  if (!ChildCount())
+AXObject* AXObject::FirstChildIncludingIgnored() const {
+  return ChildCountIncludingIgnored() ? *ChildrenIncludingIgnored().begin()
+                                      : nullptr;
+}
+
+AXObject* AXObject::LastChildIncludingIgnored() const {
+  return ChildCountIncludingIgnored() ? *(ChildrenIncludingIgnored().end() - 1)
+                                      : nullptr;
+}
+
+AXObject* AXObject::DeepestFirstChildIncludingIgnored() const {
+  if (!ChildCountIncludingIgnored())
     return nullptr;
 
-  AXObject* deepest_child = FirstChild();
-  while (deepest_child->ChildCount())
-    deepest_child = deepest_child->FirstChild();
+  AXObject* deepest_child = FirstChildIncludingIgnored();
+  while (deepest_child->ChildCountIncludingIgnored())
+    deepest_child = deepest_child->FirstChildIncludingIgnored();
 
   return deepest_child;
 }
 
-AXObject* AXObject::DeepestLastChild() const {
-  if (!ChildCount())
+AXObject* AXObject::DeepestLastChildIncludingIgnored() const {
+  if (!ChildCountIncludingIgnored())
     return nullptr;
 
-  AXObject* deepest_child = LastChild();
-  while (deepest_child->ChildCount())
-    deepest_child = deepest_child->LastChild();
+  AXObject* deepest_child = LastChildIncludingIgnored();
+  while (deepest_child->ChildCountIncludingIgnored())
+    deepest_child = deepest_child->LastChildIncludingIgnored();
 
   return deepest_child;
 }
@@ -2690,7 +2755,7 @@
 AXObject* AXObject::NextSiblingIncludingIgnored() const {
   if (!AccessibilityIsIncludedInTree()) {
     NOTREACHED() << "We don't support iterating over objects excluded "
-                    "from the accessibility tree";
+                    "from the accessibility tree.";
     return nullptr;
   }
 
@@ -2699,15 +2764,15 @@
     return nullptr;
 
   const int index_in_parent = IndexInParent();
-  if (index_in_parent < parent_in_tree->ChildCount() - 1)
-    return *(parent_in_tree->Children().begin() + index_in_parent + 1);
+  if (index_in_parent < parent_in_tree->ChildCountIncludingIgnored() - 1)
+    return parent_in_tree->ChildAtIncludingIgnored(index_in_parent + 1);
   return nullptr;
 }
 
 AXObject* AXObject::PreviousSiblingIncludingIgnored() const {
   if (!AccessibilityIsIncludedInTree()) {
     NOTREACHED() << "We don't support iterating over objects excluded "
-                    "from the accessibility tree";
+                    "from the accessibility tree.";
     return nullptr;
   }
 
@@ -2717,7 +2782,7 @@
 
   const int index_in_parent = IndexInParent();
   if (index_in_parent > 0)
-    return *(parent_in_tree->Children().begin() + index_in_parent - 1);
+    return parent_in_tree->ChildAtIncludingIgnored(index_in_parent - 1);
   return nullptr;
 }
 
@@ -2725,12 +2790,12 @@
     const AXObject* within) const {
   if (!AccessibilityIsIncludedInTree()) {
     NOTREACHED() << "We don't support iterating over objects excluded "
-                    "from the accessibility tree";
+                    "from the accessibility tree.";
     return nullptr;
   }
 
-  if (ChildCount())
-    return FirstChild();
+  if (ChildCountIncludingIgnored())
+    return FirstChildIncludingIgnored();
 
   if (within == this)
     return nullptr;
@@ -2749,15 +2814,15 @@
     const AXObject* within) const {
   if (!AccessibilityIsIncludedInTree()) {
     NOTREACHED() << "We don't support iterating over objects excluded "
-                    "from the accessibility tree";
+                    "from the accessibility tree.";
     return nullptr;
   }
   if (within == this)
     return nullptr;
 
   if (AXObject* sibling = PreviousSiblingIncludingIgnored()) {
-    if (sibling->ChildCount())
-      return sibling->DeepestLastChild();
+    if (sibling->ChildCountIncludingIgnored())
+      return sibling->DeepestLastChildIncludingIgnored();
     return sibling;
   }
 
@@ -2768,12 +2833,12 @@
     const AXObject* within) const {
   if (!AccessibilityIsIncludedInTree()) {
     NOTREACHED() << "We don't support iterating over objects excluded "
-                    "from the accessibility tree";
+                    "from the accessibility tree.";
     return nullptr;
   }
 
-  if (ChildCount())
-    return LastChild();
+  if (ChildCountIncludingIgnored())
+    return LastChildIncludingIgnored();
 
   if (within == this)
     return nullptr;
@@ -2788,9 +2853,22 @@
   return previous;
 }
 
-AXObject* AXObject::NextSibling() const {
+int AXObject::UnignoredChildCount() const {
+  return int{UnignoredChildren().size()};
+}
+
+AXObject* AXObject::UnignoredChildAt(int index) const {
+  const AXObjectVector unignored_children = UnignoredChildren();
+  if (index < 0 || index >= int{unignored_children.size()})
+    return nullptr;
+  return unignored_children[index];
+}
+
+AXObject* AXObject::UnignoredNextSibling() const {
   if (AccessibilityIsIgnored()) {
-    NOTREACHED() << "We don't support finding siblings for ignored objects.";
+    NOTREACHED() << "We don't support finding unignored siblings for ignored "
+                    "objects because it is not clear whether to search for the "
+                    "sibling in the unignored tree or in the whole tree.";
     return nullptr;
   }
 
@@ -2827,9 +2905,11 @@
   return nullptr;
 }
 
-AXObject* AXObject::PreviousSibling() const {
+AXObject* AXObject::UnignoredPreviousSibling() const {
   if (AccessibilityIsIgnored()) {
-    NOTREACHED() << "We don't support finding siblings for ignored objects.";
+    NOTREACHED() << "We don't support finding unignored siblings for ignored "
+                    "objects because it is not clear whether to search for the "
+                    "sibling in the unignored tree or in the whole tree.";
     return nullptr;
   }
 
@@ -2867,7 +2947,7 @@
   return nullptr;
 }
 
-AXObject* AXObject::NextInTreeObject() const {
+AXObject* AXObject::UnignoredNextInPreOrder() const {
   AXObject* next = NextInPreOrderIncludingIgnored();
   while (next && next->AccessibilityIsIgnored()) {
     next = next->NextInPreOrderIncludingIgnored();
@@ -2875,7 +2955,7 @@
   return next;
 }
 
-AXObject* AXObject::PreviousInTreeObject() const {
+AXObject* AXObject::UnignoredPreviousInPreOrder() const {
   AXObject* previous = PreviousInPreOrderIncludingIgnored();
   while (previous && previous->AccessibilityIsIgnored()) {
     previous = previous->PreviousInPreOrderIncludingIgnored();
@@ -3321,7 +3401,7 @@
 
 AXObject::AXObjectVector AXObject::TableRowChildren() const {
   AXObjectVector result;
-  for (const auto& child : Children()) {
+  for (const auto& child : ChildrenIncludingIgnored()) {
     if (child->IsTableRowLikeRole())
       result.push_back(child);
     else if (child->RoleValue() == ax::mojom::blink::Role::kRowGroup)
@@ -3332,7 +3412,7 @@
 
 AXObject::AXObjectVector AXObject::TableCellChildren() const {
   AXObjectVector result;
-  for (const auto& child : Children()) {
+  for (const auto& child : ChildrenIncludingIgnored()) {
     if (child->IsTableCellLikeRole())
       result.push_back(child);
     else if (child->RoleValue() == ax::mojom::blink::Role::kGenericContainer)
@@ -4080,7 +4160,8 @@
   if (ui::IsCellOrTableHeader(RoleValue())) {
     // For cells and row/column headers, readonly is supported within a grid.
     return std::any_of(
-        AncestorsBegin(), AncestorsEnd(), [](const AXObject& ancestor) {
+        UnignoredAncestorsBegin(), UnignoredAncestorsEnd(),
+        [](const AXObject& ancestor) {
           return ancestor.RoleValue() == ax::mojom::blink::Role::kGrid ||
                  ancestor.RoleValue() == ax::mojom::blink::Role::kTreeGrid;
         });
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h
index 64429d2..c47fb79 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object.h
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -179,7 +179,9 @@
   typedef HeapVector<Member<AXObject>> AXObjectVector;
 
   // Iterator for doing an in-order traversal of the accessibility tree.
-  // Includes ignored objects in the traversal.
+  //
+  // Includes objects that are ignored but included in the accessibility tree in
+  // the traversal.
   class MODULES_EXPORT InOrderTraversalIterator final
       : public GarbageCollected<InOrderTraversalIterator> {
    public:
@@ -197,7 +199,7 @@
     InOrderTraversalIterator& operator++() {
       previous_ = current_;
       current_ = (current_ && !current_->IsDetached())
-                     ? current_->NextInTreeObject()
+                     ? current_->NextInPreOrderIncludingIgnored()
                      : nullptr;
       return *this;
     }
@@ -211,7 +213,7 @@
     InOrderTraversalIterator& operator--() {
       current_ = previous_;
       previous_ = (current_ && !current_->IsDetached())
-                      ? current_->PreviousInTreeObject()
+                      ? current_->PreviousInPreOrderIncludingIgnored()
                       : nullptr;
       return *this;
     }
@@ -805,89 +807,197 @@
   // AXLayoutObject.
   virtual AXObject* ElementAccessibilityHitTest(const IntPoint&) const;
 
+  //
   // High-level accessibility tree access. Other modules should only use these
-  // functions.
-  AncestorsIterator AncestorsBegin() const;
-  AncestorsIterator AncestorsEnd() const;
+  // methods.
+  //
+  // The following methods may support one or more kinds of objects. There are
+  // three kinds: Objects that are excluded from the accessibility tree by
+  // default, such as white space found in HTML, objects that are included in
+  // the tree but that are ignored, such as an empty div, and unignored objects.
+
+  // Iterates through the node's unignored ancestors up to the root, starting
+  // from the node's unignored parent, i.e. does not include the node itself in
+  // the list of ancestors.
+  //
+  // Initially, it can be called on all nodes, including those that are
+  // accessibility ignored, but only traverses through the list of ancestors
+  // that are unignored and included in the accessibility tree.
+  AncestorsIterator UnignoredAncestorsBegin() const;
+  AncestorsIterator UnignoredAncestorsEnd() const;
+
+  // Iterator for doing an in-order traversal of the accessibility tree.
+  //
+  // Includes nodes that are accessibility ignored but "included in tree" in the
+  // traversal.
   InOrderTraversalIterator GetInOrderTraversalIterator();
-  int ChildCount() const;
-  const AXObjectVector& Children() const;
-  const AXObjectVector& Children();
+
+  // Returns the number of children, including children that are included in the
+  // accessibility tree but are accessibility ignored.
+  //
+  // Can be called on all nodes, even on nodes that are excluded from the
+  // accessibility tree.
+  int ChildCountIncludingIgnored() const;
+
+  // Returns the child with the given index in the list of all children,
+  // including those that are accessibility ignored.
+  //
+  // Can be called on all nodes, even on nodes that are excluded from the
+  // accessibility tree.
+  AXObject* ChildAtIncludingIgnored(int index) const;
+
+  // Returns the node's children, including any children that are included in
+  // the accessibility tree but are accessibility ignored.
+  //
+  // Can be called on all nodes, including nodes that are excluded from the
+  // accessibility tree.
+  const AXObjectVector& ChildrenIncludingIgnored() const;
+  const AXObjectVector& ChildrenIncludingIgnored();
+
+  // Returns the node's unignored descendants that are one level deeper than
+  // this node, after removing all accessibility ignored nodes from the tree.
+  //
+  // Flattens accessibility ignored nodes, so each unignored child will have the
+  // same unignored parent, but may have a different parent in tree.
+  //
+  // Can be called on all nodes that are included in the accessibility tree,
+  // including those that are accessibility ignored.
+  const AXObjectVector UnignoredChildren() const;
+  const AXObjectVector UnignoredChildren();
+
   // Returns the first child for this object.
-  // Works for all nodes, and may return nodes that are accessibility ignored.
-  AXObject* FirstChild() const;
+  // Works for all nodes that are included in the accessibility tree, and may
+  // return nodes that are accessibility ignored.
+  AXObject* FirstChildIncludingIgnored() const;
+
   // Returns the last child for this object.
-  // Works for all nodes, and may return nodes that are accessibility ignored.
-  AXObject* LastChild() const;
+  // Works for all nodes that are included in the accessibility tree, and may
+  // return nodes that are accessibility ignored.
+  AXObject* LastChildIncludingIgnored() const;
+
   // Returns the deepest first child for this object.
-  // Works for all nodes, and may return nodes that are accessibility ignored.
-  AXObject* DeepestFirstChild() const;
+  // Works for all nodes that are included in the accessibility tree, and may
+  // return nodes that are accessibility ignored.
+  AXObject* DeepestFirstChildIncludingIgnored() const;
+
   // Returns the deepest last child for this object.
-  // Works for all nodes, and may return nodes that are accessibility ignored.
-  AXObject* DeepestLastChild() const;
+  // Works for all nodes that are included in the accessibility tree, and may
+  // return nodes that are accessibility ignored.
+  AXObject* DeepestLastChildIncludingIgnored() const;
+
+  // Returns true if this node is strictly an ancestor of the given node, i.e.
+  // doesn't include the current node in the list of its ancestors. Works for
+  // all nodes that are included in the accessibility tree, including nodes that
+  // are accessibility ignored.
   bool IsAncestorOf(const AXObject&) const;
+
+  // Returns true if this node is strictly a descendant of the given node, i.e.
+  // doesn't include the current node in the list of its descendants. Works for
+  // all nodes that are included in the accessibility tree, including nodes that
+  // are accessibility ignored.
   bool IsDescendantOf(const AXObject&) const;
+
   // Next sibling for this object, where the sibling may be
   // an accessibility ignored object.
   // Works for all nodes that are included in the accessibility tree,
   // and may return nodes that are accessibility ignored.
   AXObject* NextSiblingIncludingIgnored() const;
+
   // Previous sibling for this object, where the sibling may be
   // an accessibility ignored object.
   // Works for all nodes that are included in the accessibility tree,
   // and may return nodes that are accessibility ignored.
   AXObject* PreviousSiblingIncludingIgnored() const;
+
   // Returns the next object in tree using depth-first pre-order traversal,
   // optionally staying within a specified AXObject.
   // Works for all nodes that are included in the accessibility tree,
   // and may return nodes that are accessibility ignored.
   AXObject* NextInPreOrderIncludingIgnored(
       const AXObject* within = nullptr) const;
+
   // Returns the previous object in tree using depth-first pre-order traversal,
   // optionally staying within a specified AXObject.
   // Works for all nodes that are included in the accessibility tree,
   // and may return nodes that are accessibility ignored.
   AXObject* PreviousInPreOrderIncludingIgnored(
       const AXObject* within = nullptr) const;
+
   // Returns the previous object in tree using depth-first post-order traversal,
   // optionally staying within a specified AXObject.
   // Works for all nodes that are included in the accessibility tree,
   // and may return nodes that are accessibility ignored.
   AXObject* PreviousInPostOrderIncludingIgnored(
       const AXObject* within = nullptr) const;
+
+  // Returns the number of children that are not accessibility ignored.
+  //
+  // Unignored children are the objects that are one level deeper than the
+  // current object after all accessibility ignored descendants are removed.
+  //
+  // Can be called on all nodes that are included in the accessibility tree,
+  // including those that are accessibility ignored.
+  int UnignoredChildCount() const;
+
+  // Returns the unignored child with the given index.
+  //
+  // Unignored children are the objects that are one level deeper than the
+  // current object after all accessibility ignored descendants are removed.
+  //
+  // Can be called on all nodes that are included in the accessibility tree,
+  // including those that are accessibility ignored.
+  AXObject* UnignoredChildAt(int index) const;
+
   // Next sibling for this object that's not accessibility ignored.
+  //
   // Flattens accessibility ignored nodes, so the sibling will have the
   // same unignored parent, but may have a different parent in tree.
+  //
   // Doesn't work with nodes that are accessibility ignored.
-  AXObject* NextSibling() const;
+  AXObject* UnignoredNextSibling() const;
+
   // Previous sibling for this object that's not accessibility ignored.
+  //
   // Flattens accessibility ignored nodes, so the sibling will have the
   // same unignored parent, but may have a different parent in tree.
+  //
   // Doesn't work with nodes that are accessibility ignored.
-  AXObject* PreviousSibling() const;
+  AXObject* UnignoredPreviousSibling() const;
+
   // Next object in tree using depth-first pre-order traversal that's
   // not accessibility ignored.
   // Doesn't work with nodes that are accessibility ignored.
-  AXObject* NextInTreeObject() const;
+  AXObject* UnignoredNextInPreOrder() const;
+
   // Previous object in tree using depth-first pre-order traversal that's
   // not accessibility ignored.
   // Doesn't work with nodes that are accessibility ignored.
-  AXObject* PreviousInTreeObject() const;
+  AXObject* UnignoredPreviousInPreOrder() const;
+
   // Get or create the parent of this object.
-  // Works for all nodes, and may return nodes that are accessibility ignored.
+  //
+  // Works for all nodes, and may return nodes that are accessibility ignored,
+  // including nodes that might not be in the tree.
   AXObject* ParentObject() const;
+
   // Get the parent of this object if it has already been created.
-  // Works for all nodes, and may return nodes that are accessibility ignored.
+  //
+  // Works for all nodes, and may return nodes that are accessibility ignored,
+  // including nodes that might not be in the tree.
   AXObject* ParentObjectIfExists() const;
+
   virtual AXObject* ComputeParent() const = 0;
   virtual AXObject* ComputeParentIfExists() const { return nullptr; }
   AXObject* CachedParentObject() const { return parent_; }
+
   // Get or create the first ancestor that's not accessibility ignored.
   // Works for all nodes.
   AXObject* ParentObjectUnignored() const;
+
   // Get or create the first ancestor that's included in the accessibility tree.
   // Works for all nodes, and may return nodes that are accessibility ignored.
   AXObject* ParentObjectIncludedInTree() const;
+
   AXObject* ContainerWidget() const;
   bool IsContainerWidget() const;
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
index a582740..bb194aed 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -240,7 +240,8 @@
   if (!ax_layout_image)
     return nullptr;
 
-  const AXObject::AXObjectVector& image_children = ax_layout_image->Children();
+  const AXObject::AXObjectVector& image_children =
+      ax_layout_image->ChildrenIncludingIgnored();
   unsigned count = image_children.size();
   for (unsigned k = 0; k < count; ++k) {
     AXObject* child = image_children[k];
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
index ad4aa1c..f22e316f 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
@@ -56,14 +56,51 @@
   EXPECT_FALSE(button->IsAncestorOf(*root));
 }
 
+TEST_F(AccessibilityTest, UnignoredChildren) {
+  SetBodyInnerHTML(R"HTML(This is a test with
+                   <p role="presentation">
+                     ignored objects
+                   </p>
+                   <p>
+                     which are at multiple
+                   </p>
+                   <p role="presentation">
+                     <p role="presentation">
+                       depth levels
+                     </p>
+                     in the accessibility tree.
+                   </p>)HTML");
+
+  const AXObject* ax_body = GetAXRootObject()->FirstChildIncludingIgnored();
+  ASSERT_NE(nullptr, ax_body);
+
+  ASSERT_EQ(5, ax_body->UnignoredChildCount());
+  EXPECT_EQ(ax::mojom::blink::Role::kStaticText,
+            ax_body->UnignoredChildAt(0)->RoleValue());
+  EXPECT_EQ("This is a test with",
+            ax_body->UnignoredChildAt(0)->ComputedName());
+  EXPECT_EQ(ax::mojom::blink::Role::kStaticText,
+            ax_body->UnignoredChildAt(1)->RoleValue());
+  EXPECT_EQ("ignored objects", ax_body->UnignoredChildAt(1)->ComputedName());
+  EXPECT_EQ(ax::mojom::blink::Role::kParagraph,
+            ax_body->UnignoredChildAt(2)->RoleValue());
+  EXPECT_EQ(ax::mojom::blink::Role::kStaticText,
+            ax_body->UnignoredChildAt(3)->RoleValue());
+  EXPECT_EQ("depth levels", ax_body->UnignoredChildAt(3)->ComputedName());
+  EXPECT_EQ(ax::mojom::blink::Role::kStaticText,
+            ax_body->UnignoredChildAt(4)->RoleValue());
+  EXPECT_EQ("in the accessibility tree.",
+            ax_body->UnignoredChildAt(4)->ComputedName());
+}
+
 TEST_F(AccessibilityTest, SimpleTreeNavigation) {
   SetBodyInnerHTML(R"HTML(<input id="input" type="text" value="value">
-                   <div id='ignored_a' aria-hidden='true'></div>
+                   <div id="ignored_a" aria-hidden="true"></div>
                    <p id="paragraph">hello<br id="br">there</p>
-                   <span id='ignored_b' aria-hidden='true'></span>
+                   <span id="ignored_b" aria-hidden="true"></span>
                    <button id="button">button</button>)HTML");
 
-  const AXObject* body = GetAXRootObject()->FirstChild();
+  const AXObject* body = GetAXRootObject()->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, body);
   const AXObject* input = GetAXObjectByElementId("input");
   ASSERT_NE(nullptr, input);
@@ -78,34 +115,51 @@
   const AXObject* button = GetAXObjectByElementId("button");
   ASSERT_NE(nullptr, button);
 
-  EXPECT_EQ(input, body->FirstChild());
-  EXPECT_EQ(button, body->LastChild());
+  EXPECT_EQ(input, body->FirstChildIncludingIgnored());
+  EXPECT_EQ(button, body->LastChildIncludingIgnored());
 
-  ASSERT_NE(nullptr, paragraph->FirstChild());
-  EXPECT_EQ(ax::mojom::Role::kStaticText, paragraph->FirstChild()->RoleValue());
-  ASSERT_NE(nullptr, paragraph->LastChild());
-  EXPECT_EQ(ax::mojom::Role::kStaticText, paragraph->LastChild()->RoleValue());
-  ASSERT_NE(nullptr, paragraph->DeepestFirstChild());
+  ASSERT_NE(nullptr, paragraph->FirstChildIncludingIgnored());
   EXPECT_EQ(ax::mojom::Role::kStaticText,
-            paragraph->DeepestFirstChild()->RoleValue());
-  ASSERT_NE(nullptr, paragraph->DeepestLastChild());
+            paragraph->FirstChildIncludingIgnored()->RoleValue());
+  ASSERT_NE(nullptr, paragraph->LastChildIncludingIgnored());
   EXPECT_EQ(ax::mojom::Role::kStaticText,
-            paragraph->DeepestLastChild()->RoleValue());
+            paragraph->LastChildIncludingIgnored()->RoleValue());
+  ASSERT_NE(nullptr, paragraph->DeepestFirstChildIncludingIgnored());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            paragraph->DeepestFirstChildIncludingIgnored()->RoleValue());
+  ASSERT_NE(nullptr, paragraph->DeepestLastChildIncludingIgnored());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            paragraph->DeepestLastChildIncludingIgnored()->RoleValue());
 
-  EXPECT_EQ(paragraph->PreviousSibling(), input);
-  EXPECT_EQ(paragraph, input->NextSibling());
-  ASSERT_NE(nullptr, br->NextSibling());
-  EXPECT_EQ(ax::mojom::Role::kStaticText, br->NextSibling()->RoleValue());
-  ASSERT_NE(nullptr, br->PreviousSibling());
-  EXPECT_EQ(ax::mojom::Role::kStaticText, br->PreviousSibling()->RoleValue());
-
-  ASSERT_NE(nullptr, button->FirstChild());
-  EXPECT_EQ(ax::mojom::Role::kStaticText, button->FirstChild()->RoleValue());
-  ASSERT_NE(nullptr, button->LastChild());
-  EXPECT_EQ(ax::mojom::Role::kStaticText, button->LastChild()->RoleValue());
-  ASSERT_NE(nullptr, button->DeepestFirstChild());
+  EXPECT_EQ(paragraph->PreviousSiblingIncludingIgnored(),
+            GetAXObjectByElementId("ignored_a"));
+  EXPECT_EQ(GetAXObjectByElementId("ignored_a"),
+            input->NextSiblingIncludingIgnored());
+  ASSERT_NE(nullptr, br->NextSiblingIncludingIgnored());
   EXPECT_EQ(ax::mojom::Role::kStaticText,
-            paragraph->DeepestFirstChild()->RoleValue());
+            br->NextSiblingIncludingIgnored()->RoleValue());
+  ASSERT_NE(nullptr, br->PreviousSiblingIncludingIgnored());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            br->PreviousSiblingIncludingIgnored()->RoleValue());
+
+  EXPECT_EQ(paragraph->UnignoredPreviousSibling(), input);
+  EXPECT_EQ(paragraph, input->UnignoredNextSibling());
+  ASSERT_NE(nullptr, br->UnignoredNextSibling());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            br->UnignoredNextSibling()->RoleValue());
+  ASSERT_NE(nullptr, br->UnignoredPreviousSibling());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            br->UnignoredPreviousSibling()->RoleValue());
+
+  ASSERT_NE(nullptr, button->FirstChildIncludingIgnored());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            button->FirstChildIncludingIgnored()->RoleValue());
+  ASSERT_NE(nullptr, button->LastChildIncludingIgnored());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            button->LastChildIncludingIgnored()->RoleValue());
+  ASSERT_NE(nullptr, button->DeepestFirstChildIncludingIgnored());
+  EXPECT_EQ(ax::mojom::Role::kStaticText,
+            paragraph->DeepestFirstChildIncludingIgnored()->RoleValue());
 }
 
 TEST_F(AccessibilityTest, TreeNavigationWithIgnoredContainer) {
@@ -124,31 +178,31 @@
     </body>)HTML");
 
   const AXObject* root = GetAXRootObject();
-  const AXObject* body = root->FirstChild();
-  ASSERT_EQ(3, body->ChildCount());
-  ASSERT_EQ(1, body->Children()[1]->ChildCount());
+  const AXObject* body = root->FirstChildIncludingIgnored();
+  ASSERT_EQ(3, body->ChildCountIncludingIgnored());
+  ASSERT_EQ(1, body->ChildAtIncludingIgnored(1)->ChildCountIncludingIgnored());
 
   ASSERT_FALSE(root->AccessibilityIsIgnored());
   ASSERT_TRUE(body->AccessibilityIsIgnored());
   const AXObject* obj_a = GetAXObjectByElementId("A");
   ASSERT_NE(nullptr, obj_a);
   ASSERT_FALSE(obj_a->AccessibilityIsIgnored());
-  const AXObject* obj_a_text = obj_a->FirstChild();
+  const AXObject* obj_a_text = obj_a->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, obj_a_text);
   EXPECT_EQ(ax::mojom::Role::kStaticText, obj_a_text->RoleValue());
   const AXObject* obj_b = GetAXObjectByElementId("B");
   ASSERT_NE(nullptr, obj_b);
   ASSERT_FALSE(obj_b->AccessibilityIsIgnored());
-  const AXObject* obj_b_text = obj_b->FirstChild();
+  const AXObject* obj_b_text = obj_b->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, obj_b_text);
   EXPECT_EQ(ax::mojom::Role::kStaticText, obj_b_text->RoleValue());
   const AXObject* obj_c = GetAXObjectByElementId("C");
   ASSERT_NE(nullptr, obj_c);
   ASSERT_FALSE(obj_c->AccessibilityIsIgnored());
-  const AXObject* obj_c_text = obj_c->FirstChild();
+  const AXObject* obj_c_text = obj_c->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, obj_c_text);
   EXPECT_EQ(ax::mojom::Role::kStaticText, obj_c_text->RoleValue());
-  const AXObject* obj_ignored = body->Children()[1];
+  const AXObject* obj_ignored = body->ChildAtIncludingIgnored(1);
   ASSERT_NE(nullptr, obj_ignored);
   ASSERT_TRUE(obj_ignored->AccessibilityIsIgnored());
 
@@ -159,22 +213,37 @@
   EXPECT_EQ(root, obj_c->ParentObjectUnignored());
   EXPECT_EQ(body, obj_c->ParentObjectIncludedInTree());
 
-  EXPECT_EQ(obj_b, obj_ignored->FirstChild());
+  EXPECT_EQ(obj_b, obj_ignored->FirstChildIncludingIgnored());
 
-  EXPECT_EQ(nullptr, obj_a->PreviousSibling());
-  EXPECT_EQ(obj_b, obj_a->NextSibling());
-  EXPECT_EQ(root, obj_a->PreviousInTreeObject());
-  EXPECT_EQ(obj_a_text, obj_a->NextInTreeObject());
+  EXPECT_EQ(nullptr, obj_a->PreviousSiblingIncludingIgnored());
+  EXPECT_EQ(nullptr, obj_a->UnignoredPreviousSibling());
+  EXPECT_EQ(obj_ignored, obj_a->NextSiblingIncludingIgnored());
+  EXPECT_EQ(obj_b, obj_a->UnignoredNextSibling());
 
-  EXPECT_EQ(obj_a, obj_b->PreviousSibling());
-  EXPECT_EQ(obj_c, obj_b->NextSibling());
-  EXPECT_EQ(obj_a_text, obj_b->PreviousInTreeObject());
-  EXPECT_EQ(obj_b_text, obj_b->NextInTreeObject());
+  EXPECT_EQ(body, obj_a->PreviousInPreOrderIncludingIgnored());
+  EXPECT_EQ(root, obj_a->UnignoredPreviousInPreOrder());
+  EXPECT_EQ(obj_a_text, obj_a->NextInPreOrderIncludingIgnored());
+  EXPECT_EQ(obj_a_text, obj_a->UnignoredNextInPreOrder());
 
-  EXPECT_EQ(obj_b, obj_c->PreviousSibling());
-  EXPECT_EQ(nullptr, obj_c->NextSibling());
-  EXPECT_EQ(obj_b_text, obj_c->PreviousInTreeObject());
-  EXPECT_EQ(obj_c_text, obj_c->NextInTreeObject());
+  EXPECT_EQ(nullptr, obj_b->PreviousSiblingIncludingIgnored());
+  EXPECT_EQ(obj_a, obj_b->UnignoredPreviousSibling());
+  EXPECT_EQ(nullptr, obj_b->NextSiblingIncludingIgnored());
+  EXPECT_EQ(obj_c, obj_b->UnignoredNextSibling());
+
+  EXPECT_EQ(obj_ignored, obj_b->PreviousInPreOrderIncludingIgnored());
+  EXPECT_EQ(obj_a_text, obj_b->UnignoredPreviousInPreOrder());
+  EXPECT_EQ(obj_b_text, obj_b->NextInPreOrderIncludingIgnored());
+  EXPECT_EQ(obj_b_text, obj_b->UnignoredNextInPreOrder());
+
+  EXPECT_EQ(obj_ignored, obj_c->PreviousSiblingIncludingIgnored());
+  EXPECT_EQ(obj_b, obj_c->UnignoredPreviousSibling());
+  EXPECT_EQ(nullptr, obj_c->NextSiblingIncludingIgnored());
+  EXPECT_EQ(nullptr, obj_c->UnignoredNextSibling());
+
+  EXPECT_EQ(obj_b_text, obj_c->PreviousInPreOrderIncludingIgnored());
+  EXPECT_EQ(obj_b_text, obj_c->UnignoredPreviousInPreOrder());
+  EXPECT_EQ(obj_c_text, obj_c->NextInPreOrderIncludingIgnored());
+  EXPECT_EQ(obj_c_text, obj_c->UnignoredNextInPreOrder());
 }
 
 TEST_F(AccessibilityTest, AXObjectComparisonOperators) {
@@ -219,7 +288,7 @@
   EXPECT_FALSE(*button > *button);
 }
 
-TEST_F(AccessibilityTest, AXObjectAncestorsIterator) {
+TEST_F(AccessibilityTest, AXObjectUnignoredAncestorsIterator) {
   SetBodyInnerHTML(
       R"HTML(<p id="paragraph"><b id="bold"><br id="br"></b></p>)HTML");
 
@@ -233,12 +302,12 @@
   ASSERT_NE(nullptr, br);
   ASSERT_EQ(ax::mojom::Role::kLineBreak, br->RoleValue());
 
-  AXObject::AncestorsIterator iter = br->AncestorsBegin();
+  AXObject::AncestorsIterator iter = br->UnignoredAncestorsBegin();
   EXPECT_EQ(*paragraph, *iter);
   EXPECT_EQ(ax::mojom::Role::kParagraph, iter->RoleValue());
   EXPECT_EQ(*root, *++iter);
   EXPECT_EQ(*root, *iter++);
-  EXPECT_EQ(br->AncestorsEnd(), ++iter);
+  EXPECT_EQ(br->UnignoredAncestorsEnd(), ++iter);
 }
 
 TEST_F(AccessibilityTest, AXObjectInOrderTraversalIterator) {
@@ -343,7 +412,7 @@
 
 TEST_F(AccessibilityTest, AxObjectPreservedWhitespaceIsLineBreakingObjects) {
   SetBodyInnerHTML(R"HTML(
-    <span style='white-space: pre-line' id="preserved">
+    <span style="white-space: pre-line" id="preserved">
       First Paragraph
       Second Paragraph
       Third Paragraph
@@ -355,10 +424,10 @@
   const AXObject* preserved_span = GetAXObjectByElementId("preserved");
   ASSERT_NE(nullptr, preserved_span);
   ASSERT_EQ(ax::mojom::Role::kGenericContainer, preserved_span->RoleValue());
-  ASSERT_EQ(1, preserved_span->ChildCount());
+  ASSERT_EQ(1, preserved_span->ChildCountIncludingIgnored());
   EXPECT_FALSE(preserved_span->IsLineBreakingObject());
 
-  AXObject* preserved_text = preserved_span->FirstChild();
+  AXObject* preserved_text = preserved_span->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, preserved_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, preserved_text->RoleValue());
   EXPECT_FALSE(preserved_text->IsLineBreakingObject());
@@ -366,9 +435,9 @@
   // Expect 7 kInlineTextBox children
   // 3 lines of text, and 4 newlines
   preserved_text->LoadInlineTextBoxes();
-  ASSERT_EQ(7, preserved_text->ChildCount());
+  ASSERT_EQ(7, preserved_text->ChildCountIncludingIgnored());
   bool all_children_are_inline_text_boxes = true;
-  for (const AXObject* child : preserved_text->Children()) {
+  for (const AXObject* child : preserved_text->ChildrenIncludingIgnored()) {
     if (child->RoleValue() != ax::mojom::Role::kInlineTextBox) {
       all_children_are_inline_text_boxes = false;
       break;
@@ -376,20 +445,30 @@
   }
   ASSERT_TRUE(all_children_are_inline_text_boxes);
 
-  ASSERT_EQ(preserved_text->Children()[0]->ComputedName(), "\n");
-  EXPECT_TRUE(preserved_text->Children()[0]->IsLineBreakingObject());
-  ASSERT_EQ(preserved_text->Children()[1]->ComputedName(), "First Paragraph");
-  EXPECT_FALSE(preserved_text->Children()[1]->IsLineBreakingObject());
-  ASSERT_EQ(preserved_text->Children()[2]->ComputedName(), "\n");
-  EXPECT_TRUE(preserved_text->Children()[2]->IsLineBreakingObject());
-  ASSERT_EQ(preserved_text->Children()[3]->ComputedName(), "Second Paragraph");
-  EXPECT_FALSE(preserved_text->Children()[3]->IsLineBreakingObject());
-  ASSERT_EQ(preserved_text->Children()[4]->ComputedName(), "\n");
-  EXPECT_TRUE(preserved_text->Children()[4]->IsLineBreakingObject());
-  ASSERT_EQ(preserved_text->Children()[5]->ComputedName(), "Third Paragraph");
-  EXPECT_FALSE(preserved_text->Children()[5]->IsLineBreakingObject());
-  ASSERT_EQ(preserved_text->Children()[6]->ComputedName(), "\n");
-  EXPECT_TRUE(preserved_text->Children()[6]->IsLineBreakingObject());
+  ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(0)->ComputedName(), "\n");
+  EXPECT_TRUE(
+      preserved_text->ChildAtIncludingIgnored(0)->IsLineBreakingObject());
+  ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(1)->ComputedName(),
+            "First Paragraph");
+  EXPECT_FALSE(
+      preserved_text->ChildAtIncludingIgnored(1)->IsLineBreakingObject());
+  ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(2)->ComputedName(), "\n");
+  EXPECT_TRUE(
+      preserved_text->ChildAtIncludingIgnored(2)->IsLineBreakingObject());
+  ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(3)->ComputedName(),
+            "Second Paragraph");
+  EXPECT_FALSE(
+      preserved_text->ChildAtIncludingIgnored(3)->IsLineBreakingObject());
+  ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(4)->ComputedName(), "\n");
+  EXPECT_TRUE(
+      preserved_text->ChildAtIncludingIgnored(4)->IsLineBreakingObject());
+  ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(5)->ComputedName(),
+            "Third Paragraph");
+  EXPECT_FALSE(
+      preserved_text->ChildAtIncludingIgnored(5)->IsLineBreakingObject());
+  ASSERT_EQ(preserved_text->ChildAtIncludingIgnored(6)->ComputedName(), "\n");
+  EXPECT_TRUE(
+      preserved_text->ChildAtIncludingIgnored(6)->IsLineBreakingObject());
 }
 
 TEST_F(AccessibilityTest, CheckNoDuplicateChildren) {
@@ -402,7 +481,8 @@
   ax_select->SetNeedsToUpdateChildren();
   ax_select->UpdateChildrenIfNecessary();
 
-  ASSERT_EQ(ax_select->FirstChild()->ChildCount(), 1);
+  ASSERT_EQ(
+      ax_select->FirstChildIncludingIgnored()->ChildCountIncludingIgnored(), 1);
 }
 
 TEST_F(AccessibilityTest, InitRelationCache) {
diff --git a/third_party/blink/renderer/modules/accessibility/ax_position.cc b/third_party/blink/renderer/modules/accessibility/ax_position.cc
index f0b73cc..b88f12e4 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_position.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_position.cc
@@ -98,8 +98,9 @@
   }
 
   // If the container is not a text object, creating a position inside an
-  // ignored container might result in an invalid position, because child count
-  // is inaccurate.
+  // object that is excluded from the accessibility tree will result in an
+  // invalid position, because child count is not always accurate for such
+  // objects.
   const AXObject* unignored_container =
       !container.AccessibilityIsIncludedInTree()
           ? container.ParentObjectIncludedInTree()
@@ -132,15 +133,17 @@
   }
 
   // If the container is not a text object, creating a position inside an
-  // ignored container might result in an invalid position, because child count
-  // is inaccurate.
+  // object that is excluded from the accessibility tree will result in an
+  // invalid position, because child count is not always accurate for such
+  // objects.
   const AXObject* unignored_container =
       !container.AccessibilityIsIncludedInTree()
           ? container.ParentObjectIncludedInTree()
           : &container;
   DCHECK(unignored_container);
   AXPosition position(*unignored_container);
-  position.text_offset_or_child_index_ = unignored_container->ChildCount();
+  position.text_offset_or_child_index_ =
+      unignored_container->ChildCountIncludingIgnored();
 #if DCHECK_IS_ON()
   String failure_reason;
   DCHECK(position.IsValid(&failure_reason)) << failure_reason;
@@ -270,7 +273,8 @@
   // positions.
   const Node* node_after_position = position.ComputeNodeAfterPosition();
   if (!node_after_position) {
-    ax_position.text_offset_or_child_index_ = container->ChildCount();
+    ax_position.text_offset_or_child_index_ =
+        container->ChildCountIncludingIgnored();
 
     } else {
       const AXObject* ax_child =
@@ -312,7 +316,7 @@
         }
       }
 
-      if (!container->Children().Contains(ax_child)) {
+      if (!container->ChildrenIncludingIgnored().Contains(ax_child)) {
         // The |ax_child| is aria-owned by another object.
         return CreatePositionBeforeObject(*ax_child, adjustment_behavior);
       }
@@ -365,9 +369,7 @@
 const AXObject* AXPosition::ChildAfterTreePosition() const {
   if (!IsValid() || IsTextPosition())
     return nullptr;
-  if (container_object_->ChildCount() <= ChildIndex())
-    return nullptr;
-  return *(container_object_->Children().begin() + ChildIndex());
+  return container_object_->ChildAtIncludingIgnored(ChildIndex());
 }
 
 int AXPosition::ChildIndex() const {
@@ -463,11 +465,13 @@
       return false;
     }
   } else {
-    if (text_offset_or_child_index_ > container_object_->ChildCount()) {
+    if (text_offset_or_child_index_ >
+        container_object_->ChildCountIncludingIgnored()) {
       if (failure_reason) {
         *failure_reason = String::Format(
             "\nPosition invalid: child index too large.\n%d vs. %d",
-            text_offset_or_child_index_, container_object_->ChildCount());
+            text_offset_or_child_index_,
+            container_object_->ChildCountIncludingIgnored());
       }
       return false;
     }
@@ -509,9 +513,10 @@
     // text boxes when present, because we'll just be creating a text position
     // in the same piece of text.
     const AXObject* next_in_order =
-        container_object_->ChildCount()
-            ? container_object_->DeepestLastChild()->NextInTreeObject()
-            : container_object_->NextInTreeObject();
+        container_object_->ChildCountIncludingIgnored()
+            ? container_object_->DeepestLastChildIncludingIgnored()
+                  ->NextInPreOrderIncludingIgnored()
+            : container_object_->NextInPreOrderIncludingIgnored();
     if (!next_in_order || !next_in_order->ParentObjectIncludedInTree())
       return {};
 
@@ -544,8 +549,10 @@
     // If this is a static text object, we should not descend into its inline
     // text boxes when present, because we'll just be creating a text position
     // in the same piece of text.
-    if (!container_object_->IsTextObject() && container_object_->ChildCount()) {
-      const AXObject* last_child = container_object_->LastChild();
+    if (!container_object_->IsTextObject() &&
+        container_object_->ChildCountIncludingIgnored()) {
+      const AXObject* last_child =
+          container_object_->LastChildIncludingIgnored();
       // Dont skip over any intervening text.
       if (last_child->IsTextObject() || last_child->IsNativeTextControl()) {
         return CreatePositionAfterObject(
@@ -556,9 +563,10 @@
           *last_child, AXPositionAdjustmentBehavior::kMoveLeft);
     }
 
-    object_before_position = container_object_->PreviousInTreeObject();
+    object_before_position =
+        container_object_->PreviousInPreOrderIncludingIgnored();
   } else {
-    object_before_position = child->PreviousInTreeObject();
+    object_before_position = child->PreviousInPreOrderIncludingIgnored();
   }
 
   if (!object_before_position ||
@@ -695,7 +703,7 @@
   const AXObject* container = container_object_;
   DCHECK(container);
   const AXObject* child = ChildAfterTreePosition();
-  const AXObject* last_child = container->LastChild();
+  const AXObject* last_child = container->LastChildIncludingIgnored();
   if ((IsTextPosition() && (!container->GetNode() ||
                             container->GetNode()->IsMarkerPseudoElement())) ||
       container->IsMockObject() || container->IsVirtualObject() ||
@@ -737,7 +745,8 @@
   } else {
     switch (adjustment_behavior) {
       case AXPositionAdjustmentBehavior::kMoveRight:
-        position.text_offset_or_child_index_ = new_container->ChildCount();
+        position.text_offset_or_child_index_ =
+            new_container->ChildCountIncludingIgnored();
         break;
       case AXPositionAdjustmentBehavior::kMoveLeft:
         position.text_offset_or_child_index_ = 0;
@@ -788,7 +797,7 @@
     }
 
     // "After children" positions.
-    const AXObject* last_child = container_object_->LastChild();
+    const AXObject* last_child = container_object_->LastChildIncludingIgnored();
     if (last_child) {
       const Node* last_child_node = last_child->GetNode();
       DCHECK(last_child_node) << "AX objects used in AX positions that are "
@@ -865,8 +874,8 @@
   switch (adjustment_behavior) {
     case AXPositionAdjustmentBehavior::kMoveRight: {
       const Node* next_node = &child_node;
-      while ((next_node = NodeTraversal::NextSkippingChildren(
-                  *next_node, container_node))) {
+      while ((next_node = NodeTraversal::NextIncludingPseudo(*next_node,
+                                                             container_node))) {
         const AXObject* next_object =
             ax_object_cache_impl->GetOrCreate(next_node);
         if (next_object && next_object->AccessibilityIsIncludedInTree())
@@ -877,8 +886,14 @@
 
     case AXPositionAdjustmentBehavior::kMoveLeft: {
       const Node* previous_node = &child_node;
-      while ((previous_node = NodeTraversal::PreviousSkippingChildren(
-                  *previous_node, container_node))) {
+      // Since this is a pre-order traversal,
+      // "NodeTraversal::PreviousIncludingPseudo" will eventually reach
+      // |container_node| if |container_node| is not nullptr. We should exclude
+      // this as we are strictly interested in |container_node|'s unignored
+      // descendantsin the accessibility tree.
+      while ((previous_node = NodeTraversal::PreviousIncludingPseudo(
+                  *previous_node, container_node)) &&
+             previous_node != container_node) {
         const AXObject* previous_object =
             ax_object_cache_impl->GetOrCreate(previous_node);
         if (previous_object && previous_object->AccessibilityIsIncludedInTree())
diff --git a/third_party/blink/renderer/modules/accessibility/ax_position_test.cc b/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
index 5019ed0..0c1bcb5 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_position_test.cc
@@ -95,7 +95,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -118,7 +118,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -141,7 +141,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -165,7 +165,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -208,7 +208,8 @@
   const AXObject* ax_br = GetAXObjectByElementId("br");
   ASSERT_NE(nullptr, ax_br);
   ASSERT_EQ(ax::mojom::Role::kLineBreak, ax_br->RoleValue());
-  const AXObject* ax_static_text = GetAXRootObject()->DeepestLastChild();
+  const AXObject* ax_static_text =
+      GetAXRootObject()->DeepestLastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -233,7 +234,8 @@
   const AXObject* ax_div = GetAXObjectByElementId("div");
   ASSERT_NE(nullptr, ax_div);
   ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_div->RoleValue());
-  const AXObject* ax_static_text = GetAXRootObject()->DeepestFirstChild();
+  const AXObject* ax_static_text =
+      GetAXRootObject()->DeepestFirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -278,7 +280,8 @@
   const Node* text = GetElementById("div")->firstChild();
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
-  const AXObject* ax_static_text = GetAXObjectByElementId("div")->FirstChild();
+  const AXObject* ax_static_text =
+      GetAXObjectByElementId("div")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -298,7 +301,8 @@
   const Node* text = GetElementById("div")->lastChild();
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
-  const AXObject* ax_static_text = GetAXObjectByElementId("div")->LastChild();
+  const AXObject* ax_static_text =
+      GetAXObjectByElementId("div")->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -322,7 +326,7 @@
   SetBodyInnerHTML(R"HTML(<input id="input" type="text" value="value">
                    <p id="paragraph">hello<br>there</p>)HTML");
 
-  const AXObject* body = GetAXRootObject()->FirstChild();
+  const AXObject* body = GetAXRootObject()->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, body);
   const auto root_first = AXPosition::CreateFirstPositionInObject(*body);
   const auto root_last = AXPosition::CreateLastPositionInObject(*body);
@@ -334,16 +338,16 @@
 
   const AXObject* paragraph = GetAXObjectByElementId("paragraph");
   ASSERT_NE(nullptr, paragraph);
-  ASSERT_NE(nullptr, paragraph->FirstChild());
-  ASSERT_NE(nullptr, paragraph->LastChild());
-  const auto paragraph_before =
-      AXPosition::CreatePositionBeforeObject(*paragraph->FirstChild());
-  const auto paragraph_after =
-      AXPosition::CreatePositionAfterObject(*paragraph->LastChild());
-  const auto paragraph_start =
-      AXPosition::CreatePositionInTextObject(*paragraph->FirstChild(), 0);
-  const auto paragraph_end =
-      AXPosition::CreatePositionInTextObject(*paragraph->LastChild(), 5);
+  ASSERT_NE(nullptr, paragraph->FirstChildIncludingIgnored());
+  ASSERT_NE(nullptr, paragraph->LastChildIncludingIgnored());
+  const auto paragraph_before = AXPosition::CreatePositionBeforeObject(
+      *paragraph->FirstChildIncludingIgnored());
+  const auto paragraph_after = AXPosition::CreatePositionAfterObject(
+      *paragraph->LastChildIncludingIgnored());
+  const auto paragraph_start = AXPosition::CreatePositionInTextObject(
+      *paragraph->FirstChildIncludingIgnored(), 0);
+  const auto paragraph_end = AXPosition::CreatePositionInTextObject(
+      *paragraph->LastChildIncludingIgnored(), 5);
 
   EXPECT_TRUE(root_first == root_first);
   EXPECT_TRUE(root_last == root_last);
@@ -394,7 +398,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -415,7 +419,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -436,7 +440,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->LastChild();
+      GetAXObjectByElementId("paragraph")->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -479,7 +483,8 @@
   const AXObject* ax_br = GetAXObjectByElementId("br");
   ASSERT_NE(nullptr, ax_br);
   ASSERT_EQ(ax::mojom::Role::kLineBreak, ax_br->RoleValue());
-  const AXObject* ax_static_text = GetAXRootObject()->DeepestLastChild();
+  const AXObject* ax_static_text =
+      GetAXRootObject()->DeepestLastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -505,7 +510,8 @@
   const AXObject* ax_div = GetAXObjectByElementId("div");
   ASSERT_NE(nullptr, ax_div);
   ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_div->RoleValue());
-  const AXObject* ax_static_text = GetAXRootObject()->DeepestFirstChild();
+  const AXObject* ax_static_text =
+      GetAXRootObject()->DeepestFirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -551,7 +557,8 @@
   const Node* text = GetElementById("div")->firstChild();
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
-  const AXObject* ax_static_text = GetAXObjectByElementId("div")->FirstChild();
+  const AXObject* ax_static_text =
+      GetAXObjectByElementId("div")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -572,7 +579,8 @@
   const Node* text = GetElementById("div")->lastChild();
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
-  const AXObject* ax_static_text = GetAXObjectByElementId("div")->LastChild();
+  const AXObject* ax_static_text =
+      GetAXObjectByElementId("div")->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -595,7 +603,8 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   ASSERT_EQ(15U, text->textContent().length());
-  const AXObject* ax_static_text = GetAXObjectByElementId("div")->FirstChild();
+  const AXObject* ax_static_text =
+      GetAXObjectByElementId("div")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -642,7 +651,7 @@
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -680,7 +689,7 @@
   const Node* paragraph = GetElementById("paragraph");
   ASSERT_NE(nullptr, paragraph);
 
-  const AXObject* ax_body = GetAXRootObject()->FirstChild();
+  const AXObject* ax_body = GetAXRootObject()->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_body);
   ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_body->RoleValue());
 
@@ -735,12 +744,12 @@
   const AXObject* ax_root = GetAXRootObject();
   ASSERT_NE(nullptr, ax_root);
   ASSERT_EQ(ax::mojom::Role::kRootWebArea, ax_root->RoleValue());
-  ASSERT_EQ(1, ax_root->ChildCount());
+  ASSERT_EQ(1, ax_root->ChildCountIncludingIgnored());
 
-  const AXObject* ax_body = ax_root->FirstChild();
+  const AXObject* ax_body = ax_root->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_body);
   ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_body->RoleValue());
-  ASSERT_EQ(2, ax_body->ChildCount());
+  ASSERT_EQ(2, ax_body->ChildCountIncludingIgnored());
 
   const AXObject* ax_hidden = GetAXObjectByElementId("hidden");
   ASSERT_NE(nullptr, ax_hidden);
@@ -844,17 +853,17 @@
   EXPECT_EQ(ax_hidden, ax_position_from_dom.ChildAfterTreePosition());
 }
 
-TEST_F(AccessibilityTest, PreviousPositionAfterARIAHiddenShouldSkipARIAHidden) {
+TEST_F(AccessibilityTest,
+       PreviousPositionAfterARIAHiddenShouldNotSkipARIAHidden) {
   SetBodyInnerHTML(R"HTML(
       <p id="before">Before aria-hidden.</p>
       <p id="ariaHidden" aria-hidden="true">Aria-hidden.</p>
       <p id="after">After aria-hidden.</p>
       )HTML");
 
-  const Node* before = GetElementById("before");
-  ASSERT_NE(nullptr, before);
-  ASSERT_NE(nullptr, before->firstChild());
-  ASSERT_TRUE(before->firstChild()->IsTextNode());
+  const Node* hidden = GetElementById("ariaHidden");
+  ASSERT_NE(nullptr, hidden);
+  ASSERT_NE(nullptr, hidden->firstChild());
   const Node* after = GetElementById("after");
   ASSERT_NE(nullptr, after);
 
@@ -876,8 +885,8 @@
 
   const auto ax_position_previous = ax_position.CreatePreviousPosition();
   const auto position_previous = ax_position_previous.ToPositionWithAffinity();
-  EXPECT_EQ(before->firstChild(), position_previous.AnchorNode());
-  EXPECT_EQ(19, position_previous.GetPosition().OffsetInContainerNode());
+  EXPECT_EQ(hidden->firstChild(), position_previous.AnchorNode());
+  EXPECT_EQ(12, position_previous.GetPosition().OffsetInContainerNode());
   EXPECT_EQ(nullptr,
             position_previous.GetPosition().ComputeNodeAfterPosition());
 
@@ -902,36 +911,39 @@
   const AXObject* ax_container = GetAXObjectByElementId("container");
   ASSERT_NE(nullptr, ax_container);
   ASSERT_EQ(ax::mojom::Role::kMain, ax_container->RoleValue());
-  ASSERT_EQ(3, ax_container->ChildCount());
+  ASSERT_EQ(3, ax_container->ChildCountIncludingIgnored());
   const AXObject* ax_before = GetAXObjectByElementId("before");
   ASSERT_NE(nullptr, ax_before);
   ASSERT_EQ(ax::mojom::Role::kParagraph, ax_before->RoleValue());
   const AXObject* ax_after = GetAXObjectByElementId("after");
   ASSERT_NE(nullptr, ax_after);
   ASSERT_EQ(ax::mojom::Role::kParagraph, ax_after->RoleValue());
-  ASSERT_NE(nullptr, GetAXObjectByElementId("ariaHidden"));
   const AXObject* ax_hidden = GetAXObjectByElementId("ariaHidden");
+  ASSERT_NE(nullptr, ax_hidden);
   ASSERT_TRUE(ax_hidden->AccessibilityIsIgnored());
 
   const auto position_first = Position::FirstPositionInNode(*hidden);
+  // Since "ax_hidden" has a static text child, the AXPosition should move to an
+  // equivalent position on the static text child.
   auto ax_position_left =
       AXPosition::FromPosition(position_first, TextAffinity::kDownstream,
                                AXPositionAdjustmentBehavior::kMoveLeft);
   EXPECT_TRUE(ax_position_left.IsValid());
   EXPECT_TRUE(ax_position_left.IsTextPosition());
-  EXPECT_EQ(ax_hidden->FirstChild(), ax_position_left.ContainerObject());
+  EXPECT_EQ(ax_hidden->FirstChildIncludingIgnored(),
+            ax_position_left.ContainerObject());
   EXPECT_EQ(0, ax_position_left.TextOffset());
-  // This is an "after children" position.
-  EXPECT_EQ(nullptr, ax_position_left.ChildAfterTreePosition());
 
+  // In this case, the adjustment behavior should not affect the outcome because
+  // there is an equivalent AXPosition in the static text child.
   auto ax_position_right =
       AXPosition::FromPosition(position_first, TextAffinity::kDownstream,
                                AXPositionAdjustmentBehavior::kMoveRight);
   EXPECT_TRUE(ax_position_right.IsValid());
   EXPECT_TRUE(ax_position_right.IsTextPosition());
-  EXPECT_EQ(ax_hidden->FirstChild(), ax_position_right.ContainerObject());
+  EXPECT_EQ(ax_hidden->FirstChildIncludingIgnored(),
+            ax_position_right.ContainerObject());
   EXPECT_EQ(0, ax_position_right.TextOffset());
-  EXPECT_EQ(nullptr, ax_position_right.ChildAfterTreePosition());
 
   const auto position_before = Position::BeforeNode(*hidden);
   ax_position_left =
@@ -941,9 +953,11 @@
   EXPECT_FALSE(ax_position_left.IsTextPosition());
   EXPECT_EQ(ax_container, ax_position_left.ContainerObject());
   EXPECT_EQ(1, ax_position_left.ChildIndex());
-  // This is an "after children" position.
   EXPECT_EQ(ax_hidden, ax_position_left.ChildAfterTreePosition());
 
+  // Since an AXPosition before "ax_hidden" is valid, i.e. it does not need to
+  // be adjusted, then adjustment behavior should not make a difference in the
+  // outcome.
   ax_position_right =
       AXPosition::FromPosition(position_before, TextAffinity::kDownstream,
                                AXPositionAdjustmentBehavior::kMoveRight);
@@ -953,16 +967,17 @@
   EXPECT_EQ(1, ax_position_right.ChildIndex());
   EXPECT_EQ(ax_hidden, ax_position_right.ChildAfterTreePosition());
 
+  // The DOM node right after "hidden" is accessibility ignored, so we should
+  // see an adjustment in the relevant direction.
   const auto position_after = Position::AfterNode(*hidden);
   ax_position_left =
       AXPosition::FromPosition(position_after, TextAffinity::kDownstream,
                                AXPositionAdjustmentBehavior::kMoveLeft);
   EXPECT_TRUE(ax_position_left.IsValid());
-  EXPECT_FALSE(ax_position_left.IsTextPosition());
-  EXPECT_EQ(ax_hidden, ax_position_left.ContainerObject());
-  EXPECT_EQ(1, ax_position_left.ChildIndex());
-  // This is an "after children" position.
-  EXPECT_EQ(nullptr, ax_position_left.ChildAfterTreePosition());
+  EXPECT_TRUE(ax_position_left.IsTextPosition());
+  EXPECT_EQ(ax_hidden->FirstChildIncludingIgnored(),
+            ax_position_left.ContainerObject());
+  EXPECT_EQ(12, ax_position_left.TextOffset());
 
   ax_position_right =
       AXPosition::FromPosition(position_after, TextAffinity::kDownstream,
@@ -1000,7 +1015,7 @@
   const AXObject* ax_canvas_1 = GetAXObjectByElementId("canvas1");
   ASSERT_NE(nullptr, ax_canvas_1);
   ASSERT_EQ(ax::mojom::Role::kCanvas, ax_canvas_1->RoleValue());
-  const AXObject* ax_text = ax_canvas_1->FirstChild();
+  const AXObject* ax_text = ax_canvas_1->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text->RoleValue());
   const AXObject* ax_canvas_2 = GetAXObjectByElementId("canvas2");
@@ -1093,8 +1108,8 @@
   const AXObject* ax_item = GetAXObjectByElementId("listItem");
   ASSERT_NE(nullptr, ax_item);
   ASSERT_EQ(ax::mojom::Role::kListItem, ax_item->RoleValue());
-  ASSERT_EQ(2, ax_item->ChildCount());
-  const AXObject* ax_marker = ax_item->FirstChild();
+  ASSERT_EQ(2, ax_item->ChildCountIncludingIgnored());
+  const AXObject* ax_marker = ax_item->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_marker);
   ASSERT_EQ(ax::mojom::Role::kListMarker, ax_marker->RoleValue());
 
@@ -1173,11 +1188,11 @@
   const AXObject* ax_item = GetAXObjectByElementId("listItem");
   ASSERT_NE(nullptr, ax_item);
   ASSERT_EQ(ax::mojom::Role::kListItem, ax_item->RoleValue());
-  ASSERT_EQ(2, ax_item->ChildCount());
-  const AXObject* ax_marker = ax_item->FirstChild();
+  ASSERT_EQ(2, ax_item->ChildCountIncludingIgnored());
+  const AXObject* ax_marker = ax_item->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_marker);
   ASSERT_EQ(ax::mojom::Role::kListMarker, ax_marker->RoleValue());
-  const AXObject* ax_text = ax_item->LastChild();
+  const AXObject* ax_text = ax_item->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text->RoleValue());
 
@@ -1207,15 +1222,17 @@
 
   const AXObject* ax_quote = GetAXObjectByElementId("quote");
   ASSERT_NE(nullptr, ax_quote);
-  ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_quote->RoleValue());
-  ASSERT_EQ(3, ax_quote->ChildCount());
-  const AXObject* ax_css_before = ax_quote->FirstChild();
+  ASSERT_TRUE(ax_quote->AccessibilityIsIgnored());
+  const AXObject* ax_quote_parent = ax_quote->ParentObjectUnignored();
+  ASSERT_NE(nullptr, ax_quote_parent);
+  ASSERT_EQ(4, ax_quote_parent->UnignoredChildCount());
+  const AXObject* ax_css_before = ax_quote_parent->UnignoredChildAt(0);
   ASSERT_NE(nullptr, ax_css_before);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_css_before->RoleValue());
-  const AXObject* ax_text = *(ax_quote->Children().begin() + 1);
+  const AXObject* ax_text = ax_quote_parent->UnignoredChildAt(1);
   ASSERT_NE(nullptr, ax_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text->RoleValue());
-  const AXObject* ax_css_after = ax_quote->LastChild();
+  const AXObject* ax_css_after = ax_quote_parent->UnignoredChildAt(2);
   ASSERT_NE(nullptr, ax_css_after);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_css_after->RoleValue());
 
@@ -1256,9 +1273,9 @@
   const AXObject* ax_heading = GetAXObjectByElementId("heading");
   ASSERT_NE(nullptr, ax_heading);
   ASSERT_EQ(ax::mojom::Role::kHeading, ax_heading->RoleValue());
-  ASSERT_EQ(2, ax_heading->ChildCount());
+  ASSERT_EQ(2, ax_heading->ChildCountIncludingIgnored());
 
-  const AXObject* ax_css_before = ax_heading->FirstChild();
+  const AXObject* ax_css_before = ax_heading->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_css_before);
   ASSERT_EQ(ax::mojom::Role::kImage, ax_css_before->RoleValue());
 
@@ -1314,14 +1331,16 @@
   ASSERT_NE(nullptr, ax_last_header_cell);
   ASSERT_EQ(ax::mojom::Role::kColumnHeader, ax_last_header_cell->RoleValue());
 
-  ASSERT_EQ(3, ax_first_header_cell->ChildCount());
-  AXObject* const ax_first_cell_css_before = ax_first_header_cell->FirstChild();
+  ASSERT_EQ(3, ax_first_header_cell->ChildCountIncludingIgnored());
+  AXObject* const ax_first_cell_css_before =
+      ax_first_header_cell->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_first_cell_css_before);
   ASSERT_EQ(ax::mojom::Role::kStaticText,
             ax_first_cell_css_before->RoleValue());
 
-  ASSERT_EQ(3, ax_last_header_cell->ChildCount());
-  AXObject* const ax_last_cell_css_after = ax_last_header_cell->LastChild();
+  ASSERT_EQ(3, ax_last_header_cell->ChildCountIncludingIgnored());
+  AXObject* const ax_last_cell_css_after =
+      ax_last_header_cell->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_last_cell_css_after);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_last_cell_css_after->RoleValue());
 
@@ -1352,9 +1371,9 @@
   // Same situation as above, but now create a text position inside the inline
   // text box representing the CSS content after the last header cell.
   ax_first_cell_css_before->LoadInlineTextBoxes();
-  ASSERT_NE(nullptr, ax_first_cell_css_before->FirstChild());
+  ASSERT_NE(nullptr, ax_first_cell_css_before->FirstChildIncludingIgnored());
   ax_position_before = AXPosition::CreateFirstPositionInObject(
-      *ax_first_cell_css_before->FirstChild());
+      *ax_first_cell_css_before->FirstChildIncludingIgnored());
   EXPECT_TRUE(ax_position_before.IsTextPosition());
   EXPECT_EQ(0, ax_position_before.TextOffset());
   position_before = ax_position_before.ToPositionWithAffinity(
@@ -1388,9 +1407,9 @@
   // Same situation as above, but now create a text position inside the inline
   // text box representing the CSS content after the last header cell.
   ax_last_cell_css_after->LoadInlineTextBoxes();
-  ASSERT_NE(nullptr, ax_last_cell_css_after->FirstChild());
+  ASSERT_NE(nullptr, ax_last_cell_css_after->FirstChildIncludingIgnored());
   ax_position_after = AXPosition::CreateLastPositionInObject(
-      *ax_last_cell_css_after->FirstChild());
+      *ax_last_cell_css_after->FirstChildIncludingIgnored());
   EXPECT_TRUE(ax_position_after.IsTextPosition());
   EXPECT_EQ(1, ax_position_after.TextOffset());
   position_after = ax_position_after.ToPositionWithAffinity(
@@ -1593,8 +1612,8 @@
   const AXObject* ax_parent = GetAXObjectByElementId("aomParent");
   ASSERT_NE(nullptr, ax_parent);
   ASSERT_EQ(ax::mojom::Role::kGenericContainer, ax_parent->RoleValue());
-  ASSERT_EQ(1, ax_parent->ChildCount());
-  const AXObject* ax_button = ax_parent->FirstChild();
+  ASSERT_EQ(1, ax_parent->ChildCountIncludingIgnored());
+  const AXObject* ax_button = ax_parent->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_button);
   ASSERT_EQ(ax::mojom::Role::kButton, ax_button->RoleValue());
   const AXObject* ax_after = GetAXObjectByElementId("after");
@@ -1663,19 +1682,20 @@
   const Node* text = GetElementById("paragraph")->firstChild();
   ASSERT_NE(nullptr, text);
   ASSERT_TRUE(text->IsTextNode());
-  AXObject* ax_static_text = GetAXObjectByElementId("paragraph")->FirstChild();
+  AXObject* ax_static_text =
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
 
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
   ax_static_text->LoadInlineTextBoxes();
-  ASSERT_EQ(3, ax_static_text->ChildCount());
+  ASSERT_EQ(3, ax_static_text->ChildCountIncludingIgnored());
 
   // This test expects the starting offset of the last InlineTextBox object to
   // equates the sum of the previous inline text boxes length, without the
   // collapsed white-spaces.
-  const auto ax_position =
-      AXPosition::CreatePositionBeforeObject(*(ax_static_text->LastChild()));
+  const auto ax_position = AXPosition::CreatePositionBeforeObject(
+      *(ax_static_text->LastChildIncludingIgnored()));
   const auto position = ax_position.ToPositionWithAffinity();
   EXPECT_EQ(LayoutNGEnabled() ? 7 : 6,
             position.GetPosition().OffsetInContainerNode());
diff --git a/third_party/blink/renderer/modules/accessibility/ax_range_test.cc b/third_party/blink/renderer/modules/accessibility/ax_range_test.cc
index a8a73f7..96fa70e 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_range_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_range_test.cc
@@ -19,18 +19,18 @@
 
   const AXObject* root = GetAXRootObject();
   ASSERT_NE(nullptr, root);
-  const AXObject* body = root->FirstChild();
+  const AXObject* body = root->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, body);
   const AXObject* input = GetAXObjectByElementId("input");
   ASSERT_NE(nullptr, input);
   const AXObject* paragraph = GetAXObjectByElementId("paragraph");
   ASSERT_NE(nullptr, paragraph);
-  const AXObject* text1 = paragraph->FirstChild();
+  const AXObject* text1 = paragraph->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, text1);
   ASSERT_EQ(ax::mojom::Role::kStaticText, text1->RoleValue());
   const AXObject* br = GetAXObjectByElementId("br");
   ASSERT_NE(nullptr, br);
-  const AXObject* text2 = paragraph->LastChild();
+  const AXObject* text2 = paragraph->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, text2);
   ASSERT_EQ(ax::mojom::Role::kStaticText, text2->RoleValue());
   const AXObject* button = GetAXObjectByElementId("button");
@@ -55,7 +55,7 @@
 
   const AXObject* paragraph = GetAXObjectByElementId("paragraph");
   ASSERT_NE(nullptr, paragraph);
-  const AXObject* text = paragraph->FirstChild();
+  const AXObject* text = paragraph->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, text->RoleValue());
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
index 5316fe5..0970f700 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_selection_test.cc
@@ -62,7 +62,7 @@
   UpdateAllLifecyclePhasesForTest();
 
   const AXObject* ax_static_text_1 =
-      GetAXObjectByElementId("paragraph1")->FirstChild();
+      GetAXObjectByElementId("paragraph1")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text_1);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text_1->RoleValue());
   const AXObject* ax_paragraph_2 = GetAXObjectByElementId("paragraph2");
@@ -109,7 +109,7 @@
 
   ASSERT_FALSE(ax_selection.Extent().IsTextPosition());
   EXPECT_EQ(GetAXRootObject(), ax_selection.Extent().ContainerObject());
-  EXPECT_EQ(GetAXRootObject()->ChildCount(),
+  EXPECT_EQ(GetAXRootObject()->ChildCountIncludingIgnored(),
             ax_selection.Extent().ChildIndex());
 
   EXPECT_EQ(
@@ -175,7 +175,7 @@
   UpdateAllLifecyclePhasesForTest();
 
   const AXObject* ax_static_text_1 =
-      GetAXObjectByElementId("paragraph1")->FirstChild();
+      GetAXObjectByElementId("paragraph1")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text_1);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text_1->RoleValue());
   const AXObject* ax_paragraph_2 = GetAXObjectByElementId("paragraph2");
@@ -213,7 +213,7 @@
       )HTML");
 
   const AXObject* ax_static_text_1 =
-      GetAXObjectByElementId("paragraph1")->FirstChild();
+      GetAXObjectByElementId("paragraph1")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text_1);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text_1->RoleValue());
   const AXObject* ax_paragraph_2 = GetAXObjectByElementId("paragraph2");
@@ -241,7 +241,7 @@
   ASSERT_TRUE(text->IsTextNode());
 
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -272,7 +272,7 @@
   ASSERT_TRUE(text->IsTextNode());
 
   const AXObject* ax_static_text =
-      GetAXObjectByElementId("paragraph")->FirstChild();
+      GetAXObjectByElementId("paragraph")->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
 
@@ -313,7 +313,8 @@
   const AXObject* ax_br = GetAXObjectByElementId("br");
   ASSERT_NE(nullptr, ax_br);
   ASSERT_EQ(ax::mojom::Role::kLineBreak, ax_br->RoleValue());
-  const AXObject* ax_line2 = GetAXObjectByElementId("paragraph")->LastChild();
+  const AXObject* ax_line2 =
+      GetAXObjectByElementId("paragraph")->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_line2);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_line2->RoleValue());
 
@@ -358,7 +359,8 @@
   const AXObject* ax_br = GetAXObjectByElementId("br");
   ASSERT_NE(nullptr, ax_br);
   ASSERT_EQ(ax::mojom::Role::kLineBreak, ax_br->RoleValue());
-  const AXObject* ax_line2 = GetAXObjectByElementId("paragraph")->LastChild();
+  const AXObject* ax_line2 =
+      GetAXObjectByElementId("paragraph")->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_line2);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_line2->RoleValue());
 
@@ -519,13 +521,13 @@
   const AXObject* ax_item_1 = GetAXObjectByElementId("item1");
   ASSERT_NE(nullptr, ax_item_1);
   ASSERT_EQ(ax::mojom::Role::kListItem, ax_item_1->RoleValue());
-  const AXObject* ax_bullet_1 = ax_item_1->FirstChild();
+  const AXObject* ax_bullet_1 = ax_item_1->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_bullet_1);
   ASSERT_EQ(ax::mojom::Role::kListMarker, ax_bullet_1->RoleValue());
   const AXObject* ax_item_2 = GetAXObjectByElementId("item2");
   ASSERT_NE(nullptr, ax_item_2);
   ASSERT_EQ(ax::mojom::Role::kListItem, ax_item_2->RoleValue());
-  const AXObject* ax_text_2 = ax_item_2->LastChild();
+  const AXObject* ax_text_2 = ax_item_2->LastChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_text_2);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text_2->RoleValue());
 
@@ -828,7 +830,8 @@
       GetAXObjectByElementId("contenteditable");
   ASSERT_NE(nullptr, ax_contenteditable);
   ASSERT_EQ(ax::mojom::Role::kTextField, ax_contenteditable->RoleValue());
-  const AXObject* ax_static_text = ax_contenteditable->FirstChild();
+  const AXObject* ax_static_text =
+      ax_contenteditable->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   // Guard against the structure of the accessibility tree unexpectedly
   // changing, causing a hard to debug test failure.
@@ -887,7 +890,8 @@
       GetAXObjectByElementId("contenteditable");
   ASSERT_NE(nullptr, ax_contenteditable);
   ASSERT_EQ(ax::mojom::Role::kTextField, ax_contenteditable->RoleValue());
-  const AXObject* ax_static_text = ax_contenteditable->FirstChild();
+  const AXObject* ax_static_text =
+      ax_contenteditable->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   // Guard against the structure of the accessibility tree unexpectedly
   // changing, causing a hard to debug test failure.
@@ -942,10 +946,10 @@
       GetAXObjectByElementId("contenteditable");
   ASSERT_NE(nullptr, ax_contenteditable);
   ASSERT_EQ(ax::mojom::Role::kTextField, ax_contenteditable->RoleValue());
-  ASSERT_EQ(3, ax_contenteditable->ChildCount())
+  ASSERT_EQ(3, ax_contenteditable->UnignoredChildCount())
       << "The content editable should have two lines with a line break between "
          "them.";
-  const AXObject* ax_static_text_2 = ax_contenteditable->Children()[2];
+  const AXObject* ax_static_text_2 = ax_contenteditable->UnignoredChildAt(2);
   ASSERT_NE(nullptr, ax_static_text_2);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text_2->RoleValue());
 
@@ -1599,7 +1603,7 @@
       GetAXObjectByElementId("contenteditable");
   ASSERT_NE(nullptr, ax_contenteditable);
   ASSERT_EQ(ax::mojom::Role::kTextField, ax_contenteditable->RoleValue());
-  const AXObject* ax_text = ax_contenteditable->FirstChild();
+  const AXObject* ax_text = ax_contenteditable->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_text->RoleValue());
 
@@ -1640,8 +1644,9 @@
   const AXObject* ax_contenteditable =
       GetAXObjectByElementId("contenteditable");
   ASSERT_NE(nullptr, ax_contenteditable);
-  ASSERT_EQ(1, ax_contenteditable->ChildCount());
-  const AXObject* ax_static_text = ax_contenteditable->FirstChild();
+  ASSERT_EQ(1, ax_contenteditable->ChildCountIncludingIgnored());
+  const AXObject* ax_static_text =
+      ax_contenteditable->FirstChildIncludingIgnored();
   ASSERT_NE(nullptr, ax_static_text);
   ASSERT_EQ(ax::mojom::Role::kStaticText, ax_static_text->RoleValue());
   String computed_name = ax_static_text->ComputedName();
@@ -1704,7 +1709,8 @@
   SetBodyInnerHTML(R"HTML(
       <select id="sel"><option>1</option></select>
       )HTML");
-  AXObject* ax_sel = GetAXObjectByElementId("sel")->FirstChild();
+  AXObject* ax_sel =
+      GetAXObjectByElementId("sel")->FirstChildIncludingIgnored();
   AXPosition ax_position = AXPosition::CreatePositionBeforeObject(*ax_sel);
   AXSelection::Builder builder;
   AXSelection ax_selection =
@@ -1750,6 +1756,17 @@
   ParameterizedAccessibilitySelectionTest::RunSelectionTest("list");
 }
 
+TEST_F(AccessibilitySelectionTest, ParagraphPresentational) {
+  // The focus of the selection is an "after children" position on a paragraph
+  // with role="presentation" and in which the last child is an empty div. In
+  // other words, both the paragraph and its last child are ignored in the
+  // accessibility tree. In order to become valid, the focus should move to
+  // before the next unignored child of the presentational paragraph's unignored
+  // parent, which in this case is another paragraph that comes after the
+  // presentational one.
+  RunSelectionTest("paragraph-presentational");
+}
+
 TEST_F(AccessibilitySelectionTest, SVG) {
   RunSelectionTest("svg");
 }
diff --git a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
index 664f4cc..b6e8dbc 100644
--- a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
+++ b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
@@ -732,7 +732,8 @@
         BuildProtocolAXObject(*ax_object, nullptr, false, *nodes, cache);
 
     auto child_ids = std::make_unique<protocol::Array<AXNodeId>>();
-    const AXObject::AXObjectVector& children = ax_object->Children();
+    const AXObject::AXObjectVector& children =
+        ax_object->ChildrenIncludingIgnored();
     for (unsigned i = 0; i < children.size(); i++) {
       AXObject& child_ax_object = *children[i].Get();
       child_ids->emplace_back(String::Number(child_ax_object.AXObjectID()));
@@ -815,7 +816,8 @@
     return;
   }
 
-  const AXObject::AXObjectVector& children = ax_object.Children();
+  const AXObject::AXObjectVector& children =
+      ax_object.ChildrenIncludingIgnored();
   for (unsigned i = 0; i < children.size(); i++) {
     AXObject& child_ax_object = *children[i].Get();
     child_ids->emplace_back(String::Number(child_ax_object.AXObjectID()));
diff --git a/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc b/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc
index 9056487..446a8e4 100644
--- a/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/testing/accessibility_selection_test.cc
@@ -150,7 +150,7 @@
   }
 
   void SerializeSubtree(const AXObject& subtree) {
-    if (subtree.ChildCount() == 0) {
+    if (!subtree.ChildCountIncludingIgnored()) {
       // Though they are in this particular case both equivalent to an "after
       // object" position, "Before children" and "after children" positions are
       // still valid within empty subtrees.
@@ -159,7 +159,7 @@
       return;
     }
 
-    for (const AXObject* child : subtree.Children()) {
+    for (const AXObject* child : subtree.ChildrenIncludingIgnored()) {
       DCHECK(child);
       const auto position = AXPosition::CreatePositionBeforeObject(*child);
       HandleSelection(position);
@@ -315,7 +315,7 @@
   }
 
   void HandleObject(const AXObject& object) {
-    for (const AXObject* child : object.Children()) {
+    for (const AXObject* child : object.ChildrenIncludingIgnored()) {
       DCHECK(child);
       FindSelectionMarkers(*child);
     }
diff --git a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
index 6f8bb3a2..adbc4a21 100644
--- a/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
+++ b/third_party/blink/renderer/modules/accessibility/testing/accessibility_test.cc
@@ -64,7 +64,7 @@
 
   stream << std::string(level * 2, '+');
   stream << *root << std::endl;
-  for (const AXObject* child : root->Children()) {
+  for (const AXObject* child : root->ChildrenIncludingIgnored()) {
     DCHECK(child);
     PrintAXTreeHelper(stream, child, level + 1);
   }
diff --git a/third_party/blink/renderer/modules/accessibility/testing/data/selection/paragraph-presentational-ax.txt b/third_party/blink/renderer/modules/accessibility/testing/data/selection/paragraph-presentational-ax.txt
new file mode 100644
index 0000000..6eff2ce
--- /dev/null
+++ b/third_party/blink/renderer/modules/accessibility/testing/data/selection/paragraph-presentational-ax.txt
@@ -0,0 +1,12 @@
+
+================================================================================
+AXSelection from AX text position in "StaticText": "Some text.", 0 to AX object anchored position in "Main": "", 2
+================================================================================
+++<GenericContainer>
+++++<Main>
+++++++<Presentational>
+^++++++++<StaticText: ^Some text.>
+++++++<GenericContainer>
+|++++++<Paragraph>
+++++++<Paragraph>
+++++++++<StaticText: After presentational paragraph.>
diff --git a/third_party/blink/renderer/modules/accessibility/testing/data/selection/paragraph-presentational.html b/third_party/blink/renderer/modules/accessibility/testing/data/selection/paragraph-presentational.html
new file mode 100644
index 0000000..2728235
--- /dev/null
+++ b/third_party/blink/renderer/modules/accessibility/testing/data/selection/paragraph-presentational.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+  <body>
+    <div role="main">
+      <p role="presentation">^
+        <span>Some text.</span>
+        <div></div>
+      |</p>
+      <p>After presentational paragraph.</p>
+    </div>
+  </body>
+</html>
diff --git a/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc b/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc
index 64bbd13..b44b0c7 100644
--- a/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/federated_credential.cc
@@ -16,20 +16,32 @@
 FederatedCredential* FederatedCredential::Create(
     const FederatedCredentialInit* data,
     ExceptionState& exception_state) {
-  if (data->id().IsEmpty())
+  if (data->id().IsEmpty()) {
     exception_state.ThrowTypeError("'id' must not be empty.");
-  if (data->provider().IsEmpty())
+    return nullptr;
+  }
+  if (data->provider().IsEmpty()) {
     exception_state.ThrowTypeError("'provider' must not be empty.");
+    return nullptr;
+  }
 
-  KURL icon_url = ParseStringAsURLOrThrow(data->iconURL(), exception_state);
-  KURL provider_url =
-      ParseStringAsURLOrThrow(data->provider(), exception_state);
-
+  KURL icon_url;
+  if (data->hasIconURL())
+    icon_url = ParseStringAsURLOrThrow(data->iconURL(), exception_state);
   if (exception_state.HadException())
     return nullptr;
 
+  KURL provider_url =
+      ParseStringAsURLOrThrow(data->provider(), exception_state);
+  if (exception_state.HadException())
+    return nullptr;
+
+  String name;
+  if (data->hasName())
+    name = data->name();
+
   return MakeGarbageCollected<FederatedCredential>(
-      data->id(), SecurityOrigin::Create(provider_url), data->name(), icon_url);
+      data->id(), SecurityOrigin::Create(provider_url), name, icon_url);
 }
 
 FederatedCredential* FederatedCredential::Create(
diff --git a/third_party/blink/renderer/modules/credentialmanager/password_credential.cc b/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
index 22dbd5b..72705195 100644
--- a/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/password_credential.cc
@@ -22,18 +22,27 @@
 PasswordCredential* PasswordCredential::Create(
     const PasswordCredentialData* data,
     ExceptionState& exception_state) {
-  if (data->id().IsEmpty())
+  if (data->id().IsEmpty()) {
     exception_state.ThrowTypeError("'id' must not be empty.");
-  if (data->password().IsEmpty())
+    return nullptr;
+  }
+  if (data->password().IsEmpty()) {
     exception_state.ThrowTypeError("'password' must not be empty.");
+    return nullptr;
+  }
 
-  KURL icon_url = ParseStringAsURLOrThrow(data->iconURL(), exception_state);
-
+  KURL icon_url;
+  if (data->hasIconURL())
+    icon_url = ParseStringAsURLOrThrow(data->iconURL(), exception_state);
   if (exception_state.HadException())
     return nullptr;
 
+  String name;
+  if (data->hasName())
+    name = data->name();
+
   return MakeGarbageCollected<PasswordCredential>(data->id(), data->password(),
-                                                  data->name(), icon_url);
+                                                  name, icon_url);
 }
 
 // https://w3c.github.io/webappsec-credential-management/#construct-passwordcredential-form
@@ -45,7 +54,10 @@
   FormData* form_data = FormData::Create(form, exception_state);
   if (exception_state.HadException())
     return nullptr;
+
   PasswordCredentialData* data = PasswordCredentialData::Create();
+  bool is_id_set = false;
+  bool is_password_set = false;
   for (ListedElement* submittable_element : form->ListedElements()) {
     // The "form data set" contains an entry for a |submittable_element| only if
     // it has a non-empty `name` attribute.
@@ -66,16 +78,31 @@
     for (const auto& token : autofill_tokens) {
       if (token == "current-password" || token == "new-password") {
         data->setPassword(value.GetAsUSVString());
+        is_password_set = true;
       } else if (token == "photo") {
         data->setIconURL(value.GetAsUSVString());
       } else if (token == "name" || token == "nickname") {
         data->setName(value.GetAsUSVString());
       } else if (token == "username") {
         data->setId(value.GetAsUSVString());
+        is_id_set = true;
       }
     }
   }
 
+  // Check required fields of PasswordCredentialData dictionary.
+  if (!is_id_set) {
+    exception_state.ThrowTypeError(
+        "'username' must be specified in the form's autocomplete attribute.");
+    return nullptr;
+  }
+  if (!is_password_set) {
+    exception_state.ThrowTypeError(
+        "Either 'current-password' or 'new-password' must be specified in the "
+        "form's autocomplete attribute.");
+    return nullptr;
+  }
+
   // Create a PasswordCredential using the data gathered above.
   return PasswordCredential::Create(data, exception_state);
 }
diff --git a/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc b/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc
index 2d7d62bc..7374a50 100644
--- a/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/password_credential_test.cc
@@ -97,7 +97,10 @@
   EXPECT_EQ(nullptr, credential);
   EXPECT_TRUE(exception_state.HadException());
   EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
-  EXPECT_EQ("'password' must not be empty.", exception_state.Message());
+  EXPECT_EQ(
+      "Either 'current-password' or 'new-password' must be specified in the "
+      "form's autocomplete attribute.",
+      exception_state.Message());
 }
 
 TEST_F(PasswordCredentialTest, CreateFromFormNoId) {
@@ -116,7 +119,9 @@
   EXPECT_EQ(nullptr, credential);
   EXPECT_TRUE(exception_state.HadException());
   EXPECT_EQ(ESErrorType::kTypeError, exception_state.CodeAs<ESErrorType>());
-  EXPECT_EQ("'id' must not be empty.", exception_state.Message());
+  EXPECT_EQ(
+      "'username' must be specified in the form's autocomplete attribute.",
+      exception_state.Message());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/exported/web_ax_object.cc b/third_party/blink/renderer/modules/exported/web_ax_object.cc
index f9d72474..32049260 100644
--- a/third_party/blink/renderer/modules/exported/web_ax_object.cc
+++ b/third_party/blink/renderer/modules/exported/web_ax_object.cc
@@ -234,17 +234,14 @@
   if (IsDetached())
     return 0;
 
-  return private_->Children().size();
+  return private_->ChildCountIncludingIgnored();
 }
 
 WebAXObject WebAXObject::ChildAt(unsigned index) const {
   if (IsDetached())
     return WebAXObject();
 
-  if (private_->Children().size() <= index)
-    return WebAXObject();
-
-  return WebAXObject(private_->Children()[index]);
+  return WebAXObject(private_->ChildAtIncludingIgnored(int{index}));
 }
 
 WebAXObject WebAXObject::ParentObject() const {
diff --git a/third_party/blink/renderer/modules/hid/hid.cc b/third_party/blink/renderer/modules/hid/hid.cc
index ce90c83..677ef41 100644
--- a/third_party/blink/renderer/modules/hid/hid.cc
+++ b/third_party/blink/renderer/modules/hid/hid.cc
@@ -141,7 +141,7 @@
     return ScriptPromise();
   }
 
-  if (!GetExecutionContext()->IsFeatureEnabled(
+  if (!frame->GetDocument()->IsFeatureEnabled(
           mojom::blink::FeaturePolicyFeature::kHid,
           ReportOptions::kReportOnFailure)) {
     exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
index 77fa17b..2c821f2b 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
@@ -989,9 +989,12 @@
   MediaCapabilitiesKeySystemAccessInitializer* initializer =
       MakeGarbageCollected<MediaCapabilitiesKeySystemAccessInitializer>(
           script_state, key_system_config->keySystem(), config_vector,
-          WTF::Bind(&MediaCapabilities::GetPerfInfo, WrapPersistent(this),
-                    video_codec, video_profile,
-                    WrapPersistent(configuration->video()), request_time));
+          WTF::Bind(
+              &MediaCapabilities::GetPerfInfo, WrapPersistent(this),
+              video_codec, video_profile,
+              WrapPersistent(configuration->hasVideo() ? configuration->video()
+                                                       : nullptr),
+              request_time));
 
   // IMPORTANT: Acquire the promise before potentially synchronously resolving
   // it in the code that follows. Otherwise the promise returned to JS will be
diff --git a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
index 5889883..feff64f 100644
--- a/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
+++ b/third_party/blink/renderer/modules/media_controls/media_controls_orientation_lock_delegate.cc
@@ -6,7 +6,6 @@
 
 #include <memory>
 
-#include "base/metrics/histogram_functions.h"
 #include "build/build_config.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/task_type.h"
@@ -39,22 +38,6 @@
 
 namespace {
 
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class MetadataAvailabilityMetrics {
-  kAvailable = 0,  // Available when lock was attempted.
-  kMissing = 1,    // Missing when lock was attempted.
-  kReceived = 2,   // Received after being missing in order to lock.
-
-  // Keep at the end.
-  kMaxValue = kReceived,
-};
-
-void RecordMetadataAvailability(MetadataAvailabilityMetrics metrics) {
-  base::UmaHistogramEnumeration(
-      "Media.Video.FullscreenOrientationLock.MetadataAvailability", metrics);
-}
-
 // WebLockOrientationCallback implementation that will not react to a success
 // nor a failure.
 class DummyScreenOrientationCallback : public WebLockOrientationCallback {
@@ -100,16 +83,10 @@
   DCHECK(state_ != State::kMaybeLockedFullscreen);
 
   if (VideoElement().getReadyState() == HTMLMediaElement::kHaveNothing) {
-    RecordMetadataAvailability(MetadataAvailabilityMetrics::kMissing);
     state_ = State::kPendingMetadata;
     return;
   }
 
-  if (state_ == State::kPendingMetadata)
-    RecordMetadataAvailability(MetadataAvailabilityMetrics::kReceived);
-  else
-    RecordMetadataAvailability(MetadataAvailabilityMetrics::kAvailable);
-
   state_ = State::kMaybeLockedFullscreen;
 
   if (!GetDocument().domWindow())
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
index c778a33..7d88ec6 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.cc
@@ -12,6 +12,7 @@
 #include "media/base/video_frame.h"
 #include "media/base/video_frame_metadata.h"
 #include "media/base/video_util.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_source.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 
@@ -133,12 +134,12 @@
 };
 
 MediaStreamVideoRendererSink::MediaStreamVideoRendererSink(
-    const WebMediaStreamTrack& video_track,
+    MediaStreamComponent* video_component,
     const RepaintCB& repaint_cb,
     scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
     scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner)
     : repaint_cb_(repaint_cb),
-      video_track_(video_track),
+      video_component_(video_component),
       io_task_runner_(std::move(io_task_runner)),
       main_render_task_runner_(std::move(main_render_task_runner)) {}
 
@@ -157,7 +158,7 @@
                           WTF::CrossThreadUnretained(frame_deliverer_.get())));
 
   MediaStreamVideoSink::ConnectToTrack(
-      video_track_,
+      WebMediaStreamTrack(video_component_.Get()),
       // This callback is run on IO thread. It is safe to use base::Unretained
       // here because |frame_receiver_| will be destroyed on IO thread after
       // sink is disconnected from track.
@@ -167,9 +168,9 @@
       // Local display video rendering is considered a secure link.
       true);
 
-  if (video_track_.Source().GetReadyState() ==
-          WebMediaStreamSource::kReadyStateEnded ||
-      !video_track_.IsEnabled()) {
+  if (video_component_->Source()->GetReadyState() ==
+          MediaStreamSource::kReadyStateEnded ||
+      !video_component_->Enabled()) {
     PostCrossThreadTask(
         *io_task_runner_, FROM_HERE,
         CrossThreadBindOnce(&FrameDeliverer::RenderEndOfStream,
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.h b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.h
index eedf022..c8b8f13 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_renderer_sink.h
@@ -11,9 +11,9 @@
 #include "base/threading/thread_checker.h"
 #include "third_party/blink/public/common/media/video_capture.h"
 #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_video_renderer.h"
-#include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/blink/public/web/modules/mediastream/media_stream_video_sink.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace base {
@@ -39,7 +39,7 @@
       public MediaStreamVideoSink {
  public:
   MediaStreamVideoRendererSink(
-      const WebMediaStreamTrack& video_track,
+      MediaStreamComponent* video_component,
       const WebMediaStreamVideoRenderer::RepaintCB& repaint_cb,
       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
       scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner);
@@ -69,7 +69,7 @@
   State GetStateForTesting();
 
   const RepaintCB repaint_cb_;
-  const WebMediaStreamTrack video_track_;
+  Persistent<MediaStreamComponent> video_component_;
 
   // Inner class used for transfering frames on compositor thread and running
   // |repaint_cb_|.
diff --git a/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc b/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc
index 87413a9..74bfc6a 100644
--- a/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc
+++ b/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.cc
@@ -24,9 +24,9 @@
 const size_t WebAudioMediaStreamAudioSink::kWebAudioRenderBufferSize = 128;
 
 WebAudioMediaStreamAudioSink::WebAudioMediaStreamAudioSink(
-    const WebMediaStreamTrack& track,
+    MediaStreamComponent* component,
     int context_sample_rate)
-    : is_enabled_(false), track_(track), track_stopped_(false) {
+    : is_enabled_(false), component_(component), track_stopped_(false) {
   // Get the native audio output hardware sample-rate for the sink.
   // We need to check if there is a valid frame since the unittests
   // do not have one and they will inject their own |sink_params_| for testing.
@@ -37,7 +37,8 @@
                        kWebAudioRenderBufferSize);
   }
   // Connect the source provider to the track as a sink.
-  WebMediaStreamAudioSink::AddToAudioTrack(this, track_);
+  WebMediaStreamAudioSink::AddToAudioTrack(
+      this, WebMediaStreamTrack(component_.Get()));
 }
 
 WebAudioMediaStreamAudioSink::~WebAudioMediaStreamAudioSink() {
@@ -46,8 +47,10 @@
 
   // If the track is still active, it is necessary to notify the track before
   // the source provider goes away.
-  if (!track_stopped_)
-    WebMediaStreamAudioSink::RemoveFromAudioTrack(this, track_);
+  if (!track_stopped_) {
+    WebMediaStreamAudioSink::RemoveFromAudioTrack(
+        this, WebMediaStreamTrack(component_.Get()));
+  }
 }
 
 void WebAudioMediaStreamAudioSink::OnSetFormat(
diff --git a/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h b/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h
index 40633bd..ef1f148 100644
--- a/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h
+++ b/third_party/blink/renderer/modules/mediastream/webaudio_media_stream_audio_sink.h
@@ -16,9 +16,9 @@
 #include "media/base/reentrancy_checker.h"
 #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h"
 #include "third_party/blink/public/platform/web_audio_source_provider.h"
-#include "third_party/blink/public/platform/web_media_stream_track.h"
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
 
 namespace media {
 class AudioBus;
@@ -48,7 +48,7 @@
  public:
   static const size_t kWebAudioRenderBufferSize;
 
-  explicit WebAudioMediaStreamAudioSink(const WebMediaStreamTrack& track,
+  explicit WebAudioMediaStreamAudioSink(MediaStreamComponent* component,
                                         int context_sample_rate);
   ~WebAudioMediaStreamAudioSink() override;
 
@@ -95,7 +95,7 @@
   // The audio track that this source provider is connected to.
   // No lock protection needed since only accessed in constructor and
   // destructor.
-  WebMediaStreamTrack track_;
+  Persistent<MediaStreamComponent> component_;
 
   // Flag to tell if the track has been stopped or not.
   // No lock protection needed since only accessed in constructor, destructor
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.cc
index f1c2b25..5af9c17 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_crypto_config_factory_impl.cc
@@ -49,6 +49,7 @@
 
   quic::QuicAsyncStatus VerifyCertChain(
       const std::string& hostname,
+      const uint16_t port,
       const std::vector<std::string>& certs,
       const std::string& ocsp_response,
       const std::string& cert_sct,
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
index d8325ae..538dc937 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_stream_unittest.cc
@@ -90,7 +90,7 @@
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 0u, 0u,
                                      quic::StreamSendingState::FIN,
-                                     quic::NOT_RETRANSMISSION, QuicheNullOpt);
+                                     quic::NOT_RETRANSMISSION, QUICHE_NULLOPT);
       }));
 
   stream_->WriteData({}, /*fin=*/true);
@@ -129,7 +129,7 @@
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 0u, 0u,
                                      quic::StreamSendingState::FIN,
-                                     quic::NOT_RETRANSMISSION, QuicheNullOpt);
+                                     quic::NOT_RETRANSMISSION, QUICHE_NULLOPT);
       }));
 
   stream_->WriteData({}, /*fin=*/true);
@@ -157,7 +157,7 @@
       .WillOnce(InvokeWithoutArgs([this]() {
         return session_->ConsumeData(stream_->id(), 0u, 0u,
                                      quic::StreamSendingState::FIN,
-                                     quic::NOT_RETRANSMISSION, QuicheNullOpt);
+                                     quic::NOT_RETRANSMISSION, QUICHE_NULLOPT);
       }));
 
   stream_->WriteData({}, /*fin=*/true);
diff --git a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
index c79a474..fb09e9c 100644
--- a/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
+++ b/third_party/blink/renderer/modules/peerconnection/adapters/p2p_quic_transport_test.cc
@@ -365,6 +365,7 @@
 
   quic::QuicAsyncStatus VerifyCertChain(
       const std::string& hostname,
+      const uint16_t port,
       const std::vector<std::string>& certs,
       const std::string& ocsp_response,
       const std::string& cert_sct,
diff --git a/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
index 6ba143f..99c2229 100644
--- a/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
+++ b/third_party/blink/renderer/modules/peerconnection/media_stream_video_webrtc_sink.cc
@@ -269,7 +269,7 @@
   video_track_->set_enabled(track.IsEnabled());
 
   source_adapter_ = base::MakeRefCounted<WebRtcVideoSourceAdapter>(
-      factory->GetWebRtcWorkerTaskRunner(), video_source_.get(),
+      factory->GetWebRtcNetworkTaskRunner(), video_source_.get(),
       refresh_interval,
       ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
           &MediaStreamVideoWebRtcSink::RequestRefreshFrame,
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
index 3e7a15c..4e589e7 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.cc
@@ -115,10 +115,8 @@
     : network_manager_(nullptr),
       p2p_socket_dispatcher_(
           create_p2p_socket_dispatcher ? new P2PSocketDispatcher() : nullptr),
-      signaling_thread_(nullptr),
-      worker_thread_(nullptr),
       chrome_signaling_thread_("WebRTC_Signaling"),
-      chrome_worker_thread_("WebRTC_Worker") {
+      chrome_network_thread_("WebRTC_Network") {
   TryScheduleStunProbeTrial();
 }
 
@@ -166,11 +164,11 @@
 void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
   DCHECK(!pc_factory_.get());
   DCHECK(!signaling_thread_);
-  DCHECK(!worker_thread_);
+  DCHECK(!network_thread_);
   DCHECK(!network_manager_);
   DCHECK(!socket_factory_);
   DCHECK(!chrome_signaling_thread_.IsRunning());
-  DCHECK(!chrome_worker_thread_.IsRunning());
+  DCHECK(!chrome_network_thread_.IsRunning());
 
   DVLOG(1) << "PeerConnectionDependencyFactory::CreatePeerConnectionFactory()";
 
@@ -192,18 +190,15 @@
 
   EnsureWebRtcAudioDeviceImpl();
 
-  CHECK(chrome_signaling_thread_.Start());
-  CHECK(chrome_worker_thread_.Start());
+  // Init SSL, which will be needed by PeerConnection.
+  if (!rtc::InitializeSSL()) {
+    LOG(ERROR) << "Failed on InitializeSSL.";
+    NOTREACHED();
+    return;
+  }
 
-  base::WaitableEvent start_worker_event(
-      base::WaitableEvent::ResetPolicy::MANUAL,
-      base::WaitableEvent::InitialState::NOT_SIGNALED);
-  PostCrossThreadTask(
-      *chrome_worker_thread_.task_runner().get(), FROM_HERE,
-      CrossThreadBindOnce(
-          &PeerConnectionDependencyFactory::InitializeWorkerThread,
-          CrossThreadUnretained(this), CrossThreadUnretained(&worker_thread_),
-          CrossThreadUnretained(&start_worker_event)));
+  CHECK(chrome_signaling_thread_.Start());
+  CHECK(chrome_network_thread_.Start());
 
   base::WaitableEvent create_network_manager_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
@@ -218,24 +213,16 @@
   }
 #endif  // BUILDFLAG(ENABLE_MDNS)
   PostCrossThreadTask(
-      *chrome_worker_thread_.task_runner().get(), FROM_HERE,
+      *chrome_network_thread_.task_runner().get(), FROM_HERE,
       CrossThreadBindOnce(&PeerConnectionDependencyFactory::
-                              CreateIpcNetworkManagerOnWorkerThread,
+                              CreateIpcNetworkManagerOnNetworkThread,
                           CrossThreadUnretained(this),
                           CrossThreadUnretained(&create_network_manager_event),
-                          std::move(mdns_responder)));
+                          std::move(mdns_responder),
+                          CrossThreadUnretained(&network_thread_)));
 
-  start_worker_event.Wait();
   create_network_manager_event.Wait();
-
-  CHECK(worker_thread_);
-
-  // Init SSL, which will be needed by PeerConnection.
-  if (!rtc::InitializeSSL()) {
-    LOG(ERROR) << "Failed on InitializeSSL.";
-    NOTREACHED();
-    return;
-  }
+  CHECK(network_thread_);
 
   base::WaitableEvent start_signaling_event(
       base::WaitableEvent::ResetPolicy::MANUAL,
@@ -256,7 +243,7 @@
     media::GpuVideoAcceleratorFactories* gpu_factories,
     base::WaitableEvent* event) {
   DCHECK(chrome_signaling_thread_.task_runner()->BelongsToCurrentThread());
-  DCHECK(worker_thread_);
+  DCHECK(network_thread_);
   DCHECK(p2p_socket_dispatcher_.get());
 
   jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
@@ -323,9 +310,9 @@
   }
 
   webrtc::PeerConnectionFactoryDependencies pcf_deps;
-  pcf_deps.worker_thread = worker_thread_;
-  pcf_deps.network_thread = worker_thread_;
+  pcf_deps.worker_thread = signaling_thread_;
   pcf_deps.signaling_thread = signaling_thread_;
+  pcf_deps.network_thread = network_thread_;
   pcf_deps.task_queue_factory = CreateWebRtcTaskQueueFactory();
   pcf_deps.call_factory = webrtc::CreateCallFactory();
   pcf_deps.event_log_factory = std::make_unique<webrtc::RtcEventLogFactory>(
@@ -494,12 +481,12 @@
 PeerConnectionDependencyFactory::CreateVideoTrackSourceProxy(
     webrtc::VideoTrackSourceInterface* source) {
   // PeerConnectionFactory needs to be instantiated to make sure that
-  // signaling_thread_ and worker_thread_ exist.
+  // signaling_thread_ and network_thread_ exist.
   if (!PeerConnectionFactoryCreated())
     CreatePeerConnectionFactory();
 
   return webrtc::VideoTrackSourceProxy::Create(signaling_thread_,
-                                               worker_thread_, source)
+                                               network_thread_, source)
       .get();
 }
 
@@ -533,15 +520,6 @@
   return audio_device_.get();
 }
 
-void PeerConnectionDependencyFactory::InitializeWorkerThread(
-    rtc::Thread** thread,
-    base::WaitableEvent* event) {
-  jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
-  jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
-  *thread = jingle_glue::JingleThreadWrapper::current();
-  event->Signal();
-}
-
 void PeerConnectionDependencyFactory::TryScheduleStunProbeTrial() {
   base::Optional<WebString> params =
       Platform::Current()->WebRtcStunProbeTrialParameter();
@@ -551,34 +529,41 @@
   GetPcFactory();
 
   PostDelayedCrossThreadTask(
-      *chrome_worker_thread_.task_runner().get(), FROM_HERE,
+      *chrome_network_thread_.task_runner().get(), FROM_HERE,
       CrossThreadBindOnce(
-          &PeerConnectionDependencyFactory::StartStunProbeTrialOnWorkerThread,
+          &PeerConnectionDependencyFactory::StartStunProbeTrialOnNetworkThread,
           CrossThreadUnretained(this), String(*params)),
       base::TimeDelta::FromMilliseconds(blink::kExperimentStartDelayMs));
 }
 
-void PeerConnectionDependencyFactory::StartStunProbeTrialOnWorkerThread(
+void PeerConnectionDependencyFactory::StartStunProbeTrialOnNetworkThread(
     const String& params) {
   DCHECK(network_manager_);
-  DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
+  DCHECK(chrome_network_thread_.task_runner()->BelongsToCurrentThread());
   // TODO(crbug.com/787254): Remove the UTF8 conversion when StunProberTrial
   // operates over WTF::String.
   stun_trial_.reset(new StunProberTrial(network_manager_.get(), params.Utf8(),
                                         socket_factory_.get()));
 }
 
-void PeerConnectionDependencyFactory::CreateIpcNetworkManagerOnWorkerThread(
+void PeerConnectionDependencyFactory::CreateIpcNetworkManagerOnNetworkThread(
     base::WaitableEvent* event,
-    std::unique_ptr<MdnsResponderAdapter> mdns_responder) {
-  DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
+    std::unique_ptr<MdnsResponderAdapter> mdns_responder,
+    rtc::Thread** thread) {
+  DCHECK(chrome_network_thread_.task_runner()->BelongsToCurrentThread());
+
+  jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
+  jingle_glue::JingleThreadWrapper::current()->set_send_allowed(true);
+  *thread = jingle_glue::JingleThreadWrapper::current();
+
   network_manager_ = std::make_unique<blink::IpcNetworkManager>(
       p2p_socket_dispatcher_.get(), std::move(mdns_responder));
+
   event->Signal();
 }
 
 void PeerConnectionDependencyFactory::DeleteIpcNetworkManager() {
-  DCHECK(chrome_worker_thread_.task_runner()->BelongsToCurrentThread());
+  DCHECK(chrome_network_thread_.task_runner()->BelongsToCurrentThread());
   network_manager_.reset();
 }
 
@@ -588,16 +573,17 @@
   if (network_manager_) {
     // The network manager needs to free its resources on the thread they were
     // created, which is the worked thread.
-    if (chrome_worker_thread_.IsRunning()) {
+    if (chrome_network_thread_.IsRunning()) {
       PostCrossThreadTask(
-          *chrome_worker_thread_.task_runner().get(), FROM_HERE,
+          *chrome_network_thread_.task_runner().get(), FROM_HERE,
           CrossThreadBindOnce(
               &PeerConnectionDependencyFactory::DeleteIpcNetworkManager,
               CrossThreadUnretained(this)));
       // Stopping the thread will wait until all tasks have been
       // processed before returning. We wait for the above task to finish before
       // letting the the function continue to avoid any potential race issues.
-      chrome_worker_thread_.Stop();
+      chrome_network_thread_.Stop();
+      DCHECK(!network_manager_);
     } else {
       NOTREACHED() << "Worker thread not running.";
     }
@@ -610,10 +596,11 @@
 }
 
 scoped_refptr<base::SingleThreadTaskRunner>
-PeerConnectionDependencyFactory::GetWebRtcWorkerTaskRunner() {
+PeerConnectionDependencyFactory::GetWebRtcNetworkTaskRunner() {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  return chrome_worker_thread_.IsRunning() ? chrome_worker_thread_.task_runner()
-                                           : nullptr;
+  return chrome_network_thread_.IsRunning()
+             ? chrome_network_thread_.task_runner()
+             : nullptr;
 }
 
 scoped_refptr<base::SingleThreadTaskRunner>
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
index 9984fa11..3029b4a 100644
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_dependency_factory.h
@@ -115,7 +115,7 @@
 
   // Returns the SingleThreadTaskRunner suitable for running WebRTC networking.
   // An rtc::Thread will have already been created.
-  scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcWorkerTaskRunner();
+  scoped_refptr<base::SingleThreadTaskRunner> GetWebRtcNetworkTaskRunner();
 
   virtual scoped_refptr<base::SingleThreadTaskRunner>
   GetWebRtcSignalingTaskRunner();
@@ -139,7 +139,7 @@
   // Functions related to Stun probing trial to determine how fast we could send
   // Stun request without being dropped by NAT.
   void TryScheduleStunProbeTrial();
-  void StartStunProbeTrialOnWorkerThread(const String& params);
+  void StartStunProbeTrialOnNetworkThread(const String& params);
 
   // Creates |pc_factory_|, which in turn is used for
   // creating PeerConnection objects.
@@ -149,11 +149,10 @@
       media::GpuVideoAcceleratorFactories* gpu_factories,
       base::WaitableEvent* event);
 
-  void InitializeWorkerThread(rtc::Thread** thread, base::WaitableEvent* event);
-
-  void CreateIpcNetworkManagerOnWorkerThread(
+  void CreateIpcNetworkManagerOnNetworkThread(
       base::WaitableEvent* event,
-      std::unique_ptr<MdnsResponderAdapter> mdns_responder);
+      std::unique_ptr<MdnsResponderAdapter> mdns_responder,
+      rtc::Thread** thread);
   void DeleteIpcNetworkManager();
   void CleanupPeerConnectionFactory();
 
@@ -173,10 +172,10 @@
 
   // PeerConnection threads. signaling_thread_ is created from the
   // "current" chrome thread.
-  rtc::Thread* signaling_thread_;
-  rtc::Thread* worker_thread_;
+  rtc::Thread* signaling_thread_ = nullptr;
+  rtc::Thread* network_thread_ = nullptr;
   base::Thread chrome_signaling_thread_;
-  base::Thread chrome_worker_thread_;
+  base::Thread chrome_network_thread_;
 
   THREAD_CHECKER(thread_checker_);
 
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc b/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc
index 60a6ff4..77c2a8c 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_certificate_generator.cc
@@ -94,7 +94,7 @@
 
   scoped_refptr<RTCCertificateGeneratorRequest> request =
       base::MakeRefCounted<RTCCertificateGeneratorRequest>(
-          task_runner, pc_dependency_factory->GetWebRtcWorkerTaskRunner());
+          task_runner, pc_dependency_factory->GetWebRtcNetworkTaskRunner());
   request->GenerateCertificateAsync(key_params, expires_ms,
                                     std::move(completion_callback));
 }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc
index c1caf9ff..2764b87 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc
@@ -53,7 +53,7 @@
       frame->GetTaskRunner(TaskType::kNetworking);
   scoped_refptr<base::SingleThreadTaskRunner> host_thread =
       PeerConnectionDependencyFactory::GetInstance()
-          ->GetWebRtcWorkerTaskRunner();
+          ->GetWebRtcNetworkTaskRunner();
 
   return DtlsTransportProxy::Create(*frame, proxy_thread, host_thread,
                                     native_transport, delegate);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
index b1881ca..4e8dd132 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_ice_transport.cc
@@ -116,7 +116,7 @@
   PeerConnectionDependencyFactory::GetInstance()->EnsureInitialized();
   scoped_refptr<base::SingleThreadTaskRunner> host_thread =
       PeerConnectionDependencyFactory::GetInstance()
-          ->GetWebRtcWorkerTaskRunner();
+          ->GetWebRtcNetworkTaskRunner();
   return MakeGarbageCollected<RTCIceTransport>(
       context, std::move(proxy_thread), std::move(host_thread),
       std::make_unique<DefaultIceTransportAdapterCrossThreadFactory>());
@@ -132,7 +132,7 @@
   PeerConnectionDependencyFactory::GetInstance()->EnsureInitialized();
   scoped_refptr<base::SingleThreadTaskRunner> host_thread =
       PeerConnectionDependencyFactory::GetInstance()
-          ->GetWebRtcWorkerTaskRunner();
+          ->GetWebRtcNetworkTaskRunner();
   return MakeGarbageCollected<RTCIceTransport>(
       context, std::move(proxy_thread), std::move(host_thread),
       std::make_unique<DtlsIceTransportAdapterCrossThreadFactory>(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc
index 02c0965c..ac76dd14 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_quic_transport.cc
@@ -92,7 +92,7 @@
   return Create(context, transport, certificates, exception_state,
                 std::make_unique<DefaultP2PQuicTransportFactory>(
                     PeerConnectionDependencyFactory::GetInstance()
-                        ->GetWebRtcWorkerTaskRunner()));
+                        ->GetWebRtcNetworkTaskRunner()));
 }
 
 RTCQuicTransport* RTCQuicTransport::Create(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_sctp_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_sctp_transport.cc
index da661a6..2fedeb93 100644
--- a/third_party/blink/renderer/modules/peerconnection/rtc_sctp_transport.cc
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_sctp_transport.cc
@@ -65,7 +65,7 @@
                        native_transport,
                        context->GetTaskRunner(TaskType::kNetworking),
                        PeerConnectionDependencyFactory::GetInstance()
-                           ->GetWebRtcWorkerTaskRunner()) {}
+                           ->GetWebRtcNetworkTaskRunner()) {}
 
 RTCSctpTransport::RTCSctpTransport(
     ExecutionContext* context,
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
index 862966d..27cf460 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
@@ -74,7 +74,7 @@
   // If document is not allowed to use the policy-controlled feature named
   // "picture-in-picture", return kDisabledByFeaturePolicy status.
   if (RuntimeEnabledFeatures::PictureInPictureAPIEnabled() &&
-      !GetSupplementable()->GetExecutionContext()->IsFeatureEnabled(
+      !GetSupplementable()->IsFeatureEnabled(
           blink::mojom::blink::FeaturePolicyFeature::kPictureInPicture,
           report_failure ? ReportOptions::kReportOnFailure
                          : ReportOptions::kDoNotReport)) {
diff --git a/third_party/blink/renderer/modules/serial/serial.cc b/third_party/blink/renderer/modules/serial/serial.cc
index e8c393e..e7ba241 100644
--- a/third_party/blink/renderer/modules/serial/serial.cc
+++ b/third_party/blink/renderer/modules/serial/serial.cc
@@ -104,7 +104,7 @@
     return ScriptPromise();
   }
 
-  if (!GetExecutionContext()->IsFeatureEnabled(
+  if (!frame->GetDocument()->IsFeatureEnabled(
           mojom::blink::FeaturePolicyFeature::kSerial,
           ReportOptions::kReportOnFailure)) {
     exception_state.ThrowSecurityError(kFeaturePolicyBlocked);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
index 6e82556..a316d017 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_queue.cc
@@ -238,11 +238,19 @@
     return;
   }
 
+  // Check that the write size can be cast to a size_t. This should always be
+  // the case since data_byte_length comes from an ArrayBuffer size.
+  if (write_byte_size > uint64_t(std::numeric_limits<size_t>::max())) {
+    exception_state.ThrowRangeError(
+        "writeSize larger than size_t (please report a bug if you see this)");
+    return;
+  }
+
   const uint8_t* data_base_ptr_bytes =
       static_cast<const uint8_t*>(data_base_ptr);
   const uint8_t* data_ptr = data_base_ptr_bytes + data_byte_offset;
-  GetProcs().bufferSetSubData(buffer->GetHandle(), buffer_offset,
-                              write_byte_size, data_ptr);
+  GetProcs().queueWriteBuffer(GetHandle(), buffer->GetHandle(), buffer_offset,
+                              data_ptr, static_cast<size_t>(write_byte_size));
 }
 
 // TODO(shaobo.yan@intel.com): Implement this function
diff --git a/third_party/blink/renderer/platform/disk_data_allocator.cc b/third_party/blink/renderer/platform/disk_data_allocator.cc
index 1a09e32d3..faffd17 100644
--- a/third_party/blink/renderer/platform/disk_data_allocator.cc
+++ b/third_party/blink/renderer/platform/disk_data_allocator.cc
@@ -182,8 +182,8 @@
 void DiskDataAllocator::DoRead(int64_t offset, char* data, int size) {
   // This happens on the main thread, which is typically not allowed. This is
   // fine as this is expected to happen rarely, and only be slow with memory
-  // pressure, in which case writing to disk is better than swapping out random
-  // parts of the memory. See the linked bug for details.
+  // pressure, in which case writing to/reading from disk is better than
+  // swapping out random parts of the memory. See crbug.com/1029320 for details.
   base::ScopedAllowBlocking allow_blocking;
   int rv = file_.Read(offset, data, size);
   // Can only crash, since we cannot continue without the data.
diff --git a/third_party/blink/renderer/platform/exported/web_string.cc b/third_party/blink/renderer/platform/exported/web_string.cc
index fbe4828..6d9cc6f 100644
--- a/third_party/blink/renderer/platform/exported/web_string.cc
+++ b/third_party/blink/renderer/platform/exported/web_string.cc
@@ -90,12 +90,6 @@
   return WebString(s.data(), s.length());
 }
 
-WebString WebString::FromUTF16(const base::NullableString16& s) {
-  if (s.is_null())
-    return WebString();
-  return WebString(s.string().data(), s.string().length());
-}
-
 WebString WebString::FromUTF16(const base::Optional<base::string16>& s) {
   if (!s.has_value())
     return WebString();
diff --git a/third_party/blink/renderer/platform/fonts/README.md b/third_party/blink/renderer/platform/fonts/README.md
index 5dba5c4..ef7f2b3a 100644
--- a/third_party/blink/renderer/platform/fonts/README.md
+++ b/third_party/blink/renderer/platform/fonts/README.md
@@ -381,4 +381,5 @@
 In summary, `FontFallbackIterator` feeds fonts from the CSS `font-family` list
 as well as system fallback fonts to `HarfBuzzShaper` for use in the shaping
 iterations until ideally all gaps are filled and the full text run can be drawn
-with the correct glyphs.
+with the correct glyphs.  When there are gaps, and the .notdef tofu character
+must be rendered, the primary font is used for this.
diff --git a/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc b/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
index eb07672..e1778f3 100644
--- a/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_iterator.cc
@@ -33,7 +33,7 @@
 }
 
 bool FontFallbackIterator::RangeSetContributesForHint(
-    const Vector<UChar32> hint_list,
+    const Vector<UChar32>& hint_list,
     const FontDataForRangeSet* segmented_face) {
   for (auto* it = hint_list.begin(); it != hint_list.end(); ++it) {
     if (segmented_face->Contains(*it)) {
@@ -56,6 +56,9 @@
 scoped_refptr<FontDataForRangeSet> FontFallbackIterator::UniqueOrNext(
     scoped_refptr<FontDataForRangeSet> candidate,
     const Vector<UChar32>& hint_list) {
+  if (!candidate->HasFontData())
+    return Next(hint_list);
+
   SkTypeface* candidate_typeface =
       candidate->FontData()->PlatformData().Typeface();
   if (!candidate_typeface)
@@ -70,6 +73,11 @@
   // depends on the subsetting.
   if (candidate->IsEntireRange())
     unique_font_data_for_range_sets_returned_.insert(candidate_id);
+
+  // Save first candidate to be returned if all other fonts fail, and we need
+  // it to render the .notdef glyph.
+  if (!first_candidate_)
+    first_candidate_ = candidate;
   return candidate;
 }
 
@@ -121,14 +129,19 @@
     // resort font that has glyphs for everything, for example the Unicode
     // LastResort font, not just Times or Arial.
     FontCache* font_cache = FontCache::GetFontCache();
-    fallback_stage_ = kOutOfLuck;
+    fallback_stage_ = kFirstCandidateForNotdefGlyph;
     scoped_refptr<SimpleFontData> last_resort =
         font_cache->GetLastResortFallbackFont(font_description_).get();
-    if (!last_resort)
+    return UniqueOrNext(
+        base::AdoptRef(new FontDataForRangeSetFromCache(last_resort)),
+        hint_list);
+  }
+
+  if (fallback_stage_ == kFirstCandidateForNotdefGlyph) {
+    fallback_stage_ = kOutOfLuck;
+    if (!first_candidate_)
       FontCache::CrashWithFontInfo(&font_description_);
-    // Don't skip the LastResort font in uniqueOrNext() since HarfBuzzShaper
-    // needs to use this one to place missing glyph boxes.
-    return base::AdoptRef(new FontDataForRangeSetFromCache(last_resort));
+    return first_candidate_;
   }
 
   DCHECK(fallback_stage_ == kFontGroupFonts ||
diff --git a/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h b/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
index b17424f89..3eaa249 100644
--- a/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
+++ b/third_party/blink/renderer/platform/fonts/font_fallback_iterator.h
@@ -46,7 +46,7 @@
   scoped_refptr<FontDataForRangeSet> Next(const Vector<UChar32>& hint_list);
 
  private:
-  bool RangeSetContributesForHint(const Vector<UChar32> hint_list,
+  bool RangeSetContributesForHint(const Vector<UChar32>& hint_list,
                                   const FontDataForRangeSet*);
   bool AlreadyLoadingRangeForHintChar(UChar32 hint_char);
   void WillUseRange(const AtomicString& family, const FontDataForRangeSet&);
@@ -70,6 +70,7 @@
     kSegmentedFace,
     kPreferencesFonts,
     kSystemFonts,
+    kFirstCandidateForNotdefGlyph,
     kOutOfLuck
   };
 
@@ -77,10 +78,13 @@
   HashSet<UChar32> previously_asked_for_hint_;
   // FontFallbackIterator is meant for single use by HarfBuzzShaper,
   // traversing through the fonts for shaping only once. We must not return
-  // duplicate FontDataForRangeSet objects from the next() iteration functions
+  // duplicate FontDataForRangeSet objects from the Next() iteration function
   // as returning a duplicate value causes a shaping run that won't return any
-  // results.
+  // results. The exception is that if all fonts fail, we return the first
+  // candidate to be used for rendering the .notdef glyph, and set HasNext() to
+  // false.
   HashSet<uint32_t> unique_font_data_for_range_sets_returned_;
+  scoped_refptr<FontDataForRangeSet> first_candidate_ = nullptr;
   Vector<scoped_refptr<FontDataForRangeSet>> tracked_loading_range_sets_;
   FontFallbackPriority font_fallback_priority_;
 };
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
index c919c686..24f0d3c4 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -319,7 +319,7 @@
                                   const SimpleFontData* current_font,
                                   UScriptCode current_run_script,
                                   CanvasRotationInVertical canvas_rotation,
-                                  bool is_last_resort,
+                                  bool is_last_font,
                                   const BufferSlice& slice,
                                   ShapeResult* shape_result) const {
   hb_direction_t direction = range_data->HarfBuzzDirection(canvas_rotation);
@@ -346,7 +346,7 @@
                   current_slice->num_glyphs - num_glyphs_inserted};
     current_slice = &next_slice;
   }
-  if (is_last_resort)
+  if (is_last_font)
     range_data->font->ReportNotDefGlyph();
 }
 
@@ -357,7 +357,7 @@
     const SimpleFontData* current_font,
     UScriptCode current_run_script,
     CanvasRotationInVertical canvas_rotation,
-    bool is_last_resort,
+    bool is_last_font,
     ShapeResult* shape_result) const {
   enum ClusterResult { kShaped, kNotDef, kUnknown };
   ClusterResult current_cluster_result = kUnknown;
@@ -397,7 +397,7 @@
         // If the most recent cluster is shaped and there is a state change,
         // it means the previous ones were unshaped, so we queue them, unless
         // we're using the last resort font.
-        if (current_cluster_result == kShaped && !is_last_resort) {
+        if (current_cluster_result == kShaped && !is_last_font) {
           QueueCharacters(range_data, current_font, font_cycle_queued, slice);
         } else {
           // If the most recent cluster is unshaped and there is a state
@@ -405,7 +405,7 @@
           // the glyphs. We also commit when we've reached the last resort
           // font.
           CommitGlyphs(range_data, current_font, current_run_script,
-                       canvas_rotation, is_last_resort, slice, shape_result);
+                       canvas_rotation, is_last_font, slice, shape_result);
         }
         last_change_glyph_index = previous_cluster_start_glyph_index;
       }
@@ -427,7 +427,7 @@
 
   // End of the run.
   if (current_cluster_result != previous_cluster_result &&
-      previous_cluster_result != kUnknown && !is_last_resort) {
+      previous_cluster_result != kUnknown && !is_last_font) {
     // The last cluster in the run still had shaping status different from
     // the cluster(s) before it, we need to submit one shaped and one
     // unshaped segment.
@@ -440,13 +440,13 @@
           ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
                        previous_cluster_start_glyph_index, num_glyphs);
       CommitGlyphs(range_data, current_font, current_run_script,
-                   canvas_rotation, is_last_resort, slice, shape_result);
+                   canvas_rotation, is_last_font, slice, shape_result);
     } else {
       BufferSlice slice = ComputeSlice(
           range_data, current_queue_item, glyph_info, num_glyphs,
           last_change_glyph_index, previous_cluster_start_glyph_index);
       CommitGlyphs(range_data, current_font, current_run_script,
-                   canvas_rotation, is_last_resort, slice, shape_result);
+                   canvas_rotation, is_last_font, slice, shape_result);
       slice =
           ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
                        previous_cluster_start_glyph_index, num_glyphs);
@@ -458,11 +458,11 @@
     BufferSlice slice =
         ComputeSlice(range_data, current_queue_item, glyph_info, num_glyphs,
                      last_change_glyph_index, num_glyphs);
-    if (current_cluster_result == kNotDef && !is_last_resort) {
+    if (current_cluster_result == kNotDef && !is_last_font) {
       QueueCharacters(range_data, current_font, font_cycle_queued, slice);
     } else {
       CommitGlyphs(range_data, current_font, current_run_script,
-                   canvas_rotation, is_last_resort, slice, shape_result);
+                   canvas_rotation, is_last_font, slice, shape_result);
     }
   }
 }
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
index 817cd33..d7802f0c 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h
@@ -105,7 +105,7 @@
                            const SimpleFontData*,
                            UScriptCode,
                            CanvasRotationInVertical,
-                           bool is_last_resort,
+                           bool is_last_font,
                            ShapeResult*) const;
 
   bool CollectFallbackHintChars(const Deque<ReshapeQueueItem>&,
@@ -116,7 +116,7 @@
                     const SimpleFontData* current_font,
                     UScriptCode current_run_script,
                     CanvasRotationInVertical,
-                    bool is_last_resort,
+                    bool is_last_font,
                     const BufferSlice&,
                     ShapeResult*) const;
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 8f8fca4..b03e338 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -487,6 +487,11 @@
       name: "CSSMaskSourceType",
       status: "experimental",
     },
+    // Enables dependency support for the MatchedPropertiesCache.
+    {
+      name: "CSSMatchedPropertiesCacheDependencies",
+      depends_on: ["CSSCascade"]
+    },
     {
       name: "CSSMathStyle",
       status: "experimental",
@@ -1156,11 +1161,6 @@
       // When enabled, iframes are not capturing mouse events by default.
       name: "MouseSubframeNoImplicitCapture",
     },
-    // Enables dependency support for the MatchedPropertiesCache.
-    {
-      name: "MPCDependencies",
-      depends_on: ["CSSCascade"]
-    },
     {
       // Named pages for pagination (the "page" CSS property).
       name: "NamedPages",
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 ea01022..a8b3848 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
@@ -390,6 +390,13 @@
                                {blink::features::kStopNonTimersInBackground}) {}
 };
 
+class FrameSchedulerImplStopInBackgroundDisabledTest
+    : public FrameSchedulerImplTest {
+ public:
+  FrameSchedulerImplStopInBackgroundDisabledTest()
+      : FrameSchedulerImplTest({}, {blink::features::kStopInBackground}) {}
+};
+
 namespace {
 
 class MockLifecycleObserver final : public FrameScheduler::Observer {
@@ -633,6 +640,62 @@
   EXPECT_TRUE(UnpausableTaskQueue()->IsQueueEnabled());
 }
 
+namespace {
+
+// A task that re-posts itself with a delay in order until it has run
+// |num_remaining_tasks| times.
+void RePostTask(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+                base::TimeDelta delay,
+                int* num_remaining_tasks) {
+  --(*num_remaining_tasks);
+  if (*num_remaining_tasks > 0) {
+    task_runner->PostDelayedTask(
+        FROM_HERE,
+        base::BindOnce(&RePostTask, task_runner, delay,
+                       base::Unretained(num_remaining_tasks)),
+        delay);
+  }
+}
+
+}  // namespace
+
+// Verify that tasks in a throttled task queues run at the expected time, when
+// intensive wake up throttling is disabled. Disable the kStopInBackground
+// feature because it hides the effect of intensive wake up throttling.
+TEST_F(FrameSchedulerImplStopInBackgroundDisabledTest, ThrottledTaskExecution) {
+  // This test posts enough tasks to run past the default intensive wake up
+  // throttling grace period. This allows verifying that intensive wake up
+  // throttling is disabled by default.
+  constexpr int kNumTasks =
+      base::TimeDelta::FromMinutes(10) / base::TimeDelta::FromSeconds(1);
+  // Tasks are posted with a delay shorter than the default throttled wake up
+  // period, to allow verifying that the default throttled wake up period is
+  // correctly enforced.
+  constexpr base::TimeDelta kShortDelay = base::TimeDelta::FromMilliseconds(10);
+  // This TaskRunner is throttled.
+  const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+      frame_scheduler_->GetTaskRunner(TaskType::kJavascriptTimer);
+
+  // Hide the page. This enables wake up throttling.
+  EXPECT_TRUE(page_scheduler_->IsPageVisible());
+  page_scheduler_->SetPageVisible(false);
+
+  // Post an initial task.
+  int num_remaining_tasks = kNumTasks;
+  task_runner->PostDelayedTask(
+      FROM_HERE,
+      base::BindOnce(&RePostTask, task_runner, kShortDelay,
+                     base::Unretained(&num_remaining_tasks)),
+      kShortDelay);
+
+  // A task should run every second.
+  while (num_remaining_tasks > 0) {
+    int previous_num_remaining_tasks = num_remaining_tasks;
+    task_environment_.FastForwardBy(base::TimeDelta::FromSeconds(1));
+    EXPECT_EQ(previous_num_remaining_tasks - 1, num_remaining_tasks);
+  }
+}
+
 TEST_F(FrameSchedulerImplTest, FreezeForegroundOnlyTasks) {
   int counter = 0;
   ForegroundOnlyTaskQueue()->task_runner()->PostTask(
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
index 612af8b..f2ee651b 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/page_scheduler_impl.cc
@@ -645,7 +645,8 @@
           FROM_HERE, do_throttle_cpu_time_callback_.GetCallback(),
           kThrottlingDelayAfterBackgrounding);
     }
-    if (wake_up_budget_pool_) {
+    if (wake_up_budget_pool_ &&
+        base::FeatureList::IsEnabled(kIntensiveWakeUpThrottling)) {
       main_thread_scheduler_->ControlTaskRunner()->PostDelayedTask(
           FROM_HERE, do_intensively_throttle_wake_ups_callback_.GetCallback(),
           base::TimeDelta::FromSeconds(
@@ -667,6 +668,8 @@
 }
 
 void PageSchedulerImpl::DoIntensivelyThrottleWakeUps() {
+  DCHECK(base::FeatureList::IsEnabled(kIntensiveWakeUpThrottling));
+
   do_intensively_throttle_wake_ups_callback_.Cancel();
   are_wake_ups_intensively_throttled_ = true;
 
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
index 66553f7..a59c6e50f 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
@@ -127,6 +127,12 @@
   client_->ScheduleAnimationForWebTests();
 }
 
+void WidgetBase::GetWidgetInputHandler(
+    mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+    mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) {
+  client_->GetWidgetInputHandler(std::move(request), std::move(host));
+}
+
 void WidgetBase::ApplyViewportChanges(
     const cc::ApplyViewportChangesArgs& args) {
   client_->ApplyViewportChanges(args);
diff --git a/third_party/blink/renderer/platform/widget/widget_base.h b/third_party/blink/renderer/platform/widget/widget_base.h
index e0cda5f..3cbedc4 100644
--- a/third_party/blink/renderer/platform/widget/widget_base.h
+++ b/third_party/blink/renderer/platform/widget/widget_base.h
@@ -75,6 +75,9 @@
 
   // mojom::blink::Widget overrides:
   void ForceRedraw(mojom::blink::Widget::ForceRedrawCallback callback) override;
+  void GetWidgetInputHandler(
+      mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+      mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) override;
 
   // LayerTreeDelegate overrides:
   // Applies viewport related properties during a commit from the compositor
diff --git a/third_party/blink/renderer/platform/widget/widget_base_client.h b/third_party/blink/renderer/platform/widget/widget_base_client.h
index 1c1aacd..00f0753 100644
--- a/third_party/blink/renderer/platform/widget/widget_base_client.h
+++ b/third_party/blink/renderer/platform/widget/widget_base_client.h
@@ -8,6 +8,7 @@
 #include "base/time/time.h"
 #include "cc/paint/element_id.h"
 #include "third_party/blink/public/common/metrics/document_update_reason.h"
+#include "third_party/blink/public/mojom/page/widget.mojom-blink.h"
 #include "third_party/blink/public/platform/input/input_handler_proxy.h"
 #include "third_party/blink/public/platform/web_text_input_type.h"
 #include "third_party/blink/public/web/web_lifecycle_update.h"
@@ -141,6 +142,10 @@
     return WebTextInputType::kWebTextInputTypeNone;
   }
 
+  virtual void GetWidgetInputHandler(
+      mojo::PendingReceiver<mojom::blink::WidgetInputHandler> request,
+      mojo::PendingRemote<mojom::blink::WidgetInputHandlerHost> host) = 0;
+
   // Test-specific methods below this point.
   virtual void ScheduleAnimationForWebTests() {}
 };
diff --git a/third_party/blink/renderer/platform/wtf/deque.h b/third_party/blink/renderer/platform/wtf/deque.h
index 3a3c59e0..3cad25b 100644
--- a/third_party/blink/renderer/platform/wtf/deque.h
+++ b/third_party/blink/renderer/platform/wtf/deque.h
@@ -613,7 +613,7 @@
 
 template <typename T, wtf_size_t inlineCapacity, typename Allocator>
 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase()
-    : deque_(0) {}
+    : deque_(nullptr) {}
 
 template <typename T, wtf_size_t inlineCapacity, typename Allocator>
 inline DequeIteratorBase<T, inlineCapacity, Allocator>::DequeIteratorBase(
diff --git a/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater.py b/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater.py
index 5cc131cb..752346c8 100644
--- a/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater.py
+++ b/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater.py
@@ -41,19 +41,18 @@
 
     def __init__(self, host, args=None):
         super(AndroidWPTExpectationsUpdater, self).__init__(host, args)
-        expectations_dict = {}
-        for product in self.options.android_product:
-            path = PRODUCTS_TO_EXPECTATION_FILE_PATHS[product]
-            expectations_dict.update(
-                {path: self.host.filesystem.read_text_file(path)})
-
-        self._test_expectations = TestExpectations(
-            self.port, expectations_dict=expectations_dict)
         self._never_fix_expectations = TestExpectations(
             self.port, {
                 ANDROID_DISABLED_TESTS:
                 host.filesystem.read_text_file(ANDROID_DISABLED_TESTS)})
 
+    def expectations_files(self):
+        # We need to put all the Android expectation files in
+        # the _test_expectations member variable so that the
+        # files get cleaned in cleanup_test_expectations_files()
+        return (PRODUCTS_TO_EXPECTATION_FILE_PATHS.values() +
+                [ANDROID_DISABLED_TESTS])
+
     def _get_web_test_results(self, build):
         """Gets web tests results for Android builders. We need to
         bypass the step which gets the step names for the builder
@@ -128,9 +127,9 @@
         raise ScriptError('Marker comment does not exist in %s' % path)
 
     def _get_untriaged_test_expectations(
-            self, test_expectations, marker_comment):
+            self, test_expectations, paths, marker_comment):
         untriaged_exps = defaultdict(dict)
-        for path in test_expectations.expectations_dict:
+        for path in paths:
             marker_lineno = self._get_marker_line_number(
                 test_expectations, path, marker_comment)
             exp_lines = test_expectations.get_updated_lines(path)
@@ -170,11 +169,13 @@
         browser_to_exp_path = {
             browser: PRODUCTS_TO_EXPECTATION_FILE_PATHS[product]
             for product, browser in PRODUCTS_TO_BROWSER_TAGS.items()}
+        product_exp_paths = {PRODUCTS_TO_EXPECTATION_FILE_PATHS[prod]
+                             for prod in self.options.android_product}
         untriaged_exps = self._get_untriaged_test_expectations(
-            self._test_expectations, self.MARKER_COMMENT)
+            self._test_expectations, product_exp_paths, self.MARKER_COMMENT)
         neverfix_tests = self._get_untriaged_test_expectations(
-            self._never_fix_expectations, self.NEVER_FIX_MARKER_COMMENT)[
-                ANDROID_DISABLED_TESTS]
+            self._never_fix_expectations, [ANDROID_DISABLED_TESTS],
+            self.NEVER_FIX_MARKER_COMMENT)[ANDROID_DISABLED_TESTS]
 
         for path, test_exps in untriaged_exps.items():
             self._test_expectations.remove_expectations(
diff --git a/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py b/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py
index c7058a1..b867556 100644
--- a/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/android_wpt_expectations_updater_unittest.py
@@ -13,10 +13,15 @@
 from blinkpy.web_tests.builder_list import BuilderList
 from blinkpy.web_tests.port.factory_mock import MockPortFactory
 from blinkpy.web_tests.port.android import (
-    PRODUCTS_TO_EXPECTATION_FILE_PATHS, ANDROID_DISABLED_TESTS)
+    PRODUCTS_TO_EXPECTATION_FILE_PATHS, ANDROID_DISABLED_TESTS,
+    ANDROID_WEBLAYER, ANDROID_WEBVIEW, CHROME_ANDROID,
+    PRODUCTS_TO_STEPNAMES)
 from blinkpy.w3c.android_wpt_expectations_updater import (
     AndroidWPTExpectationsUpdater)
 
+WEBLAYER_WPT_STEP = PRODUCTS_TO_STEPNAMES[ANDROID_WEBLAYER]
+WEBVIEW_WPT_STEP = PRODUCTS_TO_STEPNAMES[ANDROID_WEBVIEW]
+CHROME_ANDROID_WPT_STEP = PRODUCTS_TO_STEPNAMES[CHROME_ANDROID]
 
 class AndroidWPTExpectationsUpdaterTest(LoggingTestCase):
 
@@ -48,6 +53,7 @@
         self.set_logging_level(logging.DEBUG)
         host = MockHost()
         host.port_factory = MockPortFactory(host)
+        host.executive._output = ''
 
         # Set up a fake list of try builders.
         host.builders = BuilderList({
@@ -105,10 +111,10 @@
                         'is_unexpected': True,
                     },
                 },
-            }, step_name='system_webview_wpt (with patch)'),
-            step_name='system_webview_wpt (with patch)')
+            }, step_name=WEBVIEW_WPT_STEP + ' (with patch)'),
+            step_name=WEBVIEW_WPT_STEP + ' (with patch)')
         updater = AndroidWPTExpectationsUpdater(
-            host, ['-vvv',  '--android-product', 'android_webview'])
+            host, ['-vvv',  '--android-product', ANDROID_WEBVIEW])
         updater.git_cl = MockGitCL(host, {
             Build('MOCK Android Pie', 123):
             TryJobStatus('COMPLETED', 'FAILURE')})
@@ -116,7 +122,7 @@
         updater.run()
         # Get new expectations
         content = host.filesystem.read_text_file(
-            PRODUCTS_TO_EXPECTATION_FILE_PATHS['android_webview'])
+            PRODUCTS_TO_EXPECTATION_FILE_PATHS[ANDROID_WEBVIEW])
         self.assertEqual(
             content,
             ('# results: [ Failure Crash Timeout]\n'
@@ -149,12 +155,21 @@
         # expectations
         self.assertEqual(
             host.filesystem.read_text_file(
-                PRODUCTS_TO_EXPECTATION_FILE_PATHS['chrome_android']),
+                PRODUCTS_TO_EXPECTATION_FILE_PATHS[CHROME_ANDROID]),
             self._raw_android_expectations)
         # Check logs
         logs = ''.join(self.logMessages()).lower()
-        self.assertNotIn('weblayer', logs)
-        self.assertNotIn('chrome', logs)
+        self.assertNotIn(WEBLAYER_WPT_STEP, logs)
+        self.assertNotIn(CHROME_ANDROID_WPT_STEP, logs)
+        # Check that weblayer and chrome expectation files were not changed
+        self.assertEqual(
+            self._raw_android_expectations,
+            host.filesystem.read_text_file(
+                PRODUCTS_TO_EXPECTATION_FILE_PATHS[CHROME_ANDROID]))
+        self.assertEqual(
+            self._raw_android_expectations,
+            host.filesystem.read_text_file(
+                PRODUCTS_TO_EXPECTATION_FILE_PATHS[ANDROID_WEBLAYER]))
 
     def testUpdateTestExpectationsForWeblayer(self):
         host = self._setup_host()
@@ -183,10 +198,10 @@
                         'is_unexpected': True,
                     },
                 },
-            }, step_name='weblayer_shell_wpt (with patch)'),
-            step_name='weblayer_shell_wpt (with patch)')
+            }, step_name=WEBLAYER_WPT_STEP + ' (with patch)'),
+            step_name=WEBLAYER_WPT_STEP + ' (with patch)')
         updater = AndroidWPTExpectationsUpdater(
-            host, ['-vvv', '--android-product', 'android_weblayer'])
+            host, ['-vvv', '--android-product', ANDROID_WEBLAYER])
         updater.git_cl = MockGitCL(host, {
             Build('MOCK Android Weblayer - Pie', 123):
             TryJobStatus('COMPLETED', 'FAILURE')})
@@ -194,7 +209,7 @@
         updater.run()
         # Get new expectations
         content = host.filesystem.read_text_file(
-            PRODUCTS_TO_EXPECTATION_FILE_PATHS['android_weblayer'])
+            PRODUCTS_TO_EXPECTATION_FILE_PATHS[ANDROID_WEBLAYER])
         self.assertEqual(
             content,
             ('# results: [ Failure Crash Timeout]\n'
@@ -215,10 +230,24 @@
              'crbug.com/111111 external/wpt/hello_world.html [ Crash ]\n'))
         # Check logs
         logs = ''.join(self.logMessages()).lower()
-        self.assertNotIn('webview', logs)
-        self.assertNotIn('chrome', logs)
+        self.assertNotIn(WEBVIEW_WPT_STEP, logs)
+        self.assertNotIn(CHROME_ANDROID_WPT_STEP, logs)
+        # Check that webview and chrome expectation files were not changed
+        self.assertEqual(
+            self._raw_android_expectations,
+            host.filesystem.read_text_file(
+                PRODUCTS_TO_EXPECTATION_FILE_PATHS[CHROME_ANDROID]))
+        self.assertEqual(
+            self._raw_android_expectations,
+            host.filesystem.read_text_file(
+                PRODUCTS_TO_EXPECTATION_FILE_PATHS[ANDROID_WEBVIEW]))
+        self.assertEqual(
+            self._raw_android_never_fix_tests,
+            host.filesystem.read_text_file(ANDROID_DISABLED_TESTS))
 
-    def testUpdateTestExpectationsForAll(self):
+    def testCleanupAndUpdateTestExpectationsForAll(self):
+        # Full integration test for expectations cleanup and update
+        # using builder results.
         host = self._setup_host()
         # Add results for Weblayer
         host.results_fetcher.set_results(
@@ -241,8 +270,8 @@
                         'is_unexpected': True,
                     },
                 },
-            }, step_name='weblayer_shell_wpt (with patch)'),
-            step_name='weblayer_shell_wpt (with patch)')
+            }, step_name=WEBLAYER_WPT_STEP + ' (with patch)'),
+            step_name=WEBLAYER_WPT_STEP + ' (with patch)')
         # Add Results for Webview
         host.results_fetcher.set_results(
             Build('MOCK Android Pie', 101),
@@ -263,8 +292,8 @@
                         'actual': 'SKIP',
                     },
                 },
-            }, step_name='system_webview_wpt (with patch)'),
-            step_name='system_webview_wpt (with patch)')
+            }, step_name=WEBVIEW_WPT_STEP + ' (with patch)'),
+            step_name=WEBVIEW_WPT_STEP + ' (with patch)')
         # Add Results for Chrome
         host.results_fetcher.set_results(
             Build('MOCK Android Pie', 101),
@@ -286,23 +315,36 @@
                         'is_unexpected': True,
                     },
                 },
-            }, step_name='chrome_public_wpt (with patch)'),
-            step_name='chrome_public_wpt (with patch)')
+            }, step_name=CHROME_ANDROID_WPT_STEP + ' (with patch)'),
+            step_name=CHROME_ANDROID_WPT_STEP + ' (with patch)')
         updater = AndroidWPTExpectationsUpdater(
             host, ['-vvv',
-                   '--android-product', 'android_weblayer',
-                   '--android-product', 'chrome_android',
-                   '--android-product', 'android_webview'])
+                   '--clean-up-affected-tests-only',
+                   '--android-product', ANDROID_WEBLAYER,
+                   '--android-product', CHROME_ANDROID,
+                   '--android-product', ANDROID_WEBVIEW])
+
+        def _git_command_return_val(cmd):
+            if '--diff-filter=D' in cmd:
+                return 'external/wpt/ghi.html'
+            if '--diff-filter=R' in cmd:
+                return 'C external/wpt/van.html external/wpt/wagon.html'
+            return ''
+
         updater.git_cl = MockGitCL(host, {
             Build('MOCK Android Weblayer - Pie', 123):
             TryJobStatus('COMPLETED', 'FAILURE'),
             Build('MOCK Android Pie', 101):
             TryJobStatus('COMPLETED', 'FAILURE')})
+
+        updater.git.run = _git_command_return_val
+        updater._relative_to_web_test_dir = lambda test_path: test_path
+
         # Run command
         updater.run()
         # Check expectations for weblayer
         content = host.filesystem.read_text_file(
-            PRODUCTS_TO_EXPECTATION_FILE_PATHS['android_weblayer'])
+            PRODUCTS_TO_EXPECTATION_FILE_PATHS[ANDROID_WEBLAYER])
         self.assertEqual(
             content,
             ('# results: [ Failure Crash Timeout]\n'
@@ -312,9 +354,8 @@
              'crbug.com/1050754 external/wpt/cat.html [ Failure ]\n'
              'crbug.com/1050754 external/wpt/def.html [ Crash ]\n'
              'external/wpt/dog.html [ Crash Timeout ]\n'
-             'crbug.com/1050754 external/wpt/ghi.html [ Timeout ]\n'
              'crbug.com/1111111 external/wpt/jkl.html [ Failure ]\n'
-             'crbug.com/6789043 external/wpt/van.html [ Failure ]\n'
+             'crbug.com/6789043 external/wpt/wagon.html [ Failure ]\n'
              'crbug.com/1050754 external/wpt/weblayer_only.html [ Failure Crash ]\n'
              'external/wpt/www.html [ Crash Failure ]\n'
              '\n'
@@ -322,7 +363,7 @@
              'crbug.com/111111 external/wpt/hello_world.html [ Crash ]\n'))
         # Check expectations for webview
         content = host.filesystem.read_text_file(
-            PRODUCTS_TO_EXPECTATION_FILE_PATHS['android_webview'])
+            PRODUCTS_TO_EXPECTATION_FILE_PATHS[ANDROID_WEBVIEW])
         self.assertEqual(
             content,
             ('# results: [ Failure Crash Timeout]\n'
@@ -332,9 +373,8 @@
              'crbug.com/1050754 external/wpt/cat.html [ Crash Failure Timeout ]\n'
              'crbug.com/1050754 external/wpt/def.html [ Crash ]\n'
              'external/wpt/dog.html [ Crash Timeout ]\n'
-             'crbug.com/1050754 external/wpt/ghi.html [ Timeout ]\n'
              'crbug.com/1111111 external/wpt/jkl.html [ Failure ]\n'
-             'crbug.com/6789043 external/wpt/van.html [ Failure ]\n'
+             'crbug.com/6789043 external/wpt/wagon.html [ Failure ]\n'
              'crbug.com/1050754 external/wpt/webview_only.html [ Timeout ]\n'
              'external/wpt/www.html [ Crash Failure ]\n'
              '\n'
@@ -342,7 +382,7 @@
              'crbug.com/111111 external/wpt/hello_world.html [ Crash ]\n'))
         # Check expectations chrome
         content = host.filesystem.read_text_file(
-            PRODUCTS_TO_EXPECTATION_FILE_PATHS['chrome_android'])
+            PRODUCTS_TO_EXPECTATION_FILE_PATHS[CHROME_ANDROID])
         self.assertEqual(
             content,
             ('# results: [ Failure Crash Timeout]\n'
@@ -353,10 +393,9 @@
              'crbug.com/1050754 external/wpt/chrome_only.html [ Crash Timeout ]\n'
              'crbug.com/1050754 external/wpt/def.html [ Crash ]\n'
              'external/wpt/dog.html [ Crash Timeout ]\n'
-             'crbug.com/1050754 external/wpt/ghi.html [ Timeout ]\n'
              'crbug.com/1111111 crbug.com/1050754'
              ' external/wpt/jkl.html [ Failure ]\n'
-             'crbug.com/6789043 external/wpt/van.html [ Failure ]\n'
+             'crbug.com/6789043 external/wpt/wagon.html [ Failure ]\n'
              'external/wpt/www.html [ Crash Failure ]\n'
              '\n'
              '# This comment will not be deleted\n'
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer.py b/third_party/blink/tools/blinkpy/w3c/test_importer.py
index 5a7a17a7..5a22cac3 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer.py
@@ -70,6 +70,9 @@
         self.new_test_expectations = {}
         self.verbose = False
 
+        args = ['--clean-up-affected-tests-only']
+        self._expectations_updater = WPTExpectationsUpdater(self.host, args)
+
     def main(self, argv=None):
         # TODO(robertma): Test this method! Split it to make it easier to test
         # if necessary.
@@ -156,10 +159,9 @@
         # TODO(crbug.com/800570 robertma): Re-enable it once we fix the bug.
         # self._delete_orphaned_baselines()
 
-        _log.info(
-            'Updating TestExpectations for any removed or renamed tests.')
-        self.update_all_test_expectations_files(self._list_deleted_tests(),
-                                                self._list_renamed_tests())
+        # Remove expectations for tests that were deleted and rename tests
+        # in expectations for renamed tests.
+        self._expectations_updater.cleanup_test_expectations_files()
 
         if not self.chromium_git.has_working_directory_changes():
             _log.info('Done: no changes to import.')
@@ -601,91 +603,8 @@
         This is the same as invoking the `wpt-update-expectations` script.
         """
         _log.info('Adding test expectations lines to TestExpectations.')
-        expectation_updater = WPTExpectationsUpdater(self.host)
-        self.rebaselined_tests, self.new_test_expectations = expectation_updater.update_expectations(
-        )
-
-    def update_all_test_expectations_files(self, deleted_tests, renamed_tests):
-        """Updates all test expectations files for tests that have been deleted or renamed.
-
-        This is only for deleted or renamed tests in the initial import,
-        not for tests that have failures in try jobs.
-        """
-        port = self.host.port_factory.get()
-        for path, file_contents in port.all_expectations_dict().iteritems():
-            self._update_single_test_expectations_file(
-                port, path, file_contents, deleted_tests, renamed_tests)
-
-    def _update_single_test_expectations_file(self, port, path, file_contents,
-                                              deleted_tests, renamed_tests):
-        """Updates a single test expectations file."""
-        test_expectations = TestExpectations(
-            port, expectations_dict={path: file_contents})
-
-        new_lines = []
-        for line in test_expectations.get_updated_lines(path):
-            # if a test is a glob type expectation or empty line or comment then add it to the updated
-            # expectations file without modifications
-            if not line.test or line.is_glob:
-                new_lines.append(line.to_string())
-                continue
-            test_name = line.test
-            if self.finder.is_webdriver_test_path(test_name):
-                root_test_file, subtest_suffix = port.split_webdriver_test_name(
-                    test_name)
-            else:
-                root_test_file = test_name
-            if root_test_file in deleted_tests:
-                continue
-            if root_test_file in renamed_tests:
-                if self.finder.is_webdriver_test_path(root_test_file):
-                    renamed_test = renamed_tests[root_test_file]
-                    test_name = port.add_webdriver_subtest_suffix(
-                        renamed_test, subtest_suffix)
-                else:
-                    test_name = renamed_tests[root_test_file]
-            line.test = test_name
-            new_lines.append(line.to_string())
-        self.host.filesystem.write_text_file(path, '\n'.join(new_lines) + '\n')
-
-    def _list_deleted_tests(self):
-        """List of web tests that have been deleted."""
-        # TODO(robertma): Improve Git.changed_files so that we can use it here.
-        out = self.chromium_git.run([
-            'diff', 'origin/master', '-M100%', '--diff-filter=D', '--name-only'
-        ])
-        deleted_tests = []
-        for path in out.splitlines():
-            test = self._relative_to_web_test_dir(path)
-            if test:
-                deleted_tests.append(test)
-        return deleted_tests
-
-    def _list_renamed_tests(self):
-        """Lists tests that have been renamed.
-
-        Returns a dict mapping source name to destination name.
-        """
-        out = self.chromium_git.run([
-            'diff', 'origin/master', '-M100%', '--diff-filter=R',
-            '--name-status'
-        ])
-        renamed_tests = {}
-        for line in out.splitlines():
-            _, source_path, dest_path = line.split()
-            source_test = self._relative_to_web_test_dir(source_path)
-            dest_test = self._relative_to_web_test_dir(dest_path)
-            if source_test and dest_test:
-                renamed_tests[source_test] = dest_test
-        return renamed_tests
-
-    def _relative_to_web_test_dir(self, path_relative_to_repo_root):
-        """Returns a path that's relative to the web tests directory."""
-        abs_path = self.finder.path_from_chromium_base(
-            path_relative_to_repo_root)
-        if not abs_path.startswith(self.finder.web_tests_dir()):
-            return None
-        return self.fs.relpath(abs_path, self.finder.web_tests_dir())
+        self.rebaselined_tests, self.new_test_expectations = (
+            self._expectation_updater.update_expectations())
 
     def _get_last_imported_wpt_revision(self):
         """Finds the last imported WPT revision."""
diff --git a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
index ab1e5ab..0153d8e 100644
--- a/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/test_importer_unittest.py
@@ -24,13 +24,21 @@
 from blinkpy.w3c.wpt_github_mock import MockWPTGitHub
 from blinkpy.w3c.wpt_manifest import BASE_MANIFEST_NAME
 from blinkpy.web_tests.builder_list import BuilderList
+from blinkpy.web_tests.port.android import PRODUCTS_TO_EXPECTATION_FILE_PATHS
 
 MOCK_WEB_TESTS = '/mock-checkout/' + RELATIVE_WEB_TESTS
 
 
 class TestImporterTest(LoggingTestCase):
-    def test_update_expectations_for_cl_no_results(self):
+
+    def mock_host(self):
         host = MockHost()
+        for path in PRODUCTS_TO_EXPECTATION_FILE_PATHS.values():
+            host.filesystem.write_text_file(path, '')
+        return host
+
+    def test_update_expectations_for_cl_no_results(self):
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -44,7 +52,7 @@
         self.assertEqual(importer.git_cl.calls[-1], ['git', 'cl', 'set-close'])
 
     def test_update_expectations_for_cl_closed_cl(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -62,7 +70,7 @@
         ])
 
     def test_update_expectations_for_cl_all_jobs_pass(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -80,7 +88,7 @@
         self.assertTrue(success)
 
     def test_update_expectations_for_cl_fail_but_no_changes(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -99,7 +107,7 @@
         ])
 
     def test_run_commit_queue_for_cl_pass(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -128,7 +136,7 @@
         ])
 
     def test_run_commit_queue_for_cl_fail_cq(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -157,7 +165,7 @@
         ])
 
     def test_run_commit_queue_for_cl_fail_to_land(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -188,7 +196,7 @@
         ])
 
     def test_run_commit_queue_for_cl_closed_cl(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -213,7 +221,7 @@
 
     def test_run_commit_queue_for_cl_timeout(self):
         # This simulates the case where we time out while waiting for try jobs.
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         importer.git_cl = MockGitCL(host, time_out=True)
         success = importer.run_commit_queue_for_cl()
@@ -229,7 +237,7 @@
         # Here we simulate a case where we timeout waiting for the CQ to submit a
         # CL because we miss the notification that it was merged. We then get an
         # error when trying to close the CL because it's already been merged.
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         importer = TestImporter(host)
@@ -271,7 +279,7 @@
 
     def test_apply_exportable_commits_locally(self):
         # TODO(robertma): Consider using MockLocalWPT.
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(
             host, wpt_github=MockWPTGitHub(pull_requests=[]))
         importer.wpt_git = MockGit(cwd='/tmp/wpt', executive=host.executive)
@@ -315,7 +323,7 @@
             [['Applying patch 14fd77e88e42147c57935c49d9e3b2412b8491b7']])
 
     def test_apply_exportable_commits_locally_returns_none_on_failure(self):
-        host = MockHost()
+        host = self.mock_host()
         wpt_github = MockWPTGitHub(pull_requests=[])
         importer = TestImporter(host, wpt_github=wpt_github)
         commit = MockChromiumCommit(host, subject='My fake commit')
@@ -325,58 +333,8 @@
         applied = importer.apply_exportable_commits_locally(local_wpt)
         self.assertIsNone(applied)
 
-    def test_update_all_test_expectations_files(self):
-        host = MockHost()
-        host.filesystem.files[MOCK_WEB_TESTS + 'TestExpectations'] = (
-            '# results: [ Failure ]\n'
-            'some/test/a.html [ Failure ]\n'
-            'some/test/b.html [ Failure ]\n'
-            'ignore/globs/* [ Failure ]\n'
-            'some/test/c\*.html [ Failure ]\n'
-            # default test case, line below should exist in new file
-            'some/test/d.html [ Failure ]\n')
-        host.filesystem.files[MOCK_WEB_TESTS + 'WebDriverExpectations'] = (
-            '# results: [ Failure ]\n'
-            'external/wpt/webdriver/some/test/a\*.html>>foo\* [ Failure ]\n'
-            'external/wpt/webdriver/some/test/a\*.html>>bar [ Failure ]\n'
-            'external/wpt/webdriver/some/test/b.html>>foo [ Failure ]\n'
-            'external/wpt/webdriver/some/test/c.html>>a [ Failure ]\n'
-            # default test case, line below should exist in new file
-            'external/wpt/webdriver/some/test/d.html>>foo [ Failure ]\n')
-        host.filesystem.files[MOCK_WEB_TESTS + 'VirtualTestSuites'] = '[]'
-        host.filesystem.files[MOCK_WEB_TESTS + 'new/a.html'] = ''
-        host.filesystem.files[MOCK_WEB_TESTS + 'new/b.html'] = ''
-        importer = TestImporter(host)
-        deleted_tests = [
-            'some/test/b.html', 'external/wpt/webdriver/some/test/b.html'
-        ]
-        renamed_test_pairs = {
-            'some/test/a.html': 'new/a.html',
-            'some/test/c*.html': 'new/c*.html',
-            'external/wpt/webdriver/some/test/a*.html': 'old/a*.html',
-            'external/wpt/webdriver/some/test/c.html': 'old/c.html',
-        }
-        importer.update_all_test_expectations_files(deleted_tests,
-                                                    renamed_test_pairs)
-        self.assertMultiLineEqual(
-            host.filesystem.read_text_file(MOCK_WEB_TESTS +
-                                           'TestExpectations'),
-            ('# results: [ Failure ]\n'
-             'new/a.html [ Failure ]\n'
-             'ignore/globs/* [ Failure ]\n'
-             'new/c\*.html [ Failure ]\n'
-             'some/test/d.html [ Failure ]\n'))
-        self.assertMultiLineEqual(
-            host.filesystem.read_text_file(MOCK_WEB_TESTS +
-                                           'WebDriverExpectations'),
-            ('# results: [ Failure ]\n'
-             'old/a\*.html>>foo\* [ Failure ]\n'
-             'old/a\*.html>>bar [ Failure ]\n'
-             'old/c.html>>a [ Failure ]\n'
-             'external/wpt/webdriver/some/test/d.html>>foo [ Failure ]\n'))
-
     def test_get_directory_owners(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         host.filesystem.write_text_file(
@@ -388,7 +346,7 @@
                          {('someone@chromium.org', ): ['external/wpt/foo']})
 
     def test_get_directory_owners_no_changed_files(self):
-        host = MockHost()
+        host = self.mock_host()
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'W3CImportExpectations', '')
         host.filesystem.write_text_file(
@@ -400,21 +358,21 @@
     # Tests for protected methods - pylint: disable=protected-access
 
     def test_commit_changes(self):
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         importer._commit_changes('dummy message')
         self.assertEqual(importer.chromium_git.local_commits(),
                          [['dummy message']])
 
     def test_commit_message(self):
-        importer = TestImporter(MockHost())
+        importer = TestImporter(self.mock_host())
         self.assertEqual(
             importer._commit_message('aaaa', '1111'), 'Import 1111\n\n'
             'Using wpt-import in Chromium aaaa.\n\n'
             'No-Export: true')
 
     def test_cl_description_with_empty_environ(self):
-        host = MockHost()
+        host = self.mock_host()
         host.executive = MockExecutive(output='Last commit message\n\n')
         importer = TestImporter(host)
         description = importer._cl_description(directory_owners={})
@@ -432,14 +390,14 @@
                          [['git', 'log', '-1', '--format=%B']])
 
     def test_cl_description_moves_noexport_tag(self):
-        host = MockHost()
+        host = self.mock_host()
         host.executive = MockExecutive(output='Summary\n\nNo-Export: true\n\n')
         importer = TestImporter(host)
         description = importer._cl_description(directory_owners={})
         self.assertIn('No-Export: true', description)
 
     def test_cl_description_with_directory_owners(self):
-        host = MockHost()
+        host = self.mock_host()
         host.executive = MockExecutive(output='Last commit message\n\n')
         importer = TestImporter(host)
         description = importer._cl_description(
@@ -457,7 +415,7 @@
             '  external/wpt/baz\n\n', description)
 
     def test_tbr_reviewer_no_response_uses_backup(self):
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer())
         self.assertLog([
@@ -466,7 +424,7 @@
         ])
 
     def test_tbr_reviewer_no_emails_field(self):
-        host = MockHost()
+        host = self.mock_host()
         host.web.urls[ROTATIONS_URL] = json.dumps(
             {'updated_unix_timestamp': '1591108191'})
         importer = TestImporter(host)
@@ -477,7 +435,7 @@
         ])
 
     def test_tbr_reviewer_nobody_on_rotation(self):
-        host = MockHost()
+        host = self.mock_host()
         host.web.urls[ROTATIONS_URL] = json.dumps({
             'emails': [],
             'updated_unix_timestamp':
@@ -494,14 +452,14 @@
         def raise_exception(*_):
             raise NetworkTimeout
 
-        host = MockHost()
+        host = self.mock_host()
         host.web.get_binary = raise_exception
         importer = TestImporter(host)
         self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer())
         self.assertLog(['ERROR: Cannot fetch %s\n' % ROTATIONS_URL])
 
     def test_tbr_reviewer(self):
-        host = MockHost()
+        host = self.mock_host()
         host.web.urls[ROTATIONS_URL] = json.dumps({
             'emails': ['current-sheriff@chromium.org'],
             'updated_unix_timestamp':
@@ -513,7 +471,7 @@
         self.assertLog([])
 
     def test_tbr_reviewer_skips_non_committer(self):
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         importer._fetch_ecosystem_infra_sheriff_email = lambda: 'kyleju@google.com'
         self.assertEqual(TBR_FALLBACK, importer.tbr_reviewer())
@@ -523,7 +481,7 @@
     def test_generate_manifest_successful_run(self):
         # This test doesn't test any aspect of the real manifest script, it just
         # asserts that TestImporter._generate_manifest would invoke the script.
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         host.filesystem.write_text_file(
             MOCK_WEB_TESTS + 'external/wpt/MANIFEST.json', '{}')
@@ -540,7 +498,7 @@
                          {MOCK_WEB_TESTS + 'external/' + BASE_MANIFEST_NAME})
 
     def test_only_wpt_manifest_changed(self):
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         importer.chromium_git.changed_files = lambda: [
             RELATIVE_WEB_TESTS + 'external/' + BASE_MANIFEST_NAME,
@@ -555,7 +513,7 @@
     # variant tests.
     @unittest.skip('Finding orphaned baselines is broken')
     def test_delete_orphaned_baselines_basic(self):
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         dest_path = importer.dest_path
         host.filesystem.write_text_file(
@@ -584,7 +542,7 @@
     def test_delete_orphaned_baselines_worker_js_tests(self):
         # This test checks that baselines for existing tests shouldn't be
         # deleted, even if the test name isn't the same as the file name.
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         dest_path = importer.dest_path
         host.filesystem.write_text_file(
@@ -627,7 +585,7 @@
         self.assertTrue(host.filesystem.exists(dest_path + '/c-expected.txt'))
 
     def test_clear_out_dest_path(self):
-        host = MockHost()
+        host = self.mock_host()
         importer = TestImporter(host)
         dest_path = importer.dest_path
         host.filesystem.write_text_file(dest_path + '/foo-test.html', '')
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
index 4729d75b..5436b7d 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater.py
@@ -18,7 +18,9 @@
 from blinkpy.common.path_finder import PathFinder
 from blinkpy.common.system.executive import ScriptError
 from blinkpy.common.system.log_utils import configure_logging
-from blinkpy.web_tests.port.android import PRODUCTS
+from blinkpy.web_tests.models.test_expectations import TestExpectations
+from blinkpy.web_tests.port.android import (
+    PRODUCTS, PRODUCTS_TO_EXPECTATION_FILE_PATHS)
 
 _log = logging.getLogger(__name__)
 
@@ -38,8 +40,9 @@
     def __init__(self, host, args=None):
         self.host = host
         self.port = self.host.port_factory.get()
-        self.git_cl = GitCL(host)
         self.finder = PathFinder(self.host.filesystem)
+        self.git_cl = GitCL(host)
+        self.git = self.host.git(self.finder.chromium_base())
         self.configs_with_no_results = []
         self.configs_with_all_pass = []
         self.patchset = None
@@ -49,14 +52,39 @@
         self.add_arguments(parser)
         self.options = parser.parse_args(args or [])
 
+        # Set up TestExpectations instance which contains all
+        # expectations files associated with the platform.
+        expectations_dict = {p: self.host.filesystem.read_text_file(p)
+                             for p in self.expectations_files()}
+        self._test_expectations = TestExpectations(
+            self.port, expectations_dict=expectations_dict)
+
+    def expectations_files(self):
+        """Returns list of expectations files.
+
+        Each expectation file in the list will be cleaned of expectations
+        for tests that were removed and will also have test names renamed
+        for tests that were renamed. Also the files may have their expectations
+        updated using builder results.
+        """
+        return (self.port.all_expectations_dict().keys() +
+                PRODUCTS_TO_EXPECTATION_FILE_PATHS.values())
+
     def run(self):
         """Does required setup before calling update_expectations().
+
         Do not override this function!
         """
         log_level = logging.DEBUG if self.options.verbose else logging.INFO
         configure_logging(logging_level=log_level, include_time=True)
 
         self.patchset = self.options.patchset
+
+        # Remove expectations for deleted tests and rename tests in expectations
+        # for renamed tests.
+        self.cleanup_test_expectations_files()
+
+        # Use try job results to update expectations and baselines
         self.update_expectations()
 
         return 0
@@ -71,6 +99,12 @@
             '--verbose',
             action='store_true',
             help='More verbose logging.')
+        parser.add_argument(
+            '--clean-up-affected-tests-only',
+            action='store_true',
+            help='Only cleanup expectations deleted or renamed in current CL. '
+                 'If flag is not used then a full cleanup of deleted or '
+                 'renamed tests will be done in expectations.')
         # TODO(rmhasan): Move this argument to the
         # AndroidWPTExpectationsUpdater add_arguments implementation.
         # Also look into using sub parsers to separate android and
@@ -264,7 +298,9 @@
         return test_dict
 
     def _is_wpt_test(self, test_name):
-        """In blink web tests results, each test name is relative to
+        """Check if a web test is a WPT tests.
+
+        In blink web tests results, each test name is relative to
         the web_tests directory instead of the wpt directory. We
         need to use the port.is_wpt_test() function to find out if a test
         is from the WPT suite.
@@ -643,6 +679,161 @@
                                                  wont_fix_file_content)
         return line_dict
 
+    def cleanup_test_expectations_files(self):
+        """Removes deleted tests from expectations files.
+
+        Removes expectations for deleted tests or renames test names in
+        expectation files for tests that were renamed. If the
+        --clean-up-affected-tests-only command line argument is used then
+        only tests deleted in the CL will have their expectations removed
+        through this script. If that command line argument is not used then
+        expectations for test files that no longer exist will be deleted.
+        """
+        deleted_test_files = self._list_deleted_test_files()
+        renamed_test_files = self._list_renamed_test_files()
+
+        for path in self._test_expectations.expectations_dict:
+            _log.info(
+                'Updating %s for any removed or renamed tests.' %
+                self.host.filesystem.basename(path))
+            self._clean_single_test_expectations_file(
+                path, deleted_test_files, renamed_test_files)
+        self._test_expectations.commit_changes()
+
+    def _clean_single_test_expectations_file(
+            self, path, deleted_files, renamed_files):
+        """Cleans up a single test expectations file.
+
+        Args:
+            path: Path of expectations file that is being cleaned up.
+            deleted_files: List of test file paths relative to the web tests
+                directory which were deleted.
+            renamed_files: Dictionary mapping test file paths to their new file
+                name after renaming.
+        """
+        for line in self._test_expectations.get_updated_lines(path):
+            # if a test is a glob type expectation or empty line or comment then
+            # add it to the updated expectations file without modifications
+            if not line.test or line.is_glob:
+                continue
+            root_test_file = self._get_root_file(line.test)
+            if root_test_file in deleted_files:
+                self._test_expectations.remove_expectations(
+                    path, [line])
+
+            if root_test_file in renamed_files:
+                self._test_expectations.remove_expectations(path, [line])
+                new_file_name = renamed_files[root_test_file]
+                if self.finder.is_webdriver_test_path(root_test_file):
+                    _, subtest_suffix = self.port.split_webdriver_test_name(
+                        line.test)
+                    line.test = self.port.add_webdriver_subtest_suffix(
+                        new_file_name, subtest_suffix)
+                elif '?' in line.test:
+                    line.test = (
+                        new_file_name + line.test[line.test.find('?'):])
+                else:
+                    line.test = new_file_name
+                self._test_expectations.add_expectations(
+                    path, [line], lineno=line.lineno)
+
+    @memoized
+    def _get_root_file(self, test_name):
+        """Strips arguments from a web test name in order to get the file name.
+
+        It also removes the arguments for web driver tests. For instances for
+        the test test1/example.html?Hello this function will return
+        test1/example.html. For a webdriver test it would include arguments and
+        would have the following format, {test file}>>{argument}.
+
+        Args:
+            test_name: Test name which may include test arguments.
+
+        Returns:
+            Returns the test file which is the root of a test.
+        """
+        if self.finder.is_webdriver_test_path(test_name):
+            root_test_file, _ = (
+                self.port.split_webdriver_test_name(test_name))
+        elif '?' in test_name:
+            root_test_file = test_name[:test_name.find('?')]
+        else:
+            root_test_file = test_name
+        return root_test_file
+
+    def _list_deleted_test_files(self):
+        """Returns a list of web tests that have been deleted.
+
+        If --clean-up-affected-tests-only is true then only test files deleted
+        in the current CL may be removed from expectations. Otherwise, any test
+        file may be removed from expectations if it has been deleted.
+
+        Returns: A list of web test files that have been deleted.
+        """
+        # TODO(robertma): Improve Git.changed_files so that we can use it here.
+        paths = set(self.git.run(
+            ['diff', 'origin/master', '-M100%', '--diff-filter=D',
+             '--name-only']).splitlines())
+        if not self.options.clean_up_affected_tests_only:
+            # Remove expectations for all test which have files that
+            # were deleted.
+            paths.update(self._deleted_test_files_in_expectations())
+
+        deleted_tests = set()
+        for path in paths:
+            test = self._relative_to_web_test_dir(path)
+            if test:
+                deleted_tests.add(test)
+        return deleted_tests
+
+    def _list_renamed_test_files(self):
+        """Returns a dictionary mapping tests to their new name.
+
+        Regardless of the command line arguments used this test will only
+        return a dictionary for tests affected in the current CL.
+
+        Returns a dictionary mapping source name to destination name.
+        """
+        out = self.git.run(
+            ['diff', 'origin/master', '-M100%', '--diff-filter=R',
+             '--name-status'])
+        renamed_tests = {}
+        for line in out.splitlines():
+            _, source_path, dest_path = line.split()
+            source_test = self._relative_to_web_test_dir(source_path)
+            dest_test = self._relative_to_web_test_dir(dest_path)
+            if source_test and dest_test:
+                renamed_tests[source_test] = dest_test
+        return renamed_tests
+
+    def _relative_to_web_test_dir(self, path_relative_to_repo_root):
+        """Returns a path that's relative to the web tests directory."""
+        abs_path = self.finder.path_from_chromium_base(
+            path_relative_to_repo_root)
+        if not abs_path.startswith(self.finder.web_tests_dir()):
+            return None
+        return self.host.filesystem.relpath(
+            abs_path, self.finder.web_tests_dir())
+
+    def _deleted_test_files_in_expectations(self):
+        """Returns a list of test files that were deleted.
+
+        Returns a list of test file names that are still in the expectations
+        files but no longer exists in the web tests directory.
+        """
+        deleted_files = set()
+        existing_files = {
+            self._get_root_file(p)
+            for p in self.port.tests()}
+        for path in self._test_expectations.expectations_dict:
+            for line in self._test_expectations.get_updated_lines(path):
+                if not line.test or line.is_glob:
+                    continue
+                root_test_file = self._get_root_file(line.test)
+                if root_test_file not in existing_files:
+                    deleted_files.add(root_test_file)
+        return deleted_files
+
     # TODO(robertma): Unit test this method.
     def download_text_baselines(self, test_results):
         """Fetches new baseline files for tests that should be rebaselined.
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py
index f959622..2ecc6d5 100644
--- a/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py
+++ b/third_party/blink/tools/blinkpy/w3c/wpt_expectations_updater_unittest.py
@@ -12,6 +12,7 @@
 from blinkpy.common.net.results_fetcher_mock import (
     MockTestResultsFetcher, BuilderStep)
 from blinkpy.common.net.web_test_results import WebTestResult, WebTestResults
+from blinkpy.common.path_finder import RELATIVE_WEB_TESTS
 from blinkpy.common.system.executive import ScriptError
 from blinkpy.common.system.log_testing import LoggingTestCase
 
@@ -20,14 +21,17 @@
 from blinkpy.w3c.wpt_manifest import BASE_MANIFEST_NAME
 
 from blinkpy.web_tests.builder_list import BuilderList
+from blinkpy.web_tests.port.android import PRODUCTS_TO_EXPECTATION_FILE_PATHS
 from blinkpy.web_tests.port.factory_mock import MockPortFactory
 
+MOCK_WEB_TESTS = '/mock-checkout/' + RELATIVE_WEB_TESTS
 
 class WPTExpectationsUpdaterTest(LoggingTestCase):
     def mock_host(self):
         """Returns a mock host with fake values set up for testing."""
         host = MockHost()
         host.port_factory = MockPortFactory(host)
+        host.executive._output = ''
 
         # Set up a fake list of try builders.
         host.builders = BuilderList({
@@ -87,6 +91,8 @@
                 },
             }))
 
+        for path in PRODUCTS_TO_EXPECTATION_FILE_PATHS.values():
+            host.filesystem.write_text_file(path, '')
         return host
 
     def test_run_single_platform_failure(self):
@@ -749,6 +755,53 @@
              ' webdriverexpectations or neverfixtests.'),
             logs)
 
+    def test_write_to_test_expectations_and_cleanup_expectations(self):
+        host = self.mock_host()
+        expectations_path = \
+            host.port_factory.get().path_to_generic_test_expectations_file()
+        host.filesystem.write_text_file(
+            expectations_path,
+            '# tags: [ Linux ]\n' +
+            '# results: [ Pass Failure ]\n' +
+            WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
+            '[ linux ] external/wpt/fake/some_test.html?HelloWorld [ Failure ]\n' +
+            'external/wpt/fake/file/deleted_path.html [ Pass ]\n')
+        updater = WPTExpectationsUpdater(
+            host, ['--clean-up-affected-tests-only'])
+
+        def _git_command_return_val(cmd):
+            if '--diff-filter=D' in cmd:
+                return 'external/wpt/fake/file/deleted_path.html'
+            if '--diff-filter=R' in cmd:
+                return 'C external/wpt/fake/some_test.html external/wpt/fake/new.html'
+            return ''
+
+        updater.git.run = _git_command_return_val
+        updater._relative_to_web_test_dir = lambda test_path: test_path
+        updater.cleanup_test_expectations_files()
+
+        test_expectations = {'external/wpt/fake/file/path.html': {
+            tuple([DesktopConfig(port_name='test-linux-trusty')]):
+            SimpleTestResult(actual='PASS', expected='', bug='crbug.com/123')}}
+        skip_path = host.port_factory.get().path_to_never_fix_tests_file()
+        skip_value_origin = host.filesystem.read_text_file(skip_path)
+
+        updater.write_to_test_expectations(test_expectations)
+        value = host.filesystem.read_text_file(expectations_path)
+        print ('# tags: [ Linux ]\n' +
+               '# results: [ Pass Failure ]\n' +
+               WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
+               'crbug.com/123 [ Trusty ] external/wpt/fake/file/path.html [ Pass ]\n' +
+               '[ linux ] external/wpt/fake/some_test.html?HelloWorld [ Failure ]')
+        self.assertMultiLineEqual(
+            value, ('# tags: [ Linux ]\n' +
+                    '# results: [ Pass Failure ]\n' +
+                    WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
+                    'crbug.com/123 [ Trusty ] external/wpt/fake/file/path.html [ Pass ]\n' +
+                    '[ linux ] external/wpt/fake/new.html?HelloWorld [ Failure ]\n'))
+        skip_value = host.filesystem.read_text_file(skip_path)
+        self.assertMultiLineEqual(skip_value, skip_value_origin)
+
     def test_write_to_test_expectations_with_marker_comment(self):
         host = self.mock_host()
         expectations_path = \
@@ -811,8 +864,10 @@
         host = self.mock_host()
         expectations_path = \
             host.port_factory.get().path_to_generic_test_expectations_file()
+        raw_exps = '# tags: [ Trusty ]\n# results: [ Pass Failure ]\n'
         host.filesystem.write_text_file(
             expectations_path,
+            raw_exps + '\n' +
             'crbug.com/111 [ Trusty ] foo/bar.html [ Failure ]\n')
         updater = WPTExpectationsUpdater(host)
         test_expectations = {'external/wpt/fake/file/path.html': {
@@ -825,7 +880,8 @@
         value = host.filesystem.read_text_file(expectations_path)
 
         self.assertMultiLineEqual(
-            value, ('crbug.com/111 [ Trusty ] foo/bar.html [ Failure ]\n'
+            value, (raw_exps + '\n' +
+                    'crbug.com/111 [ Trusty ] foo/bar.html [ Failure ]\n'
                     '\n' + WPTExpectationsUpdater.MARKER_COMMENT + '\n'
                     'crbug.com/123 [ Trusty ] external/wpt/fake/file/path.html [ Pass ]'))
         skip_value = host.filesystem.read_text_file(skip_path)
@@ -835,8 +891,11 @@
         host = self.mock_host()
         expectations_path = \
             host.port_factory.get().path_to_generic_test_expectations_file()
+        raw_exps = '# tags: [ Trusty ]\n# results: [ Pass ]\n'
         host.filesystem.write_text_file(
-            expectations_path, WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
+            expectations_path,
+            raw_exps + '\n' +
+            WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
             'crbug.com/123 [ Trusty ] fake/file/path.html [ Pass ]\n')
         skip_path = host.port_factory.get().path_to_never_fix_tests_file()
         skip_value_origin = host.filesystem.read_text_file(skip_path)
@@ -846,7 +905,9 @@
 
         value = host.filesystem.read_text_file(expectations_path)
         self.assertMultiLineEqual(
-            value, WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
+            value,
+            raw_exps + '\n' +
+            WPTExpectationsUpdater.MARKER_COMMENT + '\n' +
             'crbug.com/123 [ Trusty ] fake/file/path.html [ Pass ]\n')
         skip_value = host.filesystem.read_text_file(skip_path)
         self.assertMultiLineEqual(skip_value, skip_value_origin)
@@ -856,14 +917,16 @@
         expectations_path = \
             host.port_factory.get().path_to_generic_test_expectations_file()
         skip_path = host.port_factory.get().path_to_never_fix_tests_file()
-
+        raw_exps = '# tags: [ Trusty ]\n# results: [ Skip ]\n'
         test_expectations = {'external/wpt/fake/file/path-manual.html': {
             tuple([DesktopConfig(port_name='test-linux-trusty')]):
             SimpleTestResult(actual='TIMEOUT', expected={}, bug='')}}
         host.filesystem.write_text_file(expectations_path,
                                         WPTExpectationsUpdater.MARKER_COMMENT + '\n')
         host.filesystem.write_text_file(
-            skip_path, '[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n')
+            skip_path,
+            raw_exps +
+            '\n[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n')
         updater = WPTExpectationsUpdater(host)
 
         updater.write_to_test_expectations(test_expectations)
@@ -872,7 +935,9 @@
         skip_value = host.filesystem.read_text_file(skip_path)
         self.assertMultiLineEqual(expectations_value, WPTExpectationsUpdater.MARKER_COMMENT + '\n')
         self.assertMultiLineEqual(
-            skip_value, '[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n'
+            skip_value,
+            raw_exps + '\n'
+            '[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n'
             '[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n')
 
     def test_write_to_test_expectations_without_newline(self):
@@ -883,10 +948,13 @@
         test_expectations = {'external/wpt/fake/file/path-manual.html': {
             tuple([DesktopConfig(port_name='test-linux-trusty')]):
             SimpleTestResult(actual='TIMEOUT', expected={}, bug='')}}
-        host.filesystem.write_text_file(expectations_path,
-                                        WPTExpectationsUpdater.MARKER_COMMENT + '\n')
+        raw_exps = '# tags: [ Trusty ]\n# results: [ Skip ]\n'
         host.filesystem.write_text_file(
-            skip_path, '[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]')
+            expectations_path,
+            WPTExpectationsUpdater.MARKER_COMMENT + '\n')
+        host.filesystem.write_text_file(
+            skip_path,
+            raw_exps + '\n[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]')
         updater = WPTExpectationsUpdater(host)
 
         updater.write_to_test_expectations(test_expectations)
@@ -895,7 +963,8 @@
         skip_value = host.filesystem.read_text_file(skip_path)
         self.assertMultiLineEqual(expectations_value, WPTExpectationsUpdater.MARKER_COMMENT + '\n')
         self.assertMultiLineEqual(
-            skip_value, '[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n'
+            skip_value,
+            raw_exps + '\n[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n'
             '[ Trusty ] external/wpt/fake/file/path-manual.html [ Skip ]\n')
 
     def test_is_reference_test_given_testharness_test(self):
@@ -1099,6 +1168,100 @@
                 ]
             })
 
+    def test_cleanup_all_deleted_tests_in_expectations_files(self):
+        host = MockHost()
+
+        host.filesystem.files[MOCK_WEB_TESTS + 'TestExpectations'] = (
+            '# results: [ Failure ]\n'
+            'some/test/a.html?hello%20world [ Failure ]\n'
+            'some/test/b.html [ Failure ]\n'
+            '# line below should exist in new file\n'
+            'some/test/d.html [ Failure ]\n')
+        host.filesystem.files[MOCK_WEB_TESTS + 'VirtualTestSuites'] = '[]'
+        host.filesystem.files[MOCK_WEB_TESTS + 'new/a.html'] = ''
+        host.filesystem.files[MOCK_WEB_TESTS + 'new/b.html'] = ''
+        # TODO(rmhasan): Remove creation of Android files within
+        # tests.
+        for path in PRODUCTS_TO_EXPECTATION_FILE_PATHS.values():
+            host.filesystem.write_text_file(path, '')
+
+        updater = WPTExpectationsUpdater(host)
+
+        def _git_command_return_val(cmd):
+            if '--diff-filter=D' in cmd:
+                return 'some/test/b.html'
+            return ''
+
+        updater.git.run = _git_command_return_val
+        updater.port.tests = lambda: [
+            'some/test/b.html?Goodbye', 'some/test/d.html']
+        updater._relative_to_web_test_dir = lambda test_path: test_path
+        updater.cleanup_test_expectations_files()
+        self.assertMultiLineEqual(
+            host.filesystem.read_text_file(MOCK_WEB_TESTS +
+                                           'TestExpectations'),
+            ('# results: [ Failure ]\n'
+             '# line below should exist in new file\n'
+             'some/test/d.html [ Failure ]\n'))
+
+    def test_cleanup_all_test_expectations_files(self):
+        host = MockHost()
+        host.filesystem.files[MOCK_WEB_TESTS + 'TestExpectations'] = (
+            '# results: [ Failure ]\n'
+            'some/test/a.html [ Failure ]\n'
+            'some/test/b.html [ Failure ]\n'
+            'ignore/globs/* [ Failure ]\n'
+            'some/test/c\*.html [ Failure ]\n'
+            # default test case, line below should exist in new file
+            'some/test/d.html [ Failure ]\n')
+        host.filesystem.files[MOCK_WEB_TESTS + 'WebDriverExpectations'] = (
+            '# results: [ Failure ]\n'
+            'external/wpt/webdriver/some/test/a\*.html>>foo\* [ Failure ]\n'
+            'external/wpt/webdriver/some/test/a\*.html>>bar [ Failure ]\n'
+            'external/wpt/webdriver/some/test/b.html>>foo [ Failure ]\n'
+            'external/wpt/webdriver/some/test/c.html>>a [ Failure ]\n'
+            # default test case, line below should exist in new file
+            'external/wpt/webdriver/some/test/d.html>>foo [ Failure ]\n')
+        host.filesystem.files[MOCK_WEB_TESTS + 'VirtualTestSuites'] = '[]'
+        host.filesystem.files[MOCK_WEB_TESTS + 'new/a.html'] = ''
+        host.filesystem.files[MOCK_WEB_TESTS + 'new/b.html'] = ''
+
+        # TODO(rmhasan): Remove creation of Android files within
+        # tests.
+        for path in PRODUCTS_TO_EXPECTATION_FILE_PATHS.values():
+            host.filesystem.write_text_file(path, '')
+
+        updater = WPTExpectationsUpdater(
+            host, ['--clean-up-affected-tests-only'])
+        deleted_files = [
+            'some/test/b.html', 'external/wpt/webdriver/some/test/b.html'
+        ]
+        renamed_file_pairs = {
+            'some/test/a.html': 'new/a.html',
+            'some/test/c*.html': 'new/c*.html',
+            'external/wpt/webdriver/some/test/a*.html': 'old/a*.html',
+            'external/wpt/webdriver/some/test/c.html': 'old/c.html',
+        }
+        updater._list_deleted_test_files = lambda: deleted_files
+        updater._list_renamed_test_files = lambda: renamed_file_pairs
+        updater.cleanup_test_expectations_files()
+        self.assertMultiLineEqual(
+            host.filesystem.read_text_file(MOCK_WEB_TESTS +
+                                           'TestExpectations'),
+            ('# results: [ Failure ]\n'
+             'new/a.html [ Failure ]\n'
+             'ignore/globs/* [ Failure ]\n'
+             'new/c\*.html [ Failure ]\n'
+             'some/test/d.html [ Failure ]\n'))
+        self.assertMultiLineEqual(
+            host.filesystem.read_text_file(MOCK_WEB_TESTS +
+                                           'WebDriverExpectations'),
+            ('# results: [ Failure ]\n'
+             'old/a\*.html>>foo\* [ Failure ]\n'
+             'old/a\*.html>>bar [ Failure ]\n'
+             'old/c.html>>a [ Failure ]\n'
+             'external/wpt/webdriver/some/test/d.html>>foo [ Failure ]\n'))
+
     def test_merging_platforms_if_possible(self):
         host = self.mock_host()
         updater = WPTExpectationsUpdater(host)
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base.py b/third_party/blink/tools/blinkpy/web_tests/port/base.py
index eab2f4b..a55054e 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/base.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/base.py
@@ -90,6 +90,7 @@
     [[CONTENT_SHELL_FONTS_DIR], 'NotoSansCJKjp-Regular.otf', None],
     [[CONTENT_SHELL_FONTS_DIR], 'NotoSansKhmer-Regular.ttf', None],
     [[CONTENT_SHELL_FONTS_DIR], 'NotoSansSymbols2-Regular.ttf', None],
+    [[CONTENT_SHELL_FONTS_DIR], 'NotoSansTibetan-Regular.ttf', None],
     [[CONTENT_SHELL_FONTS_DIR], 'Tinos-Bold.ttf', None],
     [[CONTENT_SHELL_FONTS_DIR], 'Tinos-BoldItalic.ttf', None],
     [[CONTENT_SHELL_FONTS_DIR], 'Tinos-Italic.ttf', None],
@@ -843,7 +844,7 @@
             reftest_list.append((expectation, ref_absolute_path))
         return reftest_list
 
-    def tests(self, paths):
+    def tests(self, paths=None):
         """Returns all tests or tests matching supplied paths.
 
         Args:
@@ -966,6 +967,16 @@
         return self.wpt_manifest(wpt_path).is_crash_test(path_in_wpt)
 
     def is_slow_wpt_test(self, test_file):
+        # When DCHECK is enabled, idlharness tests run 5-6x slower due to the
+        # amount of JavaScript they use (most web_tests run very little JS).
+        # This causes flaky timeouts for a lot of them, as a 0.5-1s test becomes
+        # close to the default 6s timeout.
+        #
+        # Since we can't detect DCHECK being enabled, we instead always consider
+        # idlharness tests to be slow. See https://crbug.com/1047818
+        if self.is_wpt_idlharness_test(test_file):
+            return True
+
         match = self.WPT_REGEX.match(test_file)
         if not match:
             return False
diff --git a/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py b/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
index e9b631c..9a39997 100644
--- a/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
+++ b/third_party/blink/tools/blinkpy/web_tests/port/base_unittest.py
@@ -1138,6 +1138,11 @@
             port.is_slow_wpt_test(
                 'external/wpt/html/dom/elements/global-attributes/dir_auto-EN-L.html'
             ))
+        # We always consider idlharness tests slow, even if they aren't marked
+        # such in the manifest. See https://crbug.com/1047818
+        self.assertTrue(
+            port.is_slow_wpt_test(
+                'external/wpt/css/css-pseudo/idlharness.html'))
 
     def test_is_slow_wpt_test_with_variations(self):
         port = self.make_port(with_tests=True)
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index 46100ea..89b4109 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -395,6 +395,9 @@
 ### fast/css/
 crbug.com/591099 fast/css/absolute-inline-alignment-2.html [ Failure ]
 
+### fast/writing-mode/
+crbug.com/591099 fast/writing-mode/flipped-blocks-inline-map-local-to-container.html [ Failure ]
+
 ### external/wpt/html/rendering
 crbug.com/875235 external/wpt/html/rendering/non-replaced-elements/the-fieldset-and-legend-elements/legend-painting-order.html [ Failure ]
 
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations
index e81c8d1..7cf46b3 100644
--- a/third_party/blink/web_tests/MSANExpectations
+++ b/third_party/blink/web_tests/MSANExpectations
@@ -67,7 +67,6 @@
 crbug.com/729136 [ Linux ] fast/css/css-selector-deeply-nested.html [ Timeout ]
 crbug.com/729136 [ Linux ] http/tests/devtools/forced-layout-in-microtask.js [ Timeout ]
 crbug.com/729136 [ Linux ] http/tests/devtools/tracing/timeline-xhr-response-type-blob-event.js [ Timeout ]
-crbug.com/729136 [ Linux ] http/tests/devtools/components/file-path-scoring.js [ Timeout ]
 crbug.com/729136 [ Linux ] http/tests/devtools/elements/styles-4/styles-should-not-force-sync-style-recalc.js [ Timeout ]
 crbug.com/729136 [ Linux ] webaudio/mixing.html [ Timeout ]
 
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index a181416..c4eb0e85 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -496,6 +496,7 @@
 crbug.com/1071114 external/wpt/css/css-fonts/test_font_family_parsing.html [ Slow ]
 crbug.com/1071418 external/wpt/css/css-transitions/idlharness.html [ Slow ]
 crbug.com/1048204 external/wpt/selection/idlharness.window.html [ Slow ]
+crbug.com/1047818 external/wpt/css/css-masking/idlharness.html [ Slow ]
 
 # This test contains a slow loading image that results in timeouts.
 crbug.com/853360 [ Mac ] http/tests/misc/slow-loading-image-in-pattern.html [ Slow ]
@@ -534,3 +535,4 @@
 crbug.com/1091716 svg/as-object/sizing/svg-in-object-placeholder-percentage-percentage-no-intrinsic-ratio.html [ Slow ]
 
 crbug.com/1043669 [ Mac ] inspector-protocol/emulation/set-vision-deficiency.js [ Slow ]
+crbug.com/1092121 fast/css/large-list-of-rules-crash.html [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index aac4e363..ebac8fa 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1889,6 +1889,7 @@
 crbug.com/1075869 http/tests/devtools/elements/styles-3/spectrum.js [ Pass Failure ]
 crbug.com/1075869 http/tests/devtools/elements/styles-4/styles-invalid-color-values.js [ Pass Failure ]
 crbug.com/1075869 http/tests/devtools/extensions/extensions-timeline-api.js [ Pass Failure Timeout ]
+crbug.com/946975 http/tests/devtools/sources/autocomplete-css.js [ Pass Failure ]
 
 # On these platforms (all but Android) media tests don't currently use gpu-accelerated (proprietary) codecs, so no
 # benefit to running them again with gpu acceleration enabled.
@@ -2677,6 +2678,12 @@
 crbug.com/1086855 external/wpt/css/css-pseudo/file-chooser-button-001.tentative.html [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 [ Linux ] external/wpt/css/css-ruby/abs-in-ruby-base-container.html [ Failure ]
+crbug.com/626703 [ Mac ] external/wpt/css/css-ruby/abs-in-ruby-base-container.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/css/css-ruby/abs-in-ruby-base-container.html [ Failure ]
+crbug.com/626703 [ Linux ] external/wpt/css/css-ruby/abs-in-ruby-base.html [ Failure ]
+crbug.com/626703 [ Mac ] external/wpt/css/css-ruby/abs-in-ruby-base.html [ Failure ]
+crbug.com/626703 [ Win ] external/wpt/css/css-ruby/abs-in-ruby-base.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/mathml/presentation-markup/fractions/frac-invalid-3.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/mathml/presentation-markup/fractions/frac-invalid-3.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/mathml/presentation-markup/fractions/frac-invalid-3.html [ Failure ]
@@ -4501,6 +4508,12 @@
 crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/scrolled-grid-painting.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/mozilla/grid-repeat-auto-fill-fit-005-part-1.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/fast/css-grid-layout/mozilla/grid-repeat-auto-fill-fit-005-part-2.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-001.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-002.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-003.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-004.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-005.html [ Failure ]
+crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-006.html [ Failure ]
 
 # [css-logical]
 crbug.com/865579 external/wpt/css/css-logical/animation-001.html [ Failure Pass ]
@@ -4764,11 +4777,9 @@
 crbug.com/1069817 fast/ruby/float-overhang-from-ruby-text.html [ Failure ]
 crbug.com/1069817 fast/ruby/line-break-ruby.html [ Failure ]
 crbug.com/1069817 fast/ruby/position-after.html [ Failure ]
-crbug.com/1069817 fast/ruby/select-ruby.html [ Failure ]
 crbug.com/1069817 [ Linux ] fast/writing-mode/Kusa-Makura-background-canvas.html [ Failure ]
 crbug.com/1069817 [ Mac ] fast/writing-mode/Kusa-Makura-background-canvas.html [ Failure ]
 crbug.com/1069817 [ Win10 ] fast/writing-mode/Kusa-Makura-background-canvas.html [ Failure ]
-crbug.com/1069817 fast/writing-mode/flipped-blocks-inline-map-local-to-container.html [ Failure ]
 crbug.com/1069817 fast/writing-mode/japanese-ruby-vertical-lr.html [ Failure ]
 crbug.com/1069817 fast/writing-mode/japanese-ruby-vertical-rl.html [ Failure ]
 crbug.com/1069817 virtual/text-antialias/emphasis-avoid-ruby.html [ Failure ]
@@ -5038,10 +5049,6 @@
 # This was previously skipped on Windows in the section for crbug.com/757165
 crbug.com/775957 virtual/gpu/fast/canvas/canvas-incremental-repaint.html [ Skip ]
 
-# Canvas tests that are affected by change to Skia GPU rect shadow rendering.
-crbug.com/990918 virtual/gpu/fast/canvas/canvas-shadow-source-in.html [ Pass Failure ]
-crbug.com/990918 virtual/gpu/fast/canvas/canvas-composite-shadow.html [ Pass Failure ]
-
 # Sheriff failures 2017-09-21
 crbug.com/767469 http/tests/navigation/start-load-during-provisional-loader-detach.html [ Pass Failure ]
 
@@ -5841,7 +5848,6 @@
 
 # Sheriff 2019-06-13
 crbug.com/973692 [ Mac ] external/wpt/css/css-text/parsing/hyphens-computed.html [ Failure ]
-crbug.com/973726 [ Mac ] fast/css/large-list-of-rules-crash.html [ Pass Timeout ]
 
 # Sheriff 2019-06-20
 crbug.com/976045 fast/scrolling/unscrollable-layer-subpixel-size-with-negative-overflow.html [ Pass Failure ]
@@ -5968,6 +5974,11 @@
 crbug.com/970285 [ Mac ] virtual/forced-high-contrast-cascade/* [ Failure ]
 crbug.com/970285 [ Mac ] virtual/forced-high-contrast-colors/* [ Failure ]
 
+# Expected failures for dark mode tests when the corresponding flags
+# are not enabled.
+crbug.com/1090660 external/wpt/css/css-color-adjust/rendering/dark-color-scheme/svg-as-image.html [ Skip ]
+crbug.com/1090660 virtual/dark-color-scheme/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/svg-as-image.html [ Pass ]
+
 # Sheriff 2019-08-14
 crbug.com/993671 [ Win ] http/tests/media/video-frame-size-change.html [ Pass Failure ]
 
@@ -6656,6 +6667,7 @@
 # Sheriff 2020-05-04
 crbug.com/952717 [ Debug ] http/tests/xmlhttprequest/redirect-cross-origin-post.html [ Pass Failure ]
 crbug.com/984467 virtual/gpu/fast/canvas/canvas-composite-stroke-alpha.html [ Pass Timeout ]
+crbug.com/984467 fast/canvas/canvas-composite-stroke-alpha.html [ Pass Timeout ]
 
 # Sheriff 2020-05-06
 crbug.com/1078863 [ Mac ] fast/speech/scripted/speechrecognition-restart-onend.html [ Pass Timeout ]
@@ -6701,10 +6713,6 @@
 crbug.com/1083362 compositing/reflections/load-video-in-reflection.html [ Pass Failure ]
 crbug.com/1087471 [ Linux ] virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow.html [ Pass Failure ]
 
-# Temporary disabling to allow landing https://webrtc-review.googlesource.com/c/src/+/176509
-crbug.com/webrtc/8787 external/wpt/webrtc/RTCPeerConnection-mandatory-getStats.https.html [ Pass Failure ]
-crbug.com/webrtc/8787 external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Pass Failure ]
-
 # Sheriff 2020-06-01
 # Also see crbug.com/626703, these timed-out before but now fail as well.
 crbug.com/1088220 [ Linux ] external/wpt/html/infrastructure/safe-passing-of-structured-data/shared-array-buffers/window-domain-failure.https.sub.html [ Pass Failure Timeout ]
@@ -6734,7 +6742,19 @@
 # Sheriff 2020-06-05
 crbug.com/1091829 [ Mac ] fast/scrolling/scroll-non-composited-scroller.html [ Pass Failure ]
 crbug.com/1091829 [ Linux ] virtual/threaded-prefer-compositing/fast/scrolling/scroll-non-composited-scroller.html [ Pass Failure ]
-crbug.com/1091885 fast/peerconnection/RTCPeerConnection-iframe-gc.html [ Pass Failure ]
 crbug.com/1091250 [ Win10 ] virtual/cors/http/tests/misc/resource-timing-sizes-multipart.html [ Pass Failure ]
 crbug.com/1091948 [ Linux ] external/wpt/html/canvas/element/manual/fill-and-stroke-styles/canvas_colorsandstyles_createlineargradient_001.htm [ Pass Timeout ]
 crbug.com/1092091 [ Mac ] virtual/dark-color-scheme/datetimelocal-picker/datetimelocal-open.html [ Pass Failure ]
+
+# Test giving differing results on different build bots
+crbug.com/1092721 [ Mac ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Pass Failure ]
+crbug.com/1092721 [ Mac ] external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Pass Failure ]
+crbug.com/1092721 [ Linux ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Pass Failure ]
+crbug.com/1092721 [ Linux ] external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Pass Failure ]
+
+# Sheriff 2020-06-06
+crbug.com/1091843 fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Pass Failure ]
+crbug.com/1091843 virtual/gpu/fast/canvas/color-space/canvas-createImageBitmap-p3.html [ Pass Failure ]
+
+# Sheriff 2020-06-09
+crbug.com/1092813 [ Retina ] virtual/text-antialias/emoticons.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/accessibility/contenteditable-notifications.html b/third_party/blink/web_tests/accessibility/contenteditable-notifications.html
index 1836c35..a518cf52 100644
--- a/third_party/blink/web_tests/accessibility/contenteditable-notifications.html
+++ b/third_party/blink/web_tests/accessibility/contenteditable-notifications.html
@@ -1,7 +1,7 @@
 <!DOCTYPE html>
-<script src="../resources/accessibility-helper.js"></script>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
+<script src="../resources/run-after-layout-and-paint.js"></script>
 
 <div id="textbox" contenteditable="true">
   First<p>Second</p>
@@ -11,10 +11,6 @@
 'use strict';
 
 async_test((t) => {
-  // TODO(aboxhall): No longer necessary when updates are processed after layout.
-  // Ensure entire a11y tree has already been seen.
-  traverseAccessibilityTree(accessibilityController.rootElement);
-
   const textbox = document.getElementById('textbox');
   const axTextBox = accessibilityController.accessibleElementById('textbox');
   let valueChangedCount = 0;
@@ -34,26 +30,28 @@
     }
   }));
 
-  textbox.focus();
-  // Initial setting of the selection.
-  expectedIntents.push('AXEventIntent(setSelection,character,forward)');
-  eventSender.keyDown("ArrowDown", []);
-  expectedIntents.push('AXEventIntent(moveSelection,lineEnd,forward)');
-  eventSender.keyDown("ArrowDown", []);
-  expectedIntents.push('AXEventIntent(moveSelection,lineEnd,forward)');
-  eventSender.keyDown("ArrowLeft", []);
-  expectedIntents.push('AXEventIntent(moveSelection,character,backward)');
-  eventSender.keyDown("ArrowLeft", []);
-  expectedIntents.push('AXEventIntent(moveSelection,character,backward)');
-  eventSender.keyDown("w", []);
-  // TODO(nektar): Support an intent for the typing command.
-  expectedIntents.push('AXEventIntent(setSelection,character,forward)');
-  eventSender.keyDown("x", []);
-  expectedIntents.push('AXEventIntent(setSelection,character,forward)');
-  eventSender.keyDown("y", []);
-  expectedIntents.push('AXEventIntent(setSelection,character,forward)');
-  eventSender.keyDown("z", []);
-  expectedIntents.push('AXEventIntent(setSelection,character,forward)');
+  runAfterLayoutAndPaint(t.step_func(() => {
+    textbox.focus();
+    // Initial setting of the selection.
+    expectedIntents.push('AXEventIntent(setSelection,character,forward)');
+    eventSender.keyDown("ArrowDown", []);
+    expectedIntents.push('AXEventIntent(moveSelection,lineEnd,forward)');
+    eventSender.keyDown("ArrowDown", []);
+    expectedIntents.push('AXEventIntent(moveSelection,lineEnd,forward)');
+    eventSender.keyDown("ArrowLeft", []);
+    expectedIntents.push('AXEventIntent(moveSelection,character,backward)');
+    eventSender.keyDown("ArrowLeft", []);
+    expectedIntents.push('AXEventIntent(moveSelection,character,backward)');
+    eventSender.keyDown("w", []);
+    // TODO(nektar): Support an intent for the typing command.
+    expectedIntents.push('AXEventIntent(setSelection,character,forward)');
+    eventSender.keyDown("x", []);
+    expectedIntents.push('AXEventIntent(setSelection,character,forward)');
+    eventSender.keyDown("y", []);
+    expectedIntents.push('AXEventIntent(setSelection,character,forward)');
+    eventSender.keyDown("z", []);
+    expectedIntents.push('AXEventIntent(setSelection,character,forward)');
+  }));
 }, 'This test ensures that moving the cursor in a contentEditable sends a selected text change notification, and typing in a contentEditable sends both a value changed and selected text changed notification.');
 
 </script>
diff --git a/third_party/blink/web_tests/accessibility/contenteditable-selection-with-ignored-nodes.html b/third_party/blink/web_tests/accessibility/contenteditable-selection-with-ignored-nodes.html
new file mode 100644
index 0000000..64dd6050
--- /dev/null
+++ b/third_party/blink/web_tests/accessibility/contenteditable-selection-with-ignored-nodes.html
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="../resources/run-after-layout-and-paint.js"></script>
+
+<!-- The span surrounding "Apple" is ignored in the accessibility tree.
+    The same occurs with both the span surrounding "Banana" and the paragraph
+    surrounding that span. -->
+
+<div id="textbox" tabindex="0" role="textbox" aria-multiline="true"
+    contenteditable="true">
+  <div>
+    <span id="line1">&nbsp;</span>
+  </div>
+  <p>
+    <span id="line2">Apple</span>
+  </p>
+  <ul>
+    <li>
+      <p role="presentation">
+        <span id="line3">Banana</span>
+      </p>
+    </li>
+  </ul>
+</div>
+
+<script>
+'use strict';
+
+function verifySelection(anchorObject, anchorOffset, focusObject, focusOffset,
+    selectionString) {
+  const axTextBox = accessibilityController.accessibleElementById('textbox');
+  assert_equals(axTextBox.selectionAnchorObject, anchorObject, 'anchorObject');
+  assert_equals(axTextBox.selectionAnchorOffset, anchorOffset, 'anchorOffset');
+  assert_equals(axTextBox.selectionFocusObject, focusObject, 'focusObject');
+  assert_equals(axTextBox.selectionFocusOffset, focusOffset, 'focusOffset');
+  assert_equals(getSelection().toString(), selectionString,
+      'getSelection.toString()');
+}
+
+async_test((t) => {
+  const axTextBox = accessibilityController.accessibleElementById('textbox');
+  assert_not_equals(undefined, axTextBox);
+
+  // The &nbsp; on line one is found in the first text child of the first span.
+  const axLine1 = accessibilityController.accessibleElementById('line1').childAtIndex(0);
+  assert_not_equals(undefined, axLine1);
+
+  // Line two starts at the paragraph that contains 'Apple'.
+  const axLine2 = accessibilityController.accessibleElementById('line2').parentElement();
+  assert_not_equals(undefined, axLine2);
+
+  // Line three starts at the presentational paragraph that contains 'Apple'.
+  const axLine3 = accessibilityController.accessibleElementById('line3').parentElement();
+  assert_not_equals(undefined, axLine3);
+  const axLine3Text = accessibilityController.accessibleElementById('line3').childAtIndex(0);
+  assert_not_equals(undefined, axLine3Text);
+
+  let selectedTextChangedCount = 0;
+  const expectedSelection = [];
+  const expectedIntents = [];
+  const testSteps = [];
+
+  axTextBox.setNotificationListener(t.step_func((notification, intents) => {
+    if (notification == "SelectedTextChanged") {
+      verifySelection(expectedSelection[selectedTextChangedCount].anchorObject,
+          expectedSelection[selectedTextChangedCount].anchorOffset,
+          expectedSelection[selectedTextChangedCount].focusObject,
+          expectedSelection[selectedTextChangedCount].focusOffset,
+          expectedSelection[selectedTextChangedCount].selectedText);
+      assert_array_equals(intents, [expectedIntents[selectedTextChangedCount]]);
+      ++selectedTextChangedCount;
+      t.step(testSteps[selectedTextChangedCount]);
+    }
+  }));
+
+  testSteps.push((t) => {
+    expectedSelection.push({
+      anchorObject: axTextBox,
+      anchorOffset: 0,
+      focusObject: axTextBox,
+      focusOffset: 0,
+      selectedText: ''});
+    expectedIntents.push('AXEventIntent(setSelection,character,forward)');
+
+    const textBox = document.getElementById('textbox');
+    textBox.focus();
+  });
+
+  testSteps.push(() => {
+    expectedSelection.push({
+      anchorObject: axLine1,
+      anchorOffset: 0,
+      focusObject: axLine2,
+      focusOffset: 0,
+      selectedText: '\xA0\n'});  // '\xA0' == &nbsp;
+    expectedIntents.push('AXEventIntent(extendSelection,lineEnd,forward)');
+
+    eventSender.keyDown('ArrowDown', ['shiftKey']);
+  });
+
+  testSteps.push(() => {
+    expectedSelection.push({
+      anchorObject: axLine1,
+      anchorOffset: 0,
+      focusObject: axLine3,
+      focusOffset: 0,
+      selectedText: '\xA0\nApple\n\n'});
+    expectedIntents.push('AXEventIntent(extendSelection,lineEnd,forward)');
+
+    eventSender.keyDown('ArrowDown', ['shiftKey']);
+  });
+
+  testSteps.push(() => {
+    expectedSelection.push({
+      anchorObject: axLine1,
+      anchorOffset: 0,
+      focusObject: axLine3Text,
+      focusOffset: 6,
+      selectedText: '\xA0\nApple\n\nBanana'});
+    expectedIntents.push('AXEventIntent(extendSelection,lineEnd,forward)');
+
+    eventSender.keyDown('ArrowDown', ['shiftKey']);
+  });
+
+  testSteps.push(() => {
+    t.done();
+  });
+
+  runAfterLayoutAndPaint(testSteps[0]);
+}, 'Selecting by line works properly when there are ignored objects at the beginning of the line.');
+
+</script>
diff --git a/third_party/blink/web_tests/editing/caret/empty_editables.html b/third_party/blink/web_tests/editing/caret/empty_editables.html
new file mode 100644
index 0000000..255c4c5
--- /dev/null
+++ b/third_party/blink/web_tests/editing/caret/empty_editables.html
@@ -0,0 +1,48 @@
+<!doctype html>
+<script src="../../resources/ahem.js"></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
+<script>
+const kLineHeight = 20;
+const kStyle = `font: 10px/${kLineHeight}px Ahem;`;
+
+function checkHeight(content, expectedHeight = kLineHeight) {
+    const sample = [
+        `<div contenteditable id="target" style="${kStyle}">|`,
+        content,
+        '</div>',
+    ].join('');
+
+    selection_test(
+        sample,
+        selection => {
+            const target = selection.document.getElementById('target');
+            assert_equals(target.offsetHeight, expectedHeight);
+        },
+        sample,
+        `Height of <editable>${content}</editable> is ${expectedHeight}px.`);
+}
+
+
+checkHeight('');
+checkHeight('<div></div>', 0);
+checkHeight('<div style="display:inline-block"></div>', 0);
+checkHeight('<div style="display:inline-block; height: 10px;"></div>', 10);
+checkHeight('<div style="float:left"></div>');
+checkHeight('<div style="float:left">x</div>');
+checkHeight('<div style="position:absolute"></div>');
+checkHeight('<div style="position:absolute">x</div>');
+checkHeight('<div style="position:relative"></div>', 0);
+checkHeight('<div style="position:relative">x</div>');
+
+checkHeight('<span></span>');
+checkHeight('<span style="display:inline-block"></span>', 0);
+checkHeight('<span style="display:inline-block; height: 10px;"></span>', 10);
+checkHeight('<span style="float:left"></span>');
+checkHeight('<span style="float:left">x</span>');
+checkHeight('<span style="position:absolute"></span>');
+checkHeight('<span style="position:absolute">x</span>');
+checkHeight('<span style="position:relative"></span>');
+checkHeight('<span style="position:relative">x</span>');
+</script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 273f6ea..a4889544 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -659,6 +659,13 @@
           null,
           {}
          ]
+        ],
+        "template-element-clone-into-inactive-document-crash.html": [
+         "56b199d1eb19a03d22dab427cc3f32a7a38348ae",
+         [
+          null,
+          {}
+         ]
         ]
        }
       }
@@ -795,6 +802,13 @@
       null,
       {}
      ]
+    ],
+    "transformToFragment-on-node-from-inactive-document-crash.html": [
+     "38a62a0a9d9c2979603c68bcea07f48f8ddbd40c",
+     [
+      null,
+      {}
+     ]
     ]
    }
   },
@@ -45156,6 +45170,19 @@
          ],
          {}
         ]
+       ],
+       "svg-as-image.html": [
+        "c2475f3afbf3795ead6e6a94e3299209484865d2",
+        [
+         null,
+         [
+          [
+           "/css/css-layout-api/green-square-ref.html",
+           "=="
+          ]
+         ],
+         {}
+        ]
        ]
       }
      }
@@ -78883,6 +78910,45 @@
      ]
     },
     "css-ruby": {
+     "abs-in-ruby-base-container.html": [
+      "0a4ad8a24cc7c7dcda673f243153e446e21aa475",
+      [
+       null,
+       [
+        [
+         "/css/css-ruby/abs-in-ruby-base-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "abs-in-ruby-base.html": [
+      "bff3a3b748c21000f7f27271660a9965779383c5",
+      [
+       null,
+       [
+        [
+         "/css/css-ruby/abs-in-ruby-base-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "abs-in-ruby-container.html": [
+      "41be48c47a4eed6c5f167765f841613dd450feb7",
+      [
+       null,
+       [
+        [
+         "/css/css-ruby/abs-in-ruby-base-ref.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "block-ruby-001.html": [
       "f6a058807c48dc5c0cfe056a95355f3d234ac0ad",
       [
@@ -124962,6 +125028,19 @@
        {}
       ]
      ],
+     "svg-sourcegraphic-invalidation-001.html": [
+      "2776aa50cf81977f216bfc4e51d041e132f06935",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "svg-unknown-input-001.html": [
       "7789f2a9af4f1492fa6db36b53a72ada151f61d5",
       [
@@ -163454,6 +163533,10 @@
         "dark-frame.html": [
          "11f88db4a0b3e94d620b5a92314c88040210cfae",
          []
+        ],
+        "prefers-color-scheme.svg": [
+         "3afcac70fe9b561280f32d53420404a3cf23e1cf",
+         []
         ]
        }
       }
@@ -177318,6 +177401,10 @@
       "b0098caea13c61def740fa706be68efb74b3bd9b",
       []
      ],
+     "abs-in-ruby-base-ref.html": [
+      "0c7f57b1d795ef1f61ee5a8387466db0bc8db37d",
+      []
+     ],
      "block-ruby-001-ref.html": [
       "b8d851fb532107b8d3e7fd792438295577b6ac23",
       []
@@ -189612,6 +189699,10 @@
       "f6d43bebfad6b9dd6715dc4326d4cdbe0eda7902",
       []
      ],
+     "prefers-color-scheme-expected.txt": [
+      "f70ee0d165ac3b2d36742da6642d617f86d9c3dd",
+      []
+     ],
      "prefers-reduced-data-expected.txt": [
       "203c98f13b194cf7b2595ddec53c907de1bed029",
       []
@@ -201762,17 +201853,41 @@
       "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
       []
      ],
+     "reporting-coop-navigated-popup.https.html.sub.headers": [
+      "b4d5d16cf8d5163549af0a1fc4c3148bc5b9b02e",
+      []
+     ],
+     "reporting-popup-same-origin-allow-popups-report-to.https.html.headers": [
+      "bcc03a6fa38bc83ff3eb1333fdb5615d9c140e9f",
+      []
+     ],
+     "reporting-popup-same-origin-coep-report-to.https.html.headers": [
+      "fb5526fbdac60fed12455459d6ae872d8a444ff3",
+      []
+     ],
+     "reporting-popup-same-origin-report-to.https.html.sub.headers": [
+      "3850783812d3ad31402ef7ae14def5a9028c68ca",
+      []
+     ],
+     "reporting-popup-same-origin.https.html.headers": [
+      "46ad58d83bf6e98913ca4c564b7acb8f19fa0093",
+      []
+     ],
+     "reporting-popup-unafe-none-report-to.https.html.headers": [
+      "d6a6e7ecdcd131f202111f55c22d2bb1e13ead03",
+      []
+     ],
      "resources": {
       "call-functionCalledByOpenee.html": [
        "d0ff0b723e0f31c6ed635db95851769a598ce2a1",
        []
       ],
       "common.js": [
-       "fb517e8c40ac56587f21ecec2af7a5c30c3a191a",
+       "8a3cd133734dc38d18c190c77c8ebc947c260030",
        []
       ],
       "coop-coep.py": [
-       "8a7e0bc0a838fd7b432f40614212cfa63752a0e6",
+       "03fe6ccb1b96ce2e9c9ee7904013f0bcc7dbf6fb",
        []
       ],
       "iframe-popup.sub.html": [
@@ -201791,6 +201906,14 @@
        "4e798cd9f5d3f756df077a43ce9a1a6f9b41fd28",
        []
       ],
+      "report.py": [
+       "c9ea353a12fb1879508223993c11f8ed97a3cc18",
+       []
+      ],
+      "reporting-common.js": [
+       "d834c080e44787a335bc6ed525e482dda0c94ed3",
+       []
+      ],
       "universal-worker.js": [
        "244167937219cfd784f13d8ed37eedead64665e9",
        []
@@ -216306,7 +216429,11 @@
     "xfo": {
      "resources": {
       "xfo-deny.asis": [
-       "429a40e559abeb5cf6512fe4133b7d20b806e832",
+       "7779830852a3da3b3776043dfe9396bd6457f59f",
+       []
+      ],
+      "xfo-sameorigin.asis": [
+       "8f3982bd841ab883808af17345ba5ca037539842",
        []
       ]
      }
@@ -223917,7 +224044,7 @@
       []
      ],
      "manifest.py": [
-      "47a33121113623baefc7542a2ea7c62edc270297",
+      "c0832d7475175131e1755ab2dcd28b612c47b886",
       []
      ],
      "sourcefile.py": [
@@ -224002,7 +224129,7 @@
      ]
     },
     "requirements_flake8.txt": [
-     "ae16be3955fbf3d5fa9648967c6c8d397519013d",
+     "ae3e4f4b5a64e692fa9c2992f12dcaa0ca582cc2",
      []
     ],
     "requirements_mypy.txt": [
@@ -229243,7 +229370,7 @@
         []
        ],
        "executormarionette.py": [
-        "0635e2d1cb2f56688c040f99e2847317dca70244",
+        "494944e23346fe45871a408b8cea44ec3bfa922a",
         []
        ],
        "executoropera.py": [
@@ -229255,7 +229382,7 @@
         []
        ],
        "executorselenium.py": [
-        "96312f3f9f9542fede609e6f99ef93127f122d1a",
+        "b12299c1ff1914a1e5ef39779e5e1d95822bd158",
         []
        ],
        "executorservo.py": [
@@ -229267,7 +229394,7 @@
         []
        ],
        "executorwebdriver.py": [
-        "2e31f46309133e21b81055b3eb2438caac918b76",
+        "ea26fbcd20dda44f13bb500e10bb059c262bc4da",
         []
        ],
        "executorwebkit.py": [
@@ -229279,7 +229406,7 @@
         []
        ],
        "protocol.py": [
-        "e2a9154e3fbedd319ebe7a8fc3460eb0e53b8d0e",
+        "3f0e44339f9b5499b22e40fc5c4ee4e044691478",
         []
        ],
        "pytestrunner": {
@@ -229311,6 +229438,10 @@
        "testharness_webdriver_resume.js": [
         "36d086c9747a56ca7122c899cfcb46d00dd60b15",
         []
+       ],
+       "window-loaded.js": [
+        "78d73285a441609d597c33832a5dfc34f6b4a684",
+        []
        ]
       },
       "expected.py": [
@@ -233009,7 +233140,7 @@
       []
      ],
      "simple_handshake_wsh.py": [
-      "a612a1a833d93758175d0b9d2e4afa18e7ba2e91",
+      "ad466877fe045be36bfebdcfb30026f2245deae9",
       []
      ],
      "sleep_10_v13_wsh.py": [
@@ -249471,7 +249602,7 @@
      ]
     ],
     "idlharness.https.any.js": [
-     "65688bb878cb9343f60f0c07a7fd8c95dedd99fc",
+     "3e3ee9e7c4cb43afc84eab85a98fd8d5f11adeb1",
      [
       "badging/idlharness.https.any.html",
       {
@@ -249483,8 +249614,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ],
      [
@@ -249498,8 +249634,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ]
@@ -249576,7 +249717,7 @@
      ]
     ],
     "idlharness.https.window.js": [
-     "b33c82e426c7fe35c6c54a649d12685d3419d9e7",
+     "8113d9e7796387c690ca518434c4dd77e9ed0402",
      [
       "battery-status/idlharness.https.window.html",
       {
@@ -249588,8 +249729,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ]
@@ -260407,7 +260553,7 @@
      ]
     ],
     "idlharness.https.window.js": [
-     "789643e2369fca0baed12579bc0cfb23f943f61e",
+     "26d7c493b045399871fa9b941e0e5a03208d2454",
      [
       "credential-management/idlharness.https.window.html",
       {
@@ -260419,8 +260565,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ],
@@ -268778,6 +268929,48 @@
       ]
      ],
      "layout-algorithm": {
+      "baseline-alignment-affects-intrinsic-size-001.html": [
+       "d48e9aefcc6228cdb8c239966dde7d8aafdaac6e",
+       [
+        null,
+        {}
+       ]
+      ],
+      "baseline-alignment-affects-intrinsic-size-002.html": [
+       "8732d2f77fe43cdf2f41485fe71150afb7dd99ad",
+       [
+        null,
+        {}
+       ]
+      ],
+      "baseline-alignment-affects-intrinsic-size-003.html": [
+       "d23c651b6c18971496d5c0cda4fc6f8ac59f5635",
+       [
+        null,
+        {}
+       ]
+      ],
+      "baseline-alignment-affects-intrinsic-size-004.html": [
+       "dbb36cc6d62a7d952aacc181a6d726212a549bf8",
+       [
+        null,
+        {}
+       ]
+      ],
+      "baseline-alignment-affects-intrinsic-size-005.html": [
+       "76e52a2f7d62c6dd84d5699ac298b494481c780e",
+       [
+        null,
+        {}
+       ]
+      ],
+      "baseline-alignment-affects-intrinsic-size-006.html": [
+       "c2d99ca83a59ba05b0998e974e90ca888fcb30d2",
+       [
+        null,
+        {}
+       ]
+      ],
       "flex-and-intrinsic-sizes-001.html": [
        "5144450dd8cb6106768d55088bd4900405be05ce",
        [
@@ -284927,7 +285120,7 @@
       ]
      ],
      "prefers-color-scheme.html": [
-      "c6ca45ab17201466e01006cab78331a0765cc6c8",
+      "594003b1183ee81e9d3d61611166c8a365665f24",
       [
        null,
        {}
@@ -307981,7 +308174,7 @@
      ]
     ],
     "forced-colors-mode-20.html": [
-     "6e9ef2f9c1c7653c2fd52550bd2ea0997adc58bf",
+     "b0cf9e2b49245d3a0298d0b06b89bc7a23428dc5",
      [
       null,
       {}
@@ -328911,6 +329104,58 @@
         "timeout": "long"
        }
       ]
+     ],
+     "reporting-coop-navigated-popup.https.html": [
+      "8642a0aba710ba2903a85f9fd12b5d23e1eb2f7d",
+      [
+       null,
+       {}
+      ]
+     ],
+     "reporting-popup-same-origin-allow-popups-report-to.https.html": [
+      "678fe83a9a7db86cb8939cb16cbb7aefdbb38d72",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
+     "reporting-popup-same-origin-coep-report-to.https.html": [
+      "80a7853ce8803091bf249670b421d208aa7f7b53",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
+     "reporting-popup-same-origin-report-to.https.html": [
+      "02f70d5458ac50a8f75040336187cc9b535c7783",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
+     "reporting-popup-same-origin.https.html": [
+      "a2ed37e46752ebcdc0c12494e7535269f7ddd40a",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
+     ],
+     "reporting-popup-unafe-none-report-to.https.html": [
+      "62eb006586478a1a91b3421e0e9d11a2a0e7666c",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
      ]
     },
     "dom": {
@@ -356027,7 +356272,7 @@
    },
    "permissions-request": {
     "idlharness.any.js": [
-     "c40868f0e92ad4886cd82e62b9c6e574ef95a927",
+     "b393b1b78af2401f1fad4a2c8e2831f604d000c8",
      [
       "permissions-request/idlharness.any.html",
       {
@@ -356039,8 +356284,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ],
      [
@@ -356054,8 +356304,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ]
@@ -357444,6 +357699,15 @@
         "timeout": "long"
        }
       ]
+     ],
+     "portals-xfo-sameorigin.html": [
+      "24824767826af4f7a7789400bc0b3a58a3a2fc8e",
+      [
+       null,
+       {
+        "timeout": "long"
+       }
+      ]
      ]
     }
    },
@@ -369121,7 +369385,7 @@
    },
    "screen-wake-lock": {
     "idlharness.https.window.js": [
-     "275454248f5792b89883d67944ba5f46158c58a1",
+     "b5eaa14efe2bcd6f686467e86d7832e4804f8710",
      [
       "screen-wake-lock/idlharness.https.window.html",
       {
@@ -369141,8 +369405,13 @@
         [
          "script",
          "/resources/testdriver-vendor.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ],
@@ -382945,42 +383214,42 @@
      ]
     ],
     "eval-csp-no-tt.tentative.html": [
-     "e8ed57708ef158d36cff2c0d0883910c84bb75e8",
+     "6720d80fe762b3b2f4b5507f91d57d9d6a43374b",
      [
       null,
       {}
      ]
     ],
     "eval-csp-tt-default-policy.tentative.html": [
-     "106a024f2c1a8f4e2b2e99d2f15a81457179d807",
+     "2ec1422d57bd31ae4a40746ed518dc9ae038f48a",
      [
       null,
       {}
      ]
     ],
     "eval-csp-tt-no-default-policy.tentative.html": [
-     "2f1e2a281b8859c0bda41f78818da4b48a2b46b5",
+     "983dd5601a4da3444c311e552b824463307eae96",
      [
       null,
       {}
      ]
     ],
     "eval-no-csp-no-tt-default-policy.tentative.html": [
-     "84c224eac28f6b26d4c0a15d7390185a576df716",
+     "d36afbc8ac429516a4baab6816281b1a54308eee",
      [
       null,
       {}
      ]
     ],
     "eval-no-csp-no-tt.tentative.html": [
-     "45086a1d6abdec58df8f3d5de5421bab0a2162a5",
+     "3013c084470767a88dc5df3e93e8fdb9b19d9bc3",
      [
       null,
       {}
      ]
     ],
     "eval-with-permissive-csp.tentative.html": [
-     "abc698a46d31569cd105776b1c933d71c8bebf78",
+     "51bb0aaa188c48990c49e085c48842336c34fc6d",
      [
       null,
       {}
@@ -385745,7 +386014,7 @@
      ]
     ],
     "idlharness.any.js": [
-     "d1cb9b57a780143296a70c98579e3c816bfaad81",
+     "511f2d0455b833a895ae9e52230ef82681851142",
      [
       "user-timing/idlharness.any.html",
       {
@@ -385761,8 +386030,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ],
      [
@@ -385780,8 +386054,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ],
      [
@@ -385799,8 +386078,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ],
      [
@@ -385818,8 +386102,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ],
@@ -386156,7 +386445,7 @@
    },
    "video-rvfc": {
     "idlharness.window.js": [
-     "71fa6e0a3b9e8bd296ab6d5835ba8a166130b29c",
+     "fa9e4e0988bf67c88dccd297cf564bb97d5de6bd",
      [
       "video-rvfc/idlharness.window.html",
       {
@@ -386168,8 +386457,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ],
@@ -393544,7 +393838,7 @@
    },
    "webmidi": {
     "idlharness.https.window.js": [
-     "5fb88073b169cfac1d8353e5e8416bdd46ceab0e",
+     "5e1043772058c0bb60d666fc400970f59c76d0d1",
      [
       "webmidi/idlharness.https.window.html",
       {
@@ -393556,8 +393850,13 @@
         [
          "script",
          "/resources/idlharness.js"
+        ],
+        [
+         "timeout",
+         "long"
         ]
-       ]
+       ],
+       "timeout": "long"
       }
      ]
     ]
@@ -398113,7 +398412,7 @@
       ]
      ],
      "005.html": [
-      "c55cd655cfec59ee1a56ee9d1e08226363d658f4",
+      "e7cec47eae17a0049b26f2d925be09fac00207e8",
       [
        null,
        {}
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/support/prefers-color-scheme.svg b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/support/prefers-color-scheme.svg
new file mode 100644
index 0000000..3afcac70
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/support/prefers-color-scheme.svg
@@ -0,0 +1,10 @@
+<svg xmlns="http://www.w3.org/2000/svg" width='100px' height='100px'>
+  <style>
+    @media (prefers-color-scheme: dark) {
+      rect {
+        fill: green;
+      }
+    }
+  </style>
+  <rect fill='blue' width='100px' height='100px' />
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/svg-as-image.html b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/svg-as-image.html
new file mode 100644
index 0000000..c2475f3a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-color-adjust/rendering/dark-color-scheme/svg-as-image.html
@@ -0,0 +1,7 @@
+<!doctype html>
+<head>
+  <title>prefers-color-scheme inside an SVG image</title>
+  <link rel="help" href="https://www.w3.org/TR/mediaqueries-5/#descdef-media-prefers-color-scheme">
+  <link rel="match" href="../../../css-layout-api/green-square-ref.html">
+</head>
+<img src='support/prefers-color-scheme.svg'>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-001.html
new file mode 100644
index 0000000..d48e9ae
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-001.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: evaluate how the baseline affects the grid intrinsic size</title>
+<link rel="author" title="Javier Fernandez" href="mailto:jfernandez@igalia.com">
+<link rel="help" href="https://drafts.csswg.org/css-grid/#alignment">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#baseline-align-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#align-by-baseline">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="/css/support/alignment.css">
+<link rel="stylesheet" href="/css/support/grid.css">
+<meta name="assert" content="The grid intrinsic size is comptuted correctly, considering the effect of baseline alignment in the size of the column tracks"/>
+<style>
+.grid {
+   position: relative;
+   background: grey;
+   float: left;
+   margin: 5px;
+   text-orientation: sideways;
+   height: 350px;
+   font-family: Ahem;
+   line-height: 1;
+   grid-auto-flow: row;
+}
+.grid > :nth-child(1) { font-size:20px; }
+.grid > :nth-child(2) { font-size:30px; }
+.grid > :nth-child(3) { font-size:50px; }
+.grid > :nth-child(4) { font-size:60px; }
+.item {
+   border-width: 2px 5px 3px 4px;
+   border-style: solid;
+   padding: 6px 3px 7px 8px;
+   margin: 10px 6px 4px 12px;
+}
+.extraLeftPadding { padding-left: 50px; }
+.extraRightPadding { padding-right: 50px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script type="text/javascript">
+  setup({ explicit_done: true });
+</script>
+
+<body onload="document.fonts.ready.then(() => { runTests(); })">
+
+<p>Horizontal 4x1 grid with parallel and orthogonal items.</p>
+<div id="grid1" class="grid contentStart itemsBaseline" data-expected-width="98">
+    <div class="item"                             data-offset-x="12" data-offset-y="10"  data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item verticalLR"                  data-offset-x="18" data-offset-y="62"  data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item"                             data-offset-x="12" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalLR"                  data-offset-x="12" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid2" class="grid contentStart itemsBaseline" data-expected-width="134">
+    <div class="item extraRightPadding"           data-offset-x="12" data-offset-y="10"  data-expected-width="87" data-expected-height="38">É</div>
+    <div class="item verticalLR extraLeftPadding" data-offset-x="12" data-offset-y="62"  data-expected-width="92" data-expected-height="48">É</div>
+    <div class="item"                             data-offset-x="12" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalLR"                  data-offset-x="48" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid3" class="grid contentStart itemsBaseline" data-expected-width="98">
+    <div class="item"                             data-offset-x="12" data-offset-y="10"  data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item verticalRL"                  data-offset-x="18" data-offset-y="62"  data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item"                             data-offset-x="12" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalRL"                  data-offset-x="12" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid4" class="grid contentStart itemsBaseline" data-expected-width="134">
+    <div class="item extraRightPadding"           data-offset-x="12" data-offset-y="10"  data-expected-width="87" data-expected-height="38">É</div>
+    <div class="item verticalRL extraLeftPadding" data-offset-x="12" data-offset-y="62"  data-expected-width="92" data-expected-height="48">É</div>
+    <div class="item"                             data-offset-x="12" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalRL"                  data-offset-x="48" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+
+<br clear="all">
+
+<script>
+    "use strict";
+    function runTests() {
+
+        let values = [ "auto", "min-content", "max-content" ];
+        let minValues = values.concat([ "0px" ]);
+
+        var grid1 = document.getElementById("grid1");
+        var grid2 = document.getElementById("grid2");
+        var grid3 = document.getElementById("grid3");
+        var grid4 = document.getElementById("grid4");
+
+        minValues.forEach(function (minValue) {
+            values.forEach(function (maxValue) {
+
+                grid1.id = "grid1-" + minValue + "-" + maxValue
+                grid2.id = "grid2-" + minValue + "-" + maxValue
+                grid3.id = "grid3-" + minValue + "-" + maxValue
+                grid4.id = "grid4-" + minValue + "-" + maxValue
+
+                grid1.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid2.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid3.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid4.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+
+                checkLayout("#" + grid1.id, false);
+                checkLayout("#" + grid2.id, false);
+                checkLayout("#" + grid3.id, false);
+                checkLayout("#" + grid4.id, false);
+            });
+        });
+
+        done();
+    }
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-002.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-002.html
new file mode 100644
index 0000000..8732d2f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-002.html
@@ -0,0 +1,110 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: evaluate how the baseline affects the grid intrinsic size</title>
+<link rel="author" title="Javier Fernandez" href="mailto:jfernandez@igalia.com">
+ <link rel="help" href="https://drafts.csswg.org/css-grid/#alignment">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#baseline-align-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#align-by-baseline">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="/css/support/alignment.css">
+<link rel="stylesheet" href="/css/support/grid.css">
+<meta name="assert" content="The grid intrinsic size is comptuted correctly, considering the effect of baseline alignment in the size of the column tracks" />
+<style>
+.grid {
+   position: relative;
+   background: grey;
+   float: left;
+   margin: 5px;
+   text-orientation: sideways;
+   height: 350px;
+   font-family: Ahem;
+   line-height: 1;
+   grid-auto-flow: row;
+}
+.grid > :nth-child(1) { font-size:20px; }
+.grid > :nth-child(2) { font-size:30px; }
+.grid > :nth-child(3) { font-size:50px; }
+.grid > :nth-child(4) { font-size:60px; }
+.item {
+   border-width: 2px 5px 3px 4px;
+   border-style: solid;
+   padding: 6px 3px 7px 8px;
+   margin: 10px 6px 4px 12px;
+}
+.extraLeftPadding { padding-left: 50px; }
+.extraRightPadding { padding-right: 50px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script type="text/javascript">
+  setup({ explicit_done: true });
+</script>
+
+<body onload="document.fonts.ready.then(() => { runTests(); })">
+
+<p>4x1 with orthogonal items.</p>
+<div id="grid1" class="grid contentStart itemsBaseline" data-expected-width="98">
+    <div class="item verticalLR"                   data-offset-x="20" data-offset-y="10"  data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item verticalLR"                   data-offset-x="18" data-offset-y="62"  data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item verticalLR"                   data-offset-x="14" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalLR"                   data-offset-x="12" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid2" class="grid contentStart itemsBaseline" data-expected-width="149">
+    <div class="item verticalLR extraRightPadding" data-offset-x="56" data-offset-y="10"  data-expected-width="87" data-expected-height="38">É</div>
+    <div class="item verticalLR extraLeftPadding"  data-offset-x="12" data-offset-y="62"  data-expected-width="92" data-expected-height="48">É</div>
+    <div class="item verticalLR"                   data-offset-x="50" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalLR"                   data-offset-x="48" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid3" class="grid contentStart itemsBaseline" data-expected-width="98">
+    <div class="item verticalRL"                   data-offset-x="20" data-offset-y="10"  data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item verticalRL"                   data-offset-x="18" data-offset-y="62"  data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item verticalRL"                   data-offset-x="14" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalRL"                   data-offset-x="12" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid4" class="grid contentStart itemsBaseline" data-expected-width="149">
+    <div class="item verticalRL extraRightPadding" data-offset-x="56" data-offset-y="10"  data-expected-width="87" data-expected-height="38">É</div>
+    <div class="item verticalRL extraLeftPadding"  data-offset-x="12" data-offset-y="62"  data-expected-width="92" data-expected-height="48">É</div>
+    <div class="item verticalRL"                   data-offset-x="50" data-offset-y="124" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item verticalRL"                   data-offset-x="48" data-offset-y="206" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+
+<br clear="all">
+
+<script>
+    "use strict";
+    function runTests() {
+
+        let values = [ "auto", "min-content", "max-content" ];
+        let minValues = values.concat([ "0px" ]);
+
+        var grid1 = document.getElementById("grid1");
+        var grid2 = document.getElementById("grid2");
+        var grid3 = document.getElementById("grid3");
+        var grid4 = document.getElementById("grid4");
+
+        minValues.forEach(function (minValue) {
+            values.forEach(function (maxValue) {
+
+                grid1.id = "grid1-" + minValue + "-" + maxValue
+                grid2.id = "grid2-" + minValue + "-" + maxValue
+                grid3.id = "grid3-" + minValue + "-" + maxValue
+                grid4.id = "grid4-" + minValue + "-" + maxValue
+
+                grid1.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid2.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid3.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid4.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+
+                checkLayout("#" + grid1.id, false);
+                checkLayout("#" + grid2.id, false);
+                checkLayout("#" + grid3.id, false);
+                checkLayout("#" + grid4.id, false);
+            });
+        });
+
+        done();
+    }
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-003.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-003.html
new file mode 100644
index 0000000..d23c651
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-003.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: evaluate how the baseline affects the grid intrinsic size</title>
+<link rel="author" title="Javier Fernandez" href="mailto:jfernandez@igalia.com">
+ <link rel="help" href="https://drafts.csswg.org/css-grid/#alignment">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#baseline-align-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#align-by-baseline">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="/css/support/alignment.css">
+<link rel="stylesheet" href="/css/support/grid.css">
+<meta name="assert" content="The grid intrinsic size is comptuted correctly, considering the effect of baseline alignment in the size of the column tracks"/>
+<style>
+body { margin: 0; }
+.grid {
+   position: relative;
+   background: grey;
+   float: left;
+   margin: 5px;
+   text-orientation: sideways;
+   width: 350px;
+   font-family: Ahem;
+   line-height: 1;
+   grid-auto-flow: row;
+}
+.grid > :nth-child(1) { font-size:20px; }
+.grid > :nth-child(2) { font-size:30px; }
+.grid > :nth-child(3) { font-size:50px; }
+.grid > :nth-child(4) { font-size:60px; }
+.item {
+   border-width: 2px 5px 3px 4px;
+   border-style: solid;
+   padding: 6px 3px 7px 8px;
+   margin: 10px 6px 4px 12px;
+}
+.extraTopPadding { padding-top: 50px; }
+.extraBottomPadding { padding-bottom: 50px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script type="text/javascript">
+  setup({ explicit_done: true });
+</script>
+
+<body onload="document.fonts.ready.then(() => { runTests(); })">
+
+<p>Vertical LR 4x1 grid with parallel and orthogonal items.</p>
+<div id="grid1" class="grid verticalLR contentStart itemsBaseline" data-expected-height="92">
+    <div class="item"                                 data-offset-x="12"  data-offset-y="10"  data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item horizontalTB"                    data-offset-x="70"  data-offset-y="34"  data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item"                                 data-offset-x="138" data-offset-y="10"  data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="226" data-offset-y="10"  data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid2" class="grid verticalLR contentStart itemsBaseline" data-expected-height="129">
+    <div class="item extraTopPadding"                 data-offset-x="12"  data-offset-y="10"  data-expected-width="40" data-expected-height="82">É</div>
+    <div class="item horizontalTB extraBottomPadding" data-offset-x="70"  data-offset-y="34"  data-expected-width="50" data-expected-height="91">É</div>
+    <div class="item"                                 data-offset-x="138" data-offset-y="10"  data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="226" data-offset-y="10"  data-expected-width="80" data-expected-height="78">É</div>
+</div>
+
+<br clear="all">
+
+<script>
+    "use strict";
+    function runTests() {
+
+        let values = [ "auto", "min-content", "max-content" ];
+        let minValues = values.concat([ "0px" ]);
+
+        var grid1 = document.getElementById("grid1");
+        var grid2 = document.getElementById("grid2");
+
+        minValues.forEach(function (minValue) {
+            values.forEach(function (maxValue) {
+
+                grid1.id = "grid1-" + minValue + "-" + maxValue
+                grid2.id = "grid2-" + minValue + "-" + maxValue
+
+                grid1.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid2.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+
+                checkLayout("#" + grid1.id, false);
+                checkLayout("#" + grid2.id, false);
+            });
+        });
+
+        done();
+    }
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-004.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-004.html
new file mode 100644
index 0000000..dbb36cc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-004.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: evaluate how the baseline affects the grid intrinsic size</title>
+<link rel="author" title="Javier Fernandez" href="mailto:jfernandez@igalia.com">
+ <link rel="help" href="https://drafts.csswg.org/css-grid/#alignment">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#baseline-align-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#align-by-baseline">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="/css/support/alignment.css">
+<link rel="stylesheet" href="/css/support/grid.css">
+<meta name="assert" content="The grid intrinsic size is comptuted correctly, considering the effect of baseline alignment in the size of the column tracks"/>
+<style>
+.grid {
+   position: relative;
+   background: grey;
+   float: left;
+   margin: 5px;
+   text-orientation: sideways;
+   width: 350px;
+   font-family: Ahem;
+   line-height: 1;
+   grid-auto-flow: row;
+}
+.grid > :nth-child(1) { font-size:20px; }
+.grid > :nth-child(2) { font-size:30px; }
+.grid > :nth-child(3) { font-size:50px; }
+.grid > :nth-child(4) { font-size:60px; }
+.item {
+   border-width: 2px 5px 3px 4px;
+   border-style: solid;
+   padding: 6px 3px 7px 8px;
+   margin: 10px 6px 4px 12px;
+}
+.extraTopPadding { padding-top: 50px; }
+.extraBottomPadding { padding-bottom: 50px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script type="text/javascript">
+  setup({ explicit_done: true });
+</script>
+
+<body onload="document.fonts.ready.then(() => { runTests(); })">
+
+<p>Vertical RL 4x1 grid with parallel and orthogonal items.</p>
+<div id="grid1" class="grid verticalRL contentStart itemsBaseline" data-expected-height="92">
+    <div class="item"                                 data-offset-x="304" data-offset-y="10"  data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item horizontalTB"                    data-offset-x="236" data-offset-y="34"  data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item"                                 data-offset-x="148" data-offset-y="10"  data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="50"  data-offset-y="10"  data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid2" class="grid verticalRL contentStart itemsBaseline" data-expected-height="129">
+    <div class="item extraTopPadding"                 data-offset-x="304" data-offset-y="10"  data-expected-width="40" data-expected-height="82">É</div>
+    <div class="item horizontalTB extraBottomPadding" data-offset-x="236" data-offset-y="34"  data-expected-width="50" data-expected-height="91">É</div>
+    <div class="item"                                 data-offset-x="148" data-offset-y="10"  data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="50"  data-offset-y="10"  data-expected-width="80" data-expected-height="78">É</div>
+</div>
+
+<br clear="all">
+
+<script>
+    "use strict";
+    function runTests() {
+
+        let values = [ "auto", "min-content", "max-content" ];
+        let minValues = values.concat([ "0px" ]);
+
+        var grid1 = document.getElementById("grid1");
+        var grid2 = document.getElementById("grid2");
+
+        minValues.forEach(function (minValue) {
+            values.forEach(function (maxValue) {
+
+                grid1.id = "grid1-" + minValue + "-" + maxValue
+                grid2.id = "grid2-" + minValue + "-" + maxValue
+
+                grid1.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid2.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+
+                checkLayout("#" + grid1.id, false);
+                checkLayout("#" + grid2.id, false);
+            });
+        });
+
+        done();
+    }
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-005.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-005.html
new file mode 100644
index 0000000..76e52a2f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-005.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: evaluate how the baseline affects the grid intrinsic size</title>
+<link rel="author" title="Javier Fernandez" href="mailto:jfernandez@igalia.com">
+ <link rel="help" href="https://drafts.csswg.org/css-grid/#alignment">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#baseline-align-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#align-by-baseline">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="/css/support/alignment.css">
+<link rel="stylesheet" href="/css/support/grid.css">
+<meta name="assert" content="The grid intrinsic size is comptuted correctly, considering the effect of baseline alignment in the size of the column tracks"/>
+<style>
+.grid {
+   position: relative;
+   background: grey;
+   float: left;
+   margin: 5px;
+   text-orientation: sideways;
+   width: 350px;
+   font-family: Ahem;
+   line-height: 1;
+   grid-auto-flow: row;
+}
+.grid > :nth-child(1) { font-size:20px; }
+.grid > :nth-child(2) { font-size:30px; }
+.grid > :nth-child(3) { font-size:50px; }
+.grid > :nth-child(4) { font-size:60px; }
+.item {
+   border-width: 2px 5px 3px 4px;
+   border-style: solid;
+   padding: 6px 3px 7px 8px;
+   margin: 10px 6px 4px 12px;
+}
+.extraTopPadding { padding-top: 50px; }
+.extraBottomPadding { padding-bottom: 50px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script type="text/javascript">
+  setup({ explicit_done: true });
+</script>
+
+<body onload="document.fonts.ready.then(() => { runTests(); })">
+
+<p>Vertical LR 4x1 grid with orthogonal items.</p>
+<div id="grid1" class="grid verticalLR contentStart itemsBaseline" data-expected-height="92">
+    <div class="item horizontalTB"                    data-offset-x="12"  data-offset-y="42" data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item horizontalTB"                    data-offset-x="70"  data-offset-y="34" data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item horizontalTB"                    data-offset-x="138" data-offset-y="18" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="226" data-offset-y="10" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid2" class="grid verticalLR contentStart itemsBaseline" data-expected-height="141">
+    <div class="item horizontalTB extraTopPadding"    data-offset-x="12"  data-offset-y="10" data-expected-width="40" data-expected-height="82">É</div>
+    <div class="item horizontalTB extraBottomPadding" data-offset-x="70"  data-offset-y="46" data-expected-width="50" data-expected-height="91">É</div>
+    <div class="item horizontalTB"                    data-offset-x="138" data-offset-y="30" data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="226" data-offset-y="22" data-expected-width="80" data-expected-height="78">É</div>
+</div>
+
+<br clear="all">
+
+<script>
+    "use strict";
+    function runTests() {
+
+        let values = [ "auto", "min-content", "max-content" ];
+        let minValues = values.concat([ "0px" ]);
+
+        var grid1 = document.getElementById("grid1");
+        var grid2 = document.getElementById("grid2");
+
+        minValues.forEach(function (minValue) {
+            values.forEach(function (maxValue) {
+
+                grid1.id = "grid1-" + minValue + "-" + maxValue
+                grid2.id = "grid2-" + minValue + "-" + maxValue
+
+                grid1.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid2.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+
+                checkLayout("#" + grid1.id, false);
+                checkLayout("#" + grid2.id, false);
+            });
+        });
+
+        done();
+    }
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-006.html b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-006.html
new file mode 100644
index 0000000..c2d99ca
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/layout-algorithm/baseline-alignment-affects-intrinsic-size-006.html
@@ -0,0 +1,90 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>CSS Grid Layout Test: evaluate how the baseline affects the grid intrinsic size</title>
+<link rel="author" title="Javier Fernandez" href="mailto:jfernandez@igalia.com">
+ <link rel="help" href="https://drafts.csswg.org/css-grid/#alignment">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#baseline-align-self">
+<link rel="help" href="https://drafts.csswg.org/css-align-3/#align-by-baseline">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="/css/support/alignment.css">
+<link rel="stylesheet" href="/css/support/grid.css">
+<meta name="assert" content="The grid intrinsic size is comptuted correctly, considering the effect of baseline alignment in the size of the column tracks"/>
+<style>
+.grid {
+   position: relative;
+   background: grey;
+   float: left;
+   margin: 5px;
+   text-orientation: sideways;
+   width: 350px;
+   font-family: Ahem;
+   line-height: 1;
+   grid-auto-flow: row;
+}
+.grid > :nth-child(1) { font-size:20px; }
+.grid > :nth-child(2) { font-size:30px; }
+.grid > :nth-child(3) { font-size:50px; }
+.grid > :nth-child(4) { font-size:60px; }
+.item {
+   border-width: 2px 5px 3px 4px;
+   border-style: solid;
+   padding: 6px 3px 7px 8px;
+   margin: 10px 6px 4px 12px;
+}
+.extraTopPadding { padding-top: 50px; }
+.extraBottomPadding { padding-bottom: 50px; }
+</style>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/check-layout-th.js"></script>
+<script type="text/javascript">
+  setup({ explicit_done: true });
+</script>
+
+<body onload="document.fonts.ready.then(() => { runTests(); })">
+
+<p>Vertical RL 4x1 grid with orthogonal items.</p>
+<div id="grid1" class="grid verticalRL contentStart itemsBaseline" data-expected-height="92">
+    <div class="item horizontalTB"                    data-offset-x="304" data-offset-y="42"  data-expected-width="40" data-expected-height="38">É</div>
+    <div class="item horizontalTB"                    data-offset-x="236" data-offset-y="34"  data-expected-width="50" data-expected-height="48">É</div>
+    <div class="item horizontalTB"                    data-offset-x="148" data-offset-y="18"  data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="50"  data-offset-y="10"  data-expected-width="80" data-expected-height="78">É</div>
+</div>
+<div id="grid2" class="grid verticalRL contentStart itemsBaseline" data-expected-height="141">
+    <div class="item horizontalTB extraTopPadding"    data-offset-x="304" data-offset-y="10"  data-expected-width="40" data-expected-height="82">É</div>
+    <div class="item horizontalTB extraBottomPadding" data-offset-x="236" data-offset-y="46"  data-expected-width="50" data-expected-height="91">É</div>
+    <div class="item horizontalTB"                    data-offset-x="148" data-offset-y="30"  data-expected-width="70" data-expected-height="68">É</div>
+    <div class="item horizontalTB"                    data-offset-x="50"  data-offset-y="22"  data-expected-width="80" data-expected-height="78">É</div>
+</div>
+
+<br clear="all">
+
+<script>
+    "use strict";
+    function runTests() {
+
+        let values = [ "auto", "min-content", "max-content" ];
+        let minValues = values.concat([ "0px" ]);
+
+        var grid1 = document.getElementById("grid1");
+        var grid2 = document.getElementById("grid2");
+
+        minValues.forEach(function (minValue) {
+            values.forEach(function (maxValue) {
+
+                grid1.id = "grid1-" + minValue + "-" + maxValue
+                grid2.id = "grid2-" + minValue + "-" + maxValue
+
+                grid1.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+                grid2.style.gridTemplateColumns = "minmax(" + minValue + ", " + maxValue + ")";
+
+                checkLayout("#" + grid1.id, false);
+                checkLayout("#" + grid2.id, false);
+            });
+        });
+
+        done();
+    }
+</script>
+
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base-container.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base-container.html
new file mode 100644
index 0000000..0a4ad8a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base-container.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Absolutely-positioned element in ruby base container</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#formatting-context">
+<link rel="match" href="abs-in-ruby-base-ref.html">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="support/ruby-common.css">
+<style>
+  .rel { position: relative; }
+  .abs { position: absolute; left: 0; top: -1em; }
+</style>
+<body style="font: 50px/3 Ahem">
+X<ruby><rbc class="rel"><rb><span class="abs">X</span></rb></rbc></ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base-ref.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base-ref.html
new file mode 100644
index 0000000..0c7f57b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>CSS Reference</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+  .rel { position: relative; }
+  .abs { position: absolute; left: 0; top: -1em; }
+</style>
+<body style="font: 50px/3 Ahem">
+X<span class="rel"><span class="abs">X</span></span>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base.html
new file mode 100644
index 0000000..bff3a3b7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-base.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Absolutely-positioned element in ruby base</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#formatting-context">
+<link rel="match" href="abs-in-ruby-base-ref.html">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="support/ruby-common.css">
+<style>
+  .rel { position: relative; }
+  .abs { position: absolute; left: 0; top: -1em; }
+</style>
+<body style="font: 50px/3 Ahem">
+X<ruby><rbc><rb class="rel"><span class="abs">X</span></rb></rbc></ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-container.html b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-container.html
new file mode 100644
index 0000000..41be48c4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-ruby/abs-in-ruby-container.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="UTF-8">
+<title>Absolutely-positioned element in ruby container</title>
+<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
+<link rel="help" href="https://drafts.csswg.org/css-ruby-1/#formatting-context">
+<link rel="match" href="abs-in-ruby-base-ref.html">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="stylesheet" href="support/ruby-common.css">
+<style>
+  .rel { position: relative; }
+  .abs { position: absolute; left: 0; top: -1em; }
+</style>
+<body style="font: 50px/3 Ahem">
+X<ruby class="rel"><rbc><rb><span class="abs">X</span></rb></rbc></ruby>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-sourcegraphic-invalidation-001.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-sourcegraphic-invalidation-001.html
new file mode 100644
index 0000000..2776aa5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-sourcegraphic-invalidation-001.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>SourceGraphic is invalidated when removing element from the document</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#attr-valuedef-in-sourcegraphic">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <filter id="f">
+    <feMerge><feMergeNode/></feMerge>
+  </filter>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="100" fill="green" filter="url(#f)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById('target');
+    let svg = rect.parentNode;
+    rect.remove();
+    rect.setAttribute('width', '100');
+    svg.appendChild(rect);
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-20.html b/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-20.html
index 6e9ef2f9..b0cf9e2 100644
--- a/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-20.html
+++ b/third_party/blink/web_tests/external/wpt/forced-colors-mode/forced-colors-mode-20.html
@@ -8,6 +8,9 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <style>
+  body {
+    background-color: Canvas;
+  }
   div {
     background-color: rgba(114, 173, 218, .3);
   }
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-coop-navigated-popup.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-coop-navigated-popup.https.html
new file mode 100644
index 0000000..8642a0a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-coop-navigated-popup.https.html
@@ -0,0 +1,82 @@
+<title>Cross-Origin-Opener-Policy: a navigated popup with reporting</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/utils.js"></script> <!-- Use token() to allow running tests in parallel -->
+<script src="resources/reporting-common.js"></script>
+
+<script>
+
+// This test does the following:
+//  1 - This document has COOP: same-origin-allow-popups; report-to="coop-report-endpoint"
+//  2 - Open a popup on a same-origin page without COOP, with the coop-popup-report-endpoint
+//  3 - Navigate the popup to a same-origin page with COOP, with the coop-redirect-report-endpoint
+// it verifies that the reports are properly send for the browsing context switch
+// during the navigation in the popup (step 3). The current document (the opener)
+// endpoint should not receive any report as no switch ocurred on 2.
+promise_test( async t => {
+  const popupName = token();
+  const noCoopChannelName = token();
+  const coopChannelName = token();
+  await reportingTest( (resolve) => {
+    const noCOOP = `resources/coop-coep.py?coop=${encodeURIComponent(`unsafe-none; report-to="${popupReportEndpoint.name}"`)}&coep=&channel=${noCoopChannelName}`;
+    const coop = `resources/coop-coep.py?coop=${encodeURIComponent(`same-origin; report-to="${redirectReportEndpoint.name}"`)}&coep=&channel=${coopChannelName}`;
+
+    const popup = window.open(noCOOP, popupName);
+    const channel = new BroadcastChannel(coopChannelName);
+    // Close the popup once the test is complete.
+    // The browsing context is closed after the navigation hence use the
+    // broadcast channel to trigger the closure.
+    t.add_cleanup(() => {
+      channel.postMessage("close");
+    });
+    popup.onload = t.step_func(() => {
+      assert_equals(popup.name.length, popupName.length, "popup name");
+      channel.onmessage = t.step_func(event => {
+        const payload = event.data;
+        // The name should be empty, but we're checking the length rather than a
+        // string comparison to "" to keep the random token out of error messages.
+        assert_equals(payload.name.length, 0, "Popup name after navigation");
+        assert_false(payload.opener, "Opener after navigation");
+        assert_true(popup.closed, "Window proxy closed after navigation");
+        resolve();
+      });
+      popup.location = coop;
+    });
+  },
+  popupName,
+  [
+    // Reports expected for the navigation from "noCOOP" to "coop"
+    {
+      "endpoint": popupReportEndpoint,
+      "report": {
+        "body": {
+          "disposition": "enforce",
+          "document-uri": RegExp(`coop-coep.py?.*channel=${noCoopChannelName}$`),
+          "effective-policy": "unsafe-none",
+          "navigation-uri": RegExp(`coop-coep.py?.*channel=${coopChannelName}$`),
+          "violation-type": "navigation-from-document"
+        },
+        "url": RegExp(`coop-coep.py?.*channel=${noCoopChannelName}$`),
+        "type": "coop"
+      }
+    },
+    {
+      "endpoint": redirectReportEndpoint,
+      "report": {
+        "body": {
+          "disposition": "enforce",
+          "document-uri": RegExp(`coop-coep.py?.*channel=${coopChannelName}$`),
+          "effective-policy": "same-origin",
+          "navigation-uri": RegExp(`coop-coep.py?.*channel=${noCoopChannelName}$`),
+          "violation-type": "navigation-to-document"
+        },
+        "url": RegExp(`coop-coep.py?.*channel=${coopChannelName}$`),
+        "type": "coop"
+      }
+    },
+  ]);
+}, "Open a popup to a document without COOP, then navigate it to a document with");
+
+verifyRemainingReports();
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-coop-navigated-popup.https.html.sub.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-coop-navigated-popup.https.html.sub.headers
new file mode 100644
index 0000000..b4d5d16c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-coop-navigated-popup.https.html.sub.headers
@@ -0,0 +1,2 @@
+Cross-Origin-Opener-Policy: same-origin-allow-popups; report-to="coop-report-endpoint"
+report-to: { "group": "coop-report-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-endpoint" }] }, { "group": "coop-report-only-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-only-endpoint" }]}
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-allow-popups-report-to.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-allow-popups-report-to.https.html
new file mode 100644
index 0000000..678fe83a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-allow-popups-report-to.https.html
@@ -0,0 +1,123 @@
+<meta name=timeout content=long>
+<title>reporting same origin with report-to</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script src="resources/reporting-common.js"></script>
+
+<script>
+
+let tests = [
+  // popup origin, popup COOP, popup COEP, expected opener, expected reports
+
+  // Open a same-origin popup with a same-origin COOP and no COEP. Produces two
+  // reports (one from and one to). Both pages being same origin, the
+  // next/pervious document urls are available.
+  [
+    SAME_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin-allow-popups",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // next document URL
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin",
+            "navigation-uri": `${location.href}`, // previous documnent url
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a cross-origin popup with a same-origin-allow-popup COOP and noCOEP.
+  // Produces two reports (one from and one to). Both pages being cross origin,
+  // the next/pervious document urls are not available and the initial document
+  // url/referrer are used instead.
+  [
+    CROSS_ORIGIN,
+    `same-origin-allow-popups; report-to="${popupReportEndpoint.name}"`,
+    "require-corp",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin-allow-popups",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // initial navigation URL
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin-allow-popups",
+            "navigation-uri": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy)
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a cross-origin popup with a same-origin COOP and COEP, and no reporting.
+  // Produces one navigation-from-report for this document (the opener). The
+  // pages being cross origin, the next/pervious document urls are not available
+  // and the initial document url/referrer are used instead.
+  [
+    CROSS_ORIGIN,
+    `same-origin`,
+    "require-corp",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin-allow-popups",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // initial navigation URL
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+];
+
+runCoopReportingTest(document.title, tests);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-allow-popups-report-to.https.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-allow-popups-report-to.https.html.headers
new file mode 100644
index 0000000..bcc03a6f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-allow-popups-report-to.https.html.headers
@@ -0,0 +1,3 @@
+report-to: { "group": "coop-report-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-endpoint" }] }, { "group": "coop-report-only-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-only-endpoint" }]}
+Cross-Origin-Opener-Policy: same-origin-allow-popups; report-to="coop-report-endpoint"
+Referrer-Policy: origin
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-coep-report-to.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-coep-report-to.https.html
new file mode 100644
index 0000000..80a7853c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-coep-report-to.https.html
@@ -0,0 +1,108 @@
+<meta name=timeout content=long>
+<title>reporting same origin with report-to</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script src="resources/reporting-common.js"></script>
+
+<script>
+
+let tests = [
+  // popup origin, popup COOP, popup COEP, expected opener, expected reports
+
+  // Open and navigate a popup to a same-origin page with the same COOP-COEP
+  // settings: no browsing context group switch hence no report expected.
+  [
+    SAME_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "require-corp",
+    true,
+    []
+  ],
+  // Open a same-origin popup with a same-origin COOP but no COEP. Produces two
+  // reports (one from and one to). The from report has an effective-policy of
+  // same-origin-plus-coep, both pages being same origin, the entire
+  // next/pervious document urls are available.
+  [
+    SAME_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin-plus-coep",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // next destination url
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin",
+            "navigation-uri": `${location.href}`, // previous document url
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a cross-origin popup with a same-origin COOP and COEP.  Produces two
+  // reports (one from and one to). The from report has an effective-policy of
+  // same-origin-plus-coep, both pages being cross origin, the next/pervious
+  // document urls are not available and the initial document url/referrer are
+  // used instead.
+  [
+    CROSS_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "require-corp",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin-plus-coep",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // initial navigation url
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin-plus-coep",
+            "navigation-uri": `${location.origin}/`, // referrer (origin, as dictated by the referrer policy)
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+];
+
+runCoopReportingTest(document.title, tests);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-coep-report-to.https.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-coep-report-to.https.html.headers
new file mode 100644
index 0000000..fb5526f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-coep-report-to.https.html.headers
@@ -0,0 +1,4 @@
+report-to: { "group": "coop-report-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-endpoint" }] }, { "group": "coop-report-only-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-only-endpoint" }]}
+Cross-Origin-Opener-Policy: same-origin; report-to="coop-report-endpoint"
+Cross-Origin-Embedder-Policy: require-corp
+Referrer-Policy: origin
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-report-to.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-report-to.https.html
new file mode 100644
index 0000000..02f70d5
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-report-to.https.html
@@ -0,0 +1,213 @@
+<meta name=timeout content=long>
+<title>reporting same origin with report-to</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script src="resources/reporting-common.js"></script>
+
+<script>
+
+let tests = [
+  // popup origin, popup COOP, popup COEP, expected opener, expected reports
+
+  // Open a popup on a same-origin page, with a compatible COOP.
+  // This is a sanity check that no report are produced.
+  [
+    SAME_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "",
+    true,
+    []
+  ],
+  // Open a cross-origin popup with a same-origin COOP. Produces two
+  // reports (one from and one to). The from report has an effective-policy of
+  // same-origin (corresponding to the current document), both pages being
+  // cross origin, the next/pervious document urls are not available and the
+  // initial document url/referrer are used instead.
+  [
+    CROSS_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // initial navigation URL (equal to the next document url in that case)
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin",
+            "navigation-uri": '', // referrer (empty due to the Referrer Policy)
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a same-origin popup with a unsafe-none COOP and no COEP. COOP switches
+  // the browsing context group and hence produces two reports (one from and one
+  // to). This test verifies that unsafe-none properly sends report.
+  [
+    SAME_ORIGIN,
+    `unsafe-none; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "unsafe-none",
+            "navigation-uri": `${location.href}`,
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a same-origin popup with a same-origin COOP and COEP. The difference
+  // of COEP values leads to the browsing context group switch and produces two
+  // reports. This verifies that the navigation-to-document report has an
+  // effective-policy of same-origin-plus-coep.
+  [
+    SAME_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "require-corp",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // Next document URL
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin-plus-coep",
+            "navigation-uri": `${location.href}`, // Previous document URL
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a cross-origin popup with no COOP (but reporting) and no COEP.
+  // Produces two reports. The pages being cross origin, the next/pervious
+  // document urls are not available and the initial document url/referrer are
+  // used instead.
+  [
+    CROSS_ORIGIN,
+    `unsafe-none; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // initial navigation URL
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "unsafe-none",
+            "navigation-uri": '', // referrer, as per the no-referrer policy.
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a same-origin popup with no COOP (without reporting) and no COEP.
+  // Produces one report to this page (opener) endpoint.
+  // This verifies that the navigated-to-document's COOP report values do not
+  // impact the navigated-from-document's COOP.
+  [
+    SAME_ORIGIN,
+    "unsafe-none",
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "same-origin",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      }
+    ]
+  ]
+];
+
+runCoopReportingTest(document.title, tests);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-report-to.https.html.sub.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-report-to.https.html.sub.headers
new file mode 100644
index 0000000..3850783
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin-report-to.https.html.sub.headers
@@ -0,0 +1,3 @@
+report-to: { "group": "coop-report-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-endpoint" }] }, { "group": "coop-report-only-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-only-endpoint" }]}
+Cross-Origin-Opener-Policy: same-origin; report-to="coop-report-endpoint"
+Referrer-Policy: no-referrer
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin.https.html
new file mode 100644
index 0000000..a2ed37e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin.https.html
@@ -0,0 +1,96 @@
+<meta name=timeout content=long>
+<title>reporting same origin</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script src="resources/reporting-common.js"></script>
+
+<script>
+
+let tests = [
+  // popup origin, popup COOP, popup COEP, expected opener, expected reports
+
+  // Open a cross-origin popup with a same-origin COOP and no COEP. COOP
+  // switches the browsing context group and hence produces one report.
+  // This test verifies that the navigated to document properly sends a
+  // navigation-to report. The navigation-uri is the referrer.
+  [
+    CROSS_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin",
+            "navigation-uri": `${location.href}`, // referrer
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a same-origin popup with a unsafe-none COOP and no COEP. COOP switches
+  // the browsing context group and hence produces one report.
+  // This test verifies that having different policies on same origin documents
+  // still properly produces report to the navigated-to-document.
+  [
+    SAME_ORIGIN,
+    `unsafe-none; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "unsafe-none",
+            "navigation-uri": `${location.href}`,
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a cross-origin popup with a unsafe-none COOP (with reporting) and no
+  // COEP. COOP switches the browsing context group and hence produces one
+  // reports to the unsafe-none document. This test verifies that unsafe-none
+  // properly sends report in that configuration.
+  [
+    CROSS_ORIGIN,
+    `unsafe-none; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "unsafe-none",
+            "navigation-uri": `${location.href}`, // referrer
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ]
+];
+
+runCoopReportingTest(document.title, tests);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin.https.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin.https.html.headers
new file mode 100644
index 0000000..46ad58d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-same-origin.https.html.headers
@@ -0,0 +1 @@
+Cross-Origin-Opener-Policy: same-origin
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-unafe-none-report-to.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-unafe-none-report-to.https.html
new file mode 100644
index 0000000..62eb006
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-unafe-none-report-to.https.html
@@ -0,0 +1,123 @@
+<meta name=timeout content=long>
+<title>reporting same origin with report-to</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/common.js"></script>
+<script src="resources/reporting-common.js"></script>
+
+<script>
+
+let tests = [
+  // popup origin, popup COOP, popup COEP, expected opener, expected reports
+
+  // Open a same-origin popup with a same-origin COOP with reporting and no COEP.
+  // COOP switches the browsing context group and hence produces two reports
+  // (one from and one to). This test verifies that unsafe-none (from the opener)
+  // properly sends a report.
+  [
+    SAME_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "unsafe-none",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // next document URL
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin",
+            "navigation-uri": `${location.href}`, // previous document url
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a same-origin popup with a same-origin COOP (no reporting)and no COEP.
+  // COOP switches the browsing context group and hence produces one report for
+  // the navigated from document (this page, the opener). This test differs with
+  // the previous one as it assert that the navigated to document's COOP reporting
+  // values do not interfere.
+  [
+    SAME_ORIGIN,
+    `same-origin`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "unsafe-none",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // next document URL
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      }
+    ]
+  ],
+  // Open a cross-origin popup with a same-origin COOP and no COEP. COOP switches
+  // the browsing context group and hence produces two reports.
+  [
+    CROSS_ORIGIN,
+    `same-origin; report-to="${popupReportEndpoint.name}"`,
+    "",
+    false,
+    [
+      {
+        "endpoint": reportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": `${location.href}`,
+            "effective-policy": "unsafe-none",
+            "navigation-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/, // initial navigation url
+            "violation-type": "navigation-from-document"
+          },
+          "url": `${location.href}`,
+          "type": "coop"
+        }
+      },
+      {
+        "endpoint": popupReportEndpoint,
+        "report": {
+          "body": {
+            "disposition": "enforce",
+            "document-uri": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+            "effective-policy": "same-origin",
+            "navigation-uri": `${location.href}`, // referrer
+            "violation-type": "navigation-to-document"
+          },
+          "url": /coop-coep.py?.*channel=CHANNEL_NAME$/,
+          "type": "coop"
+        }
+      }
+    ]
+  ]
+];
+
+runCoopReportingTest(document.title, tests);
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-unafe-none-report-to.https.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-unafe-none-report-to.https.html.headers
new file mode 100644
index 0000000..d6a6e7ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/reporting-popup-unafe-none-report-to.https.html.headers
@@ -0,0 +1,2 @@
+report-to: { "group": "coop-report-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-endpoint" }] }, { "group": "coop-report-only-endpoint", "max_age": 10886400, "endpoints": [{ "url": "https://{{hosts[][www]}}:{{ports[https][0]}}/html/cross-origin-opener-policy/resources/report.py?endpoint=coop-report-only-endpoint" }]}
+Cross-Origin-Opener-Policy: unsafe-none; report-to="coop-report-endpoint"
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/common.js b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/common.js
index fb517e8..8a3cd133 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/common.js
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/common.js
@@ -29,11 +29,14 @@
   }
 }
 
-function url_test(t, url, channelName, hasOpener, openerDOMAccess) {
+function url_test(t, url, channelName, hasOpener, openerDOMAccess, callback) {
+  if (callback === undefined) {
+    callback = () => { t.done(); };
+  }
   const bc = new BroadcastChannel(channelName);
   bc.onmessage = t.step_func(event => {
     const payload = event.data;
-    validate_results(() => { t.done(); }, t, w, channelName, hasOpener, openerDOMAccess, payload);
+    validate_results(callback, t, w, channelName, hasOpener, openerDOMAccess, payload);
   });
 
   const w = window.open(url, channelName);
@@ -46,12 +49,12 @@
   });
 }
 
-function coop_coep_test(t, host, coop, coep, channelName, hasOpener, openerDOMAccess) {
-  url_test(t, `${host.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${encodeURIComponent(coop)}&coep=${coep}&channel=${channelName}`, channelName, hasOpener, openerDOMAccess);
+function coop_coep_test(t, host, coop, coep, channelName, hasOpener, openerDOMAccess, callback) {
+  url_test(t, `${host.origin}/html/cross-origin-opener-policy/resources/coop-coep.py?coop=${encodeURIComponent(coop)}&coep=${coep}&channel=${channelName}`, channelName, hasOpener, openerDOMAccess, callback);
 }
 
-function coop_test(t, host, coop, channelName, hasOpener) {
-  coop_coep_test(t, host, coop, "", channelName, hasOpener);
+function coop_test(t, host, coop, channelName, hasOpener, callback) {
+  coop_coep_test(t, host, coop, "", channelName, hasOpener, undefined /* openerDOMAccess */, callback);
 }
 
 function run_coop_tests(documentCOOPValueTitle, testArray) {
@@ -59,7 +62,7 @@
     async_test(t => {
       coop_test(t, test[0], test[1],
                 `${documentCOOPValueTitle}_to_${test[0].name}_${test[1].replace(/ /g,"-")}`,
-                test[2]);
+                test[2], () => { t.done(); });
     }, `${documentCOOPValueTitle} document opening popup to ${test[0].origin} with COOP: "${test[1]}"`);
   }
 }
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/coop-coep.py b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/coop-coep.py
index 8a7e0bc0..03fe6ccb 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/coop-coep.py
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/coop-coep.py
@@ -1,13 +1,42 @@
+def get_reporting_group(host, endpoint):
+  return '\
+{{\
+    "group": "{endpoint}",\
+    "max_age": 10886400,\
+    "endpoints":\
+  [{{\
+    "url": "https://{host}/html/cross-origin-opener-policy/resources/report.py?endpoint={endpoint}"\
+  }}]\
+}}'.format(host=host, endpoint=endpoint)
+
 def main(request, response):
     coop = request.GET.first("coop")
+    coopReportOnly = request.GET.first("coop-report-only") if "coop-report-only" in request.GET else ""
     coep = request.GET.first("coep")
+    coepReportOnly = request.GET.first("coep-report-only") if "coep-report-only" in request.GET else ""
     redirect = request.GET.first("redirect", None)
     if coop != "":
         response.headers.set("Cross-Origin-Opener-Policy", coop)
+    if coop != "":
+        response.headers.set("Cross-Origin-Opener-Policy-Report-Only", coopReportOnly)
     if coep != "":
         response.headers.set("Cross-Origin-Embedder-Policy", coep)
+    if coep != "":
+         response.headers.set("Cross-Origin-Embedder-Policy-Report-Only", coepReportOnly)
     if 'cache' in request.GET:
         response.headers.set('Cache-Control', 'max-age=3600')
+    host = request.url_parts[1]
+
+    # add all possible reporting endpoints to the report-to header
+    # Note that this also returns the coop-report-endpoint, as it may override
+    # the test's endpoints if same-origin.
+    response.headers.set('report-to',
+      get_reporting_group(host, "coop-report-endpoint") + ',' +
+      get_reporting_group(host, "coop-report-only-endpoint") + ',' +
+      get_reporting_group(host, "coop-redirect-report-endpoint") + ',' +
+      get_reporting_group(host, "coop-redirect-report-only-endpoint") + ',' +
+      get_reporting_group(host, "coop-popup-report-endpoint") + ',' +
+      get_reporting_group(host, "coop-popup-report-only-endpoint") )
 
     if redirect != None:
         response.status = 302
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/report.py b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/report.py
new file mode 100644
index 0000000..c9ea353
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/report.py
@@ -0,0 +1,26 @@
+import json, uuid
+
+def main(request, response):
+    response.headers.set('Cache-Control', 'no-cache, no-store, must-revalidate');
+
+    key = 0;
+    if 'endpoint' in request.GET:
+        key = uuid.uuid5(uuid.NAMESPACE_OID, request.GET['endpoint']).get_urn()
+
+    if key == 0:
+        response.status = 400
+        return 'invalid endpoint'
+
+    if request.method == 'POST':
+        reports = request.server.stash.take(key) or []
+        for report in json.loads(request.body):
+            reports.append(report)
+        request.server.stash.put(key, reports)
+        return "done"
+
+    if request.method == 'GET':
+        response.headers.set('Content-Type', 'application/json')
+        return json.dumps(request.server.stash.take(key) or [])
+
+    response.status = 400
+    return 'invalid method'
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/reporting-common.js b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/reporting-common.js
new file mode 100644
index 0000000..d834c08
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/resources/reporting-common.js
@@ -0,0 +1,177 @@
+// Allows RegExps to be pretty printed when printing unmatched expected reports.
+Object.defineProperty(RegExp.prototype, "toJSON", {
+  value: RegExp.prototype.toString
+});
+
+function wait(ms) {
+  return new Promise(resolve => step_timeout(resolve, ms));
+}
+
+async function pollReports(endpoint) {
+  const res = await fetch(
+      `resources/report.py?endpoint=${endpoint.name}`,
+      {cache: 'no-store'});
+  if (res.status !== 200) {
+    return;
+  }
+  for (const report of await res.json()) {
+    endpoint.reports.push(report);
+  }
+}
+
+// Recursively check that all members of expectedReport are present or matched
+// in report.
+// Report may have members not explicitly expected by expectedReport.
+function isObjectAsExpected(report, expectedReport) {
+  if (( report === undefined || report === null
+        || expectedReport === undefined || expectedReport === null )
+      && report !== expectedReport ) {
+    return false;
+  }
+  if (expectedReport instanceof RegExp && typeof report === "string") {
+    return expectedReport.test(report);
+  }
+  // Perform this check now, as RegExp and strings above have different typeof.
+  if (typeof report !== typeof expectedReport)
+    return false;
+  if (typeof expectedReport === 'object') {
+    return Object.keys(expectedReport).every(key => {
+      return isObjectAsExpected(report[key], expectedReport[key]);
+    });
+  }
+  return report == expectedReport;
+}
+
+async function checkForExpectedReport(expectedReport) {
+  return new Promise( async (resolve, reject) => {
+    const polls = 30;
+    const waitTime = 100;
+    for (var i=0; i < polls; ++i) {
+      pollReports(expectedReport.endpoint);
+      for (var j=0; j<expectedReport.endpoint.reports.length; ++j){
+        if (isObjectAsExpected(expectedReport.endpoint.reports[j],
+            expectedReport.report)){
+          expectedReport.endpoint.reports.splice(j,1);
+          resolve();
+        }
+      };
+      await wait(waitTime);
+    }
+    reject("No report matched the expected report for endpoint: "
+      + expectedReport.endpoint.name
+      + ", expected report: " + JSON.stringify(expectedReport.report)
+      + ", within available reports: "
+      + JSON.stringify(expectedReport.endpoint.reports)
+    );
+  });
+}
+
+function replaceFromRegexOrString(str, match, value) {
+  if (str instanceof RegExp) {
+    return RegExp(str.source.replace(match, value));
+  }
+  return str.replace(match, value);
+}
+
+// Replace generated values in regexes and strings of an expected report:
+// CHANNEL_NAME: the channel name is generated from the test parameters.
+function replaceValuesInExpectedReport(expectedReport, channelName) {
+  if (expectedReport.report.body !== undefined) {
+    if (expectedReport.report.body["document-uri"] !== undefined) {
+      expectedReport.report.body["document-uri"] = replaceFromRegexOrString(
+          expectedReport.report.body["document-uri"], "CHANNEL_NAME",
+          channelName);
+    }
+    if (expectedReport.report.body["navigation-uri"] !== undefined) {
+      expectedReport.report.body["navigation-uri"] = replaceFromRegexOrString(
+          expectedReport.report.body["navigation-uri"], "CHANNEL_NAME",
+          channelName);
+    }
+  }
+  if (expectedReport.report.url !== undefined) {
+      expectedReport.report.url = replaceFromRegexOrString(
+          expectedReport.report.url, "CHANNEL_NAME", channelName);
+  }
+  return expectedReport;
+}
+
+// Run a test (such as coop_coep_test from ./common.js) then check that all
+// expected reports are present.
+async function reportingTest(testFunction, channelName, expectedReports) {
+  await new Promise( async resolve => {
+    testFunction(resolve);
+  });
+  expectedReports = Array.from(
+      expectedReports,
+      report => replaceValuesInExpectedReport(report, channelName) );
+  await Promise.all(Array.from(expectedReports, checkForExpectedReport));
+}
+
+function coopCoepReportingTest(testName, host, coop, coep, hasOpener,
+    expectedReports){
+  const channelName = `${testName.replace(/[ ;"=]/g,"-")}_to_${host.name}_${coop.replace(/[ ;"=]/g,"-")}_${coep}`;
+  promise_test(async t => {
+    await reportingTest( (resolve) => {
+      coop_coep_test(t, host, coop, coep, channelName,
+          hasOpener, undefined /* openerDOMAccess */, resolve);
+    }, channelName, expectedReports);
+  }, `coop reporting test ${channelName}`);
+}
+
+// Run an array of reporting tests then verify there's no reports that were not
+// expected.
+// Tests' elements contain: host, coop, coep, hasOpener, expectedReports.
+// See isObjectAsExpected for explanations regarding the matching behavior.
+function runCoopReportingTest(testName, tests){
+  tests.forEach( test => {
+    coopCoepReportingTest(testName, ...test);
+  });
+  verifyRemainingReports();
+}
+
+const reportEndpoint = {
+  name: "coop-report-endpoint",
+  reports: []
+}
+const reportOnlyEndpoint = {
+  name: "coop-report-only-endpoint",
+  reports: []
+}
+const popupReportEndpoint = {
+  name: "coop-popup-report-endpoint",
+  reports: []
+}
+const popupReportOnlyEndpoint = {
+  name: "coop-popup-report-only-endpoint",
+  reports: []
+}
+const redirectReportEndpoint = {
+  name: "coop-redirect-report-endpoint",
+  reports: []
+}
+const redirectReportOnlyEndpoint = {
+  name: "coop-redirect-report-only-endpoint",
+  reports: []
+}
+
+const reportEndpoints = [
+  reportEndpoint,
+  reportOnlyEndpoint,
+  popupReportEndpoint,
+  popupReportOnlyEndpoint,
+  redirectReportEndpoint,
+  redirectReportOnlyEndpoint
+]
+
+function verifyRemainingReports() {
+  promise_test( async t => {
+    await Promise.all(Array.from(reportEndpoints, (endpoint) => {
+      return new Promise( async (resolve, reject) => {
+        await pollReports(endpoint);
+        if (endpoint.reports.length != 0)
+          reject( `${endpoint.name} not empty`);
+        resolve();
+      });
+    }));
+  }, "verify remaining reports");
+}
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-option-element/dynamic-content-change-rendering-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-option-element/dynamic-content-change-rendering-ref.html
new file mode 100644
index 0000000..453bb70
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-option-element/dynamic-content-change-rendering-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<body>
+
+<select>
+<option>foo</option>
+</select>
+
+<select multiple>
+<option>bar</option>
+</select>
+
+</bod>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-option-element/dynamic-content-change-rendering.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-option-element/dynamic-content-change-rendering.html
new file mode 100644
index 0000000..c0e08d2
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-option-element/dynamic-content-change-rendering.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<title>Invalidation test on resetting &lt;select></title>
+<link rel="help" href="https://html.spec.whatwg.org/C/#concept-option-label">
+<link rel="help" href="http://crbug.com/1090806">
+<link rel="match" href="dynamic-content-change-rendering-ref.html">
+<body>
+
+<select id="dropdown">
+<option></option>
+</select>
+
+<select id="listbox" multiple>
+<option></option>
+</select>
+
+<script>
+const selects = document.querySelectorAll('select');
+
+const span0 = document.createElement('span');
+selects[0].options[0].appendChild(span0);
+
+const span1 = document.createElement('span');
+selects[1].options[0].appendChild(span1);
+
+document.documentElement.addEventListener('TestRendered', e => {
+  span0.textContent = 'foo';
+  span1.textContent = 'bar';
+  e.target.removeAttribute('class');
+});
+</script>
+</body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-element-clone-into-inactive-document-crash.html b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-element-clone-into-inactive-document-crash.html
new file mode 100644
index 0000000..56b199d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-template-element/template-element/template-element-clone-into-inactive-document-crash.html
@@ -0,0 +1,7 @@
+<template id="t"> </template>
+<iframe id="i"></iframe>
+<script>
+var doc = i.contentDocument;
+i.remove();
+doc.importNode(t, true);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/permissions-request/idlharness.any.js b/third_party/blink/web_tests/external/wpt/permissions-request/idlharness.any.js
index c40868f..b393b1b 100644
--- a/third_party/blink/web_tests/external/wpt/permissions-request/idlharness.any.js
+++ b/third_party/blink/web_tests/external/wpt/permissions-request/idlharness.any.js
@@ -1,5 +1,6 @@
 // META: script=/resources/WebIDLParser.js
 // META: script=/resources/idlharness.js
+// META: timeout=long
 
 'use strict';
 
diff --git a/third_party/blink/web_tests/external/wpt/portals/xfo/portals-xfo-sameorigin.html b/third_party/blink/web_tests/external/wpt/portals/xfo/portals-xfo-sameorigin.html
new file mode 100644
index 0000000..2482476
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/portals/xfo/portals-xfo-sameorigin.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<body>
+<script>
+async_test(t => {
+  assert_implements("HTMLPortalElement" in self);
+  var portal = document.createElement('portal');
+  portal.src = get_host_info().HTTP_REMOTE_HOST + "/portals/xfo/resources/xfo-sameorigin.asis";
+  portal.onmessage = t.unreached_func("should not have received a message");
+  document.body.appendChild(portal);
+  t.add_cleanup(() => portal.remove());
+  t.step_timeout(() => t.done(), 2000);
+}, "`XFO: SAMEORIGIN` blocks cross-origin portals.");
+</script>
+</body>
diff --git a/third_party/blink/web_tests/external/wpt/portals/xfo/resources/xfo-deny.asis b/third_party/blink/web_tests/external/wpt/portals/xfo/resources/xfo-deny.asis
index 429a40e..7779830 100644
--- a/third_party/blink/web_tests/external/wpt/portals/xfo/resources/xfo-deny.asis
+++ b/third_party/blink/web_tests/external/wpt/portals/xfo/resources/xfo-deny.asis
@@ -4,5 +4,5 @@
 
 <!DOCTYPE html>
 <script>
-window.portalHost.postMessage('loaded');
+window.portalHost.postMessage('loaded', '*');
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/portals/xfo/resources/xfo-sameorigin.asis b/third_party/blink/web_tests/external/wpt/portals/xfo/resources/xfo-sameorigin.asis
new file mode 100644
index 0000000..8f3982bd
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/portals/xfo/resources/xfo-sameorigin.asis
@@ -0,0 +1,8 @@
+HTTP/1.1 200 OK
+Content-Type: text/html
+X-Frame-Options: SAMEORIGIN
+
+<!DOCTYPE html>
+<script>
+window.portalHost.postMessage('loaded', '*');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
index 47a3312..c0832d7 100644
--- a/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
+++ b/third_party/blink/web_tests/external/wpt/tools/manifest/manifest.py
@@ -2,6 +2,7 @@
 import itertools
 import json
 import os
+from atomicwrites import atomic_write
 from copy import deepcopy
 from multiprocessing import Pool, cpu_count
 from six import (
@@ -385,6 +386,8 @@
                              allow_cached=allow_cached)
         except ManifestVersionMismatch:
             logger.info("Manifest version changed, rebuilding")
+        except ManifestError:
+            logger.warning("Failed to load manifest, rebuilding")
 
         if manifest is not None and manifest.url_base != url_base:
             logger.info("Manifest url base did not match, rebuilding")
@@ -411,7 +414,7 @@
     dir_name = os.path.dirname(manifest_path)
     if not os.path.exists(dir_name):
         os.makedirs(dir_name)
-    with open(manifest_path, "w") as f:
+    with atomic_write(manifest_path, overwrite=True) as f:
         # Use ',' instead of the default ', ' separator to prevent trailing
         # spaces: https://docs.python.org/2/library/json.html#json.dump
         json.dump(manifest.to_json(caller_owns_obj=True), f,
diff --git a/third_party/blink/web_tests/external/wpt/tools/requirements_flake8.txt b/third_party/blink/web_tests/external/wpt/tools/requirements_flake8.txt
index ae16be39..ae3e4f4b 100644
--- a/third_party/blink/web_tests/external/wpt/tools/requirements_flake8.txt
+++ b/third_party/blink/web_tests/external/wpt/tools/requirements_flake8.txt
@@ -1,4 +1,4 @@
-flake8==3.8.2
+flake8==3.8.3
 pycodestyle==2.6.0
 pyflakes==2.2.0
 pep8-naming==0.10.0
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
index 0635e2d..494944e 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -128,6 +128,8 @@
         self.runner_handle = None
         with open(os.path.join(here, "runner.js")) as f:
             self.runner_script = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
 
     def setup(self):
         self.marionette = self.parent.marionette
@@ -235,6 +237,19 @@
 
         raise Exception("unable to find test window")
 
+    def test_window_loaded(self):
+        """Wait until the page in the new window has been loaded.
+
+        Hereby ignore Javascript execptions that are thrown when
+        the document has been unloaded due to a process change.
+        """
+        while True:
+            try:
+                self.parent.base.execute_script(self.window_loaded_script, asynchronous=True)
+                break
+            except errors.JavascriptException:
+                pass
+
 
 class MarionettePrefsProtocolPart(PrefsProtocolPart):
     def setup(self):
@@ -802,10 +817,12 @@
 
         format_map = {"url": strip_server(url)}
 
-        protocol.base.execute_script("window.open(undefined, '%s', 'noopener')" % self.window_id)
+        protocol.base.execute_script("window.open('about:blank', '%s', 'noopener')" % self.window_id)
         test_window = protocol.testharness.get_test_window(self.window_id, parent_window,
-                                                           timeout=10*self.timeout_multiplier)
+                                                           timeout=10 * self.timeout_multiplier)
         self.protocol.base.set_window(test_window)
+        protocol.testharness.test_window_loaded()
+
         handler = CallbackHandler(self.logger, protocol, test_window)
         protocol.marionette.navigate(url)
         while True:
@@ -898,6 +915,7 @@
                 self.protocol.base.execute_script(self.script)
                 self.protocol.base.set_window(self.protocol.marionette.window_handles[-1])
                 self.has_window = True
+                self.protocol.testharness.test_window_loaded()
 
         if self.protocol.coverage.is_enabled:
             self.protocol.coverage.reset()
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py
index 96312f3..b12299c 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py
@@ -84,6 +84,8 @@
         self.runner_handle = None
         with open(os.path.join(here, "runner.js")) as f:
             self.runner_script = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
 
     def load_runner(self, url_protocol):
         if self.runner_handle:
@@ -145,6 +147,19 @@
 
         raise Exception("unable to find test window")
 
+    def test_window_loaded(self):
+        """Wait until the page in the new window has been loaded.
+
+        Hereby ignore Javascript execptions that are thrown when
+        the document has been unloaded due to a process change.
+        """
+        while True:
+            try:
+                self.webdriver.execute_script(self.window_loaded_script, asynchronous=True)
+                break
+            except exceptions.JavascriptException:
+                pass
+
 
 class SeleniumSelectorProtocolPart(SelectorProtocolPart):
     def setup(self):
@@ -317,6 +332,8 @@
                                                            parent_window,
                                                            timeout=5*self.timeout_multiplier)
         self.protocol.base.set_window(test_window)
+        protocol.testharness.test_window_loaded()
+
         protocol.base.load(url)
 
         if not self.supports_eager_pageload:
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
index 2e31f463..ea26fbc 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
@@ -29,6 +29,7 @@
 from ..testrunner import Stop
 
 import webdriver as client
+from webdriver import error
 
 here = os.path.join(os.path.split(__file__)[0])
 
@@ -90,6 +91,8 @@
         self.runner_handle = None
         with open(os.path.join(here, "runner.js")) as f:
             self.runner_script = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
 
     def load_runner(self, url_protocol):
         if self.runner_handle:
@@ -153,6 +156,19 @@
 
         raise Exception("unable to find test window")
 
+    def test_window_loaded(self):
+        """Wait until the page in the new window has been loaded.
+
+        Hereby ignore Javascript execptions that are thrown when
+        the document has been unloaded due to a process change.
+        """
+        while True:
+            try:
+                self.webdriver.execute_script(self.window_loaded_script, asynchronous=True)
+                break
+            except error.JavascriptErrorException:
+                pass
+
 
 class WebDriverSelectorProtocolPart(SelectorProtocolPart):
     def setup(self):
@@ -361,6 +377,9 @@
         self.protocol = self.protocol_cls(self, browser, capabilities)
         with open(os.path.join(here, "testharness_webdriver_resume.js")) as f:
             self.script_resume = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
+
         self.close_after_done = close_after_done
         self.window_id = str(uuid.uuid4())
         self.supports_eager_pageload = supports_eager_pageload
@@ -397,6 +416,10 @@
                                                            parent_window,
                                                            timeout=5*self.timeout_multiplier)
         self.protocol.base.set_window(test_window)
+
+        # Wait until about:blank has been loaded
+        protocol.base.execute_script(self.window_loaded_script, asynchronous=True)
+
         handler = WebDriverCallbackHandler(self.logger, protocol, test_window)
         protocol.webdriver.url = url
 
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/protocol.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/protocol.py
index e2a9154..3f0e443 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/protocol.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/protocol.py
@@ -190,6 +190,10 @@
         """
         pass
 
+    @abstractmethod
+    def test_window_loaded(self):
+        """Wait until the newly opened test window has been loaded."""
+
 
 class PrefsProtocolPart(ProtocolPart):
     """Protocol part that allows getting and setting browser prefs."""
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/window-loaded.js b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/window-loaded.js
new file mode 100644
index 0000000..78d73285a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/window-loaded.js
@@ -0,0 +1,9 @@
+const [resolve] = arguments;
+
+if (document.readyState != "complete") {
+  window.addEventListener("load", () => {
+    resolve();
+  }, { once: true });
+} else {
+  resolve();
+}
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.tentative.html
new file mode 100644
index 0000000..d092049
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none-skip.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="trusted-types * 'none' 'allow-duplicates'">
+<body>
+<script>
+  test(t => {
+    window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+  }, "Can create policy with name 'SomeName'");
+
+  test(t => {
+    window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+  }, "Can create a second policy with name 'SomeName'");
+
+  test(t => {
+    window.trustedTypes.createPolicy('default', { createHTML: s => s } );
+  }, "Can create policy with name 'default'");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none.tentative.html
new file mode 100644
index 0000000..48c7593
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-createPolicy-cspTests-none.tentative.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js" ></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="support/helper.sub.js"></script>
+<meta http-equiv="Content-Security-Policy" content="trusted-types 'none'">
+<body>
+<script>
+  test(t => {
+    assert_throws_js(TypeError, _ => {
+      window.trustedTypes.createPolicy('SomeName', { createHTML: s => s } );
+    });
+  }, "Cannot create policy with name 'SomeName' - policy creation throws");
+
+  test(t => {
+    assert_throws_js(TypeError, _ => {
+      window.trustedTypes.createPolicy('default', { createHTML: s => s } );
+    });
+  }, "Cannot create policy with name 'default' - policy creation throws");
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-no-tt.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-no-tt.tentative.html
index e8ed577..6720d80 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-no-tt.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-no-tt.tentative.html
@@ -24,5 +24,13 @@
     assert_equals(eval(null), null);
     assert_equals(eval(undefined), undefined);
    }, "eval of !TrustedScript and !string works.");
+
+  test(t => {
+    assert_equals(new Function(p.createScript("return 1+1"))(), 2);
+  }, "Function constructor of TrustedScript works.");
+
+  test(t => {
+    assert_equals(new Function('return 1+1')(), 2);
+  }, "Function constructor of string works.");
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-default-policy.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-default-policy.tentative.html
index 106a024..2ec1422 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-default-policy.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-default-policy.tentative.html
@@ -8,7 +8,7 @@
 </head>
 <body>
 <script>
-  trustedTypes.createPolicy("default", {createScript: s => s + 4});
+  trustedTypes.createPolicy("default", {createScript: s => s.replace("1", "4")});
   const p = trustedTypes.createPolicy("p", {createScript: s => s});
 
   test(t => {
@@ -16,7 +16,7 @@
   }, "eval of TrustedScript works.");
 
   test(t => {
-    assert_equals(eval('1+1'), 15); // '1+1' + 4 becomes '1+14'.
+    assert_equals(eval('1+1'), 5); // '1+1' becomes '4+1'.
   }, "eval of string works.");
 
   test(t => {
@@ -25,5 +25,15 @@
     assert_equals(eval(null), null);
     assert_equals(eval(undefined), undefined);
    }, "eval of !TrustedScript and !string works.");
+
+  test(t => {
+    // The Function constructor will string-ify its arguments. Hence, this
+    // will apply the default policy, despite being TrustedScript.
+    assert_equals(new Function(p.createScript('return 1+1'))(), 5);
+  }, "Function constructor of TrustedScript works.");
+
+  test(t => {
+    assert_equals(new Function('return 1+1')(), 5);
+  }, "Function constructor of string works.");
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-no-default-policy.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-no-default-policy.tentative.html
index 2f1e2a2..983dd56 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-no-default-policy.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/eval-csp-tt-no-default-policy.tentative.html
@@ -24,5 +24,15 @@
     assert_equals(eval(null), null);
     assert_equals(eval(undefined), undefined);
    }, "eval of !TrustedScript and !string works.");
+
+  test(t => {
+    // The Function constructor will string-ify its arguments. Hence, this
+    // throw because no default policy is defined.
+    assert_throws_js(EvalError, _ => new Function(p.createScript('1+1')));
+  }, "Function constructor of TrustedScript works.");
+
+  test(t => {
+    assert_throws_js(EvalError, _ => new Function('1+1')());
+  }, "Function constructor of string fails.");
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html
index 84c224e..d36afbc8 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt-default-policy.tentative.html
@@ -25,5 +25,13 @@
     assert_equals(eval(null), null);
     assert_equals(eval(undefined), undefined);
    }, "eval of !TrustedScript and !string works.");
+
+  test(t => {
+    assert_equals(new Function(p.createScript('return 1+1'))(), 2);
+  }, "Function constructor of TrustedScript works.");
+
+  test(t => {
+    assert_equals(new Function('return 1+1')(), 2);
+  }, "Function constructor of string works and does not call a default policy.");
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt.tentative.html
index 45086a1..3013c084 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/eval-no-csp-no-tt.tentative.html
@@ -24,5 +24,13 @@
     assert_equals(eval(null), null);
     assert_equals(eval(undefined), undefined);
    }, "eval of !TrustedScript and !string works.");
+
+  test(t => {
+    assert_equals(new Function(p.createScript('return 1+1'))(), 2);
+  }, "Function constructor of TrustedScript works.");
+
+  test(t => {
+    assert_equals(new Function('return 1+1')(), 2);
+  }, "Function constructor of string works.");
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/eval-with-permissive-csp.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/eval-with-permissive-csp.tentative.html
index abc698a4..51bb0aaa 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/eval-with-permissive-csp.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/eval-with-permissive-csp.tentative.html
@@ -21,14 +21,35 @@
   }, "eval with plain string with Trusted Types and permissive CSP throws (no type).");
 
   test(t => {
+    let a = 0;
+    assert_throws_js(EvalError, _ => {
+      new Function('a="hello there"');
+    });
+    assert_equals(a, 0);
+  }, "Function constructor with plain string with Trusted Types and permissive CSP throws (no type).");
+
+  test(t => {
     let s = eval(p.createScript('"Hello transformed string"'));
     assert_equals("" + s, "Hello a cat string");
   }, "eval with TrustedScript and permissive CSP works.");
 
+  test(t => {
+    assert_throws_js(EvalError, _ => {
+      // The Function constructor will string-ify its arguments. Hence, this
+      // throw because no default policy is defined.
+      let s = new Function(p.createScript('return "Hello transformed string"'));
+    });
+  }, "new Function with TrustedScript and permissive CSP works.");
+
   trustedTypes.createPolicy("default", { createScript: createScriptJS }, true);
   test(t => {
     let s = eval('"Hello transformed untrusted string"');
     assert_equals(s, "Hello a cat untrusted string");
   }, "eval with default policy and permissive CSP still obeys default policy.");
+
+  test(t => {
+    let s = new Function('return "Hello transformed untrusted string"')();
+    assert_equals(s, "Hello a cat untrusted string");
+  }, "new Function with default policy and permissive CSP still obeys default policy.");
 </script>
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp-expected.txt
deleted file mode 100644
index e2df6c1..0000000
--- a/third_party/blink/web_tests/external/wpt/webrtc-extensions/RTCRtpSynchronizationSource-captureTimestamp-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/webrtc-stats/getStats-remote-candidate-address-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc-stats/getStats-remote-candidate-address-expected.txt
index e2df6c1..a18cda0 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc-stats/getStats-remote-candidate-address-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc-stats/getStats-remote-candidate-address-expected.txt
@@ -1,4 +1,5 @@
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
+FAIL Do not expose in stats remote addresses that are not known to be already exposed to JS assert_equals: address should be null expected (object) null but got (undefined) undefined
+PASS Expose in stats remote addresses that are already exposed to JS
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
index e2df6c1..adb8b9c 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -1,4 +1,16 @@
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+PASS getStats() with track added via addTransceiver should succeed
+PASS getStats() with track associated with more than one sender should reject with InvalidAccessError
+PASS getStats() with track associated with both sender and receiver should reject with InvalidAccessError
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-mandatory-getStats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-mandatory-getStats.https-expected.txt
index e2df6c1..41724bf4 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-mandatory-getStats.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-mandatory-getStats.https-expected.txt
@@ -1,4 +1,80 @@
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
+Found 76 tests; 52 PASS, 24 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS getStats succeeds
+PASS RTCRtpStreamStats's ssrc
+PASS RTCRtpStreamStats's kind
+PASS RTCRtpStreamStats's transportId
+PASS RTCRtpStreamStats's codecId
+PASS RTCReceivedRtpStreamStats's packetsReceived
+PASS RTCReceivedRtpStreamStats's packetsLost
+PASS RTCReceivedRtpStreamStats's jitter
+FAIL RTCReceivedRtpStreamStats's packetsDiscarded assert_true: Is packetsDiscarded present expected true got false
+PASS RTCInboundRtpStreamStats's trackId
+FAIL RTCInboundRtpStreamStats's receiverId assert_true: Is receiverId present expected true got false
+FAIL RTCInboundRtpStreamStats's remoteId assert_true: Is remoteId present expected true got false
+PASS RTCInboundRtpStreamStats's framesDecoded
+PASS RTCRemoteInboundRtpStreamStats's localId
+PASS RTCRemoteInboundRtpStreamStats's roundTripTime
+PASS RTCSentRtpStreamStats's packetsSent
+PASS RTCSentRtpStreamStats's bytesSent
+PASS RTCOutboundRtpStreamStats's trackId
+FAIL RTCOutboundRtpStreamStats's senderId assert_true: Is senderId present expected true got false
+PASS RTCOutboundRtpStreamStats's remoteId
+PASS RTCOutboundRtpStreamStats's framesEncoded
+FAIL RTCRemoteOutboundRtpStreamStats's localId assert_true: Is localId present expected true got false
+FAIL RTCRemoteOutboundRtpStreamStats's remoteTimestamp assert_true: Is remoteTimestamp present expected true got false
+PASS RTCPeerConnectionStats's dataChannelsOpened
+PASS RTCPeerConnectionStats's dataChannelsClosed
+PASS RTCDataChannelStats's protocol
+PASS RTCDataChannelStats's dataChannelIdentifier
+PASS RTCDataChannelStats's state
+PASS RTCDataChannelStats's messagesSent
+PASS RTCDataChannelStats's bytesSent
+PASS RTCDataChannelStats's messagesReceived
+PASS RTCDataChannelStats's bytesReceived
+FAIL RTCMediaStreamStats's streamIdentifer assert_true: Is streamIdentifer present expected true got false
+PASS RTCMediaStreamStats's trackIds
+FAIL RTCMediaHandlerStats's trackIdentifier assert_true: Is trackIdentifier present expected true got false
+FAIL RTCMediaHandlerStats's remoteSource assert_true: Is remoteSource present expected true got false
+FAIL RTCMediaHandlerStats's ended assert_true: Is ended present expected true got false
+FAIL RTCAudioHandlerStats's audioLevel assert_true: Is audioLevel present expected true got false
+FAIL RTCVideoHandlerStats's frameWidth assert_true: Is frameWidth present expected true got false
+FAIL RTCVideoHandlerStats's frameHeight assert_true: Is frameHeight present expected true got false
+FAIL RTCVideoHandlerStats's framesPerSecond assert_true: Is framesPerSecond present expected true got false
+FAIL RTCVideoSenderStats's framesSent assert_true: Is framesSent present expected true got false
+FAIL RTCVideoReceiverStats's framesReceived assert_true: Is framesReceived present expected true got false
+FAIL RTCVideoReceiverStats's framesDecoded assert_true: Is framesDecoded present expected true got false
+FAIL RTCVideoReceiverStats's framesDropped assert_true: Is framesDropped present expected true got false
+FAIL RTCVideoReceiverStats's partialFramesLost assert_true: Is partialFramesLost present expected true got false
+PASS RTCCodecStats's payloadType
+FAIL RTCCodecStats's codecType assert_true: Is codecType present expected true got false
+PASS RTCCodecStats's clockRate
+PASS RTCCodecStats's channels
+PASS RTCCodecStats's sdpFmtpLine
+PASS RTCTransportStats's bytesSent
+PASS RTCTransportStats's bytesReceived
+FAIL RTCTransportStats's rtcpTransportStatsId assert_true: Is rtcpTransportStatsId present expected true got false
+PASS RTCTransportStats's selectedCandidatePairId
+PASS RTCTransportStats's localCertificateId
+PASS RTCTransportStats's remoteCertificateId
+PASS RTCIceCandidatePairStats's transportId
+PASS RTCIceCandidatePairStats's localCandidateId
+PASS RTCIceCandidatePairStats's remoteCandidateId
+PASS RTCIceCandidatePairStats's state
+PASS RTCIceCandidatePairStats's priority
+PASS RTCIceCandidatePairStats's nominated
+PASS RTCIceCandidatePairStats's bytesSent
+PASS RTCIceCandidatePairStats's bytesReceived
+PASS RTCIceCandidatePairStats's totalRoundTripTime
+PASS RTCIceCandidatePairStats's currentRoundTripTime
+FAIL RTCIceCandidateStats's address assert_true: Is address present expected true got false
+PASS RTCIceCandidateStats's port
+PASS RTCIceCandidateStats's protocol
+PASS RTCIceCandidateStats's candidateType
+FAIL RTCIceCandidateStats's url assert_true: Is url present expected true got false
+PASS RTCCertificateStats's fingerprint
+PASS RTCCertificateStats's fingerprintAlgorithm
+PASS RTCCertificateStats's base64Certificate
+FAIL RTCCertificateStats's issuerCertificateId assert_true: Is issuerCertificateId present expected true got false
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt
index e2df6c1..bd8e844 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-track-stats.https-expected.txt
@@ -1,4 +1,21 @@
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
+PASS addTrack() without setLocalDescription() yields track stats
+PASS addTrack() without setLocalDescription() yields media stream stats
+PASS addTrack() with setLocalDescription() yields track stats
+PASS addTrack() with setLocalDescription() yields media stream stats
+PASS addTrack(): Media stream stats references track stats
+PASS Media stream stats references track stats
+PASS O/A exchange yields outbound RTP stream stats for sending track
+PASS O/A exchange yields inbound RTP stream stats for receiving track
+PASS replaceTrack() before offer: new track attachment stats present
+PASS replaceTrack() after offer, before answer: new track attachment stats present
+PASS replaceTrack() after answer: new track attachment stats present
+FAIL replaceTrack(): original track attachment stats present after replacing assert_true: Has stats for original track expected true got false
+PASS RTCRtpSender.getStats() contains only outbound-rtp and related stats
+PASS RTCRtpReceiver.getStats() contains only inbound-rtp and related stats
+PASS RTCPeerConnection.getStats(sendingTrack) is the same as RTCRtpSender.getStats()
+PASS RTCPeerConnection.getStats(receivingTrack) is the same as RTCRtpReceiver.getStats()
+PASS RTCPeerConnection.getStats(track) throws InvalidAccessError when there are zero senders or receivers for the track
+PASS RTCPeerConnection.getStats(track) throws InvalidAccessError when there are multiple senders for the track
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https-expected.txt
index e2df6c1..002ae802 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpReceiver-getStats.https-expected.txt
@@ -1,4 +1,5 @@
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
+FAIL receiver.getStats() via addTransceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
+FAIL receiver.getStats() via addTrack should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https-expected.txt
index e2df6c1..03ffdbc 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-getStats.https-expected.txt
@@ -1,4 +1,5 @@
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
+FAIL sender.getStats() via addTransceiver should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL sender.getStats() via addTrack should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCStats-helper.js b/third_party/blink/web_tests/external/wpt/webrtc/RTCStats-helper.js
index 7bebc2e..6fa6f8e 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/RTCStats-helper.js
+++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCStats-helper.js
@@ -1,4 +1,4 @@
-R'use strict';
+'use strict';
 
 // Test is based on the following editor draft:
 // webrtc-pc 20171130
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/legacy/RTCPeerConnection-addStream.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/legacy/RTCPeerConnection-addStream.https-expected.txt
deleted file mode 100644
index e2df6c1..0000000
--- a/third_party/blink/web_tests/external/wpt/webrtc/legacy/RTCPeerConnection-addStream.https-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/protocol/crypto-suite.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/protocol/crypto-suite.https-expected.txt
index e2df6c1..1d818ac 100644
--- a/third_party/blink/web_tests/external/wpt/webrtc/protocol/crypto-suite.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webrtc/protocol/crypto-suite.https-expected.txt
@@ -1,4 +1,11 @@
 This is a testharness.js-based test.
-Harness Error. harness_status.status = 1 , harness_status.message = Uncaught SyntaxError: Unexpected string
+PASS tlsVersion is acceptable on data-only
+PASS tlsVersion is acceptable on video-only
+PASS dtlsCipher is acceptable on data-only
+PASS dtlsCipher is acceptable on video-only
+PASS srtpCipher is acceptable on data-only
+PASS srtpCipher is acceptable on video-only
+FAIL tlsGroup is acceptable on data-only assert_true: Value present: expected true got false
+FAIL tlsGroup is acceptable on video-only assert_true: Value present: expected true got false
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/xslt/transformToFragment-on-node-from-inactive-document-crash.html b/third_party/blink/web_tests/external/wpt/xslt/transformToFragment-on-node-from-inactive-document-crash.html
new file mode 100644
index 0000000..38a62a0a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/xslt/transformToFragment-on-node-from-inactive-document-crash.html
@@ -0,0 +1,11 @@
+<body>
+<iframe id=i></iframe>
+<script>
+var el = i.contentDocument.documentElement;
+i.remove()
+var x = new XSLTProcessor();
+var xsl =new DOMParser().parseFromString('<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"/>','application/xml');
+x.importStylesheet(xsl);
+x.transformToDocument(el);
+</script>
+</body>
diff --git a/third_party/blink/web_tests/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/fast/canvas/canvas-composite-shadow-expected.png
new file mode 100644
index 0000000..9eec185
--- /dev/null
+++ b/third_party/blink/web_tests/fast/canvas/canvas-composite-shadow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/blink/web_tests/fast/canvas/canvas-shadow-source-in-expected.png
new file mode 100644
index 0000000..b49882c
--- /dev/null
+++ b/third_party/blink/web_tests/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/fast/css/resize-corner-tracking-touch-expected.txt b/third_party/blink/web_tests/fast/css/resize-corner-tracking-touch-expected.txt
deleted file mode 100644
index 917e20af..0000000
--- a/third_party/blink/web_tests/fast/css/resize-corner-tracking-touch-expected.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-Test for https://code.google.com/p/chromium/issues/detail?id=150601 Can't resize a textarea with touch.
-
-a placeholder so that we have enough elements to scroll the page
-
-
-PASS successfullyParsed is true
-
-TEST COMPLETE
-
-
-Resize div at offset (-6,-7)
-PASS target.offsetWidth - old_width is deltaXExpected
-PASS target.offsetHeight - old_height is deltaYExpected
-
-Resize div at offset (6,7)
-PASS target.offsetWidth - old_width is deltaXExpected
-PASS target.offsetHeight - old_height is deltaYExpected
-
-Resize textarea1 at offset (-20,-20)
-PASS target.offsetWidth - old_width is deltaXExpected
-PASS target.offsetHeight - old_height is deltaYExpected
-
-Resize iframe1 at offset (-6,-7)
-PASS target.offsetWidth - old_width is deltaXExpected
-PASS target.offsetHeight - old_height is deltaYExpected
-
-Resize iframe1 at offset (-20,-20)
-PASS target.offsetWidth - old_width is deltaXExpected
-PASS target.offsetHeight - old_height is deltaYExpected
-
-Resize textarea2in iframe iframe1 at offset (-6,-7)
-PASS target.offsetWidth - old_width is deltaXExpected
-PASS target.offsetHeight - old_height is deltaYExpected
diff --git a/third_party/blink/web_tests/fast/css/resize-corner-tracking-touch.html b/third_party/blink/web_tests/fast/css/resize-corner-tracking-touch.html
deleted file mode 100644
index 55e47d4..0000000
--- a/third_party/blink/web_tests/fast/css/resize-corner-tracking-touch.html
+++ /dev/null
@@ -1,107 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
-<html>
-<head>
-    <title></title>
-    <script src="../../resources/js-test.js"></script>
-    <script type="text/javascript">
-        function doScroll(x, y, deltaX, deltaY) {
-            eventSender.gestureScrollBegin(x, y);
-            eventSender.gestureScrollUpdate(deltaX, deltaY);
-            eventSender.gestureScrollEnd(0, 0);
-        }
-
-        function doResize(t, offsetX, offsetY, deltaX, deltaY, expectResize)
-        {
-            target = t;
-            rect = target.getBoundingClientRect();
-            old_width = target.offsetWidth;
-            old_height = target.offsetHeight;
-            doScroll(rect.right + offsetX, rect.bottom + offsetY, deltaX, deltaY);
-            deltaXExpected = 0;
-            deltaYExpected = 0;
-            if (expectResize == "resize") {
-                deltaXExpected = deltaX;
-                deltaYExpected = deltaY;
-            }
-
-            shouldBe("target.offsetWidth - old_width", "deltaXExpected");
-            shouldBe("target.offsetHeight - old_height", "deltaYExpected");
-        }
-
-        function resize(id, offsetX, offsetY, deltaX, deltaY, expectedDeltaX, expectedDeltaY)
-        {
-            debug("\nResize " + id + " at offset (" + offsetX + "," + offsetY + ")");
-            var target = document.getElementById(id);
-            doResize(target, offsetX, offsetY, deltaX, deltaY, expectedDeltaX, expectedDeltaY);
-        }
-
-        function resizeInIframe(id, iframe_id, offsetX, offsetY, deltaX, deltaY, expectedDeltaX, expectedDeltaY)
-        {
-            debug("\nResize " + id + "in iframe " + iframe_id + " at offset (" + offsetX + "," + offsetY + ")");
-            var iframe = document.getElementById(iframe_id);
-            var rect = iframe.getBoundingClientRect();
-            doResize(iframe.contentDocument.getElementById(id),
-                     offsetX + rect.left, offsetY + rect.top,
-                     deltaX, deltaY, expectedDeltaX, expectedDeltaY);
-        }
-
-        function test()
-        {
-            if (!window.testRunner)
-                return;
-
-            // Scroll the page first to test that resize works with scrolled page.
-            document.scrollingElement.scrollTop = 50;
-
-            // 1. Touch scrolling starting at outside of the object, e.g. offset (6, 7)
-            //    to bottom right corner of the object, won't do the resize.
-            // 2. Touch scrolling starting at inside the object, and within the normal
-            //    resizer area (15x15), e.g. offset (-6, -7) to bottom right corner of
-            //    the object, will do the resize.
-            // 3. Touch scrolling starting at inside the object, and only a little bit
-            //    off the resizer area, e.g. offset (-20, -20) to bottom right corner of
-            //    the object, will do the resize.
-
-            resize("div", -6, -7, 20, 10, "resize");
-            resize("div", 6, 7, 20, 10, "noresize");
-            resize("textarea1", -20, -20, 20, 10, "resize");
-
-            // Scroll the page again
-            document.scrollingElement.scrollTop += 100;
-
-            resize("iframe1", -6, -7, 20, 10, "resize");
-            resize("iframe1", -20, -20, 20, 10, "resize");
-            resizeInIframe("textarea2", "iframe1", -6, -7, 20, 20, "resize");
-        }
-    </script>
-<style>
-div {
-        overflow: auto;
-        resize: both;
-        border: blue 2px solid;
-}
-
-textarea {
-        resize: both;
-}
-
-iframe {
-        border: blue 2px solid;
-}
-</style>
-</head>
-<body onload="test()">
-    <hr>
-    <p>
-        Test for
-        <i><a href="https://code.google.com/p/chromium/issues/detail?id=150601">https://code.google.com/p/chromium/issues/detail?id=150601</a>
-        Can't resize a textarea with touch</i>.
-    </p>
-    <hr>
-    <div id="placeholder" style="width: 150px; height: 150px;">a placeholder so that we have enough elements to scroll the page</div>
-    <div id="div" style="width: 150px; height: 100px;;"></div>
-    <textarea id="textarea1" style="width: 150px; height: 100px;"></textarea>
-    <br>
-    <iframe id="iframe1" src="resources/resize-corner-tracking-touch-iframe.html" style="resize:both; width: 200px; height: 200px"></iframe>
-    <pre id="console"></pre>
-</body>
diff --git a/third_party/blink/web_tests/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.html b/third_party/blink/web_tests/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.html
deleted file mode 100644
index 4857fd6..0000000
--- a/third_party/blink/web_tests/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-<html>
-<style>
-#mask {
-    position: absolute;
-    left: 0px;
-    top: 18px;
-    background-color: #000000;
-    height: 30px;
-    width: 180px
-}
-</style>
-<body>
-<input type=range list=foo value="100" /><br>
-<input type=range list=foo value="90" /><br>
-<input type=range list=foo value="80" /><br>
-<input type=range list=foo value="70" /><br>
-<input type=range list=foo value="60" /><br>
-<input type=range list=foo value="50" /><br>
-<input type=range list=foo value="40" /><br>
-<input type=range list=foo value="30" /><br>
-<input type=range list=foo value="0" />
-<datalist id=foo>
-    <option>0</option>
-    <option>30</option>
-    <option>40</option>
-    <option>50</option>
-    <option>60</option>
-    <option>70</option>
-    <option>80</option>
-    <option>90</option>
-    <option>100</option>
-</datalist>
-<div id=mask></div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/forms/range/input-appearance-range-rtl-expected.html b/third_party/blink/web_tests/fast/forms/range/input-appearance-range-rtl-expected.html
deleted file mode 100644
index 3854442..0000000
--- a/third_party/blink/web_tests/fast/forms/range/input-appearance-range-rtl-expected.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<!DOCTYPE html>
-<html>
-<body>
-<div><input type=range value=100></div>
-<div><input type=range value=50></div>
-<div><input type=range value=0></div>
-<div><input type=range value=0></div>
-<div><input type=range value=0></div>
-<div><input type=range value=0></div>
-<div><input type=range value=0></div>
-<div><input type=range value=0></div>
-<div><input type=range style="-webkit-appearance:slider-vertical; height:140px;" value=80></div>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-iframe-gc.html b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-iframe-gc.html
index f99b75ae..76ef110 100644
--- a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-iframe-gc.html
+++ b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-iframe-gc.html
@@ -7,16 +7,20 @@
 <body>
 <script>
 promise_test(async t => {
+  // In case other tests that leak peerconnections have run before,
+  // we record the number of peerconnections at start. Promise_test
+  // is not supposed to execute in parallel with other tests.
+  const basePeerConnectionCount = internals.peerConnectionCount();
   let iframe = document.createElement("iframe");
   document.body.appendChild( iframe );
   let iframe_pc = new iframe.contentWindow.RTCPeerConnection();
   assert_equals(iframe_pc.signalingState, 'stable');
   iframe.remove();
   assert_equals(iframe_pc.signalingState, 'closed');
-  assert_equals(internals.peerConnectionCount(), 1);
+  assert_equals(internals.peerConnectionCount(), basePeerConnectionCount + 1);
   iframe_pc = null;
   await asyncGC();
-  assert_equals(internals.peerConnectionCount(), 0);
+  assert_equals(internals.peerConnectionCount(), basePeerConnectionCount);
 }, 'PeerConnection in iframe is closed and garbage collected');
 </script>
 </body>
diff --git a/third_party/blink/web_tests/fast/scrolling/resize-corner-tracking-touch.html b/third_party/blink/web_tests/fast/scrolling/resize-corner-tracking-touch.html
new file mode 100644
index 0000000..d81334f0
--- /dev/null
+++ b/third_party/blink/web_tests/fast/scrolling/resize-corner-tracking-touch.html
@@ -0,0 +1,122 @@
+<!DOCTYPE html>
+<script src='../../resources/gesture-util.js'></script>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<style>
+div {
+        overflow: auto;
+        resize: both;
+        border: blue 2px solid;
+}
+
+textarea {
+        resize: both;
+}
+
+iframe {
+        border: blue 2px solid;
+}
+</style>
+
+<div id="placeholder" style="width: 150px; height: 150px;">a placeholder so that we have enough elements to scroll the page</div>
+<div id="div" style="width: 150px; height: 100px;;"></div>
+<textarea id="textarea1" style="width: 150px; height: 100px;"></textarea>
+<br>
+<iframe id="iframe1" src="resources/resize-corner-tracking-touch-iframe.html" style="resize:both; width: 200px; height: 200px"></iframe>
+
+<script type="text/javascript">
+    async function resize(target, offset, touch_delta, device)
+    {
+        var rect = target.getBoundingClientRect();
+        if (typeof(device) == "undefined")
+           device = GestureSourceType.TOUCH_INPUT;
+        await smoothScrollWithXY(-touch_delta.touch_delta_x, -touch_delta.touch_delta_y,
+                                 rect.right + offset.x, rect.bottom + offset.y, device,
+                                 SPEED_INSTANT);
+    }
+
+    promise_test(async () => {
+        // Scroll the page first to test that resize works with scrolled page.
+        document.scrollingElement.scrollTop = 50;
+
+        // Touch scrolling starting at inside the object, and within the normal
+        // resizer area (15x15), e.g. offset (-6, -7) from bottom right corner of
+        // the object, will do the resize.
+        var target = document.getElementById("div");
+        var old_width = target.offsetWidth;
+        var old_height = target.offsetHeight;
+        await resize(target, {x: -6, y: -7}, {touch_delta_x: 20, touch_delta_y: 10});
+        // The resize expectation includes the touch slop region and is one frame
+        // in the future based on the addition of the values of position and delta.
+        assert_equals(target.offsetWidth - old_width, 53);
+        assert_equals(target.offsetHeight - old_height, 17);
+    }, 'Touch scrolling inside the resizer area of div will do the resize.');
+
+    promise_test(async () => {
+        // Touch scrolling starting at outside of the object, e.g. offset (6, 7)
+        // from bottom right corner of the object, won't do the resize.
+        var target = document.getElementById("div");
+        var old_width = target.offsetWidth;
+        var old_height = target.offsetHeight;
+        await resize(target, {x: 6, y: 7}, {touch_delta_x: 20, touch_delta_y: 10});
+        assert_equals(target.offsetWidth - old_width, 0);
+        assert_equals(target.offsetHeight - old_height, 0);
+    }, 'Touch scrolling outside of div will not do the resize.');
+
+    promise_test(async () => {
+        // Touch scrolling starting at inside the object, and only a little bit
+        // off the resizer area, e.g. offset (-20, -20) from bottom right corner of
+        // the object, will do the resize.
+        var target = document.getElementById("textarea1");
+        var old_width = target.offsetWidth;
+        var old_height = target.offsetHeight;
+        await resize(target, {x: -20, y: -20}, {touch_delta_x: 20, touch_delta_y: 10});
+        // The resize expectation includes the touch slop region and is one frame
+        // in the future based on the addition of the values of position and delta.
+        assert_equals(target.offsetWidth - old_width, 53);
+        assert_equals(target.offsetHeight - old_height, 17);
+    }, 'Touch scrolling a little off the resizer area of textarea will do the resize.');
+
+    promise_test(async () => {
+        var target = document.getElementById("textarea1");
+        var old_width = target.offsetWidth;
+        var old_height = target.offsetHeight;
+        await resize(target, {x: -6, y: -7}, {touch_delta_x: 20, touch_delta_y: 10},
+                     GestureSourceType.TOUCHPAD_INPUT);
+        assert_equals(target.offsetWidth - old_width, 0);
+        assert_equals(target.offsetHeight - old_height, 0);
+    }, 'Touchpad scroll should not resize textarea');
+
+    promise_test(async () => {
+        // Scroll the page again
+        document.scrollingElement.scrollTop += 100;
+
+        var iframe = document.getElementById("iframe1");
+        var old_width = iframe.offsetWidth;
+        var old_height = iframe.offsetHeight;
+        await resize(iframe, {x: -6, y: -7}, {touch_delta_x: 20, touch_delta_y: 10});
+        assert_equals(iframe.offsetWidth - old_width, 53);
+        assert_equals(iframe.offsetHeight - old_height, 17);
+    }, 'Touch scrolling inside the resizer area of iframe will do the resize after scroll.');
+
+    promise_test(async () => {
+        var iframe = document.getElementById("iframe1");
+        var old_width = iframe.offsetWidth;
+        var old_height = iframe.offsetHeight;
+        await resize(iframe, {x: -20, y: -20}, {touch_delta_x: 20, touch_delta_y: 10});
+        assert_equals(iframe.offsetWidth - old_width, 53);
+        assert_equals(iframe.offsetHeight - old_height, 17);
+    }, 'Touch scrolling a little off the resizer area of iframe will do the resize after scroll.');
+
+    promise_test(async () => {
+        var iframe = document.getElementById("iframe1");
+        var rect = iframe.getBoundingClientRect();
+        var target = iframe.contentDocument.getElementById("textarea2");
+        var old_width = target.offsetWidth;
+        var old_height = target.offsetHeight;
+        await resize(target, {x: rect.left - 6, y: rect.top - 7},
+                     {touch_delta_x: 20, touch_delta_y: 10});
+        assert_equals(target.offsetWidth - old_width, 53);
+        assert_equals(target.offsetHeight - old_height, 17);
+    }, 'Touch scrolling inside the resizer area of textarea in iframe will do the resize after scroll.');
+</script>
diff --git a/third_party/blink/web_tests/fast/css/resources/resize-corner-tracking-touch-iframe.html b/third_party/blink/web_tests/fast/scrolling/resources/resize-corner-tracking-touch-iframe.html
similarity index 100%
rename from third_party/blink/web_tests/fast/css/resources/resize-corner-tracking-touch-iframe.html
rename to third_party/blink/web_tests/fast/scrolling/resources/resize-corner-tracking-touch-iframe.html
diff --git a/third_party/blink/web_tests/fast/scrolling/scroll-over-resizer.html b/third_party/blink/web_tests/fast/scrolling/scroll-over-resizer.html
deleted file mode 100644
index 9c7edfc..0000000
--- a/third_party/blink/web_tests/fast/scrolling/scroll-over-resizer.html
+++ /dev/null
@@ -1,45 +0,0 @@
-<!DOCTYPE html>
-<script src='../../resources/gesture-util.js'></script>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<textarea id="textarea" style="width: 150px; height: 100px;"></textarea>
-<div id="resizablediv" style="resize:both; overflow:scroll; width: 100px; height: 100px;"></div>
-<script>
-  async function resize(target, scrollDeltaY, device) {
-    var rect = target.getBoundingClientRect();
-    // Scrolling within the normal resizer area (15 x 15)
-    await smoothScrollWithXY(0, -scrollDeltaY, rect.right - 5, rect.bottom - 5, device, SPEED_INSTANT);
-  }
-
-  promise_test(async () => {
-    var target = document.getElementById("textarea");
-    var old_height = target.offsetHeight;
-    await resize(target, 20, GestureSourceType.TOUCH_INPUT);
-    // The resize expectation includes the touch slop region and is one frame
-    // in the future based on the addition of the values of position and delta.
-    assert_equals(target.offsetHeight - old_height, 55);
-  }, 'Touchscreen drag resizes textarea');
-
-  promise_test(async () => {
-    var target = document.getElementById("textarea");
-    var old_height = target.offsetHeight;
-    await resize(target, 20, GestureSourceType.TOUCHPAD_INPUT);
-    assert_equals(target.offsetHeight - old_height, 0);
-  }, 'Touchpad scroll should not resize textarea');
-
-  promise_test(async () => {
-    var target = document.getElementById("resizablediv");
-    var old_height = target.offsetHeight;
-    await resize(target, 20, GestureSourceType.TOUCH_INPUT);
-    // The resize expectation includes the touch slop region and is one frame
-    // in the future based on the addition of the values of position and delta.
-    assert_equals(target.offsetHeight - old_height, 55);
-  }, 'Touchscreen drag resizes resizable div');
-
-  promise_test(async () => {
-    var target = document.getElementById("resizablediv");
-    var old_height = target.offsetHeight;
-    await resize(target, 20, GestureSourceType.TOUCHPAD_INPUT);
-    assert_equals(target.offsetHeight - old_height, 0);
-  }, 'Touchpad scroll should not resize resizable div');
-</script>
diff --git a/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt b/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt
index 2a4360a..c8fdad6 100644
--- a/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt
+++ b/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt
@@ -7,6 +7,6 @@
 PASS: offset at (160,26) was 26.
 PASS: offset at (60,25) was 24.
 PASS: offset at (160,25) was 26.
-PASS: offset at (60,24) was 24.
+PASS: offset at (60,24) was 26.
 PASS: offset at (160,24) was 26.
 
diff --git a/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges.html b/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges.html
index 846a8a4..923209f 100644
--- a/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges.html
+++ b/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-hit-test-line-edges.html
@@ -36,6 +36,6 @@
     test(160, 26, 26);
     test(60, 25, 24);
     test(160, 25, 26);
-    test(60, 24, 24);
+    test(60, 24, 26);
     test(160, 24, 26);
 </script>
diff --git a/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-inline-map-local-to-container-expected.html b/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-inline-map-local-to-container-expected.html
index 140cb0d..b6a790b4 100644
--- a/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-inline-map-local-to-container-expected.html
+++ b/third_party/blink/web_tests/fast/writing-mode/flipped-blocks-inline-map-local-to-container-expected.html
@@ -15,7 +15,7 @@
     <img id="t-0">
     <ruby id="t-1">1<span id="t-2">2</span><rt id="t-3">3</rt></ruby>
     <span>
-        <div id="t-4" style="display: inline-block"><div id="t-5">5</div>4</div>
+        <div id="t-4" style="display: inline-block; vertical-align: 40px;"><div id="t-5">5</div>4</div>
     </span>
     <span id="t-5">
         <img id="t-6">
diff --git a/third_party/blink/web_tests/platform/win7/fragmentation/transformed-clip-before-second-column-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/select-ruby-expected.png
similarity index 65%
rename from third_party/blink/web_tests/platform/win7/fragmentation/transformed-clip-before-second-column-expected.png
rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/select-ruby-expected.png
index 30bd211..bf1075b 100644
--- a/third_party/blink/web_tests/platform/win7/fragmentation/transformed-clip-before-second-column-expected.png
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/ruby/select-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt
deleted file mode 100644
index c734702..0000000
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/writing-mode/flipped-blocks-hit-test-line-edges-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Lorem ipsum dolor sit amet
-PASS: offset at (100,105) was 4.
-PASS: offset at (160,105) was 5.
-PASS: offset at (100,104) was 10.
-PASS: offset at (160,104) was 11.
-PASS: offset at (60,26) was 24.
-PASS: offset at (160,26) was 26.
-PASS: offset at (60,25) was 24.
-PASS: offset at (160,25) was 26.
-FAIL: offset at (60,24) was 26. Expected 24.
-PASS: offset at (160,24) was 26.
-
diff --git a/third_party/blink/web_tests/platform/mac/fragmentation/transformed-clip-before-second-column-expected.png b/third_party/blink/web_tests/fragmentation/transformed-clip-before-second-column-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac/fragmentation/transformed-clip-before-second-column-expected.png
rename to third_party/blink/web_tests/fragmentation/transformed-clip-before-second-column-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/devtools/components/file-path-scoring-expected.txt b/third_party/blink/web_tests/http/tests/devtools/components/file-path-scoring-expected.txt
deleted file mode 100644
index 274a5bf..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/components/file-path-scoring-expected.txt
+++ /dev/null
@@ -1,57 +0,0 @@
-Test file path scoring function
-
-Expected score must be equal to the actual score
-Test set size: 588
-
-=== Test query: textepl
-    expected return: ./Source/devtools/front_end/>TextE<ditor.>pl< (score: 45271)
-      actual return: ./Source/devtools/front_end/>TextE<ditor.>pl< (score: 45271)
-
-=== Test query: defted
-    expected return: ./Source/devtools/front_end/>Def<ault>T<ext>Ed<itor.pl (score: 34512)
-      actual return: ./Source/devtools/front_end/>Def<ault>T<ext>Ed<itor.pl (score: 34512)
-
-=== Test query: CMTE
-    expected return: ./Source/devtools/front_end/>C<ode>M<irror>T<ext>E<ditor.pl (score: 28109)
-      actual return: ./Source/devtools/front_end/>C<ode>M<irror>T<ext>E<ditor.pl (score: 28109)
-
-=== Test query: frocmte
-    expected return: ./Source/devtools/>fro<nt_end/>C<ode>M<irror>T<ext>E<ditor.pl (score: 35533)
-      actual return: ./Source/devtools/>fro<nt_end/>C<ode>M<irror>T<ext>E<ditor.pl (score: 35533)
-
-=== Test query: cmtepl
-    expected return: ./Source/devtools/front_end/>C<ode>M<irror>T<ext>E<ditor.>pl< (score: 30157)
-      actual return: ./Source/devtools/front_end/>C<ode>M<irror>T<ext>E<ditor.>pl< (score: 30157)
-
-=== Test query: setscr
-    expected return: ./Source/devtools/front_end/>Set<tings>Scr<een.pl (score: 35283)
-      actual return: ./Source/devtools/front_end/>Set<tings>Scr<een.pl (score: 35283)
-
-=== Test query: cssnfv
-    expected return: ./Source/devtools/front_end/>CSSN<amed>F<low>V<iew.pl (score: 37841)
-      actual return: ./Source/devtools/front_end/>CSSN<amed>F<low>V<iew.pl (score: 37841)
-
-=== Test query: jssf
-    expected return: ./Source/devtools/front_end/>J<ava>S<cript>S<ource>F<rame.pl (score: 21964)
-      actual return: ./Source/devtools/front_end/>J<ava>S<cript>S<ource>F<rame.pl (score: 21964)
-
-=== Test query: sofrapl
-    expected return: ./Source/devtools/front_end/>So<urce>Fra<me.>pl< (score: 36566)
-      actual return: ./Source/devtools/front_end/>So<urce>Fra<me.>pl< (score: 36566)
-
-=== Test query: inspeins
-    expected return: ./Source/core/inspector/>Inspe<ctor>Ins<trumentation.z (score: 52174)
-      actual return: ./Source/core/inspector/>Inspe<ctor>Ins<trumentation.z (score: 52174)
-
-=== Test query: froscr
-    expected return: ./Source/devtools/>fro<nt_end/>Scr<ipt.pl (score: 33755)
-      actual return: ./Source/devtools/>fro<nt_end/>Scr<ipt.pl (score: 33755)
-
-=== Test query: adscon
-    expected return: ./Source/devtools/front_end/>Ad<vanced>S<earch>Con<troller.pl (score: 33225)
-      actual return: ./Source/devtools/front_end/>Ad<vanced>S<earch>Con<troller.pl (score: 33225)
-
-=== Test query: execontext
-    expected return: execution_context/>Exec<utionC>ontext<.cpp (score: 64986)
-      actual return: execution_context/>Exec<utionC>ontext<.cpp (score: 64986)
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/components/file-path-scoring.js b/third_party/blink/web_tests/http/tests/devtools/components/file-path-scoring.js
deleted file mode 100644
index 65e92689..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/components/file-path-scoring.js
+++ /dev/null
@@ -1,83 +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.
-
-(async function() {
-  TestRunner.addResult(`Test file path scoring function\n`);
-  await TestRunner.loadModule('sources_test_runner');
-  await TestRunner.addScriptTag('../resources/example-fileset-for-test.js');
-
-  const TestQueries = [
-    ['textepl', './Source/devtools/front_end/TextEditor.pl'],
-    ['defted', './Source/devtools/front_end/DefaultTextEditor.pl'],
-    ['CMTE', './Source/devtools/front_end/CodeMirrorTextEditor.pl'],
-    ['frocmte', './Source/devtools/front_end/CodeMirrorTextEditor.pl'],
-    ['cmtepl', './Source/devtools/front_end/CodeMirrorTextEditor.pl'],
-    ['setscr', './Source/devtools/front_end/SettingsScreen.pl'],
-    ['cssnfv', './Source/devtools/front_end/CSSNamedFlowView.pl'],
-    ['jssf', './Source/devtools/front_end/JavaScriptSourceFrame.pl'],
-    ['sofrapl', './Source/devtools/front_end/SourceFrame.pl'],
-    ['inspeins', './Source/core/inspector/InspectorInstrumentation.z'],
-    ['froscr', './Source/devtools/front_end/Script.pl'],
-    ['adscon', './Source/devtools/front_end/AdvancedSearchController.pl']
-  ];
-  TestRunner.evaluateInPage('blinkFilePaths()', step1);
-  TestRunner.addResult('Expected score must be equal to the actual score');
-
-  function step1(filePaths) {
-    var files = filePaths.split(':');
-    TestRunner.addResult('Test set size: ' + files.length);
-    for (var i = 0; i < TestQueries.length; ++i) {
-      runQuery(files, TestQueries[i][0], TestQueries[i][1]);
-    }
-
-    runQuery(
-        ['svg/SVGTextRunRenderingContext.cpp', 'execution_context/ExecutionContext.cpp', 'testing/NullExecutionContext.cpp'],
-        'execontext', 'execution_context/ExecutionContext.cpp');
-
-    TestRunner.completeTest();
-  }
-
-  function runQuery(paths, query, expected) {
-    var scorer = new Sources.FilePathScoreFunction(query);
-    var bestScore = -1;
-    var bestIndex = -1;
-    var filter = String.filterRegex(query);
-    for (var i = 0; i < paths.length; ++i) {
-      if (!filter.test(paths[i]))
-        continue;
-      var score = scorer.score(paths[i]);
-      if (score > bestScore) {
-        bestScore = score;
-        bestIndex = i;
-      }
-    }
-    var result = '\n=== Test query: ' + query;
-    result += '\n    expected return: ' + render(scorer, expected);
-    result += '\n      actual return: ' + render(scorer, paths[bestIndex]);
-    TestRunner.addResult(result);
-  }
-
-  function render(scorer, value) {
-    var indexes = [];
-    var score = scorer.score(value, indexes);
-    var result = '';
-    var bold = false;
-    for (var i = 0; i < value.length; ++i) {
-      if (indexes.indexOf(i) !== -1) {
-        if (!bold)
-          result += '>';
-        bold = true;
-        result += value[i];
-      } else {
-        if (bold)
-          result += '<';
-        result += value[i];
-        bold = false;
-      }
-    }
-    if (bold)
-      result += '<';
-    return result + ' (score: ' + score + ')';
-  }
-})();
diff --git a/third_party/blink/web_tests/http/tests/fetch/script-tests/fetch_upload.js b/third_party/blink/web_tests/http/tests/fetch/script-tests/fetch_upload.js
index 9505637e..23ab306 100644
--- a/third_party/blink/web_tests/http/tests/fetch/script-tests/fetch_upload.js
+++ b/third_party/blink/web_tests/http/tests/fetch/script-tests/fetch_upload.js
@@ -94,15 +94,18 @@
   await promise_rejects_js(t, TypeError, fetch_echo(stream));
 }, 'Fetch with ReadableStream body containing number should fail');
 
+function create_foo_stream() {
+  return create_stream(['Foo']).pipeThrough(new TextEncoderStream());
+}
+
 function fetch_redirect(status) {
   const redirect_target_url =
       BASE_ORIGIN + '/fetch/resources/fetch-status.php?status=200';
   const redirect_original_url = BASE_ORIGIN +
       '/serviceworker/resources/redirect.php?Redirect=' + redirect_target_url;
-  const stream = create_stream(['Foo']).pipeThrough(new TextEncoderStream());
   return fetch(
       redirect_original_url + `&Status=${status}`,
-      {method: 'POST', body: stream});
+      {method: 'POST', body: create_foo_stream()});
 }
 
 promise_test(async (t) => {
@@ -113,4 +116,20 @@
   await promise_rejects_js(t, TypeError, fetch_redirect(307));
 }, 'Fetch upload stream should fail on non-303 redirect code');
 
+promise_test(async () => {
+  await fetch('/serviceworker/resources/fetch-access-control.php?AuthFail', {
+    method: 'POST',
+    body: 'foo',
+  });
+}, 'Upload text with 401 Unauthorized response should success.');
+
+promise_test(async (t) => {
+  await promise_rejects_js(
+      t, TypeError,
+      fetch('/serviceworker/resources/fetch-access-control.php?AuthFail', {
+        method: 'POST',
+        body: create_foo_stream(),
+      }));
+}, 'Upload streaming with 401 Unauthorized response should fail.');
+
 done();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt
index 24d2792..15777d1 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt
@@ -1,4 +1,4 @@
 Verify that exposing devtools protocol yields a functional protocol.
 Protocol responses: 2
-Protocol events: 5
+Protocol events: 6
 
diff --git a/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-fixed-position.html b/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-fixed-position.html
index 3218b8d..1e7ea38 100644
--- a/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-fixed-position.html
+++ b/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-fixed-position.html
@@ -17,11 +17,16 @@
   width: 1px;
   height: 1px;
 }
+p {
+  position: fixed;
+}
 </style>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 </head>
 <body marginwidth="0" marginheight="0">
+<!-- To trigger the first contentful paint at the very start -->
+<p>some content</p>
 <!-- To be positioned further down in the main page to make the page scrollable -->
 <div class="bottom"></div>
 <script>
diff --git a/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-frequent-reposition.html b/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-frequent-reposition.html
index 3723010..1dc3674 100644
--- a/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-frequent-reposition.html
+++ b/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-bottom-frequent-reposition.html
@@ -17,11 +17,16 @@
   width: 1px;
   height: 1px;
 }
+p {
+  position: fixed;
+}
 </style>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 </head>
 <body marginwidth="0" marginheight="0">
+<!-- To trigger the first contentful paint at the very start -->
+<p>some content</p>
 <!-- To be positioned further down in the main page to make the page scrollable -->
 <div class="bottom"></div>
 <script>
diff --git a/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-center-no-use-counter.html b/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-center-no-use-counter.html
index f7be936..a9297e29 100644
--- a/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-center-no-use-counter.html
+++ b/third_party/blink/web_tests/http/tests/subresource_filter/large-sticky-ad-center-no-use-counter.html
@@ -17,11 +17,16 @@
   width: 1px;
   height: 1px;
 }
+p {
+  position: fixed;
+}
 </style>
 <script src="../resources/testharness.js"></script>
 <script src="../resources/testharnessreport.js"></script>
 </head>
 <body marginwidth="0" marginheight="0">
+<!-- To trigger the first contentful paint at the very start -->
+<p>some content</p>
 <!-- To be positioned further down in the main page to make the page scrollable -->
 <div class="bottom"></div>
 <script>
diff --git a/third_party/blink/web_tests/http/tests/subresource_filter/parallax-ad-no-large-sticky-ad-use-counter.html b/third_party/blink/web_tests/http/tests/subresource_filter/parallax-ad-no-large-sticky-ad-use-counter.html
index 2b9cb34..2afce29 100644
--- a/third_party/blink/web_tests/http/tests/subresource_filter/parallax-ad-no-large-sticky-ad-use-counter.html
+++ b/third_party/blink/web_tests/http/tests/subresource_filter/parallax-ad-no-large-sticky-ad-use-counter.html
@@ -33,6 +33,9 @@
   border: 0px;
   background-color: blue;
 }
+p {
+  position: fixed;
+}
 </style>
 
 <script src="../resources/testharness.js"></script>
@@ -40,6 +43,9 @@
 </head>
 <body marginwidth="0" marginheight="0">
 
+<!-- To trigger the first contentful paint at the very start -->
+<p>some content</p>
+
 <div class="content1">some content</div>
 <div class="empty"></div>
 <div class="content2">some content</div>
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events-expected.txt
index bcfc06b..9daa650d2 100644
--- a/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events-expected.txt
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events-expected.txt
@@ -8,6 +8,7 @@
             endLine : 4
             frameId : <string>
             isInline : false
+            isMutable : false
             length : <number>
             origin : regular
             ownerNode : <number>
@@ -28,6 +29,28 @@
     sessionId : <string>
 }
 {
+    method : CSS.styleSheetAdded
+    params : {
+        header : {
+            disabled : false
+            endColumn : 6
+            endLine : 4
+            frameId : <string>
+            isInline : false
+            isMutable : true
+            length : <number>
+            origin : regular
+            ownerNode : <number>
+            sourceURL : 
+            startColumn : 0
+            startLine : 0
+            styleSheetId : <string>
+            title : 
+        }
+    }
+    sessionId : <string>
+}
+{
     method : CSS.styleSheetRemoved
     params : {
         styleSheetId : <string>
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events.js b/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events.js
index a2730e53a..1309226 100644
--- a/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events.js
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-style-sheet-events.js
@@ -13,8 +13,9 @@
   await cssHelper.requestDocumentNodeId();
 
   // Add Event
-  dp.CSS.enable();
-  const addEvent = await dp.CSS.onceStyleSheetAdded();
+  const addEventPromise = dp.CSS.onceStyleSheetAdded();
+  await dp.CSS.enable();
+  const addEvent = await addEventPromise;
   testRunner.log(addEvent, '', [ ...TestRunner.stabilizeNames, 'length' ]);
   const styleSheetId = addEvent.params.header.styleSheetId;
 
@@ -31,10 +32,15 @@
   const changedEvent = await dp.CSS.onceStyleSheetChanged();
   testRunner.log(changedEvent);
 
+  await dp.CSS.disable();
+  const addEventAfterChangePromise = dp.CSS.onceStyleSheetAdded();
+  await dp.CSS.enable();
+  const addEventAfterChange = await addEventAfterChangePromise;
+  testRunner.log(addEventAfterChange, '', [ ...TestRunner.stabilizeNames, 'length' ]);
+
   // Remove event
   await dp.Page.navigate({url: 'about:blank'});
   const removeEvent = await dp.CSS.onceStyleSheetRemoved();
   testRunner.log(removeEvent);
   testRunner.completeTest();
 });
-
diff --git a/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt b/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
new file mode 100644
index 0000000..13fbffc
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
@@ -0,0 +1,11 @@
+Test passes if the fallback font selected for the Unicode Private Use Area test text is the priority font.
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_mono:
+"Cousine" : 14
+
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_serif:
+"Tinos" : 14
+
+PASS
+
diff --git a/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-first-candidate.js b/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-first-candidate.js
new file mode 100644
index 0000000..f4a7bc6f
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-first-candidate.js
@@ -0,0 +1,21 @@
+(async function(testRunner) {
+  var page = await testRunner.createPage();
+  await page.loadHTML(`
+    <html>
+    <meta charset="UTF-8">
+    <body>
+        <div class="test">
+            <!-- Private use area Ranges: U+E000..U+F8FF, U+F0000..U+FFFFF, U+100000..U+10FFFF -->
+            <div id="pua_test_mono" style="font-family: monospace;">abc&#xE000;&#xE401;&#xE402;&#xE403;&#xF8FF;&#xF0000;&#xFAAAA;&#xFFFFF;&#x100000;&#x10AAAA;&#x10FFFF;</div>
+            <div id="pua_test_serif" style="font-family: serif;">abc&#xE000;&#xE401;&#xE402;&#xE403;&#xF8FF;&#xF0000;&#xFAAAA;&#xFFFFF;&#x100000;&#x10AAAA;&#x10FFFF;</div>
+        </div>
+    </body>
+    </html>
+  `);
+  var session = await page.createSession();
+  testRunner.log(`Test passes if the fallback font selected for the Unicode Private Use Area test text is the priority font.`);
+
+  var helper = await testRunner.loadScript('./resources/layout-font-test.js');
+  var results = await helper(testRunner, session);
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt b/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
deleted file mode 100644
index 7c3bace..0000000
--- a/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Test passes if the fallback font selected for the Unicode Private Use Area test text matches known last resort fonts on each platform.
-󰀀󺪪󿿿􀀀􊪪􏿿
-#pua_test_run:
-"DejaVu Sans" : 11
-
-PASS
-
diff --git a/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-last-resort.js b/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-last-resort.js
deleted file mode 100644
index f41eb23e..0000000
--- a/third_party/blink/web_tests/inspector-protocol/layout-fonts/fallback-pua-last-resort.js
+++ /dev/null
@@ -1,24 +0,0 @@
-(async function(testRunner) {
-  var page = await testRunner.createPage();
-  await page.loadHTML(`
-    <html>
-    <meta charset="UTF-8">
-    <body>
-        <div class="test">
-            <!-- Private use area Ranges: U+E000..U+F8FF, U+F0000..U+FFFFF, U+100000..U+10FFFF -->
-            <div id="pua_test_run">&#xE000;&#xE401;&#xE402;&#xE403;&#xF8FF;&#xF0000;&#xFAAAA;&#xFFFFF;&#x100000;&#x10AAAA;&#x10FFFF;</div>
-        </div>
-    </body>
-    </html>
-  `);
-  var session = await page.createSession();
-  testRunner.log(`Test passes if the fallback font selected for the Unicode Private Use Area test text matches known last resort fonts on each platform.`);
-
-  var helper = await testRunner.loadScript('./resources/layout-font-test.js');
-  var results = await helper(testRunner, session);
-
-  var pua_used_fonts = results.find(x => x.selector === '#pua_test_run').usedFonts;
-  var passed = pua_used_fonts.length === 1 && /^(Times New Roman|Times|DejaVu Sans|Arial)$/.test(pua_used_fonts[0].familyName) && pua_used_fonts[0].glyphCount == 11;
-  testRunner.log(passed ? 'PASS' : 'FAIL');
-  testRunner.completeTest();
-})
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..264daa9
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
index 478c24a..d08d192 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-transform-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-transform-expected.png
index e227ef0..a3a9168 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-transform-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/datalist/input-appearance-range-with-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/range/slider-padding-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/range/slider-padding-expected.png
index 57ad5b11..64156aa 100644
--- a/third_party/blink/web_tests/platform/linux/fast/forms/range/slider-padding-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/range/slider-padding-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fast/ruby/select-ruby-expected.png b/third_party/blink/web_tests/platform/linux/fast/ruby/select-ruby-expected.png
index bf1075b..08ad322d 100644
--- a/third_party/blink/web_tests/platform/linux/fast/ruby/select-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fast/ruby/select-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/fragmentation/transformed-clip-before-second-column-expected.png b/third_party/blink/web_tests/platform/linux/fragmentation/transformed-clip-before-second-column-expected.png
index 3c9bd03..8e2bf8f 100644
--- a/third_party/blink/web_tests/platform/linux/fragmentation/transformed-clip-before-second-column-expected.png
+++ b/third_party/blink/web_tests/platform/linux/fragmentation/transformed-clip-before-second-column-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png b/third_party/blink/web_tests/platform/linux/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png
deleted file mode 100644
index 4c91e98b..0000000
--- a/third_party/blink/web_tests/platform/linux/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt b/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
new file mode 100644
index 0000000..17d0f8a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
@@ -0,0 +1,10 @@
+Test passes if the fallback font selected for the Unicode Private Use Area test text is the priority font.
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_mono:
+"Cousine" : 14
+
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_serif:
+"Tinos" : 14
+
+
diff --git a/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt b/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
deleted file mode 100644
index 7c3bace..0000000
--- a/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Test passes if the fallback font selected for the Unicode Private Use Area test text matches known last resort fonts on each platform.
-󰀀󺪪󿿿􀀀􊪪􏿿
-#pua_test_run:
-"DejaVu Sans" : 11
-
-PASS
-
diff --git a/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/lang-fallback-expected.txt b/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/lang-fallback-expected.txt
index c720698c..701215d 100644
--- a/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/lang-fallback-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/lang-fallback-expected.txt
@@ -16,7 +16,7 @@
 
 ᨀᨁ
 #bug:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ᐐᐑ
 #cans:
@@ -24,23 +24,23 @@
 
 𐊠𐊡
 #xcr:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ᎡᎢ
 #chr:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ⲁⲂ
 #copt:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𒀀𒀌
 #akk:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐠀𐠁
 #ecy:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 АБВ
 #ru:
@@ -48,7 +48,7 @@
 
 𐐀𐐁
 #en:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 अआ
 #hi:
@@ -56,7 +56,7 @@
 
 ሁሂ
 #am:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ႠႡ
 #ka:
@@ -104,27 +104,27 @@
 
 𐡁𐡂
 #arc:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐭡𐭢
 #pal:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐭁𐭂
 #xpr:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ꦑꦒ
 #jv:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ಡಢ
 #kn:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐨐𐨑
 #sa:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ໐໑
 #lo:
@@ -136,27 +136,27 @@
 
 𐊁𐊂
 #xlc:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐤡𐤢
 #xld:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ഡഢ
 #ml:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐦡𐦢
 #script_meroitic:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ကခ
 #my:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ᦁᦂ
 #script_new_tai_lue:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ߁߂
 #nko:
@@ -168,7 +168,7 @@
 
 ᱑᱒
 #script_ol_chiki:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐌁𐌂
 #script_old_italic:
@@ -176,43 +176,43 @@
 
 𐎡𐎢
 #peo:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐩡𐩢
 #script_old_south_arabian:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ଡଢ
 #or:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ꡁꡂ
 #script_phags_pa:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ᚠᚡ
 #script_runic:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𐑑𐑒
 #script_shavian:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 එඒ
 #si:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 𑃑𑃒
 #script_sora_sompeng:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ܑܒ
 #syr:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ᥑᥒ
 #script_tai_le:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 றல
 #ta:
@@ -220,11 +220,11 @@
 
 డఢ
 #te:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ށނ
 #script_thaana:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 กข
 #th:
@@ -232,7 +232,7 @@
 
 ༁༂
 #bo:
-"DejaVu Sans" : 2
+"Noto Sans Tibetan" : 2
 
 ⴱⴲ
 #script_tifinagh:
@@ -240,10 +240,10 @@
 
 ꔁꔂ
 #vai:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 ꀀꀁ
 #yi:
-"DejaVu Sans" : 2
+"Tinos" : 2
 
 
diff --git a/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt b/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
index ae8e24a..657be5a 100644
--- a/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
+++ b/third_party/blink/web_tests/platform/linux/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
@@ -30,7 +30,7 @@
 
 𓀀𓀁𓀂𓀃𓀄𓀅𓀆𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏
 #egyptian_hieroglyphs:
-"DejaVu Sans" : 16
+"Tinos" : 16
 
 ខ្ញុំអាចញុំកញ្ចក់បាន ដោយគ្មានបញ្ហារ
 #khmer:
@@ -39,15 +39,16 @@
 
 𐌲𐌿𐍄𐌹𐍃𐌺
 #gothic:
-"DejaVu Sans" : 6
+"Tinos" : 6
 
 ܐܬܘܪܝܐ
 #syriac:
-"DejaVu Sans" : 6
+"Tinos" : 6
 
 ⇦⇧⇨⇩←↑→↓⟀
 #text_presentation_arrows_maths:
-"DejaVu Sans" : 5,
-"Noto Sans CJK JP Regular" : 4
+"Noto Sans CJK JP Regular" : 4,
+"DejaVu Sans" : 4,
+"Tinos" : 1
 
 
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/combining-character-queries-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/combining-character-queries-expected.png
index 485f664..c1a4969 100644
--- a/third_party/blink/web_tests/platform/linux/svg/text/combining-character-queries-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/text/combining-character-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/non-bmp-positioning-lists-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/non-bmp-positioning-lists-expected.png
index c5bddcc7..70f2d57 100644
--- a/third_party/blink/web_tests/platform/linux/svg/text/non-bmp-positioning-lists-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/text/non-bmp-positioning-lists-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/text/surrogate-pair-queries-expected.png b/third_party/blink/web_tests/platform/linux/svg/text/surrogate-pair-queries-expected.png
index 44b22f02..a12066d 100644
--- a/third_party/blink/web_tests/platform/linux/svg/text/surrogate-pair-queries-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/text/surrogate-pair-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/range/range-appearance-border-padding-expected.png b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/range/range-appearance-border-padding-expected.png
new file mode 100644
index 0000000..1d4a88b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/controls-refresh/range/range-appearance-border-padding-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png
deleted file mode 100644
index a0ef06f..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/blink/web_tests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
deleted file mode 100644
index ea3ef0b..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/linux/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..3247ec2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/linux/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ab0b700
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
index d248757a..7b84ccb 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index f94e72a..36e326a 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/font-fallback-expected.png b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/font-fallback-expected.png
index d8dd5b8..152344f 100644
--- a/third_party/blink/web_tests/platform/linux/virtual/text-antialias/font-fallback-expected.png
+++ b/third_party/blink/web_tests/platform/linux/virtual/text-antialias/font-fallback-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..adb8b9c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+PASS getStats() with track added via addTransceiver should succeed
+PASS getStats() with track associated with more than one sender should reject with InvalidAccessError
+PASS getStats() with track associated with both sender and receiver should reject with InvalidAccessError
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..71b17fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf6131
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/emoticons-expected.png
index 56f1cb19..ca2cc8d50 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/emoticons-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/unicode-fallback-font-expected.png
index 3471e7f..02f06454 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/unicode-fallback-font-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/text-antialias/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.10/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..3b88194b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.10/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+FAIL getStats() with track added via addTransceiver should succeed promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with more than one sender should reject with InvalidAccessError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with both sender and receiver should reject with InvalidAccessError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..71b17fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf6131
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/emoticons-expected.png
index 2af5a6e8..b54aa84 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/emoticons-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/unicode-fallback-font-expected.png
index 201eca9..8001ca6 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/unicode-fallback-font-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/text-antialias/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.11/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..b57889c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.11/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+FAIL getStats() with track added via addTransceiver should succeed promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with more than one sender should reject with InvalidAccessError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with both sender and receiver should reject with InvalidAccessError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.address to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/combining-character-queries-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/combining-character-queries-expected.png
index a36b349..2c3b65f 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/combining-character-queries-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/svg/text/combining-character-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..71b17fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf6131
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/emoticons-expected.png
index ea67c862..60d86843 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/emoticons-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/unicode-fallback-font-expected.png
index 61437c4..533f375 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/unicode-fallback-font-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/text-antialias/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..0d95768
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+PASS getStats() with track added via addTransceiver should succeed
+PASS getStats() with track associated with more than one sender should reject with InvalidAccessError
+PASS getStats() with track associated with both sender and receiver should reject with InvalidAccessError
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.address to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/select-ruby-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/select-ruby-expected.png
index ccf287e..9ea5f18 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/select-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/fast/ruby/select-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..71b17fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf6131
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/emoticons-expected.png
index e1bbab9..a6044ae 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/emoticons-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/unicode-fallback-font-expected.png
index 7c71434..fedad445 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/unicode-fallback-font-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/text-antialias/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..3b88194b
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+FAIL getStats() with track added via addTransceiver should succeed promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with more than one sender should reject with InvalidAccessError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with both sender and receiver should reject with InvalidAccessError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt
deleted file mode 100644
index 24d2792..0000000
--- a/third_party/blink/web_tests/platform/mac-mac10.14/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Verify that exposing devtools protocol yields a functional protocol.
-Protocol responses: 2
-Protocol events: 5
-
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/svg/text/combining-character-queries-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/svg/text/combining-character-queries-expected.png
index 817c32a..5139ef1 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/svg/text/combining-character-queries-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/svg/text/combining-character-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..71b17fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf6131
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/emoticons-expected.png
index 3df76a3..252659b 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/emoticons-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/unicode-fallback-font-expected.png
index f5137498..6fff1aaa 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/unicode-fallback-font-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/text-antialias/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..b57889c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+FAIL getStats() with track added via addTransceiver should succeed promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with more than one sender should reject with InvalidAccessError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with both sender and receiver should reject with InvalidAccessError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.address to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..71b17fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf6131
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/text-antialias/color-emoji-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/text-antialias/color-emoji-expected.png
new file mode 100644
index 0000000..519c662
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/text-antialias/color-emoji-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/mac-retina/virtual/text-antialias/emoticons-expected.png
new file mode 100644
index 0000000..c3741f0
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-retina/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/platform/mac-retina/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..b57889c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-retina/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+FAIL getStats() with track added via addTransceiver should succeed promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with more than one sender should reject with InvalidAccessError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with both sender and receiver should reject with InvalidAccessError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.address to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/platform/mac/editing/selection/continuations-with-move-caret-to-boundary-expected.txt b/third_party/blink/web_tests/platform/mac/editing/selection/continuations-with-move-caret-to-boundary-expected.txt
deleted file mode 100644
index fdc00e0..0000000
--- a/third_party/blink/web_tests/platform/mac/editing/selection/continuations-with-move-caret-to-boundary-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-PASS Continuations across a block -20
-FAIL Continuations across a block -15 resources/testharness.js:1977:25)
-	 expected <style>* { font: 20px Ahem; }</style><p>^AAAAA</p><p>|BBBBB</p>,
-	 but got  <style>* { font: 20px Ahem; }</style><p>^AAAAA</p><p>BB|BBB</p>,
-	 sameupto <style>* { font: 20px Ahem; }</style><p>^AAAAA</p><p>
-PASS Continuations across a block 5
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..ea4ee24
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
index a158ce3..8d78a69 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-transform-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-transform-expected.png
index 85508e32..a457e59b 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-transform-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/datalist/input-appearance-range-with-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf0ea7
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/range/range-appearance-basic-expected.png
index d1eef0fc..4fd2e72f 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/range/slider-padding-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/range/slider-padding-expected.png
index 585c89e..e3a95b0 100644
--- a/third_party/blink/web_tests/platform/mac/fast/forms/range/slider-padding-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/range/slider-padding-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/ruby/select-ruby-expected.png b/third_party/blink/web_tests/platform/mac/fast/ruby/select-ruby-expected.png
index ea7f2f6..79a167d4 100644
--- a/third_party/blink/web_tests/platform/mac/fast/ruby/select-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/mac/fast/ruby/select-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png b/third_party/blink/web_tests/platform/mac/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png
deleted file mode 100644
index b33b64f9..0000000
--- a/third_party/blink/web_tests/platform/mac/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt b/third_party/blink/web_tests/platform/mac/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt
deleted file mode 100644
index 15777d1..0000000
--- a/third_party/blink/web_tests/platform/mac/http/tests/inspector-protocol/target/target-expose-devtools-protocol-expected.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-Verify that exposing devtools protocol yields a functional protocol.
-Protocol responses: 2
-Protocol events: 6
-
diff --git a/third_party/blink/web_tests/platform/mac/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt b/third_party/blink/web_tests/platform/mac/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
new file mode 100644
index 0000000..d0f98b3e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
@@ -0,0 +1,10 @@
+Test passes if the fallback font selected for the Unicode Private Use Area test text is the priority font.
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_mono:
+"Courier" : 14
+
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_serif:
+"Times" : 14
+
+
diff --git a/third_party/blink/web_tests/platform/mac/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt b/third_party/blink/web_tests/platform/mac/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
deleted file mode 100644
index 34900e5..0000000
--- a/third_party/blink/web_tests/platform/mac/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Test passes if the fallback font selected for the Unicode Private Use Area test text matches known last resort fonts on each platform.
-󰀀󺪪󿿿􀀀􊪪􏿿
-#pua_test_run:
-"Times" : 11
-
-PASS
-
diff --git a/third_party/blink/web_tests/platform/mac/svg/text/combining-character-queries-expected.png b/third_party/blink/web_tests/platform/mac/svg/text/combining-character-queries-expected.png
index ccc9f6e..1a46600 100644
--- a/third_party/blink/web_tests/platform/mac/svg/text/combining-character-queries-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/text/combining-character-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/text/non-bmp-positioning-lists-expected.png b/third_party/blink/web_tests/platform/mac/svg/text/non-bmp-positioning-lists-expected.png
index d5468dc..36ae918 100644
--- a/third_party/blink/web_tests/platform/mac/svg/text/non-bmp-positioning-lists-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/text/non-bmp-positioning-lists-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/range/range-appearance-border-padding-expected.png b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/range/range-appearance-border-padding-expected.png
new file mode 100644
index 0000000..412082cf
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/controls-refresh/range/range-appearance-border-padding-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png
deleted file mode 100644
index 59e64ca..0000000
--- a/third_party/blink/web_tests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.txt
deleted file mode 100644
index 7b9924a3..0000000
--- a/third_party/blink/web_tests/platform/mac/virtual/display_list_2d_canvas/fast/canvas/canvas-shadow-source-in-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-layer at (0,0) size 800x600
-  LayoutView at (0,0) size 800x600
-layer at (0,0) size 800x464
-  LayoutBlockFlow {HTML} at (0,0) size 800x464
-    LayoutBlockFlow {BODY} at (8,8) size 784x448
-      LayoutBlockFlow {DIV} at (0,0) size 784x18
-        LayoutText {#text} at (0,0) size 60x18
-          text run at (0,0) width 60: "Test Rect"
-      LayoutBlockFlow (anonymous) at (0,18) size 784x206
-        LayoutText {#text} at (0,0) size 0x0
-      LayoutBlockFlow {DIV} at (0,224) size 784x18
-        LayoutText {#text} at (0,0) size 71x18
-          text run at (0,0) width 71: "Test Image"
-      LayoutBlockFlow (anonymous) at (0,242) size 784x206
-        LayoutText {#text} at (0,0) size 0x0
-layer at (8,26) size 202x202
-  LayoutHTMLCanvas {CANVAS} at (0,0) size 202x202 [border: (1px solid #999999)]
-layer at (8,250) size 202x202
-  LayoutHTMLCanvas {CANVAS} at (0,0) size 202x202 [border: (1px solid #999999)]
diff --git a/third_party/blink/web_tests/platform/mac/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/mac/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..71b17fa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/mac/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ddf6131
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
index 071ddee..d703da11 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 96b6e7e..bf73a7d 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/emoticons-expected.png
index 5365137..814434ae 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/emoticons-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/unicode-fallback-font-expected.png
index 8c3b393..e945001e 100644
--- a/third_party/blink/web_tests/platform/mac/virtual/text-antialias/unicode-fallback-font-expected.png
+++ b/third_party/blink/web_tests/platform/mac/virtual/text-antialias/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..e15d8f2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
index d0c1afac..84e7ac8d 100644
--- a/third_party/blink/web_tests/platform/win/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/forms/datalist/input-appearance-range-with-padding-with-datalist-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..4c4142f6
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/range/range-appearance-basic-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/range/range-appearance-basic-expected.png
index 5fbded7f..ccf8a240 100644
--- a/third_party/blink/web_tests/platform/win/fast/forms/range/range-appearance-basic-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/forms/range/range-appearance-basic-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/range/slider-padding-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/range/slider-padding-expected.png
index 964850a..48c0790a 100644
--- a/third_party/blink/web_tests/platform/win/fast/forms/range/slider-padding-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/forms/range/slider-padding-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/select-ruby-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/select-ruby-expected.png
index 89d6da8..f6d64c0 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/select-ruby-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/select-ruby-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png b/third_party/blink/web_tests/platform/win/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png
deleted file mode 100644
index 4cff074..0000000
--- a/third_party/blink/web_tests/platform/win/http/tests/images/feature-policy-unoptimized-lossless-images-strict-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt b/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
new file mode 100644
index 0000000..d06276e
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/fallback-pua-first-candidate-expected.txt
@@ -0,0 +1,10 @@
+Test passes if the fallback font selected for the Unicode Private Use Area test text is the priority font.
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_mono:
+"Courier New" : 14
+
+abc󰀀󺪪󿿿􀀀􊪪􏿿
+#pua_test_serif:
+"Times New Roman" : 14
+
+
diff --git a/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt b/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
deleted file mode 100644
index be7b176..0000000
--- a/third_party/blink/web_tests/platform/win/inspector-protocol/layout-fonts/fallback-pua-last-resort-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-Test passes if the fallback font selected for the Unicode Private Use Area test text matches known last resort fonts on each platform.
-󰀀󺪪󿿿􀀀􊪪􏿿
-#pua_test_run:
-"Arial" : 11
-
-PASS
-
diff --git a/third_party/blink/web_tests/platform/win/svg/text/combining-character-queries-expected.png b/third_party/blink/web_tests/platform/win/svg/text/combining-character-queries-expected.png
index b912545..1828e90 100644
--- a/third_party/blink/web_tests/platform/win/svg/text/combining-character-queries-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/text/combining-character-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/text/surrogate-pair-queries-expected.png b/third_party/blink/web_tests/platform/win/svg/text/surrogate-pair-queries-expected.png
index a963dfa..7b205a2e 100644
--- a/third_party/blink/web_tests/platform/win/svg/text/surrogate-pair-queries-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/text/surrogate-pair-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/controls-refresh/range/range-appearance-border-padding-expected.png b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/range/range-appearance-border-padding-expected.png
new file mode 100644
index 0000000..eb04289
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/controls-refresh/range/range-appearance-border-padding-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png
deleted file mode 100644
index b7d90e6..0000000
--- a/third_party/blink/web_tests/platform/win/virtual/display_list_2d_canvas/fast/canvas/canvas-composite-shadow-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/win/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..34b83e33
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/win/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ab0b700
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
index c49b72e..6b9b402a 100644
--- a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
index 862ab6a..3b33dcd 100644
--- a/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/fallback-myanmar-expected.txt b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/fallback-myanmar-expected.txt
index 1858f01..7378c948 100644
--- a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/fallback-myanmar-expected.txt
+++ b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/fallback-myanmar-expected.txt
@@ -1,7 +1,7 @@
 Test passes if a maxmium of the two first glyphs are notdef's (for Myanmar fonts that do not combine a left quote with a Myanmar spacing mark and the rest of the run is shaped, given a system Myanmar font is available.
 ‘ေရွးျမန္မာမင္းေတြလက္ထက္က
 #myanmar:
-"Arial" : 25
+"Times New Roman" : 25
 
 FAIL
 
diff --git a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt
index 498be4d5..3cf67f9 100644
--- a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt
+++ b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/lang-fallback-expected.txt
@@ -16,7 +16,7 @@
 
 ᨀᨁ
 #bug:
-"Arial" : 2
+"Times New Roman" : 2
 
 ᐐᐑ
 #cans:
@@ -24,23 +24,23 @@
 
 𐊠𐊡
 #xcr:
-"Arial" : 2
+"Times New Roman" : 2
 
 ᎡᎢ
 #chr:
-"Arial" : 2
+"Times New Roman" : 2
 
 ⲁⲂ
 #copt:
-"Arial" : 2
+"Times New Roman" : 2
 
 𒀀𒀌
 #akk:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐠀𐠁
 #ecy:
-"Arial" : 2
+"Times New Roman" : 2
 
 АБВ
 #ru:
@@ -48,7 +48,7 @@
 
 𐐀𐐁
 #en:
-"Arial" : 2
+"Times New Roman" : 2
 
 अआ
 #hi:
@@ -60,7 +60,7 @@
 
 ႠႡ
 #ka:
-"Arial" : 2
+"Times New Roman" : 2
 
 ΑΒ
 #el:
@@ -104,19 +104,19 @@
 
 𐡁𐡂
 #arc:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐭡𐭢
 #pal:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐭁𐭂
 #xpr:
-"Arial" : 2
+"Times New Roman" : 2
 
 ꦑꦒ
 #jv:
-"Arial" : 2
+"Times New Roman" : 2
 
 ಡಢ
 #kn:
@@ -124,7 +124,7 @@
 
 𐨐𐨑
 #sa:
-"Arial" : 2
+"Times New Roman" : 2
 
 ໐໑
 #lo:
@@ -132,15 +132,15 @@
 
 ꓐꓑ
 #lis:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐊁𐊂
 #xlc:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐤡𐤢
 #xld:
-"Arial" : 2
+"Times New Roman" : 2
 
 ഡഢ
 #ml:
@@ -148,11 +148,11 @@
 
 𐦡𐦢
 #script_meroitic:
-"Arial" : 2
+"Times New Roman" : 2
 
 ကခ
 #my:
-"Arial" : 2
+"Times New Roman" : 2
 
 ᦁᦂ
 #script_new_tai_lue:
@@ -168,19 +168,19 @@
 
 ᱑᱒
 #script_ol_chiki:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐌁𐌂
 #script_old_italic:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐎡𐎢
 #peo:
-"Arial" : 2
+"Times New Roman" : 2
 
 𐩡𐩢
 #script_old_south_arabian:
-"Arial" : 2
+"Times New Roman" : 2
 
 ଡଢ
 #or:
@@ -196,7 +196,7 @@
 
 𐑑𐑒
 #script_shavian:
-"Arial" : 2
+"Times New Roman" : 2
 
 එඒ
 #si:
@@ -204,7 +204,7 @@
 
 𑃑𑃒
 #script_sora_sompeng:
-"Arial" : 2
+"Times New Roman" : 2
 
 ܑܒ
 #syr:
diff --git a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
index 26a4cf6..aa10419 100644
--- a/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
+++ b/third_party/blink/web_tests/platform/win7/inspector-protocol/layout-fonts/languages-emoji-rare-glyphs-expected.txt
@@ -25,12 +25,11 @@
 🌱🌲🌳🌴🌵🌷🌸🌹🌺🌻🌼💐🌾🌿🍀🍁🍂🍃🍄🌰☺️😀👪
 #emoji:
 "Segoe UI Symbol" : 19,
-"Arial" : 3,
-"Times New Roman" : 2
+"Times New Roman" : 5
 
 𓀀𓀁𓀂𓀃𓀄𓀅𓀆𓀇𓀈𓀉𓀊𓀋𓀌𓀍𓀎𓀏
 #egyptian_hieroglyphs:
-"Arial" : 16
+"Times New Roman" : 16
 
 ខ្ញុំអាចញុំកញ្ចក់បាន ដោយគ្មានបញ្ហារ
 #khmer:
@@ -49,6 +48,6 @@
 #text_presentation_arrows_maths:
 "MS PGothic" : 4,
 "Cambria Math" : 4,
-"Arial" : 1
+"Times New Roman" : 1
 
 
diff --git a/third_party/blink/web_tests/platform/win7/svg/text/surrogate-pair-queries-expected.png b/third_party/blink/web_tests/platform/win7/svg/text/surrogate-pair-queries-expected.png
index 0d2139f5..9a161f6 100644
--- a/third_party/blink/web_tests/platform/win7/svg/text/surrogate-pair-queries-expected.png
+++ b/third_party/blink/web_tests/platform/win7/svg/text/surrogate-pair-queries-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png b/third_party/blink/web_tests/platform/win7/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
new file mode 100644
index 0000000..34b83e33
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/form-controls-refresh-disabled/fast/forms/datalist/input-appearance-range-with-datalist-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png b/third_party/blink/web_tests/platform/win7/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
new file mode 100644
index 0000000..ab0b700
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win7/virtual/form-controls-refresh-disabled/fast/forms/range/input-appearance-range-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/color-emoji-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/color-emoji-expected.png
index f575ef5..1353811 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/color-emoji-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/color-emoji-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/emoticons-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/emoticons-expected.png
index 0a5c370..44658d0 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/emoticons-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/emoticons-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/font-fallback-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/font-fallback-expected.png
index 61ee5a9..eef28f4 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/font-fallback-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/font-fallback-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/unicode-fallback-font-expected.png b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/unicode-fallback-font-expected.png
index 6698225..625f928 100644
--- a/third_party/blink/web_tests/platform/win7/virtual/text-antialias/unicode-fallback-font-expected.png
+++ b/third_party/blink/web_tests/platform/win7/virtual/text-antialias/unicode-fallback-font-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/controls-refresh/range/range-appearance-border-padding.html b/third_party/blink/web_tests/virtual/controls-refresh/range/range-appearance-border-padding.html
new file mode 100644
index 0000000..133586e
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/controls-refresh/range/range-appearance-border-padding.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<script src="../../../resources/run-after-layout-and-paint.js"></script>
+<script src="../../../fast/forms/resources/common.js"></script>
+<body>
+<ul>
+  <li>Range value=50 with padding: <input type="range" min="0" max="100" value="50" style="padding:20px" /> </li>
+  <li>Range value=30 with padding-left: <input type="range" min="0" max="100" value="30" style="padding-left:20px" /> </li>
+  <li>Range value=50 with border and padding: <input type="range" min="0" max="100" value="50" style="border: 15px solid blue; padding:20px" /> </li>
+  <li>Range vertical value=50 with border and padding: <input type="range" min="0" max="100" value="50" style="border: 15px solid blue; padding:20px; -webkit-appearance: slider-vertical" /> </li>
+  <li>Range RTL value=30: <input type="range" min="0" max="100" value="30" style="direction: rtl" /> </li>
+  <li>Range RTL value=80 with border and padding: <input type="range" min="0" max="100" value="80" style="border: 15px solid blue; padding:20px; direction: rtl" /> </li>
+</ul>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png b/third_party/blink/web_tests/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
new file mode 100644
index 0000000..7b84ccb
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/gpu/fast/canvas/canvas-composite-shadow-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png b/third_party/blink/web_tests/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
new file mode 100644
index 0000000..36e326a
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/gpu/fast/canvas/canvas-shadow-source-in-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
new file mode 100644
index 0000000..3b88194b
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https-expected.txt
@@ -0,0 +1,16 @@
+This is a testharness.js-based test.
+PASS getStats() with no argument should succeed
+PASS getStats(null) should succeed
+PASS getStats() with track not added to connection should reject with InvalidAccessError
+PASS getStats() with track added via addTrack should succeed
+FAIL getStats() with track added via addTransceiver should succeed promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with more than one sender should reject with InvalidAccessError promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL getStats() with track associated with both sender and receiver should reject with InvalidAccessError Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'.
+PASS getStats() with no argument should return stats report containing peer-connection stats on an empty PC
+FAIL getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats assert_true: Expect statsReport to contain stats object of type outbound-rtp expected true got false
+FAIL getStats() with no argument should return stats for no-stream tracks assert_equals: Expect dictionary.totalAudioEnergy to be number expected "number" but got "undefined"
+FAIL getStats() on track associated with RtpSender should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+FAIL getStats() on track associated with RtpReceiver should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
+FAIL getStats() with connected peer connections having tracks and data channel should return all mandatory to implement stats assert_unreached: test failed with error: Error: assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined" Reached unreachable code
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpReceiver-getStats.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpReceiver-getStats.https-expected.txt
new file mode 100644
index 0000000..9aacd7bb1
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpReceiver-getStats.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL receiver.getStats() via addTransceiver should return stats report containing inbound-rtp stats promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL receiver.getStats() via addTrack should return stats report containing inbound-rtp stats assert_equals: Expect dictionary.codecId to be string expected "string" but got "undefined"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpSender-getStats.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpSender-getStats.https-expected.txt
new file mode 100644
index 0000000..7143aad
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCRtpSender-getStats.https-expected.txt
@@ -0,0 +1,5 @@
+This is a testharness.js-based test.
+FAIL sender.getStats() via addTransceiver should return stats report containing outbound-rtp stats promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL sender.getStats() via addTrack should return stats report containing outbound-rtp stats assert_equals: Expect dictionary.codecType to be string expected "string" but got "undefined"
+Harness: the test ran to completion.
+
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/protocol/crypto-suite.https-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/protocol/crypto-suite.https-expected.txt
new file mode 100644
index 0000000..682f695
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/protocol/crypto-suite.https-expected.txt
@@ -0,0 +1,11 @@
+This is a testharness.js-based test.
+FAIL tlsVersion is acceptable on data-only promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'transport' of null"
+FAIL tlsVersion is acceptable on video-only promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL dtlsCipher is acceptable on data-only promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'transport' of null"
+FAIL dtlsCipher is acceptable on video-only promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL srtpCipher is acceptable on data-only promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'transport' of null"
+FAIL srtpCipher is acceptable on video-only promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+FAIL tlsGroup is acceptable on data-only promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'transport' of null"
+FAIL tlsGroup is acceptable on video-only promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
+Harness: the test ran to completion.
+
diff --git a/third_party/closure_compiler/externs/pending.js b/third_party/closure_compiler/externs/pending.js
index d7326e3..44eed245 100644
--- a/third_party/closure_compiler/externs/pending.js
+++ b/third_party/closure_compiler/externs/pending.js
@@ -153,3 +153,9 @@
 
 /** @type {!StylePropertyMap} */
 HTMLElement.prototype.attributeStyleMap;
+
+/** @return {!AnimationEffectTimingProperties} */
+AnimationEffectReadOnly.prototype.getTiming = function() {};
+
+/** @return {!Array<!Object>} */
+AnimationEffectReadOnly.prototype.getKeyframes = function() {};
diff --git a/third_party/google_android_play_core/com_google_android_play_core.info b/third_party/google_android_play_core/com_google_android_play_core.info
index 0f4c57f..964bb28 100644
--- a/third_party/google_android_play_core/com_google_android_play_core.info
+++ b/third_party/google_android_play_core/com_google_android_play_core.info
@@ -1,13 +1,15 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = false
-resources = [ "res/values/styles.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/values/styles.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/google_trust_services/BUILD.gn b/third_party/google_trust_services/BUILD.gn
index be750d5..588452de 100644
--- a/third_party/google_trust_services/BUILD.gn
+++ b/third_party/google_trust_services/BUILD.gn
@@ -5,7 +5,10 @@
 static_library("google_trust_services") {
   # This is currently only used by remoting. Changes to visibility require a
   # security review.
-  visibility = [ "//remoting/*" ]
+  visibility = [
+    "//chrome/services/speech/*",
+    "//remoting/*",
+  ]
   sources = [
     "src/roots.cc",
     "src/roots.h",
diff --git a/third_party/gvr-android-sdk/controller_test_api_java.info b/third_party/gvr-android-sdk/controller_test_api_java.info
index a2ebd4a..da8df19 100644
--- a/third_party/gvr-android-sdk/controller_test_api_java.info
+++ b/third_party/gvr-android-sdk/controller_test_api_java.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/gvr-android-sdk/gvr_common_java.info b/third_party/gvr-android-sdk/gvr_common_java.info
index 5f161c3..3f2e07d 100644
--- a/third_party/gvr-android-sdk/gvr_common_java.info
+++ b/third_party/gvr-android-sdk/gvr_common_java.info
@@ -1,13 +1,86 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = true
 is_manifest_empty = true
-resources = [ "res/drawable-hdpi-v4/quantum_ic_close_white_24.png", "res/drawable-hdpi-v4/quantum_ic_settings_white_24.png", "res/drawable-hdpi-v4/transition.png", "res/drawable-mdpi-v4/quantum_ic_close_white_24.png", "res/drawable-mdpi-v4/quantum_ic_settings_white_24.png", "res/drawable-mdpi-v4/transition.png", "res/drawable-v21/rippleable.xml", "res/drawable-xhdpi-v4/quantum_ic_close_white_24.png", "res/drawable-xhdpi-v4/quantum_ic_settings_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_close_white_24.png", "res/drawable-xxhdpi-v4/quantum_ic_settings_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_close_white_24.png", "res/drawable-xxxhdpi-v4/quantum_ic_settings_white_24.png", "res/drawable/rippleable.xml", "res/layout-land/back_button.xml", "res/layout-land/settings_button.xml", "res/layout-land/ui_layer_with_portrait_support.xml", "res/layout-ldrtl-land-v17/back_button.xml", "res/layout-ldrtl-land-v17/settings_button.xml", "res/layout-ldrtl-v17/back_button.xml", "res/layout-ldrtl-v17/settings_button.xml", "res/layout/back_button.xml", "res/layout/settings_button.xml", "res/layout/transition_view.xml", "res/layout/ui_layer.xml", "res/layout/ui_layer_with_portrait_support.xml", "res/values-ar/values.xml", "res/values-bg/values.xml", "res/values-ca/values.xml", "res/values-cs/values.xml", "res/values-da/values.xml", "res/values-de/values.xml", "res/values-el/values.xml", "res/values-en-rGB/values.xml", "res/values-es-rUS/values.xml", "res/values-es/values.xml", "res/values-fa/values.xml", "res/values-fi/values.xml", "res/values-fr-rCA/values.xml", "res/values-fr/values.xml", "res/values-hi/values.xml", "res/values-hr/values.xml", "res/values-hu/values.xml", "res/values-id/values.xml", "res/values-it/values.xml", "res/values-iw/values.xml", "res/values-ja/values.xml", "res/values-ko/values.xml", "res/values-land/values.xml", "res/values-lt/values.xml", "res/values-lv/values.xml", "res/values-nb/values.xml", "res/values-nl/values.xml", "res/values-pl/values.xml", "res/values-pt-rBR/values.xml", "res/values-pt-rPT/values.xml", "res/values-ro/values.xml", "res/values-ru/values.xml", "res/values-sk/values.xml", "res/values-sl/values.xml", "res/values-sr/values.xml", "res/values-sv/values.xml", "res/values-th/values.xml", "res/values-tl/values.xml", "res/values-tr/values.xml", "res/values-uk/values.xml", "res/values-v19/values.xml", "res/values-v21/values.xml", "res/values-vi/values.xml", "res/values-zh-rCN/values.xml", "res/values-zh-rTW/values.xml", "res/values/values.xml" ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = [
+  "res/drawable-hdpi-v4/quantum_ic_close_white_24.png",
+  "res/drawable-hdpi-v4/quantum_ic_settings_white_24.png",
+  "res/drawable-hdpi-v4/transition.png",
+  "res/drawable-mdpi-v4/quantum_ic_close_white_24.png",
+  "res/drawable-mdpi-v4/quantum_ic_settings_white_24.png",
+  "res/drawable-mdpi-v4/transition.png",
+  "res/drawable-v21/rippleable.xml",
+  "res/drawable-xhdpi-v4/quantum_ic_close_white_24.png",
+  "res/drawable-xhdpi-v4/quantum_ic_settings_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_close_white_24.png",
+  "res/drawable-xxhdpi-v4/quantum_ic_settings_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_close_white_24.png",
+  "res/drawable-xxxhdpi-v4/quantum_ic_settings_white_24.png",
+  "res/drawable/rippleable.xml",
+  "res/layout-land/back_button.xml",
+  "res/layout-land/settings_button.xml",
+  "res/layout-land/ui_layer_with_portrait_support.xml",
+  "res/layout-ldrtl-land-v17/back_button.xml",
+  "res/layout-ldrtl-land-v17/settings_button.xml",
+  "res/layout-ldrtl-v17/back_button.xml",
+  "res/layout-ldrtl-v17/settings_button.xml",
+  "res/layout/back_button.xml",
+  "res/layout/settings_button.xml",
+  "res/layout/transition_view.xml",
+  "res/layout/ui_layer.xml",
+  "res/layout/ui_layer_with_portrait_support.xml",
+  "res/values-ar/values.xml",
+  "res/values-bg/values.xml",
+  "res/values-ca/values.xml",
+  "res/values-cs/values.xml",
+  "res/values-da/values.xml",
+  "res/values-de/values.xml",
+  "res/values-el/values.xml",
+  "res/values-en-rGB/values.xml",
+  "res/values-es-rUS/values.xml",
+  "res/values-es/values.xml",
+  "res/values-fa/values.xml",
+  "res/values-fi/values.xml",
+  "res/values-fr-rCA/values.xml",
+  "res/values-fr/values.xml",
+  "res/values-hi/values.xml",
+  "res/values-hr/values.xml",
+  "res/values-hu/values.xml",
+  "res/values-id/values.xml",
+  "res/values-it/values.xml",
+  "res/values-iw/values.xml",
+  "res/values-ja/values.xml",
+  "res/values-ko/values.xml",
+  "res/values-land/values.xml",
+  "res/values-lt/values.xml",
+  "res/values-lv/values.xml",
+  "res/values-nb/values.xml",
+  "res/values-nl/values.xml",
+  "res/values-pl/values.xml",
+  "res/values-pt-rBR/values.xml",
+  "res/values-pt-rPT/values.xml",
+  "res/values-ro/values.xml",
+  "res/values-ru/values.xml",
+  "res/values-sk/values.xml",
+  "res/values-sl/values.xml",
+  "res/values-sr/values.xml",
+  "res/values-sv/values.xml",
+  "res/values-th/values.xml",
+  "res/values-tl/values.xml",
+  "res/values-tr/values.xml",
+  "res/values-uk/values.xml",
+  "res/values-v19/values.xml",
+  "res/values-v21/values.xml",
+  "res/values-vi/values.xml",
+  "res/values-zh-rCN/values.xml",
+  "res/values-zh-rTW/values.xml",
+  "res/values/values.xml"
+]
+subjar_tuples = []
+subjars = []
diff --git a/third_party/gvr-android-sdk/gvr_controller_java.info b/third_party/gvr-android-sdk/gvr_controller_java.info
index a2ebd4a..da8df19 100644
--- a/third_party/gvr-android-sdk/gvr_controller_java.info
+++ b/third_party/gvr-android-sdk/gvr_controller_java.info
@@ -1,13 +1,13 @@
 # Generated by //build/android/gyp/aar.py
 # To regenerate, use "update_android_aar_prebuilts = true" and run "gn gen".
 
-aidl = [  ]
-assets = [  ]
+aidl = []
+assets = []
 has_classes_jar = true
 has_native_libraries = false
 has_proguard_flags = false
 has_r_text_file = false
 is_manifest_empty = true
-resources = [  ]
-subjar_tuples = [  ]
-subjars = [  ]
+resources = []
+subjar_tuples = []
+subjars = []
diff --git a/third_party/pyjson5/README.chromium b/third_party/pyjson5/README.chromium
index 0a0fdca..b08afb9 100644
--- a/third_party/pyjson5/README.chromium
+++ b/third_party/pyjson5/README.chromium
@@ -1,9 +1,9 @@
 Name: pyjson5
 Short Name: pyjson5
 URL: https://github.com/dpranke/pyjson5
-Version: 0.6.1
-Date: May 22, 2018
-Revision: c88ac1f
+Version: 0.9.5
+Date: May 26 2020
+Revision: 9335da8
 License: Apache 2.0
 License File: src/LICENSE
 Security Critical: No
diff --git a/third_party/pyjson5/src/MANIFEST.in b/third_party/pyjson5/src/MANIFEST.in
new file mode 100644
index 0000000..7d43f806
--- /dev/null
+++ b/third_party/pyjson5/src/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.md
+include LICENSE
diff --git a/third_party/pyjson5/src/README.md b/third_party/pyjson5/src/README.md
new file mode 100644
index 0000000..bf7aabd
--- /dev/null
+++ b/third_party/pyjson5/src/README.md
@@ -0,0 +1,156 @@
+# pyjson5
+
+A Python implementation of the JSON5 data format.
+
+[JSON5](https://json5.org) extends the
+[JSON](http://www.json.org) data interchange format to make it
+slightly more usable as a configuration language:
+
+* JavaScript-style comments (both single and multi-line) are legal.
+
+* Object keys may be unquoted if they are legal ECMAScript identifiers
+
+* Objects and arrays may end with trailing commas.
+
+* Strings can be single-quoted, and multi-line string literals are allowed.
+
+There are a few other more minor extensions to JSON; see the above page for
+the full details.
+
+This project implements a reader and writer implementation for Python;
+where possible, it mirrors the
+[standard Python JSON API](https://docs.python.org/library/json.html)
+package for ease of use.
+
+There is one notable difference from the JSON api: the `load()` and
+`loads()` methods support optionally checking for (and rejecting) duplicate
+object keys; pass `allow_duplicate_keys=False` to do so (duplicates are
+allowed by default).
+
+This is an early release. It has been reasonably well-tested, but it is
+**SLOW**. It can be 1000-6000x slower than the C-optimized JSON module,
+and is 200x slower (or more) than the pure Python JSON module.
+
+## Known issues
+
+* Did I mention that it is **SLOW**?
+
+* The implementation follows Python3's `json` implementation where
+  possible. This means that the `encoding` method to `dump()` is
+  ignored, and unicode strings are always returned.
+
+* The `cls` keyword argument that `json.load()`/`json.loads()` accepts
+  to specify a custom subclass of ``JSONDecoder`` is not and will not be
+  supported, because this implementation uses a completely different
+  approach to parsing strings and doesn't have anything like the
+  `JSONDecoder` class.
+
+* The `cls` keyword argument that `json.dump()`/`json.dumps()` accepts
+  is also not supported, for consistency with `json5.load()`. The `default`
+  keyword *is* supported, though, and might be able to serve as a
+  workaround.
+
+## Running the tests
+To run the tests, setup a venv and install the required dependencies with
+`pip install -e '.[dev]'`, then run the tests with `python setup.py test`.
+
+
+## Version History / Release Notes
+
+* v0.9.5 (2020-05-26)
+    * Miscellaneous non-source cleanups in the repo, including setting
+      up GitHub Actions for a CI system. No changes to the library from
+      v0.9.4, other than updating the version.
+
+* v0.9.4 (2020-03-26)
+    * [GitHub pull #38](https://github.com/dpranke/pyjson5/pull/38)
+      Fix from fredrik@fornwall.net for dumps() crashing when passed
+      an empty string as a key in an object.
+
+* v0.9.3 (2020-03-17)
+    * [GitHub pull #35](https://github.com/dpranke/pyjson5/pull/35)
+      Fix from pastelmind@ for dump() not passing the right args to dumps().
+    * Fix from p.skouzos@novafutur.com to remove the tests directory from
+      the setup call, making the package a bit smaller.
+
+* v0.9.2 (2020-03-02)
+    * [GitHub pull #34](https://github.com/dpranke/pyjson5/pull/34)
+      Fix from roosephu@ for a badly formatted nested list.
+
+* v0.9.1 (2020-02-09)
+    * [GitHub issue #33](https://github.com/dpranke/pyjson5/issues/33):
+       Fix stray trailing comma when dumping an object with an invalid key.
+
+* v0.9.0 (2020-01-30)
+    * [GitHub issue #29](https://github.com/dpranke/pyjson5/issues/29):
+       Fix an issue where objects keys that started with a reserved
+       word were incorrectly quoted.
+    * [GitHub issue #30](https://github.com/dpranke/pyjson5/issues/30):
+       Fix an issue where dumps() incorrectly thought a data structure
+       was cyclic in some cases.
+    * [GitHub issue #32](https://github.com/dpranke/pyjson5/issues/32):
+       Allow for non-string keys in dicts passed to ``dump()``/``dumps()``.
+       Add an ``allow_duplicate_keys=False`` to prevent possible
+       ill-formed JSON that might result.
+
+* v0.8.5 (2019-07-04)
+    * [GitHub issue #25](https://github.com/dpranke/pyjson5/issues/25):
+      Add LICENSE and README.md to the dist.
+    * [GitHub issue #26](https://github.com/dpranke/pyjson5/issues/26):
+      Fix printing of empty arrays and objects with indentation, fix
+      misreporting of the position on parse failures in some cases.
+
+* v0.8.4 (2019-06-11)
+    * Updated the version history, too.
+
+* v0.8.3 (2019-06-11)
+    * Tweaked the README, bumped the version, forgot to update the version
+      history :).
+
+* v0.8.2 (2019-06-11)
+    * Actually bump the version properly, to 0.8.2.
+
+* v0.8.1 (2019-06-11)
+    * Fix bug in setup.py that messed up the description. Unfortunately,
+      I forgot to bump the version for this, so this also identifies as 0.8.0.
+
+* v0.8.0 (2019-06-11)
+    * Add `allow_duplicate_keys=True` as a default argument to
+      `json5.load()`/`json5.loads()`. If you set the key to `False`, duplicate
+      keys in a single dict will be rejected. The default is set to `True`
+      for compatibility with `json.load()`, earlier versions of json5, and
+      because it's simply not clear if people would want duplicate checking
+      enabled by default.
+
+* v0.7 (2019-03-31)
+    * Changes dump()/dumps() to not quote object keys by default if they are
+      legal identifiers. Passing `quote_keys=True` will turn that off
+      and always quote object keys.
+    * Changes dump()/dumps() to insert trailing commas after the last item
+      in an array or an object if the object is printed across multiple lines
+      (i.e., if `indent` is not None). Passing `trailing_commas=False` will
+      turn that off.
+    * The `json5.tool` command line tool now supports the `--indent`,
+      `--[no-]quote-keys`, and `--[no-]trailing-commas` flags to allow
+      for more control over the output, in addition to the existing
+      `--as-json` flag.
+    * The `json5.tool` command line tool no longer supports reading from
+      multiple files, you can now only read from a single file or
+      from standard input.
+    * The implementation no longer relies on the standard `json` module
+      for anything. The output should still match the json module (except
+      as noted above) and discrepancies should be reported as bugs.
+
+* v0.6.2 (2019-03-08)
+    * Fix [GitHub issue #23](https://github.com/dpranke/pyjson5/issues/23) and
+      pass through unrecognized escape sequences.
+
+* v0.6.1 (2018-05-22)
+    * Cleaned up a couple minor nits in the package.
+
+* v0.6.0 (2017-11-28)
+    * First implementation that attempted to implement 100% of the spec.
+
+* v0.5.0 (2017-09-04)
+    * First implementation that supported the full set of kwargs that
+      the `json` module supports.
diff --git a/third_party/pyjson5/src/benchmarks/chromium.linux.json b/third_party/pyjson5/src/benchmarks/chromium.linux.json
index 3cb4bef4..3ee88ced 100644
--- a/third_party/pyjson5/src/benchmarks/chromium.linux.json
+++ b/third_party/pyjson5/src/benchmarks/chromium.linux.json
@@ -4133,15 +4133,15 @@
         }
       },
       {
-        "isolate_name": "devtools_lint_check",
-        "name": "devtools_lint_check",
+        "isolate_name": "devtools_closure_compile",
+        "name": "devtools_closure_compile",
         "swarming": {
           "can_use_on_swarming_builders": true
         }
       },
       {
-        "isolate_name": "devtools_type_check",
-        "name": "devtools_type_check",
+        "isolate_name": "devtools_eslint",
+        "name": "devtools_eslint",
         "swarming": {
           "can_use_on_swarming_builders": true
         }
diff --git a/third_party/pyjson5/src/benchmarks/mb_config.json b/third_party/pyjson5/src/benchmarks/mb_config.json
index fc3a96a..af93ef0f 100644
--- a/third_party/pyjson5/src/benchmarks/mb_config.json
+++ b/third_party/pyjson5/src/benchmarks/mb_config.json
@@ -1966,7 +1966,7 @@
       "gn_args": "internal_gles2_conform_tests=true"
     }, 
     "java_coverage": {
-      "gn_args": "jacoco_coverage=true"
+      "gn_args": "emma_coverage=true emma_filter=\"org.chromium.*\""
     }, 
     "libfuzzer": {
       "gn_args": "use_libfuzzer=true"
diff --git a/third_party/pyjson5/src/benchmarks/run.py b/third_party/pyjson5/src/benchmarks/run.py
index 5727558..63eb296 100755
--- a/third_party/pyjson5/src/benchmarks/run.py
+++ b/third_party/pyjson5/src/benchmarks/run.py
@@ -22,11 +22,12 @@
 import time
 
 THIS_DIR = os.path.abspath(os.path.dirname(__file__))
-REPO_DIR  = os.path.dirname(THIS_DIR)
+REPO_DIR = os.path.dirname(THIS_DIR)
 if not REPO_DIR in sys.path:
     sys.path.insert(0, REPO_DIR)
 
-import json5
+import json5  # pylint: disable=wrong-import-position
+
 
 ALL_BENCHMARKS = (
     'ios-simulator.json',
@@ -35,7 +36,9 @@
     'chromium.perf.json',
 )
 
-DEFAULT_ITERATIONS = 1
+
+DEFAULT_ITERATIONS = 3
+
 
 def main():
     parser = argparse.ArgumentParser()
@@ -54,18 +57,21 @@
 
 
     # json.decoder.c_scanstring = py_scanstring
-    def py_maker(*_args, **_kwargs):
-      decoder = json.JSONDecoder()
-      decoder.scan_once = json.scanner.py_make_scanner(decoder)
-      decoder.parse_string = json.decoder.py_scanstring
-      json.decoder.scanstring = decoder.parse_string
-      return decoder
+    def py_maker(*args, **kwargs):
+        del args
+        del kwargs
+        decoder = json.JSONDecoder()
+        decoder.scan_once = json.scanner.py_make_scanner(decoder)
+        decoder.parse_string = json.decoder.py_scanstring
+        json.decoder.scanstring = decoder.parse_string
+        return decoder
 
     maker = py_maker if args.pure else json.JSONDecoder
 
     all_times = []
     for i, c in enumerate(file_contents):
-        times = []
+        json_time = 0.0
+        json5_time = 0.0
         for _ in range(args.num_iterations):
             start = time.time()
             json_obj = json.loads(c, cls=maker)
@@ -73,16 +79,30 @@
             json5_obj = json5.loads(c)
             end = time.time()
 
-            json_time = mid - start
-            json5_time = end - mid
-            times.append((json_time, json5_time))
-            assert(json5_obj == json_obj)
-        all_times.append(times)
+            json_time += mid - start
+            json5_time += end - mid
+            assert json5_obj == json_obj
+        all_times.append((json_time, json5_time))
 
-    for i, times in enumerate(all_times):
-        avg = sum((json5_time / json_time)
-                  for json_time, json5_time in times) / args.num_iterations
-        print("%-20s: %5.1f" % (args.benchmarks[i], avg))
+    for i, (json_time, json5_time) in enumerate(all_times):
+        fname = os.path.basename(args.benchmarks[i])
+        if json5_time and json_time:
+            if json5_time > json_time:
+                avg = json5_time / json_time
+                print("%-20s: JSON was %5.1fx faster (%.6fs to %.6fs)" % (
+                      fname, avg, json_time, json5_time))
+            else:
+                avg = json_time / json5_time
+                print("%-20s: JSON5 was %5.1fx faster (%.6fs to %.6fs)" % (
+                      fname, avg, json5_time, json_time))
+        elif json5_time:
+            print("%-20s: JSON5 took %.6f secs, JSON was too fast to measure" %
+                  (fname, json5_time))
+        elif json_time:
+            print("%-20s: JSON took %.6f secs, JSON5 was too fast to measure" %
+                  (fname, json_time))
+        else:
+            print("%-20s: both were too fast to measure" % (fname,))
 
     return 0
 
diff --git a/third_party/pyjson5/src/json5/__init__.py b/third_party/pyjson5/src/json5/__init__.py
index 0e8f774d..5af52fc 100644
--- a/third_party/pyjson5/src/json5/__init__.py
+++ b/third_party/pyjson5/src/json5/__init__.py
@@ -14,7 +14,6 @@
 
 """A pure Python implementation of the JSON5 configuration language."""
 
-from . import tool
 from .lib import load, loads, dump, dumps
 from .version import VERSION
 
@@ -25,5 +24,4 @@
     'dumps',
     'load',
     'loads',
-    'tool',
 ]
diff --git a/third_party/pyjson5/src/json5/arg_parser.py b/third_party/pyjson5/src/json5/arg_parser.py
index 3f45428..5853f49 100644
--- a/third_party/pyjson5/src/json5/arg_parser.py
+++ b/third_party/pyjson5/src/json5/arg_parser.py
@@ -22,12 +22,15 @@
 class ArgumentParser(argparse.ArgumentParser):
     SUPPRESS = argparse.SUPPRESS
 
-    def __init__(self, host, **kwargs):
+    def __init__(self, host, prog, desc, **kwargs):
+        kwargs['prog'] = prog
+        kwargs['description'] = desc
+        kwargs['formatter_class'] = argparse.RawDescriptionHelpFormatter
         super(ArgumentParser, self).__init__(**kwargs)
         self._host = host
         self.exit_status = None
         self.add_argument('-V', '--version', action='store_true',
-                          help='Print the version and exit.')
+                          help='print the version and exit')
 
     def parse_args(self, args=None, namespace=None):
         try:
diff --git a/third_party/pyjson5/src/json5/host.py b/third_party/pyjson5/src/json5/host.py
index b9935319..a347fd5 100644
--- a/third_party/pyjson5/src/json5/host.py
+++ b/third_party/pyjson5/src/json5/host.py
@@ -12,7 +12,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import fileinput
 import os
 import shutil
 import sys
@@ -20,7 +19,7 @@
 
 
 if sys.version_info[0] < 3:
-    # pylint: disable=redefined-builtin
+    # pylint: disable=redefined-builtin, invalid-name
     str = unicode
 
 
@@ -33,11 +32,6 @@
     def chdir(self, *comps):
         return os.chdir(self.join(*comps))
 
-    def fileinput(self, files=None):
-        if not files:
-            return self.stdin.readlines()
-        return fileinput.input(files)
-
     def getcwd(self):
         return os.getcwd()
 
@@ -55,6 +49,10 @@
     def rmtree(self, path):
         shutil.rmtree(path, ignore_errors=True)
 
+    def read_text_file(self, path):
+        with open(path, 'rb') as fp:
+            return fp.read().decode('utf8')
+
     def write_text_file(self, path, contents):
         with open(path, 'wb') as f:
             f.write(contents.encode('utf8'))
diff --git a/third_party/pyjson5/src/json5/json5.g b/third_party/pyjson5/src/json5/json5.g
index e4ed365..1bbb798 100644
--- a/third_party/pyjson5/src/json5/json5.g
+++ b/third_party/pyjson5/src/json5/json5.g
@@ -52,6 +52,8 @@
                | squote                              -> '\u0027'
                | dquote                              -> '\u0022'
                | bslash                              -> '\u005C'
+               | ~('x'|'u'|digit|eol) anything:c     -> c
+               | '0' ~digit                          -> '\u0000'
                | hex_esc:c                           -> c
                | unicode_esc:c                       -> c
 
diff --git a/third_party/pyjson5/src/json5/lib.py b/third_party/pyjson5/src/json5/lib.py
index 4252dc6a..5b2b0ae 100644
--- a/third_party/pyjson5/src/json5/lib.py
+++ b/third_party/pyjson5/src/json5/lib.py
@@ -12,34 +12,55 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import math
 import re
-import json
 import sys
+import unicodedata
 
 from .parser import Parser
 
 
 if sys.version_info[0] < 3:
-    # pylint: disable=redefined-builtin
-    str = unicode
+    str = unicode  # pylint: disable=redefined-builtin, invalid-name
+else:
+    long = int  # pylint: disable=redefined-builtin, invalid-name
 
 
 def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
-         parse_int=None, parse_constant=None, object_pairs_hook=None):
+         parse_int=None, parse_constant=None, object_pairs_hook=None,
+         allow_duplicate_keys=True):
     """Deserialize ``fp`` (a ``.read()``-supporting file-like object
-    containing a JSON document) to a Python object."""
+    containing a JSON document) to a Python object.
+
+    Supports almost the same arguments as ``json.load()`` except that:
+        - the `cls` keyword is ignored.
+        - an extra `allow_duplicate_keys` parameter supports checking for
+          duplicate keys in a object; by default, this is True for
+          compatibility with ``json.load()``, but if set to False and
+          the object contains duplicate keys, a ValueError will be raised.
+    """
 
     s = fp.read()
     return loads(s, encoding=encoding, cls=cls, object_hook=object_hook,
                  parse_float=parse_float, parse_int=parse_int,
                  parse_constant=parse_constant,
-                 object_pairs_hook=object_pairs_hook)
+                 object_pairs_hook=object_pairs_hook,
+                 allow_duplicate_keys=allow_duplicate_keys)
 
 
 def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
-          parse_int=None, parse_constant=None, object_pairs_hook=None):
+          parse_int=None, parse_constant=None, object_pairs_hook=None,
+          allow_duplicate_keys=True):
     """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a
-    JSON5 document) to a Python object."""
+    JSON5 document) to a Python object.
+
+    Supports the same arguments as ``json.load()`` except that:
+        - the `cls` keyword is ignored.
+        - an extra `allow_duplicate_keys` parameter supports checking for
+          duplicate keys in a object; by default, this is True for
+          compatibility with ``json.load()``, but if set to False and
+          the object contains duplicate keys, a ValueError will be raised.
+    """
 
     assert cls is None, 'Custom decoders are not supported'
 
@@ -54,7 +75,7 @@
     if not s:
         raise ValueError('Empty strings are not legal JSON5')
     parser = Parser(s, '<string>')
-    ast, err, newpos = parser.parse()
+    ast, err, _ = parser.parse()
     if err:
         raise ValueError(err)
 
@@ -66,7 +87,11 @@
     elif object_hook:
         dictify = lambda pairs: object_hook(dict(pairs))
     else:
-        dictify = dict
+        dictify = lambda pairs: dict(pairs) # pylint: disable=unnecessary-lambda
+
+    if not allow_duplicate_keys:
+        _orig_dictify = dictify
+        dictify = lambda pairs: _reject_duplicate_keys(pairs, _orig_dictify)
 
     parse_float = parse_float or float
     parse_int = parse_int or int
@@ -75,6 +100,14 @@
     return _walk_ast(ast, dictify, parse_float, parse_int, parse_constant)
 
 
+def _reject_duplicate_keys(pairs, dictify):
+    keys = set()
+    for key, _ in pairs:
+        if key in keys:
+            raise ValueError('Duplicate key "%s" found in object', key)
+        keys.add(key)
+    return dictify(pairs)
+
 def _walk_ast(el, dictify, parse_float, parse_int, parse_constant):
     if el == 'None':
         return None
@@ -107,53 +140,370 @@
     raise Exception('unknown el: ' + el)  # pragma: no cover
 
 
-_notletter = re.compile('\W')
+def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
+         allow_nan=True, cls=None, indent=None, separators=None,
+         default=None, sort_keys=False,
+         quote_keys=False, trailing_commas=True,
+         allow_duplicate_keys=True,
+         **kwargs):
+    """Serialize ``obj`` to a JSON5-formatted stream to ``fp`` (a ``.write()``-
+    supporting file-like object).
+
+    Supports the same arguments as ``json.dumps()``, except that:
+
+    - The ``cls`` keyword is not supported.
+    - The ``encoding`` keyword is ignored; Unicode strings are always written.
+    - By default, object keys that are legal identifiers are not quoted;
+      if you pass quote_keys=True, they will be.
+    - By default, if lists and objects span multiple lines of output (i.e.,
+      when ``indent`` >=0), the last item will have a trailing comma
+      after it. If you pass ``trailing_commas=False, it will not.
+    - If you use a number, a boolean, or None as a key value in a dict,
+      it will be converted to the corresponding json string value, e.g.
+      "1", "true", or "null". By default, dump() will match the `json`
+      modules behavior and produce ill-formed JSON if you mix keys of
+      different types that have the same converted value, e.g.:
+      {1: "foo", "1": "bar"} produces '{"1": "foo", "1": "bar"}', an
+      object with duplicated keys. If you pass allow_duplicate_keys=False,
+      an exception will be raised instead.
+
+    Calling ``dumps(obj, fp, quote_keys=True, trailing_commas=False,
+                    allow_duplicate_keys=True)``
+    should produce exactly the same output as ``json.dumps(obj, fp).``
+    """
+
+    fp.write(str(dumps(obj=obj, skipkeys=skipkeys, ensure_ascii=ensure_ascii,
+                       check_circular=check_circular, allow_nan=allow_nan,
+                       cls=cls, indent=indent, separators=separators,
+                       default=default, sort_keys=sort_keys,
+                       quote_keys=quote_keys, trailing_commas=trailing_commas,
+                       allow_duplicate_keys=allow_duplicate_keys)))
 
 
-def _dumpkey(k):
-    if _notletter.search(k):
-        return json.dumps(k)
+def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
+          allow_nan=True, cls=None, indent=None, separators=None,
+          default=None, sort_keys=False,
+          quote_keys=False, trailing_commas=True, allow_duplicate_keys=True,
+          **kwargs):
+    """Serialize ``obj`` to a JSON5-formatted ``str``.
+
+    Supports the same arguments as ``json.dumps()``, except that:
+
+    - The ``cls`` keyword is not supported.
+    - The ``encoding`` keyword is ignored; Unicode strings are always returned.
+    - By default, object keys that are legal identifiers are not quoted;
+      if you pass quote_keys=True, they will be.
+    - By default, if lists and objects span multiple lines of output (i.e.,
+      when ``indent`` >=0), the last item will have a trailing comma
+      after it. If you pass ``trailing_commas=False, it will not.
+    - If you use a number, a boolean, or None as a key value in a dict,
+      it will be converted to the corresponding json string value, e.g.
+      "1", "true", or "null". By default, dump() will match the ``json``
+      module's behavior and produce ill-formed JSON if you mix keys of
+      different types that have the same converted value, e.g.:
+      {1: "foo", "1": "bar"} produces '{"1": "foo", "1": "bar"}', an
+      object with duplicated keys. If you pass ``allow_duplicate_keys=False``,
+      an exception will be raised instead.
+
+
+    Calling ``dumps(obj, quote_keys=True, trailing_commas=False,
+                    allow_duplicate_keys=True)``
+    should produce exactly the same output as ``json.dumps(obj).``
+    """
+
+    assert kwargs.get('cls', None) is None, 'Custom encoders are not supported'
+
+    if separators is None:
+        if indent is None:
+            separators = (u', ', u': ')
+        else:
+            separators = (u',', u': ')
+
+    default = default or _raise_type_error
+
+    if check_circular:
+        seen = set()
     else:
-        return str(k)
+        seen = None
+
+    level = 1
+    is_key = False
+
+    _, v = _dumps(obj, skipkeys, ensure_ascii, check_circular,
+                  allow_nan, indent, separators, default, sort_keys,
+                  quote_keys, trailing_commas, allow_duplicate_keys,
+                  seen, level, is_key)
+    return v
 
 
-def dumps(obj, compact=False, as_json=False, **kwargs):
-    """Serialize ``obj`` to a JSON5-formatted ``str``."""
-
-    if as_json or not compact:
-        return json.dumps(obj, **kwargs)
+def _dumps(obj, skipkeys, ensure_ascii, check_circular, allow_nan, indent,
+           separators, default, sort_keys,
+           quote_keys, trailing_commas, allow_duplicate_keys,
+           seen, level, is_key):
+    s = None
+    if obj is True:
+        s = u'true'
+    if obj is False:
+        s = u'false'
+    if obj is None:
+        s = u'null'
 
     t = type(obj)
-    if obj == True:
-        return u'true'
-    elif obj == False:
-        return u'false'
-    elif obj == None:
-        return u'null'
-    elif t == type('') or t == type(u''):
-        single = "'" in obj
-        double = '"' in obj
-        if single and double:
-            return json.dumps(obj)
-        elif single:
-            return '"' + obj + '"'
+    if t == type('') or t == type(u''):
+        if (is_key and _is_ident(obj) and not quote_keys
+            and not _is_reserved_word(obj)):
+            return True, obj
+        return True, _dump_str(obj, ensure_ascii)
+    if t is float:
+        s = _dump_float(obj,allow_nan)
+    if t is int:
+        s = str(obj)
+
+    if is_key:
+        if s is not None:
+            return True, '"%s"' % s
+        if skipkeys:
+            return False, None
+        raise TypeError('invalid key %s' % repr(obj))
+
+    if s is not None:
+        return True, s
+
+    if indent is not None:
+        end_str = ''
+        if trailing_commas:
+            end_str = ','
+        if type(indent) == int:
+            if indent > 0:
+                indent_str = '\n' + ' ' * indent * level
+                end_str += '\n' + ' ' * indent * (level - 1)
+            else:
+                indent_str = '\n'
+                end_str += '\n'
         else:
-            return "'" + obj + "'"
-    elif t is float or t is int:
-        return str(obj)
-    elif t is dict:
-        return u'{' + u','.join([
-            _dumpkey(k) + u':' + dumps(v) for k, v in obj.items()
-        ]) + '}'
-    elif t is list:
-        return u'[' + ','.join([dumps(el) for el in obj]) + u']'
-    else:  # pragma: no cover
-        return u''
+            indent_str = '\n' + indent * level
+            end_str += '\n' + indent * (level - 1)
+    else:
+        indent_str = ''
+        end_str = ''
+
+    item_sep, kv_sep = separators
+    item_sep += indent_str
+    level += 1
+
+    if seen is not None:
+        i = id(obj)
+        if i in seen:
+            raise ValueError('Circular reference detected.')
+        else:
+            seen.add(i)
+
+    # In Python3, we'd check if this was an abc.Mapping or an abc.Sequence.
+    # For now, just check for the attrs we need to iterate over the object.
+    if hasattr(t, 'keys') and hasattr(t, '__getitem__'):
+        s = _dump_dict(obj, skipkeys, ensure_ascii,
+                       check_circular, allow_nan, indent,
+                       separators, default, sort_keys,
+                       quote_keys, trailing_commas,
+                       allow_duplicate_keys, seen, level,
+                       item_sep, kv_sep, indent_str, end_str)
+    elif hasattr(t, '__getitem__') and hasattr(t, '__iter__'):
+        s = _dump_array(obj, skipkeys, ensure_ascii,
+                        check_circular, allow_nan, indent,
+                        separators, default, sort_keys,
+                        quote_keys, trailing_commas,
+                        allow_duplicate_keys, seen, level,
+                        item_sep, indent_str, end_str)
+    else:
+        s = default(obj)
+
+    if seen is not None:
+        seen.remove(i)
+    return False, s
 
 
-def dump(obj, fp, **kwargs):
-    """Serialize ``obj`` to a JSON5-formatted stream to ``fp`` (a ``.write()``-
-    supporting file-like object)."""
+def _dump_dict(obj, skipkeys, ensure_ascii, check_circular, allow_nan,
+               indent, separators, default, sort_keys,
+               quote_keys, trailing_commas, allow_duplicate_keys,
+               seen, level, item_sep, kv_sep, indent_str, end_str):
+    if not obj:
+        return u'{}'
 
-    s = dumps(obj, **kwargs)
-    fp.write(str(s))
+    if sort_keys:
+        keys = sorted(obj.keys())
+    else:
+        keys = obj.keys()
+
+    s = u'{' + indent_str
+
+    num_items_added = 0
+    new_keys = set()
+    for key in keys:
+        valid_key, key_str = _dumps(key, skipkeys, ensure_ascii, check_circular,
+                                    allow_nan, indent, separators, default,
+                                    sort_keys,
+                                    quote_keys, trailing_commas,
+                                    allow_duplicate_keys,
+                                    seen, level, is_key=True)
+        if valid_key:
+            if not allow_duplicate_keys:
+                if key_str in new_keys:
+                    raise ValueError('duplicate key %s' % repr(key))
+                else:
+                    new_keys.add(key_str)
+            if num_items_added:
+                s += item_sep
+            s += key_str + kv_sep + _dumps(obj[key], skipkeys, ensure_ascii,
+                                           check_circular, allow_nan, indent,
+                                           separators, default, sort_keys,
+                                           quote_keys, trailing_commas,
+                                           allow_duplicate_keys,
+                                           seen, level, is_key=False)[1]
+            num_items_added += 1
+        elif not skipkeys:
+            raise TypeError('invalid key %s' % repr(key))
+
+    s += end_str + u'}'
+    return s
+
+
+def _dump_array(obj, skipkeys, ensure_ascii, check_circular, allow_nan,
+                indent, separators, default, sort_keys,
+                quote_keys, trailing_commas, allow_duplicate_keys,
+                seen, level, item_sep, indent_str, end_str):
+    if not obj:
+        return u'[]'
+    return (u'[' + indent_str +
+            item_sep.join([_dumps(el, skipkeys, ensure_ascii, check_circular,
+                                  allow_nan, indent, separators, default,
+                                  sort_keys, quote_keys, trailing_commas,
+                                  allow_duplicate_keys,
+                                  seen, level, False)[1] for el in obj]) +
+            end_str + u']')
+
+
+def _dump_float(obj, allow_nan):
+    if allow_nan:
+        if math.isnan(obj):
+            return 'NaN'
+        if obj == float('inf'):
+            return 'Infinity'
+        if obj == float('-inf'):
+            return '-Infinity'
+    elif math.isnan(obj) or obj == float('inf') or obj == float('-inf'):
+        raise ValueError('Out of range float values '
+                         'are not JSON compliant')
+    return str(obj)
+
+
+def _dump_str(obj, ensure_ascii):
+    ret = ['"']
+    for ch in obj:
+        if ch == '\\':
+            ret.append('\\\\')
+        elif ch == '"':
+            ret.append('\\"')
+        elif ch == u'\u2028':
+            ret.append('\\u2028')
+        elif ch == u'\u2029':
+            ret.append('\\u2029')
+        elif ch == '\n':
+            ret.append('\\n')
+        elif ch == '\r':
+            ret.append('\\r')
+        elif ch == '\b':
+            ret.append('\\b')
+        elif ch == '\f':
+            ret.append('\\f')
+        elif ch == '\t':
+            ret.append('\\t')
+        elif ch == '\v':
+            ret.append('\\v')
+        elif ch == '\0':
+            ret.append('\\0')
+        elif not ensure_ascii:
+            ret.append(ch)
+        else:
+            o = ord(ch)
+            if o >= 32 and o < 128:
+                ret.append(ch)
+            elif o < 65536:
+                ret.append('\\u' + '%04x' % o)
+            else:
+                val = o - 0x10000
+                high = 0xd800 + (val >> 10)
+                low = 0xdc00 + (val & 0x3ff)
+                ret.append('\\u%04x\\u%04x' % (high, low))
+    return u''.join(ret) + '"'
+
+
+def _is_ident(k):
+    k = str(k)
+    if not k or not _is_id_start(k[0]) and k[0] not in (u'$', u'_'):
+        return False
+    for ch in k[1:]:
+        if not _is_id_continue(ch) and ch not in (u'$', u'_'):
+            return False
+    return True
+
+
+def _is_id_start(ch):
+    return unicodedata.category(ch) in (
+        'Lu', 'Ll', 'Li', 'Lt', 'Lm', 'Lo', 'Nl')
+
+
+def _is_id_continue(ch):
+    return unicodedata.category(ch) in (
+        'Lu', 'Ll', 'Li', 'Lt', 'Lm', 'Lo', 'Nl', 'Nd', 'Mn', 'Mc', 'Pc')
+
+
+_reserved_word_re = None
+
+def _is_reserved_word(k):
+    global _reserved_word_re
+
+    if _reserved_word_re is None:
+        # List taken from section 7.6.1 of ECMA-262.
+        _reserved_word_re = re.compile('(' + '|'.join([
+            'break',
+            'case',
+            'catch',
+            'class',
+            'const',
+            'continue',
+            'debugger',
+            'default',
+            'delete',
+            'do',
+            'else',
+            'enum',
+            'export',
+            'extends',
+            'false',
+            'finally',
+            'for',
+            'function',
+            'if',
+            'import',
+            'in',
+            'instanceof',
+            'new',
+            'null',
+            'return',
+            'super',
+            'switch',
+            'this',
+            'throw',
+            'true',
+            'try',
+            'typeof',
+            'var',
+            'void',
+            'while',
+            'with',
+        ]) + ')$')
+    return _reserved_word_re.match(k) is not None
+
+
+def _raise_type_error(obj):
+    raise TypeError('%s is not JSON5 serializable' % repr(obj))
diff --git a/third_party/pyjson5/src/json5/parser.py b/third_party/pyjson5/src/json5/parser.py
index db1bd70..a2a0039 100644
--- a/third_party/pyjson5/src/json5/parser.py
+++ b/third_party/pyjson5/src/json5/parser.py
@@ -1,10 +1,10 @@
-# pylint: disable=line-too-long
+# pylint: disable=line-too-long,unnecessary-lambda
 
 import sys
 
 
 if sys.version_info[0] < 3:
-    # pylint: disable=redefined-builtin
+    # pylint: disable=redefined-builtin,invalid-name
     chr = unichr
     range = xrange
     str = unicode
@@ -100,6 +100,8 @@
             rule()
             if self.failed:
                 self._rewind(p)
+                if p < self.errpos:
+                    self.errpos = p
                 break
             else:
                 vs.append(self.val)
@@ -127,12 +129,12 @@
         else:
             self._fail()
 
-    def _str(self, s, l):
-        p = self.pos
-        if (p + l <= self.end) and self.msg[p:p + l] == s:
-            self._succeed(s, self.pos + l)
-        else:
-            self._fail()
+    def _str(self, s):
+        for ch in s:
+            self._ch(ch)
+            if self.failed:
+                return
+        self.val = s
 
     def _range(self, i, j):
         p = self.pos
@@ -191,7 +193,7 @@
         self._ch('\f')
 
     def _ws__c6_(self):
-        self._ch('\u00a0')
+        self._ch(u'\xa0')
 
     def _ws__c7_(self):
         self._ch(u'\ufeff')
@@ -232,21 +234,21 @@
         self._choose([self._comment__c0_, self._comment__c1_])
 
     def _comment__c0_(self):
-        self._seq([lambda: self._str('//', 2),
+        self._seq([lambda: self._str('//'),
                    lambda: self._star(self._comment__c0__s1_p_)])
 
     def _comment__c0__s1_p_(self):
         self._seq([lambda: self._not(self._eol_), self._anything_])
 
     def _comment__c1_(self):
-        self._seq([lambda: self._str('/*', 2), self._comment__c1__s1_,
-                   lambda: self._str('*/', 2)])
+        self._seq([lambda: self._str('/*'), self._comment__c1__s1_,
+                   lambda: self._str('*/')])
 
     def _comment__c1__s1_(self):
         self._star(lambda: self._seq([self._comment__c1__s1_p__s0_, self._anything_]))
 
     def _comment__c1__s1_p__s0_(self):
-        self._not(lambda: self._str('*/', 2))
+        self._not(lambda: self._str('*/'))
 
     def _value_(self):
         self._choose([self._value__c0_, self._value__c1_, self._value__c2_,
@@ -254,14 +256,13 @@
                       self._value__c6_])
 
     def _value__c0_(self):
-        self._seq([lambda: self._str('null', 4), lambda: self._succeed('None')])
+        self._seq([lambda: self._str('null'), lambda: self._succeed('None')])
 
     def _value__c1_(self):
-        self._seq([lambda: self._str('true', 4), lambda: self._succeed('True')])
+        self._seq([lambda: self._str('true'), lambda: self._succeed('True')])
 
     def _value__c2_(self):
-        self._seq([lambda: self._str('false', 5),
-                   lambda: self._succeed('False')])
+        self._seq([lambda: self._str('false'), lambda: self._succeed('False')])
 
     def _value__c3_(self):
         self._push('value__c3')
@@ -393,7 +394,8 @@
                       self._esc_char__c4_, self._esc_char__c5_,
                       self._esc_char__c6_, self._esc_char__c7_,
                       self._esc_char__c8_, self._esc_char__c9_,
-                      self._esc_char__c10_])
+                      self._esc_char__c10_, self._esc_char__c11_,
+                      self._esc_char__c12_])
 
     def _esc_char__c0_(self):
         self._seq([lambda: self._ch('b'), lambda: self._succeed('\b')])
@@ -402,10 +404,20 @@
         self._seq([lambda: self._ch('f'), lambda: self._succeed('\f')])
 
     def _esc_char__c10_(self):
-        self._push('esc_char__c10')
+        self._seq([lambda: self._ch('0'), lambda: self._not(self._digit_),
+                   lambda: self._succeed('\x00')])
+
+    def _esc_char__c11_(self):
+        self._push('esc_char__c11')
+        self._seq([lambda: self._bind(self._hex_esc_, 'c'),
+                   lambda: self._succeed(self._get('c'))])
+        self._pop('esc_char__c11')
+
+    def _esc_char__c12_(self):
+        self._push('esc_char__c12')
         self._seq([lambda: self._bind(self._unicode_esc_, 'c'),
                    lambda: self._succeed(self._get('c'))])
-        self._pop('esc_char__c10')
+        self._pop('esc_char__c12')
 
     def _esc_char__c2_(self):
         self._seq([lambda: self._ch('n'), lambda: self._succeed('\n')])
@@ -430,10 +442,26 @@
 
     def _esc_char__c9_(self):
         self._push('esc_char__c9')
-        self._seq([lambda: self._bind(self._hex_esc_, 'c'),
+        self._seq([self._esc_char__c9__s0_,
+                   lambda: self._bind(self._anything_, 'c'),
                    lambda: self._succeed(self._get('c'))])
         self._pop('esc_char__c9')
 
+    def _esc_char__c9__s0_(self):
+        self._not(lambda: (self._esc_char__c9__s0_n_g_)())
+
+    def _esc_char__c9__s0_n_g_(self):
+        self._choose([self._esc_char__c9__s0_n_g__c0_,
+                      self._esc_char__c9__s0_n_g__c1_,
+                      lambda: self._seq([self._digit_]),
+                      lambda: self._seq([self._eol_])])
+
+    def _esc_char__c9__s0_n_g__c0_(self):
+        self._seq([lambda: self._ch('x')])
+
+    def _esc_char__c9__s0_n_g__c1_(self):
+        self._seq([lambda: self._ch('u')])
+
     def _hex_esc_(self):
         self._push('hex_esc')
         self._seq([lambda: self._ch('x'), lambda: self._bind(self._hex_, 'h1'),
@@ -501,22 +529,6 @@
                    lambda: self._succeed([self._get('k'), self._get('v')])])
         self._pop('member__c1')
 
-    def _member_list_(self):
-        self._push('member_list')
-        self._seq([lambda: self._bind(self._member_, 'm'),
-                   self._member_list__s1_, self._sp_, self._member_list__s3_,
-                   lambda: self._succeed([self._get('m')] + self._get('ms'))])
-        self._pop('member_list')
-
-    def _member_list__s1_(self):
-        self._bind(lambda: self._star(self._member_list__s1_l_p_), 'ms')
-
-    def _member_list__s1_l_p_(self):
-        self._seq([self._sp_, lambda: self._ch(','), self._sp_, self._member_])
-
-    def _member_list__s3_(self):
-        self._opt(lambda: self._ch(','))
-
     def _ident_(self):
         self._push('ident')
         self._seq([lambda: self._bind(self._id_start_, 'hd'), self._ident__s1_,
@@ -734,10 +746,10 @@
         self._opt(lambda: self._ch('+'))
 
     def _num_literal__c3_(self):
-        self._str('Infinity', 8)
+        self._str('Infinity')
 
     def _num_literal__c4_(self):
-        self._str('NaN', 3)
+        self._str('NaN')
 
     def _dec_literal_(self):
         self._choose([self._dec_literal__c0_, self._dec_literal__c1_,
@@ -815,7 +827,7 @@
         self._pop('hex_literal')
 
     def _hex_literal__s0_(self):
-        self._choose([lambda: self._str('0x', 2), lambda: self._str('0X', 2)])
+        self._choose([lambda: self._str('0x'), lambda: self._str('0X')])
 
     def _hex_literal__s1_(self):
         self._bind(lambda: self._plus(self._hex_), 'hs')
@@ -829,25 +841,6 @@
     def _hex__c1_(self):
         self._range('A', 'F')
 
-    def _hex_esc_(self):
-        self._push('hex_esc')
-        self._seq([lambda: self._ch('x'), lambda: self._bind(self._hex_, 'h1'),
-                   lambda: self._bind(self._hex_, 'h2'),
-                   lambda: self._succeed(self._xtou(self._get('h1') + self._get('h2')))])
-        self._pop('hex_esc')
-
-    def _hex_literal_(self):
-        self._push('hex_literal')
-        self._seq([self._hex_literal__s0_, self._hex_literal__s1_,
-                   lambda: self._succeed('0x' + self._join('', self._get('hs')))])
-        self._pop('hex_literal')
-
-    def _hex_literal__s0_(self):
-        self._choose([lambda: self._str('0x', 2), lambda: self._str('0X', 2)])
-
-    def _hex_literal__s1_(self):
-        self._bind(lambda: self._plus(self._hex_), 'hs')
-
     def _frac_(self):
         self._push('frac')
         self._seq([lambda: self._ch('.'), self._frac__s1_,
diff --git a/third_party/pyjson5/src/json5/tool.py b/third_party/pyjson5/src/json5/tool.py
index ed536582..3c7d1209 100644
--- a/third_party/pyjson5/src/json5/tool.py
+++ b/third_party/pyjson5/src/json5/tool.py
@@ -12,16 +12,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""Command-line tool to validate and pretty-print JSON5.
+"""A tool to parse and pretty-print JSON5.
 
-Usage::
+Usage:
 
     $ echo '{foo:"bar"}' | python -m json5.tool
-    { foo: "bar" }
-    $
+    {
+        foo: 'bar',
+    }
+    $ echo '{foo:"bar"}' | python -m json5.tool --as-json
+    {
+        "foo": "bar"
+    }
 """
 
-import os
 import sys
 
 from . import arg_parser
@@ -33,14 +37,35 @@
 def main(argv=None, host=None):
     host = host or Host()
 
-    parser = arg_parser.ArgumentParser(host, prog='json5')
+    parser = arg_parser.ArgumentParser(host, prog='json5', desc=__doc__)
     parser.add_argument('-c', metavar='STR', dest='cmd',
-                        help='inline json5 string')
-    parser.add_argument('--json', dest='as_json', action='store_const',
+                        help='inline json5 string to read instead of '
+                             'reading from a file')
+    parser.add_argument('--as-json', dest='as_json', action='store_const',
                         const=True, default=False,
-                        help='output as json')
-    parser.add_argument('files', nargs='*', default=[],
-                        help=parser.SUPPRESS)
+                        help='output as JSON '
+                             '(same as --quote-keys --no-trailing-commas)')
+    parser.add_argument('--indent', dest='indent', default=4,
+                        help='amount to indent each line '
+                             '(default is 4 spaces)')
+    parser.add_argument('--quote-keys', action='store_true', default=False,
+                        help='quote all object keys')
+    parser.add_argument('--no-quote-keys', action='store_false',
+                        dest='quote_keys',
+                        help="don't quote object keys that are identifiers"
+                             " (this is the default)")
+    parser.add_argument('--trailing-commas', action='store_true',
+                        default=True,
+                        help='add commas after the last item in multi-line '
+                             'objects and arrays (this is the default)')
+    parser.add_argument('--no-trailing-commas', dest='trailing_commas',
+                        action='store_false',
+                        help='do not add commas after the last item in '
+                             'multi-line lists and objects')
+    parser.add_argument('file', metavar='FILE', nargs='?', default='-',
+                        help='optional file to read JSON5 document from; if '
+                             'not specified or "-", will read from stdin '
+                             'instead')
     args = parser.parse_args(argv)
 
     if parser.exit_status is not None:
@@ -52,10 +77,29 @@
 
     if args.cmd:
         inp = args.cmd
+    elif args.file == '-':
+        inp = host.stdin.read()
     else:
-        inp = ''.join(host.fileinput(args.files))
+        inp = host.read_text_file(args.file)
 
-    host.print_(lib.dumps(lib.loads(inp), compact=True, as_json=args.as_json))
+    if args.indent == 'None':
+        args.indent = None
+    else:
+        try:
+            args.indent = int(args.indent)
+        except ValueError:
+            pass
+
+    if args.as_json:
+        args.quote_keys = True
+        args.trailing_commas = False
+
+    obj = lib.loads(inp)
+    s = lib.dumps(obj,
+                  indent=args.indent,
+                  quote_keys=args.quote_keys,
+                  trailing_commas=args.trailing_commas)
+    host.print_(s)
     return 0
 
 
diff --git a/third_party/pyjson5/src/json5/version.py b/third_party/pyjson5/src/json5/version.py
index dce4f08..a0cc8a3 100644
--- a/third_party/pyjson5/src/json5/version.py
+++ b/third_party/pyjson5/src/json5/version.py
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-VERSION = '0.6.1'
+VERSION = '0.9.5'
diff --git a/third_party/pyjson5/src/pylintrc b/third_party/pyjson5/src/pylintrc
index 4abb6c60..03a3a28f 100644
--- a/third_party/pyjson5/src/pylintrc
+++ b/third_party/pyjson5/src/pylintrc
@@ -14,261 +14,44 @@
 
 [MASTER]
 
-# Specify a configuration file.
-#rcfile=
-
-# Python code to execute, usually for sys.path manipulation such as
-# pygtk.require().
-#init-hook=
-
-# Profiled execution.
-profile=no
-
-# Add files or directories to the blacklist. They should be base names, not
-# paths.
-ignore=CVS
-
 # Pickle collected data for later comparisons.
 persistent=yes
 
-# List of plugins (as comma separated values of python modules names) to load,
-# usually to register additional checkers.
-load-plugins=
-
-
 [MESSAGES CONTROL]
 
-# Enable the message, report, category or checker with the given id(s). You can
-# either give multiple identifier separated by comma (,) or put this option
-# multiple time.
-#enable=
-
-# Disable the message, report, category or checker with the given id(s). You
-# can either give multiple identifier separated by comma (,) or put this option
-# multiple time (only on the command line, not in the configuration file where
-# it should appear only once).
-# CHANGED:
-# C0111: Missing docstring
-# I0011: Locally disabling WNNNN
-# R0201: Method could be a function
-# R0801: Similar lines
-# W0141: Used builtin function 'map'
-# W0142: Used * or ** magic
-# W0511: TODO
-# W0703: Catch "Exception"
-disable=C0111,I0011,R0201,R0801,W0141,W0142,W0511,W0703
-
+disable=
+    broad-except,
+    global-statement,
+    locally-disabled,
+    missing-docstring,
+    no-self-use,
+    too-many-arguments,
+    too-few-public-methods,
+    too-many-branches,
+    too-many-instance-attributes,
+    too-many-locals,
+    too-many-public-methods,
+    too-many-return-statements,
+    unidiomatic-typecheck,
 
 [REPORTS]
 
-# Set the output format. Available formats are text, parseable, colorized, msvs
-# (visual studio) and html
-output-format=text
-
-# Include message's id in output
-include-ids=yes
-
-# Put messages in a separate file for each module / package specified on the
-# command line instead of printing them on stdout. Reports (if any) will be
-# written in a file name "pylint_global.[txt|html]".
-files-output=no
-
-# Tells whether to display a full report or only the messages
-# CHANGED:
 reports=no
 
-# Python expression which should return a note less than 10 (10 is the highest
-# note). You have access to the variables errors warning, statement which
-# respectively contain the number of errors / warnings messages and the total
-# number of statements analyzed. This is used by the global evaluation report
-# (RP0004).
-evaluation=10.0 - ((float(5 * error + warning + refactor + convention) / statement) * 10)
-
-# Add a comment according to your evaluation note. This is used by the global
-# evaluation report (RP0004).
-comment=no
-
-
-[VARIABLES]
-
-# Tells whether we should check for unused import in __init__ files.
-init-import=no
-
-# A regular expression matching the beginning of the name of dummy variables
-# (i.e. not used).
-dummy-variables-rgx=_|dummy
-
-# List of additional names supposed to be defined in builtins. Remember that
-# you should avoid to define new builtins when possible.
-additional-builtins=
-
-
-[TYPECHECK]
-
-# Tells whether missing members accessed in mixin class should be ignored. A
-# mixin class is detected if its name ends with "mixin" (case insensitive).
-ignore-mixin-members=yes
-
-# List of classes names for which member attributes should not be checked
-# (useful for classes with attributes dynamically set).
-ignored-classes=
-
-# When zope mode is activated, add a predefined set of Zope acquired attributes
-# to generated-members.
-zope=no
-
-# List of members which are set dynamically and missed by pylint inference
-# system, and so shouldn't trigger E0201 when accessed. Python regular
-# expressions are accepted.
-generated-members=
-
-
-[MISCELLANEOUS]
-
-# List of note tags to take in consideration, separated by a comma.
-notes=FIXME,XXX,TODO
-
-
-[SIMILARITIES]
-
-# Minimum lines number of a similarity.
-min-similarity-lines=4
-
-# Ignore comments when computing similarities.
-ignore-comments=yes
-
-# Ignore docstrings when computing similarities.
-ignore-docstrings=yes
-
-
-[FORMAT]
-
-# Maximum number of characters on a single line.
-# max-line-length=200
-
-# Maximum number of lines in a module
-# max-module-lines=1000
-
-# String used as indentation unit. This is usually " " (4 spaces) or "\t" (1
-# tab).
-# CHANGED:
-indent-string='    '
-
-
 [BASIC]
 
-# Required attributes for module, separated by a comma
-required-attributes=
+# By default, pylint wants method names to be at most 31 chars long,
+# but we want to allow up to 49 to allow for longer test names.
+method-rgx=[a-zA-Z_][a-zA-Z0-9_]{0,48}$
 
-# List of builtins function names that should not be used, separated by a comma
-bad-functions=map,filter,apply,input
+# By default, pylint only allows UPPER_CASE constants, but we want to
+# allow snake_case as well in some situations.
+const-rgx=[a-zA-Z_][a-zA-Z0-9_]{0,30}$
 
-# Regular expression which should only match correct module names
-module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+))$
-
-# Regular expression which should only match correct module level names
-const-rgx=(([a-zA-Z_][a-zA-Z0-9_]*)|(__.*__))$
-
-# Regular expression which should only match correct class names
-class-rgx=[A-Z_][a-zA-Z0-9]+$
-
-# Regular expression which should only match correct function names
-function-rgx=[a-z_][a-z0-9_]{0,40}$
-
-# Regular expression which should only match correct method names
-method-rgx=[a-z_][a-z0-9_]{0,48}$
-
-# Regular expression which should only match correct instance attribute names
-attr-rgx=[a-z_][a-z0-9_]{0,30}$
-
-# Regular expression which should only match correct argument names
+# By default, pylint wants all parameter names to be at least two chars long,
+# but we want to allow single-char parameter names as well.
 argument-rgx=[a-z_][a-z0-9_]{0,30}$
 
-# Regular expression which should only match correct variable names
-variable-rgx=[a-zA-Z0-9_]{0,30}$
-
-# Regular expression which should only match correct list comprehension /
-# generator expression variable names
-inlinevar-rgx=[A-Za-z_][A-Za-z0-9_]*$
-
-# Good variable names which should always be accepted, separated by a comma
-good-names=i,j,k,ex,Run,_
-
-# Bad variable names which should always be refused, separated by a comma
-bad-names=foo,bar,baz,toto,tutu,tata
-
-# Regular expression which should only match functions or classes name which do
-# not require a docstring
-no-docstring-rgx=__.*__
-
-
-[DESIGN]
-
-# Maximum number of arguments for function / method
-max-args=8
-
-# Argument names that match this expression will be ignored. Default to name
-# with leading underscore
-ignored-argument-names=_.*
-
-# Maximum number of locals for function / method body
-max-locals=32
-
-# Maximum number of return / yield for function / method body
-max-returns=32
-
-# Maximum number of branch for function / method body
-max-branchs=32
-
-# Maximum number of statements in function / method body
-max-statements=65
-
-# Maximum number of parents for a class (see R0901).
-max-parents=7
-
-# Maximum number of attributes for a class (see R0902).
-max-attributes=16
-
-# Minimum number of public methods for a class (see R0903).
-min-public-methods=0
-
-# Maximum number of public methods for a class (see R0904).
-max-public-methods=100
-
-
-[CLASSES]
-
-# List of interface methods to ignore, separated by a comma. This is used for
-# instance to not check methods defines in Zope's Interface base class.
-ignore-iface-methods=isImplementedBy,deferred,extends,names,namesAndDescriptions,queryDescriptionFor,getBases,getDescriptionFor,getDoc,getName,getTaggedValue,getTaggedValueTags,isEqualOrExtendedBy,setTaggedValue,isImplementedByInstancesOf,adaptWith,is_implemented_by
-
-# List of method names used to declare (i.e. assign) instance attributes.
-defining-attr-methods=__init__,__new__,setUp
-
-# List of valid names for the first argument in a class method.
-valid-classmethod-first-arg=cls
-
-
-[IMPORTS]
-
-# Deprecated modules which should not be used, separated by a comma
-deprecated-modules=regsub,string,TERMIOS,Bastion,rexec
-
-# Create a graph of every (i.e. internal and external) dependencies in the
-# given file (report RP0402 must not be disabled)
-import-graph=
-
-# Create a graph of external dependencies in the given file (report RP0402 must
-# not be disabled)
-ext-import-graph=
-
-# Create a graph of internal dependencies in the given file (report RP0402 must
-# not be disabled)
-int-import-graph=
-
-
-[EXCEPTIONS]
-
-# Exceptions that will emit a warning when being caught. Defaults to
-# "Exception"
-overgeneral-exceptions=Exception
+# By default, pylint wants all variable names to be at least two chars long,
+# but we want to allow single-char variable names as well.
+variable-rgx=[a-z_][a-z0-9_]{0,30}$
diff --git a/third_party/pyjson5/src/run b/third_party/pyjson5/src/run
index 22fff41..c28ba070 100755
--- a/third_party/pyjson5/src/run
+++ b/third_party/pyjson5/src/run
@@ -3,16 +3,11 @@
 from __future__ import print_function
 
 import argparse
-import os
 import subprocess
 import sys
 
 
-is_python3 = bool(sys.version_info.major == 3)
-has_python34 = False
 verbose = False
-repo_dir = os.path.abspath(os.path.dirname(__file__))
-path_to_cov = os.path.join(repo_dir, 'tools', 'cov.py')
 
 
 def call(*args, **kwargs):
@@ -25,8 +20,6 @@
 
 def main(argv):
     parser = argparse.ArgumentParser(prog='run')
-    parser.add_argument('--no3', action='store_true',
-                        help='Do not run the tests under Python 3.')
     parser.add_argument('-v', '--verbose', action='store_true')
     subps = parser.add_subparsers()
 
@@ -37,16 +30,9 @@
     subp.set_defaults(func=run_clean)
 
     subp = subps.add_parser('coverage',
-                            help='Run the tests and report code coverage.')
+                            help='Run tests and report code coverage.')
     subp.set_defaults(func=run_coverage)
 
-    subp = subps.add_parser('develop',
-                             help='Install a symlinked package locally.')
-    subp.set_defaults(func=run_develop)
-    subp.add_argument('--system', action='store_true',
-                      help=('Install to the system site-package dir '
-                            'rather than the user\'s (requires root).'))
-
     subp = subps.add_parser('format',
                             help='Reformat the source code.')
     subp.set_defaults(func=run_format)
@@ -77,34 +63,31 @@
     global verbose
     if args.verbose:
         verbose = True
-    global has_python34
-    if not args.no3:
-        try:
-            ver = subprocess.check_output(['python3', '--version'])
-            has_python34 = ver.split()[1] >= '3.4'
-        except:
-            pass
     args.func(args)
 
 
 def run_build(args):
+    del args
     call([sys.executable, 'setup.py', 'build', '--quiet'])
 
 
 def run_clean(args):
+    del args
     call(['git', 'clean', '-fxd'])
 
 
 def run_coverage(args):
-    call(['typ', '-c', 'json5'])
-
-
-def run_develop(args):
-    call([sys.executable, 'setup.py', 'develop'])
+    del args
+    call(['python', '-m', 'coverage', 'run', '-m', 'unittest',
+          'discover', '-p', '*_test.py'])
+    call(['python3', '-m', 'coverage', 'run', '--append', '-m', 'unittest',
+          'discover', '-p', '*_test.py'])
+    call([sys.executable, '-m', 'coverage', 'report', '--show-missing'])
 
 
 def run_format(args):
-    call('autopep8 --in-place *.py */*.py */*/*.py', shell=True)
+    del args
+    call('autopep8 --in-place *.py */*.py', shell=True)
 
 
 def run_help(args):
@@ -122,12 +105,14 @@
 
 
 def run_lint(args):
-    call('pylint --rcfile=pylintrc */*.py */*/*.py', shell=True)
-    call('pep8 *.py */*.py */*/*.py', shell=True)
+    del args
+    call('pylint --rcfile=pylintrc */*.py', shell=True)
 
 
 def run_tests(args):
-    call(['typ', 'json5'])
+    del args
+    call([sys.executable, '-m', 'unittest', 'discover',
+          '-p', '*_test.py'])
 
 
 if __name__ == '__main__':
diff --git a/third_party/pyjson5/src/setup.cfg b/third_party/pyjson5/src/setup.cfg
index 3c6e79c..8462fbd 100644
--- a/third_party/pyjson5/src/setup.cfg
+++ b/third_party/pyjson5/src/setup.cfg
@@ -1,2 +1,5 @@
+[metadata]
+license_files = LICENSE.txt
+
 [bdist_wheel]
 universal=1
diff --git a/third_party/pyjson5/src/setup.py b/third_party/pyjson5/src/setup.py
index d0e23fcc..f63e66c 100644
--- a/third_party/pyjson5/src/setup.py
+++ b/third_party/pyjson5/src/setup.py
@@ -23,15 +23,13 @@
 
 import json5
 
-with open(os.path.join(here, 'README.rst')) as fp:
-    readme = fp.read().strip()
+with open(os.path.join(here, 'README.md')) as fp:
+    long_description = fp.read()
 
-readme_lines = readme.splitlines()
 
 setup(
     name='json5',
-    packages=find_packages(),
-    package_data={'': ['../README.rst']},
+    packages=find_packages(exclude=['tests']),
     entry_points={
         'console_scripts': [
             'pyjson5=json5.tool:main',
@@ -39,11 +37,17 @@
     },
     install_requires=[
     ],
+    extras_require={
+        'dev': [
+            'hypothesis'
+        ]
+    },
     version=json5.VERSION,
     author='Dirk Pranke',
     author_email='dpranke@chromium.org',
-    description=readme_lines[3],
-    long_description=('\n' + '\n'.join(readme_lines)),
+    description=long_description.splitlines()[2],
+    long_description=long_description,
+    long_description_content_type='text/markdown',
     url='https://github.com/dpranke/pyjson5',
     license='Apache',
     classifiers=[
diff --git a/third_party/pyjson5/src/tests/__init__.py b/third_party/pyjson5/src/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/pyjson5/src/tests/__init__.py
diff --git a/third_party/pyjson5/src/tests/host_fake.py b/third_party/pyjson5/src/tests/host_fake.py
new file mode 100644
index 0000000..4a8445e
--- /dev/null
+++ b/third_party/pyjson5/src/tests/host_fake.py
@@ -0,0 +1,128 @@
+# Copyright 2014 Dirk Pranke. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+import sys
+
+if sys.version_info[0] < 3:
+    # pylint: disable=redefined-builtin, invalid-name
+    str = unicode
+
+
+class FakeHost(object):
+    # "too many instance attributes" pylint: disable=R0902
+    # "redefining built-in" pylint: disable=W0622
+    # "unused arg" pylint: disable=W0613
+
+    python_interpreter = 'python'
+
+    def __init__(self):
+        self.stdin = io.StringIO()
+        self.stdout = io.StringIO()
+        self.stderr = io.StringIO()
+        self.platform = 'linux2'
+        self.sep = '/'
+        self.dirs = set([])
+        self.files = {}
+        self.written_files = {}
+        self.last_tmpdir = None
+        self.current_tmpno = 0
+        self.cwd = '/tmp'
+
+    def abspath(self, *comps):
+        relpath = self.join(*comps)
+        if relpath.startswith('/'):
+            return relpath
+        return self.join(self.cwd, relpath)
+
+    def chdir(self, *comps):  # pragma: no cover
+        path = self.join(*comps)
+        if not path.startswith('/'):
+            path = self.join(self.cwd, path)
+        self.cwd = path
+
+    def dirname(self, path):
+        return '/'.join(path.split('/')[:-1])
+
+    def getcwd(self):
+        return self.cwd
+
+    def join(self, *comps):  # pragma: no cover
+        p = ''
+        for c in comps:
+            if c in ('', '.'):
+                continue
+            elif c.startswith('/'):
+                p = c
+            elif p:
+                p += '/' + c
+            else:
+                p = c
+
+        # Handle ./
+        p = p.replace('/./', '/')
+
+        # Handle ../
+        while '/..' in p:
+            comps = p.split('/')
+            idx = comps.index('..')
+            comps = comps[:idx-1] + comps[idx+1:]
+            p = '/'.join(comps)
+        return p
+
+    def maybe_mkdir(self, *comps):  # pragma: no cover
+        path = self.abspath(self.join(*comps))
+        if path not in self.dirs:
+            self.dirs.add(path)
+
+    def mkdtemp(self, suffix='', prefix='tmp', dir=None, **_kwargs):
+        if dir is None:
+            dir = self.sep + '__im_tmp'
+        curno = self.current_tmpno
+        self.current_tmpno += 1
+        self.last_tmpdir = self.join(dir, '%s_%u_%s' % (prefix, curno, suffix))
+        self.dirs.add(self.last_tmpdir)
+        return self.last_tmpdir
+
+    def print_(self, msg=u'', end=u'\n', stream=None):
+        stream = stream or self.stdout
+        stream.write(str(msg) + str(end))
+        stream.flush()
+
+    def read_text_file(self, *comps):
+        return self._read(comps)
+
+    def _read(self, comps):
+        return self.files[self.abspath(*comps)]
+
+    def remove(self, *comps):
+        path = self.abspath(*comps)
+        self.files[path] = None
+        self.written_files[path] = None
+
+    def rmtree(self, *comps):
+        path = self.abspath(*comps)
+        for f in self.files:
+            if f.startswith(path):
+                self.remove(f)
+        self.dirs.remove(path)
+
+    def write_text_file(self, path, contents):
+        self._write(path, contents)
+
+    def _write(self, path, contents):
+        full_path = self.abspath(path)
+        self.maybe_mkdir(self.dirname(full_path))
+        self.files[full_path] = contents
+        self.written_files[full_path] = contents
diff --git a/third_party/pyjson5/src/tests/host_test.py b/third_party/pyjson5/src/tests/host_test.py
new file mode 100644
index 0000000..51f9fccf
--- /dev/null
+++ b/third_party/pyjson5/src/tests/host_test.py
@@ -0,0 +1,46 @@
+# Copyright 2019 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+import unittest
+
+from json5.host import Host
+
+class HostTest(unittest.TestCase):
+    maxDiff = None
+
+    def test_directory_and_file_operations(self):
+        h = Host()
+        orig_cwd = h.getcwd()
+
+        try:
+            d = h.mkdtemp()
+            h.chdir(d)
+            h.write_text_file('foo', 'bar')
+            contents = h.read_text_file('foo')
+            self.assertEqual(contents, 'bar')
+            h.chdir('..')
+            h.rmtree(d)
+        finally:
+            h.chdir(orig_cwd)
+
+    def test_print(self):
+        s = io.StringIO()
+        h = Host()
+        h.print_('hello, world', stream=s)
+        self.assertEqual('hello, world\n', s.getvalue())
+
+
+if __name__ == '__main__':  # pragma: no cover
+    unittest.main()
diff --git a/third_party/pyjson5/src/tests/lib_test.py b/third_party/pyjson5/src/tests/lib_test.py
new file mode 100644
index 0000000..0ea37aa
--- /dev/null
+++ b/third_party/pyjson5/src/tests/lib_test.py
@@ -0,0 +1,454 @@
+# Copyright 2015 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import io
+import json
+import math
+import os
+import sys
+import unittest
+
+from collections import OrderedDict
+from string import printable
+
+import json5
+import hypothesis.strategies as some
+
+from hypothesis import given
+
+some_json = some.recursive(
+    some.none() |
+    some.booleans() |
+    some.floats(allow_nan=False) |
+    some.text(printable),
+    lambda children: some.lists(children, min_size=1)
+    | some.dictionaries(some.text(printable), children, min_size=1),
+)
+
+class TestLoads(unittest.TestCase):
+    maxDiff = None
+
+    def check(self, s, obj):
+        self.assertEqual(json5.loads(s), obj)
+
+    def check_fail(self, s, err=None):
+        try:
+            json5.loads(s)
+            self.fail()  # pragma: no cover
+        except ValueError as e:
+            if err:
+                self.assertEqual(err, str(e))
+
+    def test_arrays(self):
+        self.check('[]', [])
+        self.check('[0]', [0])
+        self.check('[0,1]', [0, 1])
+        self.check('[ 0 , 1 ]', [0, 1])
+
+        try:
+            json5.loads('[ ,]')
+            self.fail()
+        except ValueError as e:
+            self.assertIn('Unexpected "," at column 3', str(e))
+
+    def test_bools(self):
+        self.check('true', True)
+        self.check('false', False)
+
+    def test_cls_is_not_supported(self):
+        self.assertRaises(AssertionError, json5.loads, '1', cls=lambda x: x)
+
+    def test_duplicate_keys_should_be_allowed(self):
+        self.assertEqual(json5.loads('{foo: 1, foo: 2}',
+                                     allow_duplicate_keys=True),
+                         {"foo": 2})
+
+    def test_duplicate_keys_should_be_allowed_by_default(self):
+        self.check('{foo: 1, foo: 2}', {"foo": 2})
+
+    def test_duplicate_keys_should_not_be_allowed(self):
+        self.assertRaises(ValueError, json5.loads, '{foo: 1, foo: 2}',
+                          allow_duplicate_keys=False)
+
+    def test_empty_strings_are_errors(self):
+        self.check_fail('', 'Empty strings are not legal JSON5')
+
+    def test_encoding(self):
+        if sys.version_info[0] < 3:
+            s = '"\xf6"'
+        else:
+            s = b'"\xf6"'
+        self.assertEqual(json5.loads(s, encoding='iso-8859-1'),
+                         u'\xf6')
+
+    def test_numbers(self):
+        # decimal literals
+        self.check('1', 1)
+        self.check('-1', -1)
+        self.check('+1', 1)
+
+        # hex literals
+        self.check('0xf', 15)
+        self.check('0xfe', 254)
+        self.check('0xfff', 4095)
+        self.check('0XABCD', 43981)
+        self.check('0x123456', 1193046)
+
+        # floats
+        self.check('1.5', 1.5)
+        self.check('1.5e3', 1500.0)
+        self.check('-0.5e-2', -0.005)
+
+        # names
+        self.check('Infinity', float('inf'))
+        self.check('-Infinity', float('-inf'))
+        self.assertTrue(math.isnan(json5.loads('NaN')))
+        self.assertTrue(math.isnan(json5.loads('-NaN')))
+
+        # syntax errors
+        self.check_fail('14d', '<string>:1 Unexpected "d" at column 3')
+
+    def test_identifiers(self):
+        self.check('{a: 1}', {'a': 1})
+        self.check('{$: 1}', {'$': 1})
+        self.check('{_: 1}', {'_': 1})
+        self.check('{a_b: 1}', {'a_b': 1})
+        self.check('{a$: 1}', {'a$': 1})
+
+        # This valid JavaScript but not valid JSON5; keys must be identifiers
+        # or strings.
+        self.check_fail('{1: 1}')
+
+    def test_identifiers_unicode(self):
+        self.check(u'{\xc3: 1}', {u'\xc3': 1})
+
+    def test_null(self):
+        self.check('null', None)
+
+    def test_object_hook(self):
+        hook = lambda d: [d]
+        self.assertEqual(json5.loads('{foo: 1}', object_hook=hook),
+                         [{"foo": 1}])
+
+    def test_object_pairs_hook(self):
+        hook = lambda pairs: pairs
+        self.assertEqual(json5.loads('{foo: 1, bar: 2}',
+                                     object_pairs_hook=hook),
+                         [('foo', 1), ('bar', 2)])
+
+    def test_objects(self):
+        self.check('{}', {})
+        self.check('{"foo": 0}', {"foo": 0})
+        self.check('{"foo":0,"bar":1}', {"foo": 0, "bar": 1})
+        self.check('{ "foo" : 0 , "bar" : 1 }', {"foo": 0, "bar": 1})
+
+    def test_parse_constant(self):
+        hook = lambda x: x
+        self.assertEqual(json5.loads('-Infinity', parse_constant=hook),
+                         '-Infinity')
+        self.assertEqual(json5.loads('NaN', parse_constant=hook),
+                         'NaN')
+
+    def test_parse_float(self):
+        hook = lambda x: x
+        self.assertEqual(json5.loads('1.0', parse_float=hook), '1.0')
+
+    def test_parse_int(self):
+        hook = lambda x, base=10: x
+        self.assertEqual(json5.loads('1', parse_int=hook), '1')
+
+    def test_sample_file(self):
+        path = os.path.join(os.path.dirname(__file__), '..', 'sample.json5')
+        with open(path) as fp:
+            obj = json5.load(fp)
+        self.assertEqual({
+            u'oh': [
+                u"we shouldn't forget",
+                u"arrays can have",
+                u"trailing commas too",
+            ],
+            u"this": u"is a multi-line string",
+            u"delta": 10,
+            u"hex": 3735928559,
+            u"finally": "a trailing comma",
+            u"here": "is another",
+            u"to": float("inf"),
+            u"while": True,
+            u"half": 0.5,
+            u"foo": u"bar"
+            }, obj)
+
+    def test_strings(self):
+        self.check('"foo"', 'foo')
+        self.check("'foo'", 'foo')
+
+        # escape chars
+        self.check("'\\b\\t\\f\\n\\r\\v\\\\'", '\b\t\f\n\r\v\\')
+        self.check("'\\''", "'")
+        self.check('"\\""', '"')
+
+        # hex literals
+        self.check('"\\x66oo"', 'foo')
+
+        # unicode literals
+        self.check('"\\u0066oo"', 'foo')
+
+        # string literals w/ continuation markers at the end of the line.
+        # These should not have spaces is the result.
+        self.check('"foo\\\nbar"', 'foobar')
+        self.check("'foo\\\nbar'", 'foobar')
+
+        # unterminated string literals.
+        self.check_fail('"\n')
+        self.check_fail("'\n")
+
+        # bad hex literals
+        self.check_fail("'\\x0'")
+        self.check_fail("'\\xj'")
+        self.check_fail("'\\x0j'")
+
+        # bad unicode literals
+        self.check_fail("'\\u0'")
+        self.check_fail("'\\u00'")
+        self.check_fail("'\\u000'")
+        self.check_fail("'\\u000j'")
+        self.check_fail("'\\u00j0'")
+        self.check_fail("'\\u0j00'")
+        self.check_fail("'\\uj000'")
+
+    def test_unrecognized_escape_char(self):
+        self.check(r'"\/"', '/')
+
+    def test_nul(self):
+        self.check(r'"\0"', '\x00')
+
+    def test_whitespace(self):
+        self.check('\n1', 1)
+        self.check('\r1', 1)
+        self.check('\r\n1', 1)
+        self.check('\t1', 1)
+        self.check('\v1', 1)
+        self.check(u'\uFEFF 1', 1)
+        self.check(u'\u00A0 1', 1)
+        self.check(u'\u2028 1', 1)
+        self.check(u'\u2029 1', 1)
+
+
+class TestDump(unittest.TestCase):
+    def test_basic(self):
+        sio = io.StringIO()
+        json5.dump(True, sio)
+        self.assertEqual('true', sio.getvalue())
+
+
+class TestDumps(unittest.TestCase):
+    maxDiff = None
+
+    def check(self, obj, s):
+        self.assertEqual(json5.dumps(obj), s)
+
+    def test_allow_duplicate_keys(self):
+        self.assertIn(json5.dumps({1: "foo", "1": "bar"}),
+                      {'{"1": "foo", "1": "bar"}',
+                       '{"1": "bar", "1": "foo"}'})
+
+        self.assertRaises(ValueError, json5.dumps,
+                          {1: "foo", "1": "bar"},
+                           allow_duplicate_keys=False)
+
+    def test_arrays(self):
+        self.check([], '[]')
+        self.check([1, 2, 3], '[1, 2, 3]')
+        self.check([{'foo': 'bar'}, {'baz': 'quux'}],
+                    '[{foo: "bar"}, {baz: "quux"}]')
+
+    def test_bools(self):
+        self.check(True, 'true')
+        self.check(False, 'false')
+
+    def test_check_circular(self):
+        # This tests a trivial cycle.
+        l = [1, 2, 3]
+        l[2] = l
+        self.assertRaises(ValueError, json5.dumps, l)
+
+        # This checks that json5 doesn't raise an error. However,
+        # the underlying Python implementation likely will.
+        try:
+            json5.dumps(l, check_circular=False)
+            self.fail()  # pragma: no cover
+        except Exception as e:
+            self.assertNotIn(str(e), 'Circular reference detected')
+
+        # This checks that repeated but non-circular references
+        # are okay.
+        x = [1, 2]
+        y = {"foo": x, "bar": x}
+        self.check(y,
+                   '{foo: [1, 2], bar: [1, 2]}')
+
+        # This tests a more complicated cycle.
+        x = {}
+        y = {}
+        z = {}
+        z['x'] = x
+        z['y'] = y
+        z['x']['y'] = y
+        z['y']['x'] = x
+        self.assertRaises(ValueError, json5.dumps, z)
+
+    def test_default(self):
+
+        def _custom_serializer(obj):
+            del obj
+            return 'something'
+
+        self.assertRaises(TypeError, json5.dumps, set())
+        self.assertEqual(json5.dumps(set(), default=_custom_serializer),
+                         'something')
+
+    def test_ensure_ascii(self):
+        self.check(u'\u00fc', '"\\u00fc"')
+        self.assertEqual(json5.dumps(u'\u00fc', ensure_ascii=False),
+                         u'"\u00fc"')
+
+    def test_indent(self):
+        self.assertEqual(json5.dumps([1, 2, 3], indent=None),
+                         u'[1, 2, 3]')
+        self.assertEqual(json5.dumps([1, 2, 3], indent=-1),
+                         u'[\n1,\n2,\n3,\n]')
+        self.assertEqual(json5.dumps([1, 2, 3], indent=0),
+                         u'[\n1,\n2,\n3,\n]')
+        self.assertEqual(json5.dumps([], indent=2),
+                         u'[]')
+        self.assertEqual(json5.dumps([1, 2, 3], indent=2),
+                         u'[\n  1,\n  2,\n  3,\n]')
+        self.assertEqual(json5.dumps([1, 2, 3], indent=' '),
+                         u'[\n 1,\n 2,\n 3,\n]')
+        self.assertEqual(json5.dumps([1, 2, 3], indent='++'),
+                         u'[\n++1,\n++2,\n++3,\n]')
+        self.assertEqual(json5.dumps([[1, 2, 3]], indent=2),
+                         u'[\n  [\n    1,\n    2,\n    3,\n  ],\n]')
+
+        self.assertEqual(json5.dumps({}, indent=2),
+                         u'{}')
+        self.assertEqual(json5.dumps({'foo': 'bar', 'baz': 'quux'}, indent=2),
+                         u'{\n  foo: "bar",\n  baz: "quux",\n}')
+
+    def test_numbers(self):
+        self.check(15, '15')
+        self.check(1.0, '1.0')
+        self.check(float('inf'), 'Infinity')
+        self.check(float('-inf'), '-Infinity')
+        self.check(float('nan'), 'NaN')
+
+        self.assertRaises(ValueError, json5.dumps,
+                          float('inf'), allow_nan=False)
+
+    def test_null(self):
+        self.check(None, 'null')
+
+    def test_objects(self):
+        self.check({'foo': 1}, '{foo: 1}')
+        self.check({'foo bar': 1}, '{"foo bar": 1}')
+        self.check({'1': 1}, '{"1": 1}')
+
+    def test_reserved_words_in_object_keys_are_quoted(self):
+        self.check({'new': 1}, '{"new": 1}')
+
+    def test_identifiers_only_starting_with_reserved_words_are_not_quoted(self):
+        self.check({'newbie': 1}, '{newbie: 1}')
+
+    def test_non_string_keys(self):
+        self.assertEqual(json5.dumps({False: 'a', 1: 'b', 2.0: 'c', None: 'd'}),
+                         '{"false": "a", "1": "b", "2.0": "c", "null": "d"}')
+
+    def test_quote_keys(self):
+        self.assertEqual(json5.dumps({"foo": 1}, quote_keys=True),
+                         '{"foo": 1}')
+
+    def test_strings(self):
+        self.check("'single'", '"\'single\'"')
+        self.check('"double"', '"\\"double\\""')
+        self.check("'single \\' and double \"'",
+                   '"\'single \\\\\' and double \\"\'"')
+
+    def test_string_escape_sequences(self):
+        self.check(u'\u2028\u2029\b\t\f\n\r\v\\\0',
+                   '"\\u2028\\u2029\\b\\t\\f\\n\\r\\v\\\\\\0"')
+
+    def test_skip_keys(self):
+        od = OrderedDict()
+        od[(1, 2)] = 2
+        self.assertRaises(TypeError, json5.dumps, od)
+        self.assertEqual(json5.dumps(od, skipkeys=True), '{}')
+
+        od['foo'] = 1
+        self.assertEqual(json5.dumps(od, skipkeys=True), '{foo: 1}')
+
+        # Also test that having an invalid key as the last element
+        # doesn't incorrectly add a trailing comma (see
+        # https://github.com/dpranke/pyjson5/issues/33).
+        od = OrderedDict()
+        od['foo'] = 1
+        od[(1, 2)] = 2
+        self.assertEqual(json5.dumps(od, skipkeys=True), '{foo: 1}')
+
+    def test_sort_keys(self):
+        od = OrderedDict()
+        od['foo'] = 1
+        od['bar'] = 2
+        self.assertEqual(json5.dumps(od, sort_keys=True),
+                         '{bar: 2, foo: 1}')
+
+    def test_trailing_commas(self):
+        # By default, multi-line dicts and lists should have trailing
+        # commas after their last items.
+        self.assertEqual(json5.dumps({"foo": 1}, indent=2),
+                         '{\n  foo: 1,\n}')
+        self.assertEqual(json5.dumps([1], indent=2),
+                         '[\n  1,\n]')
+
+        self.assertEqual(json5.dumps({"foo": 1}, indent=2,
+                                     trailing_commas=False),
+                         '{\n  foo: 1\n}')
+        self.assertEqual(json5.dumps([1], indent=2, trailing_commas=False),
+                         '[\n  1\n]')
+
+    def test_supplemental_unicode(self):
+        try:
+            s = chr(0x10000)
+            self.check(s, '"\\ud800\\udc00"')
+        except ValueError:
+            # Python2 doesn't support supplemental unicode planes, so
+            # we can't test this there.
+            pass
+
+    def test_empty_key(self):
+        self.assertEqual(json5.dumps({'': 'value'}), '{"": "value"}')
+
+    @given(some_json)
+    def test_object_roundtrip(self, input_object):
+        dumped_string_json = json.dumps(input_object)
+        dumped_string_json5 = json5.dumps(input_object)
+
+        parsed_object_json = json5.loads(dumped_string_json)
+        parsed_object_json5 = json5.loads(dumped_string_json5)
+
+        assert parsed_object_json == input_object
+        assert parsed_object_json5 == input_object
+
+
+if __name__ == '__main__':  # pragma: no cover
+    unittest.main()
diff --git a/third_party/pyjson5/src/tests/tool_test.py b/third_party/pyjson5/src/tests/tool_test.py
new file mode 100644
index 0000000..073edc0
--- /dev/null
+++ b/third_party/pyjson5/src/tests/tool_test.py
@@ -0,0 +1,145 @@
+# Copyright 2017 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import sys
+import unittest
+
+import json5
+import json5.tool
+
+from .host_fake import FakeHost
+
+
+if sys.version_info[0] < 3:
+    # pylint: disable=redefined-builtin, invalid-name
+    str = unicode
+
+
+class CheckMixin(object):
+    def _write_files(self, host, files):
+        for path, contents in list(files.items()):
+            host.write_text_file(path, contents)
+
+    def check_cmd(self, args, stdin=None, files=None,
+                  returncode=None, out=None, err=None):
+        host = self._host()
+        orig_wd, tmpdir = None, None
+        try:
+            orig_wd = host.getcwd()
+            tmpdir = host.mkdtemp()
+            host.chdir(tmpdir)
+            if files:
+                self._write_files(host, files)
+            rv = self._call(host, args, stdin, returncode, out, err)
+            actual_ret, actual_out, actual_err = rv
+        finally:
+            if tmpdir:
+                host.rmtree(tmpdir)
+            if orig_wd:
+                host.chdir(orig_wd)
+
+        return actual_ret, actual_out, actual_err
+
+
+class UnitTestMixin(object):
+    def _host(self):
+        return FakeHost()
+
+    def _call(self, host, args, stdin=None,
+              returncode=None, out=None, err=None):
+        if stdin is not None:
+            host.stdin.write(str(stdin))
+            host.stdin.seek(0)
+        actual_ret = json5.tool.main(args, host)
+        actual_out = host.stdout.getvalue()
+        actual_err = host.stderr.getvalue()
+        if returncode is not None:
+            self.assertEqual(returncode, actual_ret)
+        if out is not None:
+            self.assertEqual(out, actual_out)
+        if err is not None:
+            self.assertEqual(err, actual_err)
+        return actual_ret, actual_out, actual_err
+
+
+class ToolTest(UnitTestMixin, CheckMixin, unittest.TestCase):
+    maxDiff = None
+
+    def test_help(self):
+        self.check_cmd(['--help'], returncode=0)
+
+    def test_inline_expression(self):
+        self.check_cmd(['-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    foo: 1,\n}\n')
+
+    def test_indent(self):
+        self.check_cmd(['--indent=None', '-c', '[1]'], returncode=0,
+                       out=u'[1]\n')
+        self.check_cmd(['--indent=2', '-c', '[1]'], returncode=0,
+                       out=u'[\n  1,\n]\n')
+        self.check_cmd(['--indent=  ', '-c', '[1]'], returncode=0,
+                       out=u'[\n  1,\n]\n')
+
+    def test_as_json(self):
+        self.check_cmd(['--as-json', '-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    "foo": 1\n}\n')
+
+    def test_quote_keys(self):
+        self.check_cmd(['--quote-keys', '-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    "foo": 1,\n}\n')
+
+    def test_no_quote_keys(self):
+        self.check_cmd(['--no-quote-keys', '-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    foo: 1,\n}\n')
+
+    def test_keys_are_quoted_by_default(self):
+        self.check_cmd(['-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    foo: 1,\n}\n')
+
+    def test_read_command(self):
+        self.check_cmd(['-c', '"foo"'], returncode=0, out=u'"foo"\n')
+
+    def test_read_from_stdin(self):
+        self.check_cmd([], stdin='"foo"\n', returncode=0, out=u'"foo"\n')
+
+    def test_read_from_a_file(self):
+        files = {
+            'foo.json5': '"foo"\n',
+        }
+        self.check_cmd(['foo.json5'], files=files, returncode=0, out=u'"foo"\n')
+
+    def test_trailing_commas(self):
+        self.check_cmd(['--trailing-commas', '-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    foo: 1,\n}\n')
+
+    def test_no_trailing_commas(self):
+        self.check_cmd(['--no-trailing-commas', '-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    foo: 1\n}\n')
+
+    def test_trailing_commas_are_there_by_default(self):
+        self.check_cmd(['-c', '{foo: 1}'], returncode=0,
+                       out=u'{\n    foo: 1,\n}\n')
+
+    def test_unknown_switch(self):
+        self.check_cmd(['--unknown-switch'], returncode=2,
+                       err=u'json5: error: unrecognized arguments: '
+                       '--unknown-switch\n\n')
+
+    def test_version(self):
+        self.check_cmd(['--version'], returncode=0,
+                       out=str(json5.VERSION) + '\n')
+
+
+if __name__ == '__main__':  # pragma: no cover
+    unittest.main()
diff --git a/third_party/test_fonts/BUILD.gn b/third_party/test_fonts/BUILD.gn
index 7ed7adc..5c5db81 100644
--- a/third_party/test_fonts/BUILD.gn
+++ b/third_party/test_fonts/BUILD.gn
@@ -31,6 +31,7 @@
     "test_fonts/NotoSansCJKjp-Regular.otf",
     "test_fonts/NotoSansKhmer-Regular.ttf",
     "test_fonts/NotoSansSymbols2-Regular.ttf",
+    "test_fonts/NotoSansTibetan-Regular.ttf",
     "test_fonts/Tinos-Bold.ttf",
     "test_fonts/Tinos-BoldItalic.ttf",
     "test_fonts/Tinos-Italic.ttf",
diff --git a/third_party/test_fonts/README.chromium b/third_party/test_fonts/README.chromium
index 6a9844f..18412a9a 100644
--- a/third_party/test_fonts/README.chromium
+++ b/third_party/test_fonts/README.chromium
@@ -36,32 +36,33 @@
 
 Font Origins:
 
-Ahem.ttf                   https://web-platform-tests.org/writing-tests/ahem.html
-Arimo-Bold.ttf             https://github.com/google/fonts/tree/master/apache/arimo
-Arimo-BoldItalic.ttf       https://github.com/google/fonts/tree/master/apache/arimo
-Arimo-Italic.ttf           https://github.com/google/fonts/tree/master/apache/arimo
-Arimo-Regular.ttf          https://github.com/google/fonts/tree/master/apache/arimo
-Cousine-Bold.ttf           https://github.com/google/fonts/tree/master/apache/cousine
-Cousine-BoldItalic.ttf     https://github.com/google/fonts/tree/master/apache/cousine
-Cousine-Italic.ttf         https://github.com/google/fonts/tree/master/apache/cousine
-Cousine-Regular.ttf        https://github.com/google/fonts/tree/master/apache/cousine
-DejaVuSans.ttf             https://dejavu-fonts.github.io/Download.html
-GardinerModBug.ttf         See README_GardinerMod.txt
-GardinerModCat.ttf         See README_GardinerMod.txt
-Garuda.ttf                 https://linux.thai.net/projects/fonts-tlwg
-Gelasio-Bold.ttf           https://fontlibrary.org/en/font/gelasio
-Gelasio-BoldItalic.ttf     https://fontlibrary.org/en/font/gelasio
-Gelasio-Italic.ttf         https://fontlibrary.org/en/font/gelasio
-Gelasio-Regular.ttf        https://fontlibrary.org/en/font/gelasio
-Lohit-Devanagari.ttf       https://pagure.io/lohit
-Lohit-Gurmukhi.ttf         https://pagure.io/lohit
-Lohit-Tamil.ttf            https://pagure.io/lohit
-MuktiNarrow.ttf            http://www.nongnu.org/freebangfont/downloads.html#mukti
-NotoColorEmoji.ttf         https://github.com/googlefonts/noto-emoji
-NotoSansCJKjp-Regular.otf  https://www.google.com/get/noto/#sans-jpan
-NotoSansKhmer-Regular.ttf  https://www.google.com/get/noto/#sans-khmr
-NotoSansSymbols2-Regular.ttf  https://github.com/googlefonts/noto-fonts/tree/master/hinted/NotoSansSymbols2
-Tinos-Bold.ttf             https://github.com/google/fonts/tree/master/apache/tinos
-Tinos-BoldItalic.ttf       https://github.com/google/fonts/tree/master/apache/tinos
-Tinos-Italic.ttf           https://github.com/google/fonts/tree/master/apache/tinos
-Tinos-Regular.ttf          https://github.com/google/fonts/tree/master/apache/tinos
+Ahem.ttf                     https://web-platform-tests.org/writing-tests/ahem.html
+Arimo-Bold.ttf               https://github.com/google/fonts/tree/master/apache/arimo
+Arimo-BoldItalic.ttf         https://github.com/google/fonts/tree/master/apache/arimo
+Arimo-Italic.ttf             https://github.com/google/fonts/tree/master/apache/arimo
+Arimo-Regular.ttf            https://github.com/google/fonts/tree/master/apache/arimo
+Cousine-Bold.ttf             https://github.com/google/fonts/tree/master/apache/cousine
+Cousine-BoldItalic.ttf       https://github.com/google/fonts/tree/master/apache/cousine
+Cousine-Italic.ttf           https://github.com/google/fonts/tree/master/apache/cousine
+Cousine-Regular.ttf          https://github.com/google/fonts/tree/master/apache/cousine
+DejaVuSans.ttf               https://dejavu-fonts.github.io/Download.html
+GardinerModBug.ttf           See README_GardinerMod.txt
+GardinerModCat.ttf           See README_GardinerMod.txt
+Garuda.ttf                   https://linux.thai.net/projects/fonts-tlwg
+Gelasio-Bold.ttf             https://fontlibrary.org/en/font/gelasio
+Gelasio-BoldItalic.ttf       https://fontlibrary.org/en/font/gelasio
+Gelasio-Italic.ttf           https://fontlibrary.org/en/font/gelasio
+Gelasio-Regular.ttf          https://fontlibrary.org/en/font/gelasio
+Lohit-Devanagari.ttf         https://pagure.io/lohit
+Lohit-Gurmukhi.ttf           https://pagure.io/lohit
+Lohit-Tamil.ttf              https://pagure.io/lohit
+MuktiNarrow.ttf              http://www.nongnu.org/freebangfont/downloads.html#mukti
+NotoColorEmoji.ttf           https://github.com/googlefonts/noto-emoji
+NotoSansCJKjp-Regular.otf    https://www.google.com/get/noto/#sans-jpan
+NotoSansKhmer-Regular.ttf    https://www.google.com/get/noto/#sans-khmr
+NotoSansSymbols2-Regular.ttf https://github.com/googlefonts/noto-fonts/tree/master/hinted/NotoSansSymbols2
+NotoSansTibetan-Regular.ttf  https://github.com/googlefonts/noto-fonts/tree/master/hinted/NotoSansTibetan
+Tinos-Bold.ttf               https://github.com/google/fonts/tree/master/apache/tinos
+Tinos-BoldItalic.ttf         https://github.com/google/fonts/tree/master/apache/tinos
+Tinos-Italic.ttf             https://github.com/google/fonts/tree/master/apache/tinos
+Tinos-Regular.ttf            https://github.com/google/fonts/tree/master/apache/tinos
diff --git a/third_party/test_fonts/test_fonts.tar.gz.sha1 b/third_party/test_fonts/test_fonts.tar.gz.sha1
index 66590f9..077f810 100644
--- a/third_party/test_fonts/test_fonts.tar.gz.sha1
+++ b/third_party/test_fonts/test_fonts.tar.gz.sha1
@@ -1 +1 @@
-d60a406cd5d35c4f01ead05a43ae8c6d7de9b39e
\ No newline at end of file
+cd96fc55dc243f6c6f4cb63ad117cad6cd48dceb
\ No newline at end of file
diff --git a/tools/check_grd_for_unused_strings.py b/tools/check_grd_for_unused_strings.py
index d0b60da..d11c3e1 100755
--- a/tools/check_grd_for_unused_strings.py
+++ b/tools/check_grd_for_unused_strings.py
@@ -140,7 +140,7 @@
     ui_chromeos_dir = os.path.join(ui_dir, 'chromeos')
     grd_files = [
       os.path.join(ash_base_dir, 'ash_strings.grd'),
-      os.path.join(ash_shortcut_viewer_dir, 'ash_components_strings.grd'),
+      os.path.join(ash_shortcut_viewer_dir, 'shortcut_viewer_strings.grd'),
       os.path.join(chrome_app_dir, 'chromium_strings.grd'),
       os.path.join(chrome_app_dir, 'generated_resources.grd'),
       os.path.join(chrome_app_dir, 'google_chrome_strings.grd'),
diff --git a/tools/chrome_proxy/webdriver/subresource_redirect.py b/tools/chrome_proxy/webdriver/subresource_redirect.py
index eb42b2aa..1f224dc 100644
--- a/tools/chrome_proxy/webdriver/subresource_redirect.py
+++ b/tools/chrome_proxy/webdriver/subresource_redirect.py
@@ -14,6 +14,7 @@
 
   def enableSubresourceRedirectFeature(self, test_driver):
     test_driver.EnableChromeFeature('SubresourceRedirect<SubresourceRedirect')
+    test_driver.AddChromeArg('--force-variation-ids=-1')
     test_driver.AddChromeArg('--force-fieldtrials=SubresourceRedirect/Enabled')
     test_driver.AddChromeArg(
         '--force-fieldtrial-params='
diff --git a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
index 25c6bf6..54f4342 100644
--- a/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
+++ b/tools/clang/rewrite_raw_ptr_fields/RewriteRawPtrFields.cpp
@@ -50,13 +50,76 @@
 
 // Name of a cmdline parameter that can be used to specify a file listing fields
 // that should not be rewritten to use CheckedPtr<T>.
+//
+// See also:
+// - FilterEmitterHelper
+// - FieldDeclFilterFile
 const char kExcludeFieldsParamName[] = "exclude-fields";
 
-// Output format is documented in //docs/clang_tool_refactoring.md
-class ReplacementsPrinter : public clang::tooling::SourceFileCallbacks {
+// Helper for an out-of-band output that
+//
+// 1. Is delimited in a way that makes it easy to extract it with sed like so:
+//    $ DELIM = ...
+//    $ cat ~/scratch/rewriter.out \
+//        | sed '/^==== BEGIN $DELIM ====$/,/^==== END $DELIM ====$/{//!b};d' \
+//        | sort | uniq > ~/scratch/some-out-of-band-output.txt
+//
+// 2. Contains one filter-string per line of output, accompanied with a comment
+//    listing a set of tags that help describe why this line of output was
+//    emitted:
+//        Some filter # tag1, tag2
+//        Another filter # tag1, tag2, tag3
+//
+// See also:
+// - FieldDeclFilterFile
+class FilterEmitterHelper {
  public:
-  ReplacementsPrinter() = default;
-  ~ReplacementsPrinter() = default;
+  explicit FilterEmitterHelper(llvm::StringRef output_delimiter)
+      : output_delimiter_(output_delimiter.str()) {}
+
+  void Add(llvm::StringRef filter, llvm::StringRef tag) {
+    filter_to_tags_[filter].insert(tag);
+  }
+
+  void Emit() {
+    if (filter_to_tags_.empty())
+      return;
+
+    llvm::outs() << "==== BEGIN " << output_delimiter_ << " ====\n";
+    for (const llvm::StringRef& filter : GetSortedKeys(filter_to_tags_)) {
+      llvm::outs() << filter;
+
+      const llvm::StringSet<>& tags = filter_to_tags_[filter];
+      if (!tags.empty()) {
+        std::vector<llvm::StringRef> sorted_tags = GetSortedKeys(tags);
+        std::string tags_comment =
+            llvm::join(sorted_tags.begin(), sorted_tags.end(), ", ");
+        llvm::outs() << "  # " << tags_comment;
+      }
+
+      llvm::outs() << "\n";
+    }
+    llvm::outs() << "==== END " << output_delimiter_ << " ====\n";
+  }
+
+ private:
+  template <typename TValue>
+  std::vector<llvm::StringRef> GetSortedKeys(
+      const llvm::StringMap<TValue>& map) {
+    std::vector<llvm::StringRef> sorted(map.keys().begin(), map.keys().end());
+    std::sort(sorted.begin(), sorted.end());
+    return sorted;
+  }
+
+  std::string output_delimiter_;
+  llvm::StringMap<llvm::StringSet<>> filter_to_tags_;
+};
+
+// Output format is documented in //docs/clang_tool_refactoring.md
+class OutputHelper : public clang::tooling::SourceFileCallbacks {
+ public:
+  OutputHelper() : field_decl_filter_helper_("FIELD FILTERS") {}
+  ~OutputHelper() = default;
 
   void PrintReplacement(const clang::SourceManager& source_manager,
                         const clang::SourceRange& replacement_range,
@@ -86,6 +149,12 @@
     }
   }
 
+  void AddFilteredField(const clang::FieldDecl& field_decl,
+                        llvm::StringRef filter_tag) {
+    std::string qualified_name = field_decl.getQualifiedNameAsString();
+    field_decl_filter_helper_.Add(qualified_name, filter_tag);
+  }
+
  private:
   // clang::tooling::SourceFileCallbacks override:
   bool handleBeginSource(clang::CompilerInstance& compiler) override {
@@ -107,8 +176,11 @@
 
   // clang::tooling::SourceFileCallbacks override:
   void handleEndSource() override {
-    if (!ShouldSuppressOutput())
-      llvm::outs() << "==== END EDITS ====\n";
+    if (ShouldSuppressOutput())
+      return;
+
+    llvm::outs() << "==== END EDITS ====\n";
+    field_decl_filter_helper_.Emit();
   }
 
   bool ShouldSuppressOutput() {
@@ -139,7 +211,8 @@
     return true;
   }
 
-  std::set<std::string> files_with_already_added_includes_;
+  llvm::StringSet<> files_with_already_added_includes_;
+  FilterEmitterHelper field_decl_filter_helper_;
   clang::Language current_language_ = clang::Language::Unknown;
 };
 
@@ -190,6 +263,12 @@
   return file_path.startswith("gen/") || file_path.contains("/gen/");
 }
 
+// Represents a filter file specified via cmdline, that can be used to filter
+// out specific FieldDecls.
+//
+// See also:
+// - kExcludeFieldsParamName
+// - FilterEmitterHelper
 class FieldDeclFilterFile {
  public:
   explicit FieldDeclFilterFile(const std::string& filepath) {
@@ -341,20 +420,20 @@
   return !has_sibling_with_same_type_loc;
 }
 
-// Rewrites |SomeClass* field| (matched as "fieldDecl") into
+// Rewrites |SomeClass* field| (matched as "affectedFieldDecl") into
 // |CheckedPtr<SomeClass> field| and for each file rewritten in such way adds an
 // |#include "base/memory/checked_ptr.h"|.
 class FieldDeclRewriter : public MatchFinder::MatchCallback {
  public:
-  explicit FieldDeclRewriter(ReplacementsPrinter* replacements_printer)
-      : replacements_printer_(replacements_printer) {}
+  explicit FieldDeclRewriter(OutputHelper* output_helper)
+      : output_helper_(output_helper) {}
 
   void run(const MatchFinder::MatchResult& result) override {
     const clang::ASTContext& ast_context = *result.Context;
     const clang::SourceManager& source_manager = *result.SourceManager;
 
     const clang::FieldDecl* field_decl =
-        result.Nodes.getNodeAs<clang::FieldDecl>("fieldDecl");
+        result.Nodes.getNodeAs<clang::FieldDecl>("affectedFieldDecl");
     assert(field_decl && "matcher should bind 'fieldDecl'");
 
     const clang::TypeSourceInfo* type_source_info =
@@ -387,9 +466,9 @@
       replacement_text.insert(0, "mutable ");
 
     // Generate and print a replacement.
-    replacements_printer_->PrintReplacement(source_manager, replacement_range,
-                                            replacement_text,
-                                            true /* should_add_include */);
+    output_helper_->PrintReplacement(source_manager, replacement_range,
+                                     replacement_text,
+                                     true /* should_add_include */);
   }
 
  private:
@@ -418,15 +497,15 @@
     return result;
   }
 
-  ReplacementsPrinter* const replacements_printer_;
+  OutputHelper* const output_helper_;
 };
 
 // Rewrites |my_struct.ptr_field| (matched as "affectedMemberExpr") into
 // |my_struct.ptr_field.get()|.
 class AffectedExprRewriter : public MatchFinder::MatchCallback {
  public:
-  AffectedExprRewriter(ReplacementsPrinter* replacements_printer)
-      : replacements_printer_(replacements_printer) {}
+  explicit AffectedExprRewriter(OutputHelper* output_helper)
+      : output_helper_(output_helper) {}
 
   void run(const MatchFinder::MatchResult& result) override {
     const clang::SourceManager& source_manager = *result.SourceManager;
@@ -442,12 +521,31 @@
 
     clang::SourceRange replacement_range(insertion_loc, insertion_loc);
 
-    replacements_printer_->PrintReplacement(source_manager, replacement_range,
-                                            ".get()");
+    output_helper_->PrintReplacement(source_manager, replacement_range,
+                                     ".get()");
   }
 
  private:
-  ReplacementsPrinter* const replacements_printer_;
+  OutputHelper* const output_helper_;
+};
+
+// Emits problematic fields (matched as "affectedFieldDecl") as filtered fields.
+class FilteredExprWriter : public MatchFinder::MatchCallback {
+ public:
+  FilteredExprWriter(OutputHelper* output_helper, llvm::StringRef filter_tag)
+      : output_helper_(output_helper), filter_tag_(filter_tag) {}
+
+  void run(const MatchFinder::MatchResult& result) override {
+    const clang::FieldDecl* field_decl =
+        result.Nodes.getNodeAs<clang::FieldDecl>("affectedFieldDecl");
+    assert(field_decl && "matcher should bind 'affectedFieldDecl'");
+
+    output_helper_->AddFilteredField(*field_decl, filter_tag_);
+  }
+
+ private:
+  OutputHelper* const output_helper_;
+  llvm::StringRef filter_tag_;
 };
 
 }  // namespace
@@ -467,7 +565,7 @@
                                  options.getSourcePathList());
 
   MatchFinder match_finder;
-  ReplacementsPrinter replacements_printer;
+  OutputHelper output_helper;
 
   // Supported pointer types =========
   // Given
@@ -525,8 +623,8 @@
                              isInExternCContext(),
                              isListedInFilterFile(fields_to_exclude),
                              implicit_field_decl_matcher))))
-          .bind("fieldDecl");
-  FieldDeclRewriter field_decl_rewriter(&replacements_printer);
+          .bind("affectedFieldDecl");
+  FieldDeclRewriter field_decl_rewriter(&output_helper);
   match_finder.addMatcher(field_decl_matcher, &field_decl_rewriter);
 
   // Matches expressions that used to return a value of type |SomeClass*|
@@ -563,7 +661,7 @@
       affected_expr_matcher,
       hasParent(expr(anyOf(callExpr(callee(functionDecl(isVariadic()))),
                            cxxConstCastExpr(), cxxReinterpretCastExpr())))));
-  AffectedExprRewriter affected_expr_rewriter(&replacements_printer);
+  AffectedExprRewriter affected_expr_rewriter(&output_helper);
   match_finder.addMatcher(affected_expr_that_needs_fixing_matcher,
                           &affected_expr_rewriter);
 
@@ -579,6 +677,24 @@
   match_finder.addMatcher(affected_ternary_operator_arg_matcher,
                           &affected_expr_rewriter);
 
+  // Calls to templated functions =========
+  // Given
+  //   struct S { int* y; };
+  //   template <typename T>
+  //   void templatedFunc(T* arg) {}
+  //   void foo(const S& s) {
+  //     templatedFunc(s.y);
+  //   }
+  // binds the |s.y| expr if it matches the |affected_expr_matcher| above.
+  auto templated_function_arg_matcher = forEachArgumentWithParam(
+      affected_expr_matcher, parmVarDecl(hasType(qualType(allOf(
+                                 findAll(qualType(substTemplateTypeParmType())),
+                                 unless(referenceType()))))));
+  match_finder.addMatcher(callExpr(templated_function_arg_matcher),
+                          &affected_expr_rewriter);
+  match_finder.addMatcher(cxxConstructExpr(templated_function_arg_matcher),
+                          &affected_expr_rewriter);
+
   // |auto| type declarations =========
   // Given
   //   struct S { int* y; };
@@ -593,10 +709,39 @@
                 initListExpr(hasInit(0, affected_implicit_expr_matcher))))))));
   match_finder.addMatcher(auto_var_decl_matcher, &affected_expr_rewriter);
 
+  // address-of(affected-expr) =========
+  // Given
+  //   ... &s.y ...
+  // matches the |s.y| expr if it matches the |affected_member_expr_matcher|
+  // above.
+  auto affected_addr_of_expr_matcher = expr(allOf(
+      affected_expr_matcher, hasParent(unaryOperator(hasOperatorName("&")))));
+  FilteredExprWriter filtered_addr_of_expr_writer(&output_helper, "addr-of");
+  match_finder.addMatcher(affected_addr_of_expr_matcher,
+                          &filtered_addr_of_expr_writer);
+
+  // in-out reference arg =========
+  // Given
+  //   struct S { SomeClass* ptr_field; };
+  //   void foo(SomeClass*& in_out_arg) { ... }
+  //   void bar() {
+  //     S s;
+  //     foo(s.ptr_field)
+  //   }
+  // matches the |s.ptr_field| expr if it matches the
+  // |affected_member_expr_matcher| and is passed as a function argument that
+  // has |FooBar*&| type.
+  auto affected_in_out_ref_arg_matcher = callExpr(forEachArgumentWithParam(
+      affected_expr_matcher.bind("expr"),
+      parmVarDecl(hasType(referenceType(pointee(pointerType()))))));
+  FilteredExprWriter filtered_in_out_ref_arg_writer(&output_helper,
+                                                    "in-out-param-ref");
+  match_finder.addMatcher(affected_in_out_ref_arg_matcher,
+                          &filtered_in_out_ref_arg_writer);
+
   // Prepare and run the tool.
   std::unique_ptr<clang::tooling::FrontendActionFactory> factory =
-      clang::tooling::newFrontendActionFactory(&match_finder,
-                                               &replacements_printer);
+      clang::tooling::newFrontendActionFactory(&match_finder, &output_helper);
   int result = tool.run(factory.get());
   if (result != 0)
     return result;
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
index e9073e4..7a65a24 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-expected.cc
@@ -4,6 +4,9 @@
 
 #include <stdint.h>  // for uintptr_t
 
+#include <tuple>    // for std::tie
+#include <utility>  // for std::swap
+
 #include "base/memory/checked_ptr.h"
 #include "gen/generated_header.h"
 
@@ -184,6 +187,79 @@
 
 }  // namespace generated_code_tests
 
+namespace templated_functions {
+
+template <typename T>
+void AffectedFunction(T* t) {}
+
+template <typename T>
+void TemplatedFunction_NonTemplatedParam(SomeClass* arg, T t) {}
+
+template <typename T>
+class MyTemplate {
+ public:
+  template <typename U>
+  MyTemplate(U* u) {}
+
+  void AffectedMethod(T* t) {}
+};
+
+// We also want to append |.get()| for |T| parameters (i.e. not just for |T*|
+// parameters).
+//
+// One motivating example is ActivityLogDatabasePolicy::ScheduleAndForget which
+// passes its argument to base::Unretained.
+//
+// Another motivating example, is the following pattern from
+// //components/variations/service/ui_string_overrider.cc where the type of the
+// 2 arguments needs to be kept consistent:
+//     const uint32_t* end = ptr_field_ + num_resources_;
+//     const uint32_t* element = std::lower_bound(ptr_field_, end, hash);
+template <typename T>
+void AffectedNonPointerFunction(T t) {}
+
+// AffectedFunctionWithDeepT mimics ConvertPPResourceArrayToObjects from
+// //ppapi/cpp/array_output.h
+template <typename T>
+void AffectedFunctionWithDeepT(MyTemplate<T>* blah) {}
+
+// StructWithPointerToTemplate is used to test AffectedFunctionWithDeepT.
+// StructWithPointerToTemplate mimics ResourceArrayOutputAdapter<T>
+// (and its |output_| field that will be converted to a CheckedPtr)
+// from //ppapi/cpp/array_output.h
+template <typename T>
+struct StructWithPointerToTemplate {
+  CheckedPtr<MyTemplate<T>> ptr_to_template;
+};
+
+void foo() {
+  MyStruct my_struct;
+
+  // Expected rewrite - appending: .get()
+  AffectedFunction(my_struct.ptr.get());
+
+  // Expected rewrite - appending: .get()
+  MyTemplate<SomeClass> mt(my_struct.ptr.get());
+  // Expected rewrite - appending: .get()
+  mt.AffectedMethod(my_struct.ptr.get());
+
+  // No rewrite expected.
+  TemplatedFunction_NonTemplatedParam(my_struct.ptr, 123);
+
+  // Expected rewrite - appending: .get()
+  AffectedNonPointerFunction(my_struct.ptr.get());
+
+  // Expected rewrite - appending: .get()
+  StructWithPointerToTemplate<SomeClass> swptt;
+  AffectedFunctionWithDeepT(swptt.ptr_to_template.get());
+
+  // No rewrite expected - T& parameter.
+  std::swap(my_struct.ptr, my_struct.ptr2);
+  std::tie(my_struct.ptr, my_struct.ptr2) = std::make_pair(nullptr, nullptr);
+}
+
+}  // namespace templated_functions
+
 namespace affected_implicit_template_specialization {
 
 template <typename T, typename T2>
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
index a161313..26f4847 100644
--- a/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/affected-expr-original.cc
@@ -4,6 +4,9 @@
 
 #include <stdint.h>  // for uintptr_t
 
+#include <tuple>    // for std::tie
+#include <utility>  // for std::swap
+
 #include "gen/generated_header.h"
 
 class SomeClass {};
@@ -183,6 +186,79 @@
 
 }  // namespace generated_code_tests
 
+namespace templated_functions {
+
+template <typename T>
+void AffectedFunction(T* t) {}
+
+template <typename T>
+void TemplatedFunction_NonTemplatedParam(SomeClass* arg, T t) {}
+
+template <typename T>
+class MyTemplate {
+ public:
+  template <typename U>
+  MyTemplate(U* u) {}
+
+  void AffectedMethod(T* t) {}
+};
+
+// We also want to append |.get()| for |T| parameters (i.e. not just for |T*|
+// parameters).
+//
+// One motivating example is ActivityLogDatabasePolicy::ScheduleAndForget which
+// passes its argument to base::Unretained.
+//
+// Another motivating example, is the following pattern from
+// //components/variations/service/ui_string_overrider.cc where the type of the
+// 2 arguments needs to be kept consistent:
+//     const uint32_t* end = ptr_field_ + num_resources_;
+//     const uint32_t* element = std::lower_bound(ptr_field_, end, hash);
+template <typename T>
+void AffectedNonPointerFunction(T t) {}
+
+// AffectedFunctionWithDeepT mimics ConvertPPResourceArrayToObjects from
+// //ppapi/cpp/array_output.h
+template <typename T>
+void AffectedFunctionWithDeepT(MyTemplate<T>* blah) {}
+
+// StructWithPointerToTemplate is used to test AffectedFunctionWithDeepT.
+// StructWithPointerToTemplate mimics ResourceArrayOutputAdapter<T>
+// (and its |output_| field that will be converted to a CheckedPtr)
+// from //ppapi/cpp/array_output.h
+template <typename T>
+struct StructWithPointerToTemplate {
+  MyTemplate<T>* ptr_to_template;
+};
+
+void foo() {
+  MyStruct my_struct;
+
+  // Expected rewrite - appending: .get()
+  AffectedFunction(my_struct.ptr);
+
+  // Expected rewrite - appending: .get()
+  MyTemplate<SomeClass> mt(my_struct.ptr);
+  // Expected rewrite - appending: .get()
+  mt.AffectedMethod(my_struct.ptr);
+
+  // No rewrite expected.
+  TemplatedFunction_NonTemplatedParam(my_struct.ptr, 123);
+
+  // Expected rewrite - appending: .get()
+  AffectedNonPointerFunction(my_struct.ptr);
+
+  // Expected rewrite - appending: .get()
+  StructWithPointerToTemplate<SomeClass> swptt;
+  AffectedFunctionWithDeepT(swptt.ptr_to_template);
+
+  // No rewrite expected - T& parameter.
+  std::swap(my_struct.ptr, my_struct.ptr2);
+  std::tie(my_struct.ptr, my_struct.ptr2) = std::make_pair(nullptr, nullptr);
+}
+
+}  // namespace templated_functions
+
 namespace affected_implicit_template_specialization {
 
 template <typename T, typename T2>
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-expected.txt b/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-expected.txt
new file mode 100644
index 0000000..59c6f3a4
--- /dev/null
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-expected.txt
@@ -0,0 +1,15 @@
+==== BEGIN EDITS ====
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-actual.cc:::861:::11:::CheckedPtr<SomeClass> 
+include-user-header:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-actual.cc:::-1:::-1:::base/memory/checked_ptr.h
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-actual.cc:::885:::11:::CheckedPtr<SomeClass> 
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-actual.cc:::914:::11:::CheckedPtr<SomeClass> 
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-actual.cc:::943:::11:::CheckedPtr<SomeClass> 
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-actual.cc:::1137:::3:::CheckedPtr<T> 
+r:::/usr/local/google/home/lukasza/src/chromium4/src/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-actual.cc:::1809:::3:::CheckedPtr<T> 
+==== END EDITS ====
+==== BEGIN FIELD FILTERS ====
+my_namespace::MyStruct::in_out_via_auto_reset  # addr-of
+my_namespace::MyStruct::in_out_via_ptr  # addr-of
+my_namespace::MyStruct::in_out_via_ref  # in-out-param-ref
+my_namespace::MyTemplateBase::ptr_  # addr-of
+==== END FIELD FILTERS ====
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-test.cc b/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-test.cc
new file mode 100644
index 0000000..d94f141a
--- /dev/null
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-test.cc
@@ -0,0 +1,75 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file tests generation of output for --field-filter-file and therefore
+// the expectations file (in-out-arg-expected.txt) needs to be compared against
+// the raw output of the rewriter (rather than against the actual edits result).
+// This makes the test incompatible with other tests, which require passing
+// --apply-edits switch to test_tool.py and so to disable the test it is named
+// *-test.cc rather than *-original.cc.
+//
+// To enable and run the test:
+// 1. Rename this file to in-out-arg-original.cc
+// 2. Run:
+//    $ tools/clang/scripts/test_tool.py rewrite_raw_ptr_fields \
+//         --test-filter=in-out-arg
+
+namespace my_namespace {
+
+class SomeClass;
+
+struct MyStruct {
+  SomeClass* ptr_field;
+  SomeClass* in_out_via_ptr;
+  SomeClass* in_out_via_ref;
+  SomeClass* in_out_via_auto_reset;
+};
+
+template <typename T>
+class AutoReset {
+ public:
+  AutoReset(T* ptr, T value) : ptr_(ptr), value_(value) {}
+  ~AutoReset() { *ptr_ = value_; }
+
+ private:
+  T* ptr_;
+  T value_;
+};
+
+void GetViaPtr(SomeClass** out_ptr) {
+  *out_ptr = nullptr;
+}
+
+// Based on a real-world example (Blink uses references more often than the rest
+// of Chromium):
+// https://source.chromium.org/chromium/chromium/src/+/master:third_party/blink/renderer/core/layout/layout_table.cc;drc=a3524fd6d1a4f4ff7e97893f6c6375dd1684e132;l=130
+void GetViaRef(SomeClass*& out_ptr) {
+  out_ptr = nullptr;
+}
+
+void foo() {
+  MyStruct my_struct;
+  GetViaPtr(&my_struct.in_out_via_ptr);
+  GetViaRef(my_struct.in_out_via_ref);
+  AutoReset<SomeClass*> auto_reset1(&my_struct.in_out_via_auto_reset, nullptr);
+}
+
+template <typename T>
+class MyTemplateBase {
+ protected:
+  T* ptr_;
+};
+
+class MyTemplateDerived : public MyTemplateBase<SomeClass> {
+ public:
+  void foo() {
+    // This should emit
+    //     my_namespace MyTemplateBase<T>::ptr_
+    // rather than
+    //     my_namespace MyTemplateBase<SomeClass>::ptr_
+    GetViaPtr(&ptr_);
+  }
+};
+
+}  // namespace my_namespace
diff --git a/tools/clang/rewrite_raw_ptr_fields/tests/run_all_tests.py b/tools/clang/rewrite_raw_ptr_fields/tests/run_all_tests.py
new file mode 100755
index 0000000..f6d5eb4
--- /dev/null
+++ b/tools/clang/rewrite_raw_ptr_fields/tests/run_all_tests.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python3
+# Copyright 2020 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os.path
+import shutil
+import subprocess
+import sys
+
+
+def RunRewritingTests():
+  subprocess.run([
+      "tools/clang/scripts/test_tool.py", "--apply-edits",
+      "rewrite_raw_ptr_fields"
+  ])
+
+
+def RunGeneratingTest(test_path):
+  tmp_test_path = test_path.replace("-test.cc", "-original.cc")
+  test_filter = os.path.basename(test_path).replace("-test.cc", "")
+
+  shutil.copyfile(test_path, tmp_test_path)
+  try:
+    subprocess.run([
+        "tools/clang/scripts/test_tool.py",
+        "--test-filter=%s" % test_filter, "rewrite_raw_ptr_fields"
+    ])
+  finally:
+    os.remove(tmp_test_path)
+
+
+def main():
+  if not os.path.exists("ENG_REVIEW_OWNERS"):
+    sys.stderr.write(
+        "Please run run_all_tests.py from the root dir of Chromium")
+    return -1
+
+  if not os.path.exists(
+      "third_party/llvm-build/Release+Asserts/bin/rewrite_raw_ptr_fields"):
+    sys.stderr.write("Please build rewrite_raw_ptr_fields first")
+    return -1
+
+  RunRewritingTests()
+  RunGeneratingTest(
+      "tools/clang/rewrite_raw_ptr_fields/tests/in-out-arg-test.cc")
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 8a3779d9..a7c5cfc 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -37,9 +37,9 @@
 # Do NOT CHANGE this if you don't know what you're doing -- see
 # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md
 # Reverting problematic clang rolls is safe, though.
-CLANG_REVISION = 'a6ae333a0c23fc9b0783ca45e2676abac00c6723'
-CLANG_SVN_REVISION = 'n355885'
-CLANG_SUB_REVISION = 2
+CLANG_REVISION = 'f7f1abdb8893af4a606ca1a8f5347a426e9c7f9e'
+CLANG_SVN_REVISION = 'n356235'
+CLANG_SUB_REVISION = 1
 
 PACKAGE_VERSION = '%s-%s-%s' % (CLANG_SVN_REVISION, CLANG_REVISION[:8],
                                 CLANG_SUB_REVISION)
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index 68157f8..b2889795 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -113,6 +113,13 @@
   "chrome/browser/resources/bookmarks/bookmarks_resources_vulcanized.grd": {
     "includes": [1300],
   },
+  "chrome/browser/resources/chromeos/camera/camera_resources.grd": {
+    "includes": [1320],
+    "structures": [1340],
+  },
+  "chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd": {
+    "messages": [1360],
+  },
   "chrome/browser/resources/chromeos/cellular_setup/cellular_setup_resources.grd": {
     "structures": [1380],
   },
@@ -277,13 +284,6 @@
     "META": {"align": 100},
     "messages": [2500],
   },
-  "chromeos/components/camera_app_ui/resources/camera_app_resources.grd": {
-    "includes": [2505],
-    "structures": [2510],
-  },
-  "chromeos/components/camera_app_ui/resources/src/strings/camera_strings.grd": {
-    "messages": [2515],
-  },
   "chromeos/components/help_app_ui/resources/help_app_resources.grd": {
     "includes": [2520],
   },
@@ -480,7 +480,7 @@
   "ash/ash_strings.grd": {
     "messages": [3060],
   },
-  "ash/shortcut_viewer/ash_components_strings.grd": {
+  "ash/shortcut_viewer/shortcut_viewer_strings.grd": {
     "messages": [3080],
   },
   "ash/keyboard/ui/keyboard_resources.grd": {
diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl
index 921b0e7..d47bdd15 100644
--- a/tools/gritsettings/translation_expectations.pyl
+++ b/tools/gritsettings/translation_expectations.pyl
@@ -25,7 +25,7 @@
       "android_webview/java/strings/android_webview_strings.grd",
       "android_webview/ui/aw_strings.grd",
       "ash/ash_strings.grd",
-      "ash/shortcut_viewer/ash_components_strings.grd",
+      "ash/shortcut_viewer/shortcut_viewer_strings.grd",
       "chrome/android/features/vr/java/strings/android_chrome_vr_strings.grd",
       "chrome/android/features/media_router/java/strings/android_chrome_media_router_strings.grd",
       "chrome/android/features/keyboard_accessory/internal/java/strings/android_keyboard_accessory_strings.grd",
@@ -36,12 +36,12 @@
       "chrome/app/chromium_strings.grd",
       "chrome/app/generated_resources.grd",
       "chrome/app/google_chrome_strings.grd",
+      "chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd",
       "chrome/browser/resources/chromeos/accessibility/strings/accessibility_strings.grd",
       "chrome/browser/touch_to_fill/android/internal/java/strings/android_touch_to_fill_strings.grd",
       "chrome/browser/ui/android/strings/android_chrome_strings.grd",
       "chrome/credential_provider/gaiacp/gaia_resources.grd",
       "chromeos/chromeos_strings.grd",
-      "chromeos/components/camera_app_ui/resources/src/strings/camera_strings.grd",
       "components/autofill/android/java/strings/autofill_strings.grd",
       "components/browser_ui/strings/android/browser_ui_strings.grd",
       "components/components_chromium_strings.grd",
diff --git a/tools/imagediff/image_diff_png.cc b/tools/imagediff/image_diff_png.cc
index 7524026..d3a962e 100644
--- a/tools/imagediff/image_diff_png.cc
+++ b/tools/imagediff/image_diff_png.cc
@@ -87,11 +87,10 @@
         output_channels(0),
         is_opaque(true),
         output(o),
-        row_converter(NULL),
+        row_converter(nullptr),
         width(0),
         height(0),
-        done(false) {
-  }
+        done(false) {}
 
   ColorFormat output_format;
   int output_channels;
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml
index 882aa16..8369eb9 100644
--- a/tools/metrics/actions/actions.xml
+++ b/tools/metrics/actions/actions.xml
@@ -8577,6 +8577,26 @@
   <description>Please enter the description of this user action.</description>
 </action>
 
+<action name="IOS.PageZoom.ZoomIn">
+  <owner>rkgibson@google.com</owner>
+  <owner>gambard@chromium.org</owner>
+  <description>The user zoomed in on a webpage. iOS only.</description>
+</action>
+
+<action name="IOS.PageZoom.ZoomOut">
+  <owner>rkgibson@google.com</owner>
+  <owner>gambard@chromium.org</owner>
+  <description>The user zoomed out on a webpage. iOS only.</description>
+</action>
+
+<action name="IOS.PageZoom.ZoomReset">
+  <owner>rkgibson@google.com</owner>
+  <owner>gambard@chromium.org</owner>
+  <description>
+    The user reset the zoom level on a webpage. iOS only.
+  </description>
+</action>
+
 <action name="IOSAccountsSettingsCloseWithSwipe">
   <owner>msarda@chromium.org</owner>
   <owner>jlebel@chromium.org</owner>
@@ -13844,12 +13864,33 @@
   <description>User closes the tab while preview page is loaded.</description>
 </action>
 
+<action name="MobilePullGestureCloseTab">
+  <owner>eugenebut@chromium.org</owner>
+  <owner>michaeldo@chromium.org</owner>
+  <description>
+    Emitted on iOS when over-scroll action touch gesture closes current tab.
+    This fires only after the triggering touch is released while the refresh
+    effect has been pulled beyond the activation threshold.
+  </description>
+</action>
+
+<action name="MobilePullGestureNewTab">
+  <owner>eugenebut@chromium.org</owner>
+  <owner>michaeldo@chromium.org</owner>
+  <description>
+    Emitted on iOS when over-scroll action touch gesture opens a new tab. This
+    fires only after the triggering touch is released while the refresh effect
+    has been pulled beyond the activation threshold.
+  </description>
+</action>
+
 <action name="MobilePullGestureReload">
+  <owner>eugenebut@chromium.org</owner>
   <owner>tedchoc@chromium.org</owner>
   <description>
-    Emitted on Android when a pull-to-refresh touch gesture initiates a page
-    reload. This fires only after the triggering touch is released while the
-    refresh effect has been pulled beyond the activation threshold.
+    Emitted on Android and iOS when a pull-to-refresh touch gesture initiates a
+    page reload. This fires only after the triggering touch is released while
+    the refresh effect has been pulled beyond the activation threshold.
   </description>
 </action>
 
diff --git a/tools/metrics/histograms/README.md b/tools/metrics/histograms/README.md
index 18785ea..536f890 100644
--- a/tools/metrics/histograms/README.md
+++ b/tools/metrics/histograms/README.md
@@ -156,7 +156,7 @@
 **Note: this method of defining histogram enums is deprecated. Do not use this
 for new enums *in C++*.**
 
-Many legacy enums define a `kCount` sentinel, reying on the compiler to
+Many legacy enums define a `kCount` sentinel, relying on the compiler to
 automatically update it when new entries are added:
 
 ```c++
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 8afd46e9..ae235385 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -31723,6 +31723,37 @@
   <int value="2" label="Gesture predicted but didn't occur"/>
 </enum>
 
+<enum name="GetAuthTokenResult">
+  <int value="0" label="Success"/>
+  <int value="1" label="kInvalidClientId"/>
+  <int value="2" label="kEmptyScopes"/>
+  <int value="3" label="kOAuth2InvalidScopes"/>
+  <int value="4" label="kGaiaFlowAuthFailure"/>
+  <int value="5" label="kMintTokenAuthFailure"/>
+  <int value="6" label="kGetAccessTokenAuthFailure"/>
+  <int value="7" label="kOAuth2Failure"/>
+  <int value="8" label="kNoGrant"/>
+  <int value="9" label="kInteractionRequired"/>
+  <int value="10" label="kInteractionAlreadyRunning"/>
+  <int value="11" label="kOAuth2AccessDenied"/>
+  <int value="12" label="kGaiaFlowRejected"/>
+  <int value="13" label="kRemoteConsentFlowRejected"/>
+  <int value="14" label="kUserNotSignedIn"/>
+  <int value="15" label="kNotWhitelistedInPublicSession"/>
+  <int value="16" label="kSignInFailed"/>
+  <int value="17" label="kRemoteConsentUserNotSignedIn"/>
+  <int value="18" label="kUserNonPrimary"/>
+  <int value="19" label="kRemoteConsentUserNonPrimary"/>
+  <int value="20" label="kBrowserSigninNotAllowed"/>
+  <int value="21" label="kInvalidRedirect"/>
+  <int value="22" label="kOffTheRecord"/>
+  <int value="23" label="kPageLoadFailure"/>
+  <int value="24" label="kRemoteConsentPageLoadFailure"/>
+  <int value="25" label="kSetAccountsInCookieFailure"/>
+  <int value="26" label="kInvalidConsentResult"/>
+  <int value="27" label="kCanceled"/>
+</enum>
+
 <enum name="GetEncryptionKeyAction">
   <int value="0" label="Key is successfully found - not first time"/>
   <int value="1" label="Key is successfully found for the first time"/>
@@ -39118,6 +39149,8 @@
   <int value="-1532014193" label="disable-encryption-migration"/>
   <int value="-1529907580" label="ImeServiceConnectable:disabled"/>
   <int value="-1528455406" label="OmniboxPedalSuggestions:enabled"/>
+  <int value="-1525129540"
+      label="OmniboxUIExperimentRevealSteadyStateUrlPathQueryAndRefOnHover:disabled"/>
   <int value="-1524323669" label="InstalledAppsInCbd:enabled"/>
   <int value="-1521296022"
       label="UpdateNotificationScheduleServiceImmediateShowOption:disabled"/>
@@ -39720,6 +39753,8 @@
   <int value="-898594349" label="ash-enable-stable-overview-order"/>
   <int value="-898499262" label="ImprovedA2HS:enabled"/>
   <int value="-898005938" label="disable-pinch-virtual-viewport"/>
+  <int value="-897994913"
+      label="OmniboxUIExperimentRevealSteadyStateUrlPathQueryAndRefOnHover:enabled"/>
   <int value="-897069393"
       label="kAutofillRationalizeRepeatedServerPredictions:disabled"/>
   <int value="-894214299" label="fill-on-account-select:enabled"/>
@@ -39994,6 +40029,7 @@
   <int value="-596337171" label="disable-ash-sidebar"/>
   <int value="-595819071"
       label="OmniboxUIExperimentBlueTitlesOnPageSuggestions:disabled"/>
+  <int value="-594076614" label="PluginVmShowCameraPermissions:disabled"/>
   <int value="-593536514" label="ExperimentalTabController:enabled"/>
   <int value="-589096918" label="ash-enable-fullscreen-app-list"/>
   <int value="-582870536" label="BluetoothNextHandsfreeProfile:enabled"/>
@@ -40162,6 +40198,8 @@
   <int value="-396046249" label="PhotoPickerVideoSupport:enabled"/>
   <int value="-395606844" label="enable-site-settings"/>
   <int value="-395454065" label="DisablePostScriptPrinting:disabled"/>
+  <int value="-389664522"
+      label="OmniboxUIExperimentHideSteadyStateUrlPathQueryAndRefOnInteraction:enabled"/>
   <int value="-387606010" label="ArcBootCompletedBroadcast:enabled"/>
   <int value="-386971711" label="ChromeSharingHubV15:disabled"/>
   <int value="-385337473" label="enable-fast-unload"/>
@@ -41133,6 +41171,8 @@
   <int value="724427456" label="WebAuthenticationPINSupport:disabled"/>
   <int value="725067265" label="enable-experimental-cookie-features"/>
   <int value="725270017" label="ScrollAnchorSerialization:disabled"/>
+  <int value="725579946"
+      label="OmniboxUIExperimentHideSteadyStateUrlPathQueryAndRefOnInteraction:disabled"/>
   <int value="725870294" label="RequestUnbufferedDispatch:disabled"/>
   <int value="726764779" label="WebXRGamepadSupport:enabled"/>
   <int value="727270087" label="PromosOnLocalNtp:enabled"/>
@@ -41488,6 +41528,7 @@
   <int value="1129888794" label="ash-touch-hud"/>
   <int value="1133207726" label="MediaInspectorLogging:enabled"/>
   <int value="1133635187" label="force-gpu-rasterization"/>
+  <int value="1135728116" label="PluginVmShowCameraPermissions:enabled"/>
   <int value="1138349838" label="EnableMDRoundedCornersOnDialogs:disabled"/>
   <int value="1138690502" label="PreconnectToSearch:enabled"/>
   <int value="1139226452" label="enable-nacl-debug"/>
@@ -53603,11 +53644,18 @@
 
 <enum name="PerformanceHintsObserverHintForURLResult">
   <int value="0" label="Hint not found for URL"/>
-  <int value="1" label="Hint not yet processed"/>
+  <int value="1" label="One or more sources were not yet ready"/>
   <int value="2" label="Invalid URL"/>
   <int value="3" label="Hint found for URL"/>
 </enum>
 
+<enum name="PerformanceHintsObserverSourceLookupStatus">
+  <int value="0" label="Source was not queried (a hint was already found)"/>
+  <int value="1" label="Source was not ready in time"/>
+  <int value="2" label="Source did not have a hint for URL"/>
+  <int value="3" label="Source had a hint for the URL"/>
+</enum>
+
 <enum name="PerformanceHintsPerformanceClass">
 <!-- This must be kept in sync with UmaPerformanceClass in
      //chrome/browser/performance_hints/performance_hints_observer.cc. -->
@@ -66160,6 +66208,29 @@
   <int value="3" label="Use new"/>
 </enum>
 
+<enum name="SyncConsentBehavior">
+  <summary>
+    Behavior of the out-of-box experience (OOBE) sync consent screen.
+  </summary>
+  <int value="0" label="Unknown"/>
+  <int value="1" label="Show"/>
+  <int value="2" label="Skip, disabled, non-GAIA account"/>
+  <int value="3" label="Skip, disabled, public account"/>
+  <int value="4" label="Skip, disabled, sync feature policy"/>
+  <int value="5" label="Skip, enabled, non-branded build"/>
+  <int value="6" label="Skip, enabled, ephemeral user"/>
+  <int value="7" label="Skip, enabled, consent screen policy"/>
+</enum>
+
+<enum name="SyncConsentUserChoice">
+  <summary>
+    Which button the user clicked in the out-of-box experience (OOBE) sync
+    consent screen.
+  </summary>
+  <int value="0" label="Declined"/>
+  <int value="1" label="Accepted"/>
+</enum>
+
 <enum name="SyncCryptographerPendingKeysState">
   <int value="0" label="Does not have pending keys"/>
   <int value="1" label="Has pending keys"/>
@@ -72577,6 +72648,17 @@
   <int value="3" label="Desktop Aura"/>
 </enum>
 
+<enum name="WindowActivityOrigin">
+  <int value="0" label="WindowActivityUnknwonOrigin"/>
+  <int value="1" label="WindowActivityExternalOrigin"/>
+  <int value="2" label="WindowActivityRestoredOrigin"/>
+  <int value="3" label="WindowActivityContextMenuOrigin"/>
+  <int value="4" label="WindowActivityReadingListOrigin"/>
+  <int value="5" label="WindowActivityBookmarksOrigin"/>
+  <int value="6" label="WindowActivityHistoryOrigin"/>
+  <int value="7" label="WindowActivityToolsOrigin"/>
+</enum>
+
 <enum name="WindowDragEndEventType">
   <int value="0" label="Drag ends with normal end event."/>
   <int value="1" label="Drag has been reverted."/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 5fb298b3..2285ad7 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -136,7 +136,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosAlwaysShowA11yMenu" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -186,7 +186,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosCaretHighlight" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
@@ -206,7 +206,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosChromeVoxNext" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
@@ -228,7 +228,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosDictation" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>anastasi@google.com</owner>
   <owner>dtseng@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -239,7 +239,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosDictation.ToggleDictationMethod"
-    enum="CrosDictationToggleDictationMethod" expires_after="M85">
+    enum="CrosDictationToggleDictationMethod" expires_after="M90">
   <owner>anastasi@google.com</owner>
   <owner>dtseng@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -258,7 +258,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosFocusHighlight" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
@@ -279,7 +279,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosLargeCursor" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -290,7 +290,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosLargeCursorSize" units="dip"
-    expires_after="M85">
+    expires_after="M90">
   <owner>yawano@chromium.org</owner>
   <owner>lpalmaro@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -301,7 +301,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosScreenMagnifier" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
@@ -360,8 +360,9 @@
 </histogram>
 
 <histogram name="Accessibility.CrosSelectToSpeak.StartSpeechMethod"
-    enum="CrosSelectToSpeakStartSpeechMethod" expires_after="M85">
+    enum="CrosSelectToSpeakStartSpeechMethod" expires_after="M90">
   <owner>katie@chromium.org</owner>
+  <owner>chrome-a11y-core@google.com</owner>
   <summary>
     A user may activate Select-to-Speak by holding down 'search' and clicking or
     dragging a region with the mouse, or by highlighting an area and using
@@ -370,8 +371,9 @@
 </histogram>
 
 <histogram name="Accessibility.CrosSelectToSpeak.StateChangeEvent"
-    enum="CrosSelectToSpeakStateChangeEvent" expires_after="M85">
+    enum="CrosSelectToSpeakStateChangeEvent" expires_after="M90">
   <owner>katie@chromium.org</owner>
+  <owner>chrome-a11y-core@google.com</owner>
   <summary>
     A user has tapped a button in the tray to change Select-to-Speak's state.
     The tap was interpreted by Select-to-Speak as a request to start selection,
@@ -434,7 +436,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosStickyKeys" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
   <owner>kenjibaheux@google.com</owner>
   <owner>tengs@chromium.org</owner>
@@ -446,8 +448,9 @@
 </histogram>
 
 <histogram name="Accessibility.CrosSwitchAccess" enum="BooleanEnabled"
-    expires_after="M85">
+    expires_after="M90">
   <owner>dmazzoni@chromium.org</owner>
+  <owner>anastasi@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
     Whether the Chrome OS switch access is on (logged once 45 secs after
@@ -7227,6 +7230,9 @@
 
 <histogram name="Apps.AppListSearchResultDistanceFromOrigin" units="keystrokes"
     expires_after="2020-05-24">
+  <obsolete>
+    Removed 2020-05. Not needed any longer.
+  </obsolete>
   <owner>calamity@chromium.org</owner>
   <summary>
     The minimum number of arrow keys a user would need to press to navigate to
@@ -11964,6 +11970,9 @@
 </histogram>
 
 <histogram name="AsyncDNS.HostsSize" units="bytes" expires_after="M82">
+  <obsolete>
+    Removed 2020-06
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -13774,7 +13783,7 @@
 </histogram>
 
 <histogram name="Autofill.CardUploadDecisionMetric"
-    enum="AutofillCardUploadDecisionMetric" expires_after="M85">
+    enum="AutofillCardUploadDecisionMetric" expires_after="2021-05-31">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>payments-autofill-team@google.com</owner>
@@ -15107,8 +15116,9 @@
 </histogram>
 
 <histogram name="Autofill.SaveCardCardholderNamePrefilled" enum="Boolean"
-    expires_after="M85">
+    expires_after="2021-05-31">
   <owner>jsaul@google.com</owner>
+  <owner>payments-autofill-team@google.com</owner>
   <summary>
     If the cardholder name fix flow is shown when credit card upload is offered,
     records if the cardholder name textfield was prefilled with the name from
@@ -15117,8 +15127,9 @@
 </histogram>
 
 <histogram name="Autofill.SaveCardCardholderNameWasEdited" enum="Boolean"
-    expires_after="M85">
+    expires_after="2021-05-31">
   <owner>jsaul@google.com</owner>
+  <owner>payments-autofill-team@google.com</owner>
   <summary>
     If the cardholder name fix flow is shown during credit card upload and the
     user accepts upload, logs whether the final cardholder name was changed from
@@ -15143,9 +15154,10 @@
 </histogram>
 
 <histogram name="Autofill.SaveCardRequestExpirationDateReason"
-    enum="AutofillSaveCardRequestExpirationDateReason" expires_after="M85">
-  <owner>hozhng@google.com</owner>
+    enum="AutofillSaveCardRequestExpirationDateReason"
+    expires_after="2021-05-31">
   <owner>jsaul@google.com</owner>
+  <owner>payments-autofill-team@google.com</owner>
   <summary>
     Records the reason expiration date was explicitly requested from the user
     during credit card save.
@@ -15477,7 +15489,7 @@
 </histogram>
 
 <histogram name="Autofill.SubmittedCardState" enum="AutofillSubmittedCardState"
-    expires_after="M85">
+    expires_after="2021-05-31">
   <owner>jsaul@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
@@ -15487,8 +15499,10 @@
 </histogram>
 
 <histogram name="Autofill.SubmittedServerCardExpirationStatus"
-    enum="AutofillSubmittedServerCardExpirationStatus" expires_after="M85">
+    enum="AutofillSubmittedServerCardExpirationStatus"
+    expires_after="2021-05-31">
   <owner>jsaul@google.com</owner>
+  <owner>payments-autofill-team@google.com</owner>
   <summary>
     Metric to measure if a submitted card's expiration date matches the same
     server card's expiration date (unmasked or not). Cards are considered to be
@@ -17117,7 +17131,7 @@
 </histogram>
 
 <histogram name="BackgroundFetch.HasRequestsWithBody" enum="Boolean"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <owner>peter@chromium.org</owner>
@@ -17294,7 +17308,7 @@
 </histogram>
 
 <histogram name="BackgroundSync.Event.BatchSize" units="units"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -17327,7 +17341,7 @@
 </histogram>
 
 <histogram name="BackgroundSync.Event.OneShotResultPattern"
-    enum="BackgroundSyncResultPattern" expires_after="M85">
+    enum="BackgroundSyncResultPattern" expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -17341,7 +17355,7 @@
 </histogram>
 
 <histogram name="BackgroundSync.Event.OneShotStartedInForeground"
-    enum="BooleanInForeground" expires_after="M85">
+    enum="BooleanInForeground" expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -17386,7 +17400,8 @@
   </summary>
 </histogram>
 
-<histogram name="BackgroundSync.Event.Time" units="ms" expires_after="M85">
+<histogram name="BackgroundSync.Event.Time" units="ms"
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -17436,7 +17451,7 @@
 </histogram>
 
 <histogram name="BackgroundSync.NetworkObserver.HasPermission" enum="Boolean"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -17504,7 +17519,7 @@
 </histogram>
 
 <histogram name="BackgroundSync.Registration.OneShot.IsDuplicate"
-    enum="BooleanRegistrationIsDuplicate" expires_after="M85">
+    enum="BooleanRegistrationIsDuplicate" expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -25149,6 +25164,27 @@
   </summary>
 </histogram>
 
+<histogram name="Chrome.Tabs.AnimationSmoothness.HoverCard.FadeIn" units="%"
+    expires_after="2021-06-04">
+  <owner>yichenz@chromium.org</owner>
+  s
+  <owner>chromeos-wmp@google.com</owner>
+  <summary>
+    Tracks the animation smoothness for the fade-in animation of tab hover card.
+  </summary>
+</histogram>
+
+<histogram name="Chrome.Tabs.AnimationSmoothness.HoverCard.FadeOut" units="%"
+    expires_after="2021-06-04">
+  <owner>yichenz@chromium.org</owner>
+  s
+  <owner>chromeos-wmp@google.com</owner>
+  <summary>
+    Tracks the animation smoothness for the fade-out animation of tab hover
+    card.
+  </summary>
+</histogram>
+
 <histogram name="Chrome.UmaPageloadCounter" enum="BooleanHit"
     expires_after="2017-06-06">
   <obsolete>
@@ -34714,6 +34750,16 @@
   </summary>
 </histogram>
 
+<histogram name="Cryptohome.TimeToMountEx" units="ms"
+    expires_after="2021-02-01">
+  <owner>jorgelo@chromium.org</owner>
+  <owner>cros-hwsec+uma@chromium.org</owner>
+  <summary>
+    The amount of time for Chrome OS cryptohome to mount the encrypted home
+    directory.
+  </summary>
+</histogram>
+
 <histogram name="Cryptohome.TimeToMountGuestAsync" units="ms"
     expires_after="2021-01-01">
   <owner>apronin@chromium.org</owner>
@@ -41322,7 +41368,10 @@
   </summary>
 </histogram>
 
-<histogram name="DNS.HostCache.RestoreSize" units="entries" expires_after="M85">
+<histogram name="DNS.HostCache.RestoreSize" units="entries" expires_after="M84">
+  <obsolete>
+    Removed 2020-06
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -41331,7 +41380,10 @@
 </histogram>
 
 <histogram name="DNS.HostCache.RestoreSuccess" enum="BooleanSuccess"
-    expires_after="M85">
+    expires_after="M84">
+  <obsolete>
+    Removed 2020-06
+  </obsolete>
   <owner>pauljensen@chromium.org</owner>
   <owner>mef@chromium.org</owner>
   <summary>
@@ -47118,6 +47170,7 @@
 <histogram name="Enterprise.DMServerRequestSuccess"
     enum="EnterpriseDMServerRequestSuccess" expires_after="2020-11-29">
   <owner>poromov@chromium.org</owner>
+  <owner>managed-devices@google.com</owner>
   <summary>
     Number of retries the client did to execute a DeviceManagementServer
     request. It's recorded after the request has been completed, either
@@ -48080,8 +48133,9 @@
 </histogram>
 
 <histogram name="Enterprise.UploadJobSuccess" enum="EnterpriseUploadJobSuccess"
-    expires_after="M82">
-  <owner>poromov@chromium.org</owner>
+    expires_after="M87">
+  <owner>bmalcolm@chromium.org</owner>
+  <owner>managed-devices@google.com</owner>
   <summary>
     Number of retries the client did to execute an UploadJob. It's recorded
     after the request has been completed, either successfully after 0 or more
@@ -54280,6 +54334,9 @@
 
 <histogram name="Extensions.CrxFetchError" enum="NetErrorCodes"
     expires_after="M85">
+  <obsolete>
+    Removed as of 06/2020.
+  </obsolete>
   <owner>waffles@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>Net error results from URLFetcher.</summary>
@@ -56543,7 +56600,7 @@
 </histogram>
 
 <histogram name="Extensions.InstallPrompt.TimeToCancel" units="ms"
-    expires_after="M85">
+    expires_after="M95">
   <owner>kelvinjiang@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -56554,7 +56611,7 @@
 </histogram>
 
 <histogram name="Extensions.InstallPrompt.TimeToInstall" units="ms"
-    expires_after="M85">
+    expires_after="M95">
   <owner>kelvinjiang@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -64672,7 +64729,11 @@
 </histogram>
 
 <histogram name="GPU.WatchdogThread.Event.V2" enum="GpuWatchdogThreadEvent"
-    expires_after="2021-07-01">
+    expires_after="2020-06-08">
+  <obsolete>
+    No longer used after GPU watchdog V2 is enabled by default in M82. It's the
+    same as the default histogram GPU.WatchdogThread.Event.
+  </obsolete>
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -64716,7 +64777,11 @@
 </histogram>
 
 <histogram name="GPU.WatchdogThread.V1.ExtraThreadTime" units="ms"
-    expires_after="2020-11-15">
+    expires_after="2020-06-08">
+  <obsolete>
+    GPU watchdog V1 is disabled in M82. Please see
+    GPU.WatchdogThread.ExtraThreadTime for the result of V2.
+  </obsolete>
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -64726,7 +64791,11 @@
 </histogram>
 
 <histogram name="GPU.WatchdogThread.V1.Timeout" enum="GpuWatchdogTimeoutEvent"
-    expires_after="2020-11-08">
+    expires_after="2020-06-08">
+  <obsolete>
+    GPU watchdog V1 is disabled in M82. Please see GPU.WatchdogThread.Timeout
+    for the result of V2.
+  </obsolete>
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -64735,7 +64804,11 @@
 </histogram>
 
 <histogram name="GPU.WatchdogThread.V1.WaitTime" units="ms"
-    expires_after="2020-07-19">
+    expires_after="2020-06-08">
+  <obsolete>
+    GPU watchdog V1 is disabled in M82. Please see GPU.WatchdogThread.WaitTime
+    for the result of V2.
+  </obsolete>
   <owner>magchen@chromium.org</owner>
   <owner>zmo@chromium.org</owner>
   <summary>
@@ -67905,8 +67978,11 @@
   </summary>
 </histogram>
 
-<histogram name="InfoBar.Shown" enum="InfoBarIdentifier" expires_after="M85">
+<histogram name="InfoBar.Shown" enum="InfoBarIdentifier" expires_after="never">
+<!-- expires-never: Required as long as infobars exist. -->
+
   <owner>rkaplow@chromium.org</owner>
+  <owner>src/components/infobars/OWNERS</owner>
   <summary>
     Records how many times a particular infobar was shown to the user. On
     Android, the infobar may be partially hidden due to stacking. On desktop, a
@@ -67916,7 +67992,9 @@
 </histogram>
 
 <histogram name="InfoBar.Shown.Hidden" enum="InfoBarIdentifier"
-    expires_after="M85">
+    expires_after="never">
+<!-- expires-never: Required as long as infobars exist. -->
+
   <owner>mdjones@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -67930,7 +68008,9 @@
 </histogram>
 
 <histogram name="InfoBar.Shown.Hiding" enum="InfoBarIdentifier"
-    expires_after="M77">
+    expires_after="never">
+<!-- expires-never: Required as long as infobars exist. -->
+
   <owner>mdjones@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -67940,7 +68020,9 @@
 </histogram>
 
 <histogram name="InfoBar.Shown.Visible" enum="InfoBarIdentifier"
-    expires_after="M85">
+    expires_after="never">
+<!-- expires-never: Required as long as infobars exist. -->
+
   <owner>mdjones@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -70467,6 +70549,17 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.ContentRuleListProviderUpdateSuccess"
+    enum="BooleanSuccess" expires_after="2020-12-31">
+  <owner>rkgibson@google.com</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    When the content rule list provider updates its lists, this can succeed or
+    fail. Failure occurs when the rule lists are updated again before the first
+    update finishes.
+  </summary>
+</histogram>
+
 <histogram name="IOS.Cookies.GetCookiesForURLCallResult"
     enum="IOSGetCookiesForURLCallResult" expires_after="2020-06-14">
   <owner>mrefaat@chromium.org</owner>
@@ -70740,6 +70833,16 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.MultiWindow.OpenInNewWindow" enum="WindowActivityOrigin"
+    expires_after="2021-06-30">
+  <owner>marq@chromium.org</owner>
+  <owner>djean@chromium.org</owner>
+  <summary>
+    The source of &quot;Open in new Window&quot; user requests. Recorded when a
+    newly created window is added to a session.
+  </summary>
+</histogram>
+
 <histogram name="IOS.NTP.Impression" enum="IOSNTPImpression"
     expires_after="2020-11-01">
   <owner>gambard@chromium.org</owner>
@@ -73176,17 +73279,21 @@
 </histogram>
 
 <histogram name="Login.PromptToCompleteLoginTime" units="ms"
-    expires_after="2020-10-25">
+    expires_after="2021-01-01">
+  <owner>rsorokin@chromium.org</owner>
   <owner>achuith@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>
     Time from first display of the login prompt until the user completes signing
     in.
   </summary>
 </histogram>
 
-<histogram name="Login.PromptToLoginTime" units="ms" expires_after="2020-10-11">
+<histogram name="Login.PromptToLoginTime" units="ms" expires_after="2021-01-01">
   <owner>elijahtaylor@google.com</owner>
   <owner>yusukes@chromium.org</owner>
+  <owner>rsorokin@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
   <summary>
     Time from first display of the login prompt until the existing user
     completes signing in.
@@ -73605,6 +73712,9 @@
 
 <histogram name="ManagedUsers.Whitelist.JsonParseDuration" units="ms"
     expires_after="M85">
+  <obsolete>
+    Removed in M85.
+  </obsolete>
   <owner>treib@chromium.org</owner>
   <owner>escordeiro@chromium.org</owner>
   <owner>menegola@chromium.org</owner>
@@ -73616,6 +73726,9 @@
 
 <histogram name="ManagedUsers.Whitelist.ReadDuration" units="ms"
     expires_after="M85">
+  <obsolete>
+    Removed in M85.
+  </obsolete>
   <owner>treib@chromium.org</owner>
   <owner>escordeiro@chromium.org</owner>
   <owner>menegola@chromium.org</owner>
@@ -73626,6 +73739,9 @@
 
 <histogram name="ManagedUsers.Whitelist.TotalLoadDuration" units="ms"
     expires_after="M85">
+  <obsolete>
+    Removed in M85.
+  </obsolete>
   <owner>treib@chromium.org</owner>
   <owner>escordeiro@chromium.org</owner>
   <owner>menegola@chromium.org</owner>
@@ -78780,7 +78896,8 @@
   </summary>
 </histogram>
 
-<histogram name="Media.Session.ActiveTime" units="ms" expires_after="M85">
+<histogram name="Media.Session.ActiveTime" units="ms"
+    expires_after="2021-06-01">
   <owner>mlamouri@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -78836,7 +78953,7 @@
 </histogram>
 
 <histogram name="Media.Session.Pause" enum="MediaSessionActionSource"
-    expires_after="M85">
+    expires_after="2021-06-01">
   <owner>mlamouri@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -78846,7 +78963,7 @@
 </histogram>
 
 <histogram name="Media.Session.Play" enum="MediaSessionActionSource"
-    expires_after="M85">
+    expires_after="2021-06-01">
   <owner>mlamouri@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -78856,7 +78973,7 @@
 </histogram>
 
 <histogram name="Media.Session.RequestAudioFocusResult" enum="BooleanSuccess"
-    expires_after="M85">
+    expires_after="2021-06-01">
   <owner>mlamouri@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -78865,7 +78982,7 @@
 </histogram>
 
 <histogram name="Media.Session.Stop" enum="MediaSessionActionSource"
-    expires_after="M85">
+    expires_after="2021-06-01">
   <owner>mlamouri@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -78875,7 +78992,7 @@
 </histogram>
 
 <histogram name="Media.Session.Suspended" enum="MediaSessionSuspendedSource"
-    expires_after="M85">
+    expires_after="2021-06-01">
   <owner>mlamouri@chromium.org</owner>
   <owner>media-dev@chromium.org</owner>
   <summary>
@@ -79523,6 +79640,9 @@
 <histogram name="Media.Video.FullscreenOrientationLock.MetadataAvailability"
     enum="VideoFullscreenOrientationLockMetadataAvailability"
     expires_after="M85">
+  <obsolete>
+    Removed from code as of 06/2020.
+  </obsolete>
   <owner>mlamouri@chromium.org</owner>
   <summary>
     Status of the metadata when attempting to lock the screen orientation for a
@@ -95588,6 +95708,9 @@
 
 <histogram name="Net.ProxyResolutionService.PacUrlScheme" enum="PacUrlScheme"
     expires_after="M85">
+  <obsolete>
+    Removed in M85.
+  </obsolete>
   <owner>eroman@chromium.org</owner>
   <summary>
     The breakdown of URL schemes seen for explicitly configured ProxyAutoConfig
@@ -113658,6 +113781,18 @@
   <summary>Time spent on specific OOBE screen grouped by exit reason.</summary>
 </histogram>
 
+<histogram name="OOBE.SyncConsentScreen.Behavior" enum="SyncConsentBehavior"
+    expires_after="2020-12-01">
+  <owner>jamescook@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
+  <summary>
+    Whether the sync consent screen was shown, skipped with sync disabled, or
+    skipped with sync enabled. Recorded when the screen is closed. Metrics
+    Sync.InitialState and OOBE.SyncConsentScreen.SyncEnabled provide more detail
+    on the state of the sync engine.
+  </summary>
+</histogram>
+
 <histogram name="OOBE.SyncConsentScreen.ReviewFollowingSetup"
     enum="BooleanChecked" expires_after="2020-10-01">
   <owner>raleksandrov@google.com</owner>
@@ -113668,6 +113803,27 @@
   </summary>
 </histogram>
 
+<histogram name="OOBE.SyncConsentScreen.SyncEnabled" enum="BooleanEnabled"
+    expires_after="2020-12-01">
+  <owner>jamescook@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
+  <summary>
+    Final state of the sync service at the end of the sync consent OOBE step.
+    The dialog may have been shown or skipped (e.g. by enterprise policy). See
+    OOBE.SyncConsentScreen.Behavior for skip reasons.
+  </summary>
+</histogram>
+
+<histogram name="OOBE.SyncConsentScreen.UserChoice"
+    enum="SyncConsentUserChoice" expires_after="2020-12-01">
+  <owner>jamescook@chromium.org</owner>
+  <owner>cros-oac@google.com</owner>
+  <summary>
+    Which button the user clicked on the out-of-box sync consent screen.
+    Recorded when the user clicks the button, which also closes the screen.
+  </summary>
+</histogram>
+
 <histogram name="OOBE.UpdateScreen.UpdateDownloadingTime" units="ms"
     expires_after="2020-10-01">
   <owner>raleksandrov@google.com</owner>
@@ -117357,8 +117513,9 @@
 </histogram>
 
 <histogram name="PageLoad.Experimental.ClickInputBurst" units="count"
-    expires_after="M85">
+    expires_after="2021-03-01">
   <owner>dougarnett@chromium.org</owner>
+  <owner>tbansal@chromium.org</owner>
   <owner>tdresser@chromium.org</owner>
   <summary>
     The maximum size click input burst for the page load. A click input burst is
@@ -124234,7 +124391,7 @@
 </histogram>
 
 <histogram name="PerformanceHints.Observer.HintForURLResult"
-    enum="PerformanceHintsObserverHintForURLResult" expires_after="2020-07-01">
+    enum="PerformanceHintsObserverHintForURLResult" expires_after="2020-10-01">
   <owner>jds@chromium.org</owner>
   <owner>src/chrome/browser/performance_hints/OWNERS</owner>
   <summary>
@@ -124245,7 +124402,7 @@
 </histogram>
 
 <histogram name="PerformanceHints.Observer.PerformanceClassForURL"
-    enum="PerformanceHintsPerformanceClass" expires_after="2020-07-01">
+    enum="PerformanceHintsPerformanceClass" expires_after="2020-10-01">
   <owner>jds@chromium.org</owner>
   <owner>src/chrome/browser/performance_hints/OWNERS</owner>
   <summary>
@@ -124255,6 +124412,19 @@
   </summary>
 </histogram>
 
+<histogram base="true" name="PerformanceHints.Observer.SourceLookupStatus"
+    enum="PerformanceHintsObserverSourceLookupStatus"
+    expires_after="2020-10-01">
+  <owner>jds@chromium.org</owner>
+  <owner>src/chrome/browser/performance_hints/OWNERS</owner>
+  <summary>
+    Records the result of a hint lookup in a single source (e.g. link hints of
+    the current page, the page's OptimizationMetadata, etc). See the
+    PerformanceHintsSource suffix for name completions. All source suffix
+    histograms should have the same total count.
+  </summary>
+</histogram>
+
 <histogram name="PerformanceManager.AgentsByTime" units="units"
     expires_after="2020-12-04">
   <owner>bokan@chromium.org</owner>
@@ -126489,6 +126659,15 @@
   </summary>
 </histogram>
 
+<histogram name="Platform.StatefulWritesDaily" units="KiB"
+    expires_after="2021-05-29">
+  <owner>asavery@chromium.org</owner>
+  <owner>gwendal@chromium.org</owner>
+  <summary>
+    Chrome OS stateful partition KiB writes per day. Sampled once daily.
+  </summary>
+</histogram>
+
 <histogram name="Platform.Storage.Flash.BadBlocks" units="units"
     expires_after="M85">
   <owner>dehrenberg@chromium.org</owner>
@@ -133422,6 +133601,9 @@
 
 <histogram name="Printing.CUPS.InvalidPpdResolved" enum="BooleanChanged"
     expires_after="2021-01-22">
+  <obsolete>
+    Removed 06/2020 because it is not longer needed (Issue 1046125).
+  </obsolete>
   <owner>luum@chromium.org</owner>
   <owner>skau@chromium.org</owner>
   <summary>
@@ -133736,6 +133918,9 @@
 
 <histogram name="PrintPreview.FontType" enum="PrintPreviewFontTypeType"
     expires_after="M85">
+  <obsolete>
+    Removed 01/2015 as part of crbug.com/278148.
+  </obsolete>
   <owner>thestig@chromium.org</owner>
   <summary>
     Count of font file formats embeeded in print preview PDFs. These numbers are
@@ -137525,7 +137710,8 @@
 </histogram>
 
 <histogram name="Renderer4.GpuImageDecodeState" enum="GpuImageUsageState"
-    expires_after="M85">
+    expires_after="2021-06-06">
+  <owner>cblume@chromium.org</owner>
   <owner>vmpstr@chromium.org</owner>
   <summary>
     Gpu image decode usage statistics. Images are decoded and locked prior to
@@ -137545,7 +137731,8 @@
 </histogram>
 
 <histogram name="Renderer4.GpuImageDecodeState.FirstLockWasted"
-    enum="BooleanWasted" expires_after="M85">
+    enum="BooleanWasted" expires_after="2021-06-06">
+  <owner>cblume@chromium.org</owner>
   <owner>vmpstr@chromium.org</owner>
   <summary>
     Indication whether the first lock of an image decode was wasted (image was
@@ -137813,6 +138000,12 @@
 
 <histogram name="Renderer4.LockExistingCachedImage" enum="BooleanSuccess"
     expires_after="M85">
+  <obsolete>
+    Removes as of 6/2020. We now get enough cache hit information from
+    Renderer4.SoftwareImageDecodeState* and don't need to divide it into tile
+    bins.
+  </obsolete>
+  <owner>cblume@chromium.org</owner>
   <owner>vmpstr@chromium.org</owner>
   <summary>
     For each attempted lock of a cached image, records whether it was
@@ -151113,7 +151306,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.DownloadStarted" enum="SafetyTipStatus"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -151126,7 +151319,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.FormSubmission" enum="SafetyTipStatus"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -151139,7 +151332,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.Interaction" enum="SafetyTipInteraction"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -151151,7 +151344,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.OpenTime.Dismiss" units="ms"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -151162,7 +151355,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.OpenTime.DismissWithClose" units="ms"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <owner>livvielin@chromium.org</owner>
@@ -151174,7 +151367,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.OpenTime.DismissWithEsc" units="ms"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <owner>livvielin@chromium.org</owner>
@@ -151186,7 +151379,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.OpenTime.DismissWithIgnore" units="ms"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <owner>livvielin@chromium.org</owner>
@@ -151198,7 +151391,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.OpenTime.LeaveSite" units="ms"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -151208,7 +151401,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.OpenTime.NoActionTaken" units="ms"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>estark@chromium.org</owner>
   <summary>
@@ -151218,7 +151411,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.PageInfo.Action"
-    enum="WebsiteSettingsAction" expires_after="M85">
+    enum="WebsiteSettingsAction" expires_after="M87">
   <owner>estark@chromium.org</owner>
   <owner>jdeblasio@chromium.org</owner>
   <summary>
@@ -151228,7 +151421,7 @@
 </histogram>
 
 <histogram base="true" name="Security.SafetyTips.ReputationCheckComplete"
-    enum="SafetyTipStatus" expires_after="M85">
+    enum="SafetyTipStatus" expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>src/chrome/browser/reputation/OWNERS</owner>
   <summary>
@@ -151239,7 +151432,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.SafetyTipIgnoredPageLoad"
-    enum="SafetyTipStatus" expires_after="M85">
+    enum="SafetyTipStatus" expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>livvielin@chromium.org</owner>
   <summary>
@@ -151249,7 +151442,7 @@
 </histogram>
 
 <histogram name="Security.SafetyTips.SafetyTipShown" enum="SafetyTipStatus"
-    expires_after="M85">
+    expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>livvielin@chromium.org</owner>
   <summary>
@@ -151259,7 +151452,7 @@
 </histogram>
 
 <histogram base="true" name="Security.SafetyTips.SafetyTipShown_AfterFlag"
-    enum="SafetyTipStatus" expires_after="M85">
+    enum="SafetyTipStatus" expires_after="M87">
   <owner>jdeblasio@chromium.org</owner>
   <owner>src/chrome/browser/reputation/OWNERS</owner>
   <summary>
@@ -151768,7 +151961,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.BackgroundFetchAbortEvent.Time" units="ms"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
@@ -151780,7 +151973,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.BackgroundFetchClickEvent.Time" units="ms"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
@@ -151806,7 +151999,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.BackgroundFetchFailEvent.Time" units="ms"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
@@ -151818,7 +152011,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.BackgroundFetchSuccessEvent.Time" units="ms"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>peter@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
@@ -151831,7 +152024,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.BackgroundSyncEvent.Time" units="ms"
-    expires_after="M85">
+    expires_after="2021-06-30">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
@@ -157695,6 +157888,16 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.Extensions.GetAuthTokenResult"
+    enum="GetAuthTokenResult" expires_after="2020-10-04">
+  <owner>alexilin@chromium.org</owner>
+  <owner>droger@chromium.org</owner>
+  <summary>
+    Result of the chrome.identity.getAuthToken() extension API call. Recorded
+    right before returning the result to an extension. Desktop only.
+  </summary>
+</histogram>
+
 <histogram name="Signin.ForceSigninVerificationRequest" enum="BooleanRequested"
     expires_after="M85">
   <owner>zmin@chromium.org</owner>
@@ -163096,8 +163299,11 @@
 </histogram>
 
 <histogram name="Stability.BrowserExitCodes" enum="WindowsExitCode"
-    expires_after="M82">
+    expires_after="never">
+<!-- expires-never: Critical stability metrics. go/chrome-stability-metrics -->
+
   <owner>siggi@chromium.org</owner>
+  <owner>chrome-stability-core@google.com</owner>
   <summary>
     Records the exit code of the browser process (on Windows) from the previous
     launch. On crash, the exit code will indicate the exception code of the
@@ -170260,6 +170466,9 @@
 
 <histogram name="Sync.UnrecoverableErrors" enum="SyncUnrecoverableErrorReason"
     expires_after="M85">
+  <obsolete>
+    Removed as of 06/2020.
+  </obsolete>
   <owner>mastiz@chromium.org</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -182279,6 +182488,9 @@
 
 <histogram name="Wallet.ApiCallDuration.AcceptLegalDocuments" units="ms"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Measures the time taken by Google Online Wallet server's accept legal
@@ -182288,6 +182500,9 @@
 
 <histogram name="Wallet.ApiCallDuration.AuthenticateInstrument" units="ms"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Measures the time taken by Google Online Wallet server's authenticate
@@ -182297,6 +182512,9 @@
 
 <histogram name="Wallet.ApiCallDuration.GetFullWallet" units="ms"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Measures the time taken by Google Online Wallet server's get full wallet API
@@ -182306,6 +182524,9 @@
 
 <histogram name="Wallet.ApiCallDuration.GetWalletItems" units="ms"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Measures the time taken by Google Online Wallet server's get wallet items
@@ -182351,6 +182572,9 @@
 
 <histogram name="Wallet.ApiCallDuration.SaveToWallet" units="ms"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Measures the time taken by Google Online Wallet server's save to wallet API
@@ -182360,6 +182584,9 @@
 
 <histogram name="Wallet.ApiCallDuration.SendStatus" units="ms"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Measures the time taken by Google Online Wallet server's send status API
@@ -182369,6 +182596,9 @@
 
 <histogram name="Wallet.ApiCallDuration.UnknownApiCall" units="ms"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Measures the time taken by Google Online Wallet server's unknown API calls.
@@ -182401,6 +182631,9 @@
 
 <histogram name="Wallet.MalformedResponse" enum="WalletApiCall"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>
     Counts the number of times each Wallet API failed due to being unable to
@@ -182410,6 +182643,9 @@
 
 <histogram name="Wallet.ResponseCode" enum="HttpResponseCode"
     expires_after="M85">
+  <obsolete>
+    requestAutocomplete was removed in M52.
+  </obsolete>
   <owner>estade@chromium.org</owner>
   <summary>HTTP response codes seen by Wallet client.</summary>
 </histogram>
@@ -192540,6 +192776,14 @@
   <affected-histogram name="Autofill.Quality.ServerType.ByFieldType"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="AutofillStoredCardHasNickname" separator=".">
+  <owner>sujiezhu@google.com</owner>
+  <owner>jsaul@google.com</owner>
+  <suffix name="WithNickname" label="Card with a valid nickname"/>
+  <affected-histogram name="Autofill.StoredCreditCardCount.Local"/>
+  <affected-histogram name="Autofill.StoredCreditCardCount.Server.Masked"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="AutofillStoredServerCardType" separator=".">
   <suffix name="Masked" label="Masked cards"/>
   <suffix name="Unmasked" label="Unmasked cards (locally cached)"/>
@@ -199133,6 +199377,11 @@
 </histogram_suffixes>
 
 <histogram_suffixes name="LockExistingCachedImage" separator=".">
+  <obsolete>
+    Removes as of 6/2020. We now get enough cache hit information from
+    Renderer4.SoftwareImageDecodeState* and don't need to divide it into tile
+    bins.
+  </obsolete>
   <suffix name="Software.EVENTUALLY" label="Eventually bin for software"/>
   <suffix name="Software.NOW" label="Now bin for software"/>
   <suffix name="Software.SOON" label="Soon bin for software"/>
@@ -204160,6 +204409,20 @@
   <affected-histogram name="PaymentRequest.NumberOfSuggestionsShown"/>
 </histogram_suffixes>
 
+<histogram_suffixes name="PerformanceHintsSource" separator=".">
+  <suffix name="LinkHint" label="From the link hints of the current page."/>
+  <suffix name="PageHint"
+      label="From the OptimizationGuide metadata of the given URL."/>
+  <affected-histogram name="PerformanceHints.Observer.SourceLookupStatus"/>
+</histogram_suffixes>
+
+<histogram_suffixes name="PerformanceHintsURLRewritten" separator=".">
+  <suffix name="Rewritten"
+      label="The URL matched one of the rewrite patterns and was extracted
+             before lookups"/>
+  <affected-histogram name="PerformanceHints.Observer.HintForURLResult"/>
+</histogram_suffixes>
+
 <histogram_suffixes name="PerformanceMonitor" separator=".">
   <suffix name="BrowserProcess" label=""/>
   <suffix name="GPUProcess" label=""/>
diff --git a/tools/metrics/histograms/merge_xml.py b/tools/metrics/histograms/merge_xml.py
index a0c89941..de5441c8 100755
--- a/tools/metrics/histograms/merge_xml.py
+++ b/tools/metrics/histograms/merge_xml.py
@@ -12,6 +12,7 @@
 
 import expand_owners
 import extract_histograms
+import histograms_print_style
 import populate_enums
 
 
@@ -104,12 +105,18 @@
   return MergeTrees(trees)
 
 
+def PrettyPrintMergedFiles(filenames=[], files=[]):
+  return histograms_print_style.GetPrintStyle().PrettyPrintXml(
+      MergeFiles(filenames=filenames, files=files))
+
+
 def main():
   parser = argparse.ArgumentParser()
   parser.add_argument('inputs', nargs="+")
   parser.add_argument('--output', required=True)
   args = parser.parse_args()
-  MergeFiles(args.inputs).writexml(open(args.output, 'w'))
+  with open(args.output, 'w') as f:
+    f.write(PrettyPrintMergedFiles(args.inputs))
 
 
 if __name__ == '__main__':
diff --git a/tools/metrics/histograms/merge_xml_test.py b/tools/metrics/histograms/merge_xml_test.py
index 13f4c6e..1884d2c 100644
--- a/tools/metrics/histograms/merge_xml_test.py
+++ b/tools/metrics/histograms/merge_xml_test.py
@@ -4,8 +4,6 @@
 
 import unittest
 
-import xml.dom.minidom
-
 import histogram_paths
 import merge_xml
 
@@ -14,21 +12,23 @@
 
   def testMergeFiles(self):
     """Checks that enums.xml and histograms.xml can merge successfully."""
-    merged = merge_xml.MergeFiles(
+    merged = merge_xml.PrettyPrintMergedFiles(
         [histogram_paths.TEST_ENUMS_XML, histogram_paths.TEST_HISTOGRAMS_XML])
     # If ukm.xml is not provided, there is no need to populate the
     # UkmEventNameHash enum.
-    expected_merged = xml.dom.minidom.parseString("""
-<histogram-configuration><enums>
+    expected_merged_xml = """
+<histogram-configuration>
+
+<enums>
 
 <enum name="Enum1">
-  <int label="Value0" value="0"/>
-  <int label="Value1" value="1"/>
+  <int value="0" label="Value0"/>
+  <int value="1" label="Value1"/>
 </enum>
 
 <enum name="TestEnum">
-  <int label="Value0" value="0"/>
-  <int label="Value1" value="1"/>
+  <int value="0" label="Value0"/>
+  <int value="1" label="Value1"/>
 </enum>
 
 <enum name="UkmEventNameHash">
@@ -38,7 +38,9 @@
 
 </enum>
 
-</enums><histograms>
+</enums>
+
+<histograms>
 
 <histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz">
   <summary>Foo</summary>
@@ -46,37 +48,37 @@
   <component>Component</component>
 </histogram>
 
-<histogram name="Test.Histogram" units="microseconds">
-  <obsolete>
-    Removed 6/2020.
-  </obsolete>
-  <owner>person@chromium.org</owner>
-  <summary>
-    Summary 2
-  </summary>
-</histogram>
-
 <histogram name="Test.EnumHistogram" enum="TestEnum" expires_after="M81">
   <owner>uma@chromium.org</owner>
   <obsolete>
     Obsolete message
   </obsolete>
-  <summary>
-    A enum histogram.
-  </summary>
+  <summary>A enum histogram.</summary>
 </histogram>
 
-</histograms><histogram_suffixes_list>
+<histogram name="Test.Histogram" units="microseconds">
+  <obsolete>
+    Removed 6/2020.
+  </obsolete>
+  <owner>person@chromium.org</owner>
+  <summary>Summary 2</summary>
+</histogram>
+
+</histograms>
+
+<histogram_suffixes_list>
 
 <histogram_suffixes name="Test.HistogramSuffixes" separator=".">
-  <suffix label="A histogram_suffixes" name="TestSuffix"/>
+  <suffix name="TestSuffix" label="A histogram_suffixes"/>
   <affected-histogram name="Test.Histogram"/>
 </histogram_suffixes>
 
-</histogram_suffixes_list></histogram-configuration>
-""")
+</histogram_suffixes_list>
+
+</histogram-configuration>
+"""
     self.maxDiff = None
-    self.assertEqual(expected_merged.toxml(), merged.toxml())
+    self.assertEqual(expected_merged_xml.strip(), merged.strip())
 
   def testMergeFiles_WithXmlEvents(self):
     """Checks that the UkmEventNameHash enum is populated correctly.
@@ -85,18 +87,20 @@
     where where each value is a xml event name hash truncated to 31 bits and
     each label is the corresponding event name.
     """
-    merged = merge_xml.MergeFiles(histogram_paths.ALL_TEST_XMLS)
-    expected_merged = xml.dom.minidom.parseString("""
-<histogram-configuration><enums>
+    merged = merge_xml.PrettyPrintMergedFiles(histogram_paths.ALL_TEST_XMLS)
+    expected_merged_xml = """
+<histogram-configuration>
+
+<enums>
 
 <enum name="Enum1">
-  <int label="Value0" value="0"/>
-  <int label="Value1" value="1"/>
+  <int value="0" label="Value0"/>
+  <int value="1" label="Value1"/>
 </enum>
 
 <enum name="TestEnum">
-  <int label="Value0" value="0"/>
-  <int label="Value1" value="1"/>
+  <int value="0" label="Value0"/>
+  <int value="1" label="Value1"/>
 </enum>
 
 <enum name="UkmEventNameHash">
@@ -104,12 +108,14 @@
      bits. This gets populated by the GetEnumsNodes function in merge_xml.py
      when producing the merged XML file. -->
 
-<int label="AbusiveExperienceHeuristic.WindowOpen" value="324605288"/>\
-<int label="AbusiveExperienceHeuristic.TabUnder" value="1621538456"/>\
-<int label="Autofill.SelectedMaskedServerCard (Obsolete)" value="1913876024"/>\
+  <int value="324605288" label="AbusiveExperienceHeuristic.WindowOpen"/>
+  <int value="1621538456" label="AbusiveExperienceHeuristic.TabUnder"/>
+  <int value="1913876024" label="Autofill.SelectedMaskedServerCard (Obsolete)"/>
 </enum>
 
-</enums><histograms>
+</enums>
+
+<histograms>
 
 <histogram name="Foo.Bar" units="xxxxxxxxxxxxxxxxxxyyyyyyyyyyyyyyyyyyyyyyzzzz">
   <summary>Foo</summary>
@@ -117,37 +123,37 @@
   <component>Component</component>
 </histogram>
 
-<histogram name="Test.Histogram" units="microseconds">
-  <obsolete>
-    Removed 6/2020.
-  </obsolete>
-  <owner>person@chromium.org</owner>
-  <summary>
-    Summary 2
-  </summary>
-</histogram>
-
 <histogram name="Test.EnumHistogram" enum="TestEnum" expires_after="M81">
   <owner>uma@chromium.org</owner>
   <obsolete>
     Obsolete message
   </obsolete>
-  <summary>
-    A enum histogram.
-  </summary>
+  <summary>A enum histogram.</summary>
 </histogram>
 
-</histograms><histogram_suffixes_list>
+<histogram name="Test.Histogram" units="microseconds">
+  <obsolete>
+    Removed 6/2020.
+  </obsolete>
+  <owner>person@chromium.org</owner>
+  <summary>Summary 2</summary>
+</histogram>
+
+</histograms>
+
+<histogram_suffixes_list>
 
 <histogram_suffixes name="Test.HistogramSuffixes" separator=".">
-  <suffix label="A histogram_suffixes" name="TestSuffix"/>
+  <suffix name="TestSuffix" label="A histogram_suffixes"/>
   <affected-histogram name="Test.Histogram"/>
 </histogram_suffixes>
 
-</histogram_suffixes_list></histogram-configuration>
-""")
+</histogram_suffixes_list>
+
+</histogram-configuration>
+"""
     self.maxDiff = None
-    self.assertEqual(expected_merged.toxml(), merged.toxml())
+    self.assertEqual(expected_merged_xml.strip(), merged.strip())
 
 
 if __name__ == '__main__':
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 8dc6bf8..0897487 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -4905,6 +4905,24 @@
       </history>
     </aggregation>
   </metric>
+  <metric name="InteractiveTiming.ProcessingTime">
+    <summary>
+      Measures Input Event processing time, the duration of event handlers
+      processing the input event. In ms.
+    </summary>
+    <aggregation>
+      <history>
+        <index fields="profile.country"/>
+        <index fields="profile.country,profile.system_ram"/>
+        <index fields="profile.is_dominant_version"/>
+        <index fields="profile.is_latest_version"/>
+        <index fields="profile.system_ram"/>
+        <statistics>
+          <quantiles type="std-percentiles"/>
+        </statistics>
+      </history>
+    </aggregation>
+  </metric>
 </event>
 
 <event name="Intervention.DocumentWrite.ScriptBlock" singular="True">
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 4bdf3686..0f6398f2 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "b7f0a11d1bd050f1615eaa75e7b1361cacbf47f8",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/3755aca72039c54e42fded4b16a1f2ac2c48fbf5/trace_processor_shell.exe"
+            "hash": "bdec289323c3b1efacd0e034973c2d6ea682cf96",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/f19675c75eab7f5f0ec5bd048fd6842896f146d0/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "cdcb1f5b233c5d3472a561a8f567d4927dec850b",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/058776deb61c3c6b1022c1e613e69518db32e443/trace_processor_shell"
+            "hash": "b71ebbc1bdd5222c37ec5d3ba2aa41609bbd67e3",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/f19675c75eab7f5f0ec5bd048fd6842896f146d0/trace_processor_shell"
         },
         "linux": {
-            "hash": "e761278db51e8f2d20fa0f43921f3f85090dfbc9",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/080c1b433d370e62a2cdd9912f473391f7d40da9/trace_processor_shell"
+            "hash": "5c546185954f415277a0510a552b950b0ac82749",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/f19675c75eab7f5f0ec5bd048fd6842896f146d0/trace_processor_shell"
         }
     }
 }
\ No newline at end of file
diff --git a/tools/perf/page_sets/system_health/loading_stories.py b/tools/perf/page_sets/system_health/loading_stories.py
index 1e6cde0..8821fa4 100644
--- a/tools/perf/page_sets/system_health/loading_stories.py
+++ b/tools/perf/page_sets/system_health/loading_stories.py
@@ -108,7 +108,7 @@
 ################################################################################
 
 
-class LoadTwitterMoibleStory2019(_LoadingStory):
+class LoadTwitterMobileStory2019(_LoadingStory):
   NAME = 'load:social:twitter:2019'
   URL = 'https://www.twitter.com/nasa'
   TAGS = [story_tags.YEAR_2019]
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index 1ae48a82..180ada3 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -52,6 +52,7 @@
  <item id="cloud_print_privet_register" hash_code="24978481" type="0" content_hash_code="131359002" os_list="linux,windows" file_path="chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc"/>
  <item id="cloud_print_proxy" hash_code="50859288" type="1" second_id="111712433" content_hash_code="90868083" os_list="linux,windows" semantics_fields="2,3,4" file_path="chrome/service/cloud_print/cloud_print_proxy.cc"/>
  <item id="cloud_print_search" hash_code="132055347" type="0" content_hash_code="123783474" os_list="linux,windows" file_path="chrome/browser/printing/cloud_print/gcd_api_flow_impl.cc"/>
+ <item id="cloud_speech_recognition" hash_code="15750036" type="0" deprecated="2020-05-27" content_hash_code="114921835" file_path="chrome/services/speech/cloud_speech_recognition_client.cc"/>
  <item id="content_hash_verification_job" hash_code="64733114" type="0" content_hash_code="127912411" os_list="linux,windows" file_path="extensions/browser/content_hash_fetcher.cc"/>
  <item id="content_resource_fetcher" hash_code="70796791" type="0" deprecated="2017-09-16" content_hash_code="135648626" file_path=""/>
  <item id="content_suggestion_get_favicon" hash_code="16653985" type="0" content_hash_code="134280933" os_list="linux,windows" file_path="components/ntp_snippets/content_suggestions_service.cc"/>
diff --git a/tools/xdisplaycheck/xdisplaycheck.cc b/tools/xdisplaycheck/xdisplaycheck.cc
index 6623153a..2e901ee 100644
--- a/tools/xdisplaycheck/xdisplaycheck.cc
+++ b/tools/xdisplaycheck/xdisplaycheck.cc
@@ -36,7 +36,7 @@
 
 class XScopedDisplay {
  public:
-  XScopedDisplay() : display_(NULL) {}
+  XScopedDisplay() : display_(nullptr) {}
   ~XScopedDisplay() {
     if (display_) XCloseDisplay(display_);
   }
diff --git a/ui/android/java/src/org/chromium/ui/drawable/StateListDrawableBuilder.java b/ui/android/java/src/org/chromium/ui/drawable/StateListDrawableBuilder.java
index 88e19bb..22c4c9c 100644
--- a/ui/android/java/src/org/chromium/ui/drawable/StateListDrawableBuilder.java
+++ b/ui/android/java/src/org/chromium/ui/drawable/StateListDrawableBuilder.java
@@ -4,13 +4,11 @@
 
 package org.chromium.ui.drawable;
 
-import android.annotation.TargetApi;
 import android.content.Context;
 import android.graphics.drawable.Animatable;
 import android.graphics.drawable.AnimatedStateListDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.StateListDrawable;
-import android.os.Build;
 
 import androidx.annotation.DrawableRes;
 import androidx.appcompat.content.res.AppCompatResources;
@@ -127,28 +125,6 @@
      * @return AnimatedStateListDrawable if platform supports it, StateListDrawable otherwise.
      */
     public StateListDrawable build() {
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
-            return buildPostL();
-        } else {
-            return buildPreL();
-        }
-    }
-
-    private StateListDrawable buildPreL() {
-        // Create StateListDrawable on API levels where AnimatedStateListDrawable is not available.
-        StateListDrawable result = new StateListDrawable();
-        int size = mStates.size();
-        for (int i = 0; i < size; ++i) {
-            State state = mStates.get(i);
-            Drawable drawable = AppCompatResources.getDrawable(mContext, state.getDrawable());
-            assert drawable != null;
-            result.addState(state.getStateSet(), drawable);
-        }
-        return result;
-    }
-
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    private StateListDrawable buildPostL() {
         AnimatedStateListDrawable result = new AnimatedStateListDrawable();
         int statesSize = mStates.size();
         for (int i = 0; i < statesSize; ++i) {
@@ -162,14 +138,8 @@
             Transition transition = mTransitions.get(i);
             Drawable drawable = AppCompatResources.getDrawable(mContext, transition.getDrawable());
             result.addTransition(transition.getFromId(), transition.getToId(),
-                    castToAnimatableDrawable(drawable), false);
+                    (Drawable & Animatable) (drawable), false);
         }
         return result;
     }
-
-    @SuppressWarnings("unchecked") // Need Java 8 to cast to intersection types
-    private static <T> T castToAnimatableDrawable(Drawable drawable) {
-        if (!(drawable instanceof Animatable)) throw new IllegalArgumentException("drawable");
-        return (T) drawable;
-    }
 }
diff --git a/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java b/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java
index 4b033999..8a13da1 100644
--- a/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java
+++ b/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java
@@ -15,7 +15,6 @@
 import org.robolectric.RuntimeEnvironment;
 import org.robolectric.annotation.Config;
 import org.robolectric.shadow.api.Shadow;
-import org.robolectric.shadows.ShadowStateListDrawable;
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.ui.shadows.ShadowAnimatedStateListDrawable;
@@ -31,23 +30,7 @@
     private static final int DEFAULT_DRAWABLE = 45678;
 
     @Test
-    @Config(sdk = 19)
-    public void testPreL() {
-        StateListDrawableBuilder b = new StateListDrawableBuilder(RuntimeEnvironment.application);
-        b.addState(CHECKED_DRAWABLE, android.R.attr.state_checked);
-        b.addState(DEFAULT_DRAWABLE, WILDCARD_STATE);
-        StateListDrawable result = b.build();
-        assertEquals(result.getClass(), StateListDrawable.class);
-        ShadowStateListDrawable drawable = shadowOf(result);
-        assertEquals(CHECKED_DRAWABLE,
-                shadowOf(drawable.getDrawableForState(CHECKED_STATE)).getCreatedFromResId());
-        assertEquals(DEFAULT_DRAWABLE,
-                shadowOf(drawable.getDrawableForState(WILDCARD_STATE)).getCreatedFromResId());
-    }
-
-    @Test
-    @Config(sdk = 21)
-    public void testPostL() {
+    public void testBuild() {
         StateListDrawableBuilder b = new StateListDrawableBuilder(RuntimeEnvironment.application);
         b.addState(CHECKED_DRAWABLE, android.R.attr.state_checked);
         b.addState(DEFAULT_DRAWABLE, WILDCARD_STATE);
diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc
index a796c629..c681aa4b 100644
--- a/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -337,7 +337,7 @@
 class QueueTouchEventDelegate : public GestureEventConsumeDelegate {
  public:
   explicit QueueTouchEventDelegate(WindowEventDispatcher* dispatcher)
-      : window_(NULL),
+      : window_(nullptr),
         dispatcher_(dispatcher),
         synchronous_ack_for_next_event_(AckState::PENDING) {}
 
@@ -2264,7 +2264,7 @@
   // A touch too far from other touches won't be locked to anything
   target =
       gesture_recognizer->GetTargetForLocation(gfx::PointF(1000.f, 1000.f), -1);
-  EXPECT_TRUE(target == NULL);
+  EXPECT_TRUE(target == nullptr);
 
   // Move a touch associated with windows[2] to 1000, 1000
   ui::TouchEvent move2(
@@ -3066,11 +3066,11 @@
   DispatchEventUsingWindowDispatcher(&press2);
   window->Hide();
   EXPECT_EQ(
-      NULL,
+      nullptr,
       aura::Env::GetInstance()->gesture_recognizer()->GetTouchLockedTarget(
           press1));
   EXPECT_EQ(
-      NULL,
+      nullptr,
       aura::Env::GetInstance()->gesture_recognizer()->GetTouchLockedTarget(
           press2));
 }
@@ -3766,7 +3766,7 @@
   aura::Env::GetInstance()->gesture_recognizer()->CancelActiveTouchesExcept(
       nullptr);
 
-  EXPECT_EQ(NULL, gesture_recognizer->GetTouchLockedTarget(press));
+  EXPECT_EQ(nullptr, gesture_recognizer->GetTouchLockedTarget(press));
   EXPECT_4_EVENTS(delegate->events(),
                   ui::ET_GESTURE_PINCH_END,
                   ui::ET_GESTURE_SCROLL_END,
@@ -4249,8 +4249,7 @@
 // A delegate that deletes a window on long press.
 class GestureEventDeleteWindowOnLongPress : public GestureEventConsumeDelegate {
  public:
-  GestureEventDeleteWindowOnLongPress()
-      : window_(NULL) {}
+  GestureEventDeleteWindowOnLongPress() : window_(nullptr) {}
 
   void set_window(aura::Window** window) { window_ = window; }
 
@@ -4259,7 +4258,7 @@
     if (gesture->type() != ui::ET_GESTURE_LONG_PRESS)
       return;
     delete *window_;
-    *window_ = NULL;
+    *window_ = nullptr;
   }
 
  private:
@@ -4283,11 +4282,11 @@
       ui::ET_TOUCH_PRESSED, gfx::Point(101, 201), ui::EventTimeForNow(),
       ui::PointerDetails(ui::EventPointerType::kTouch, kTouchId));
   DispatchEventUsingWindowDispatcher(&press1);
-  EXPECT_TRUE(window != NULL);
+  EXPECT_TRUE(window != nullptr);
 
   // Wait until the timer runs out.
   delegate.WaitUntilReceivedGesture(ui::ET_GESTURE_LONG_PRESS);
-  EXPECT_EQ(NULL, window);
+  EXPECT_EQ(nullptr, window);
 }
 
 TEST_F(GestureRecognizerWithSwitchTest, GestureEventSmallPinchDisabled) {
diff --git a/ui/aura/window_unittest.cc b/ui/aura/window_unittest.cc
index 497e080..cf382ff 100644
--- a/ui/aura/window_unittest.cc
+++ b/ui/aura/window_unittest.cc
@@ -203,8 +203,7 @@
 // OnWindowDestroyed is called.
 class DestroyOrphanDelegate : public TestWindowDelegate {
  public:
-  DestroyOrphanDelegate() : window_(NULL) {
-  }
+  DestroyOrphanDelegate() : window_(nullptr) {}
 
   void set_window(Window* window) { window_ = window; }
 
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
index 07d9672e..8ead00d 100644
--- a/ui/base/BUILD.gn
+++ b/ui/base/BUILD.gn
@@ -481,7 +481,7 @@
     deps += [ "//ui/events" ]
   }
 
-  if (is_desktop_linux && (use_x11 || ozone_platform_x11)) {
+  if ((is_desktop_linux || is_chromeos) && (use_x11 || ozone_platform_x11)) {
     public_deps += [ "//ui/base/x" ]
 
     # X11 drag and drop wants to use common drag and drop types.
diff --git a/ui/base/ime/linux/input_method_auralinux_unittest.cc b/ui/base/ime/linux/input_method_auralinux_unittest.cc
index 02819b9..8f7422a 100644
--- a/ui/base/ime/linux/input_method_auralinux_unittest.cc
+++ b/ui/base/ime/linux/input_method_auralinux_unittest.cc
@@ -271,11 +271,11 @@
 class InputMethodAuraLinuxTest : public testing::Test {
  protected:
   InputMethodAuraLinuxTest()
-      : factory_(NULL),
-        input_method_auralinux_(NULL),
-        delegate_(NULL),
-        context_(NULL),
-        context_simple_(NULL) {
+      : factory_(nullptr),
+        input_method_auralinux_(nullptr),
+        delegate_(nullptr),
+        context_(nullptr),
+        context_simple_(nullptr) {
     factory_ = new LinuxInputMethodContextFactoryForTesting();
     LinuxInputMethodContextFactory::SetInstance(factory_);
     test_result_ = TestResult::GetInstance();
diff --git a/ui/base/ime/win/tsf_text_store.cc b/ui/base/ime/win/tsf_text_store.cc
index 22f43ff7..0c00758a 100644
--- a/ui/base/ime/win/tsf_text_store.cc
+++ b/ui/base/ime/win/tsf_text_store.cc
@@ -647,9 +647,7 @@
   // 3. User commits current composition text.
   if (((new_composition_start > last_composition_start &&
         text_input_client_->HasCompositionText()) ||
-       (wparam_keydown_fired_ == 0 && !has_composition_range_ &&
-        !text_input_client_->HasCompositionText()) ||
-       (wparam_keydown_fired_ != 0 && !has_composition_range_)) &&
+       !has_composition_range_) &&
       text_input_client_) {
     CommitTextAndEndCompositionIfAny(last_composition_start,
                                      new_composition_start);
@@ -1355,8 +1353,11 @@
             : new_committed_string_size);
     // TODO(crbug.com/978678): Unify the behavior of
     //     |TextInputClient::InsertText(text)| for the empty text.
-    if (!new_committed_string.empty())
+    if (!new_committed_string.empty()) {
       text_input_client_->InsertText(new_committed_string);
+    } else {
+      text_input_client_->ClearCompositionText();
+    }
     // Notify accessibility about this committed composition
     text_input_client_->SetActiveCompositionForAccessibility(
         replace_text_range_, new_committed_string,
diff --git a/ui/base/ime/win/tsf_text_store_unittest.cc b/ui/base/ime/win/tsf_text_store_unittest.cc
index 081809d..4e81d7c1 100644
--- a/ui/base/ime/win/tsf_text_store_unittest.cc
+++ b/ui/base/ime/win/tsf_text_store_unittest.cc
@@ -3394,5 +3394,92 @@
   EXPECT_EQ(S_OK, result);
 }
 
+// regression tests for crbug.com/1091069.
+// We should allow inserting empty compositon string to cancel composition.
+class RegressionTest8Callback : public TSFTextStoreTestCallback {
+ public:
+  explicit RegressionTest8Callback(TSFTextStore* text_store)
+      : TSFTextStoreTestCallback(text_store) {}
+
+  HRESULT LockGranted1(DWORD flags) {
+    SetTextTest(0, 0, L"bbbb", S_OK);
+    SetSelectionTest(0, 4, S_OK);
+
+    text_spans()->clear();
+    ImeTextSpan text_span_1;
+    text_span_1.start_offset = 0;
+    text_span_1.end_offset = 4;
+    text_span_1.underline_color = SK_ColorBLACK;
+    text_span_1.thickness = ImeTextSpan::Thickness::kThin;
+    text_span_1.background_color = SK_ColorTRANSPARENT;
+    text_spans()->push_back(text_span_1);
+
+    *edit_flag() = true;
+    *composition_start() = 0;
+    composition_range()->set_start(0);
+    composition_range()->set_end(4);
+    *has_composition_range() = true;
+
+    text_store_->OnKeyTraceDown(65u, 1966081u);
+    return S_OK;
+  }
+
+  void SetCompositionText1(const ui::CompositionText& composition) {
+    EXPECT_EQ(L"bbbb", composition.text);
+    EXPECT_EQ(0u, composition.selection.start());
+    EXPECT_EQ(4u, composition.selection.end());
+    ASSERT_EQ(1u, composition.ime_text_spans.size());
+    EXPECT_EQ(0u, composition.ime_text_spans[0].start_offset);
+    EXPECT_EQ(4u, composition.ime_text_spans[0].end_offset);
+    SetHasCompositionText(true);
+  }
+
+  HRESULT LockGranted2(DWORD flags) {
+    GetTextTest(0, -1, L"bbbb", 4);
+    SetTextTest(0, 4, L"", S_OK);
+
+    text_spans()->clear();
+    *edit_flag() = true;
+    *composition_start() = 0;
+    composition_range()->set_start(0);
+    composition_range()->set_end(0);
+
+    *has_composition_range() = false;
+    text_store_->OnKeyTraceUp(65u, 1966081u);
+    return S_OK;
+  }
+
+  void ClearCompositionText2() { EXPECT_EQ(false, *has_composition_range()); }
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(RegressionTest8Callback);
+};
+
+TEST_F(TSFTextStoreTest, RegressionTest8) {
+  RegressionTest8Callback callback(text_store_.get());
+  EXPECT_CALL(text_input_client_, SetCompositionText(_))
+      .WillOnce(
+          Invoke(&callback, &RegressionTest8Callback::SetCompositionText1));
+
+  EXPECT_CALL(text_input_client_, ClearCompositionText())
+      .WillOnce(
+          Invoke(&callback, &RegressionTest8Callback::ClearCompositionText2));
+
+  EXPECT_CALL(*sink_, OnLockGranted(_))
+      .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted1))
+      .WillOnce(Invoke(&callback, &RegressionTest8Callback::LockGranted2));
+
+  ON_CALL(text_input_client_, HasCompositionText())
+      .WillByDefault(
+          Invoke(&callback, &TSFTextStoreTestCallback::HasCompositionText));
+
+  HRESULT result = kInvalidResult;
+  EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+  EXPECT_EQ(S_OK, result);
+  result = kInvalidResult;
+  EXPECT_EQ(S_OK, text_store_->RequestLock(TS_LF_READWRITE, &result));
+  EXPECT_EQ(S_OK, result);
+}
+
 }  // namespace
 }  // namespace ui
diff --git a/ui/base/view_prop.cc b/ui/base/view_prop.cc
index 45185f5..33b38a2 100644
--- a/ui/base/view_prop.cc
+++ b/ui/base/view_prop.cc
@@ -53,9 +53,7 @@
   typedef std::set<Data*, DataComparator> DataSet;
 
   Data(gfx::AcceleratedWidget view, const char* key)
-      : view_(view),
-        key_(key),
-        data_(NULL) {}
+      : view_(view), key_(key), data_(nullptr) {}
 
   ~Data() {
     auto i = data_set_->find(this);
diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn
index 0daf5090..881ab6a 100644
--- a/ui/base/x/BUILD.gn
+++ b/ui/base/x/BUILD.gn
@@ -46,7 +46,7 @@
     "x11_workspace_handler.h",
   ]
 
-  if (is_desktop_linux) {
+  if (is_desktop_linux || is_chromeos) {
     sources += [
       "selection_owner.cc",
       "selection_owner.h",
diff --git a/ui/base/x/x11_drag_drop_client.cc b/ui/base/x/x11_drag_drop_client.cc
index 0ec2c21..c920b3d6 100644
--- a/ui/base/x/x11_drag_drop_client.cc
+++ b/ui/base/x/x11_drag_drop_client.cc
@@ -676,7 +676,7 @@
 
 void XDragDropClient::EndMoveLoop() {
   StopEndMoveLoopTimer();
-  delegate_->EndMoveLoop();
+  delegate_->EndDragLoop();
 }
 
 }  // namespace ui
diff --git a/ui/base/x/x11_drag_drop_client.h b/ui/base/x/x11_drag_drop_client.h
index a0e5cc032d..021470d 100644
--- a/ui/base/x/x11_drag_drop_client.h
+++ b/ui/base/x/x11_drag_drop_client.h
@@ -60,8 +60,8 @@
     // Drops data at the current location and returns the resulting operation.
     virtual int PerformDrop() = 0;
 
-    // Called to end the move loop that is maintained by the subclass.
-    virtual void EndMoveLoop() = 0;
+    // Called to end the drag loop that is maintained by the subclass.
+    virtual void EndDragLoop() = 0;
 
    protected:
     virtual ~Delegate() = default;
diff --git a/ui/chromeos/ime/candidate_view.cc b/ui/chromeos/ime/candidate_view.cc
index 236a3a2..636bea7 100644
--- a/ui/chromeos/ime/candidate_view.cc
+++ b/ui/chromeos/ime/candidate_view.cc
@@ -88,7 +88,7 @@
   return shortcut_label;
 }
 
-// Creates the candidate label, and returns it (never returns NULL).
+// Creates the candidate label, and returns it (never returns nullptr).
 // The label text is not set in this function.
 std::unique_ptr<views::Label> CreateCandidateLabel(
     ui::CandidateWindow::Orientation orientation) {
@@ -109,7 +109,7 @@
   return candidate_label;
 }
 
-// Creates the annotation label, and return it (never returns NULL).
+// Creates the annotation label, and return it (never returns nullptr).
 // The label text is not set in this function.
 std::unique_ptr<views::Label> CreateAnnotationLabel(
     ui::CandidateWindow::Orientation orientation,
diff --git a/ui/chromeos/ime/candidate_view_unittest.cc b/ui/chromeos/ime/candidate_view_unittest.cc
index 89f57b41fe..31977f6 100644
--- a/ui/chromeos/ime/candidate_view_unittest.cc
+++ b/ui/chromeos/ime/candidate_view_unittest.cc
@@ -33,7 +33,7 @@
 class CandidateViewTest : public views::ViewsTestBase,
                           public views::ButtonListener {
  public:
-  CandidateViewTest() : widget_(NULL), last_pressed_(NULL) {}
+  CandidateViewTest() : widget_(nullptr), last_pressed_(nullptr) {}
   ~CandidateViewTest() override {}
 
   void SetUp() override {
diff --git a/ui/chromeos/ime/candidate_window_view_unittest.cc b/ui/chromeos/ime/candidate_window_view_unittest.cc
index 098688c8..a517f95 100644
--- a/ui/chromeos/ime/candidate_window_view_unittest.cc
+++ b/ui/chromeos/ime/candidate_window_view_unittest.cc
@@ -55,10 +55,8 @@
   InitCandidateWindow(page_size, candidate_window);
   for (size_t i = 0; i < page_size; ++i) {
     ui::CandidateWindow::Entry entry;
-    entry.value = base::UTF8ToUTF16(base::StringPrintf(
-        "value %lld", static_cast<unsigned long long>(i)));
-    entry.label = base::UTF8ToUTF16(base::StringPrintf(
-        "%lld", static_cast<unsigned long long>(i)));
+    entry.value = base::UTF8ToUTF16(base::StringPrintf("value %zu", i));
+    entry.label = base::UTF8ToUTF16(base::StringPrintf("%zu", i));
     candidate_window->mutable_candidates()->push_back(entry);
   }
 }
diff --git a/ui/chromeos/ime/suggestion_view.cc b/ui/chromeos/ime/suggestion_view.cc
index a5238494..0a16c9f8 100644
--- a/ui/chromeos/ime/suggestion_view.cc
+++ b/ui/chromeos/ime/suggestion_view.cc
@@ -35,7 +35,9 @@
 std::unique_ptr<views::Label> CreateAnnotationLabel() {
   std::unique_ptr<views::Label> annotation_label =
       std::make_unique<views::Label>();
-  annotation_label->SetFontList(kAnnotationFont);
+  annotation_label->SetFontList(gfx::FontList({kFontStyle}, gfx::Font::NORMAL,
+                                              kAnnotationFontSize,
+                                              gfx::Font::Weight::NORMAL));
   annotation_label->SetEnabledColor(kSuggestionColor);
   annotation_label->SetHorizontalAlignment(gfx::ALIGN_CENTER);
 
@@ -74,6 +76,8 @@
   // the previous one.
   suggestion_label_->SetText(base::EmptyString16());
   suggestion_label_->SetText(text);
+  gfx::FontList kSuggestionFont({kFontStyle}, gfx::Font::NORMAL,
+                                kSuggestionFontSize, gfx::Font::Weight::NORMAL);
   if (confirmed_length != 0) {
     views::StyledLabel::RangeStyleInfo confirmed_style;
     confirmed_style.custom_font = kSuggestionFont;
diff --git a/ui/chromeos/ime/suggestion_view.h b/ui/chromeos/ime/suggestion_view.h
index e5fc5055..66db63e8 100644
--- a/ui/chromeos/ime/suggestion_view.h
+++ b/ui/chromeos/ime/suggestion_view.h
@@ -18,14 +18,6 @@
 constexpr char kFontStyle[] = "Roboto";
 constexpr int kSuggestionFontSize = 14;
 constexpr int kAnnotationFontSize = 10;
-const gfx::FontList kSuggestionFont({kFontStyle},
-                                    gfx::Font::NORMAL,
-                                    kSuggestionFontSize,
-                                    gfx::Font::Weight::NORMAL);
-const gfx::FontList kAnnotationFont({kFontStyle},
-                                    gfx::Font::NORMAL,
-                                    kAnnotationFontSize,
-                                    gfx::Font::Weight::NORMAL);
 
 // Style-related constants
 constexpr int kAnnotationBorderThickness = 1;
diff --git a/ui/compositor/layer_animator.cc b/ui/compositor/layer_animator.cc
index e2dcf9b2..a9db692 100644
--- a/ui/compositor/layer_animator.cc
+++ b/ui/compositor/layer_animator.cc
@@ -46,7 +46,7 @@
 // LayerAnimator public --------------------------------------------------------
 
 LayerAnimator::LayerAnimator(base::TimeDelta transition_duration)
-    : delegate_(NULL),
+    : delegate_(nullptr),
       preemption_strategy_(IMMEDIATELY_SET_NEW_TARGET),
       is_transition_duration_locked_(false),
       transition_duration_(transition_duration),
diff --git a/ui/compositor/layer_animator_unittest.cc b/ui/compositor/layer_animator_unittest.cc
index c02519f..bbb9f4c 100644
--- a/ui/compositor/layer_animator_unittest.cc
+++ b/ui/compositor/layer_animator_unittest.cc
@@ -231,8 +231,9 @@
 
 class TestLayerAnimator : public LayerAnimator {
  public:
-  TestLayerAnimator() : LayerAnimator(base::TimeDelta::FromSeconds(0)),
-      destruction_observer_(NULL) {}
+  TestLayerAnimator()
+      : LayerAnimator(base::TimeDelta::FromSeconds(0)),
+        destruction_observer_(nullptr) {}
 
   void SetDestructionObserver(
       LayerAnimatorDestructionObserver* observer) {
diff --git a/ui/compositor/layer_unittest.cc b/ui/compositor/layer_unittest.cc
index 991c775..77945544 100644
--- a/ui/compositor/layer_unittest.cc
+++ b/ui/compositor/layer_unittest.cc
@@ -1971,7 +1971,7 @@
 
 class SchedulePaintLayerDelegate : public LayerDelegate {
  public:
-  SchedulePaintLayerDelegate() : paint_count_(0), layer_(NULL) {}
+  SchedulePaintLayerDelegate() : paint_count_(0), layer_(nullptr) {}
 
   ~SchedulePaintLayerDelegate() override {}
 
diff --git a/ui/display/win/screen_win.cc b/ui/display/win/screen_win.cc
index 0c789c4..d4fc53f 100644
--- a/ui/display/win/screen_win.cc
+++ b/ui/display/win/screen_win.cc
@@ -15,6 +15,7 @@
 #include "base/numerics/ranges.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
+#include "base/trace_event/trace_event.h"
 #include "base/win/win_util.h"
 #include "base/win/windows_version.h"
 #include "ui/display/display.h"
@@ -817,6 +818,8 @@
       (message != WM_SETTINGCHANGE || wparam != SPI_SETWORKAREA))
     return;
 
+  TRACE_EVENT1("ui", "ScreenWin::OnWndProc", "message", message);
+
   color_profile_reader_->UpdateIfNeeded();
   if (request_hdr_status_callback_)
     request_hdr_status_callback_.Run();
@@ -836,6 +839,8 @@
 }
 
 void ScreenWin::UpdateAllDisplaysAndNotify() {
+  TRACE_EVENT0("ui", "ScreenWin::UpdateAllDisplaysAndNotify");
+
   std::vector<Display> old_displays = std::move(displays_);
   UpdateFromDisplayInfos(GetDisplayInfosFromSystem());
   change_notifier_.NotifyDisplaysChanged(old_displays, displays_);
diff --git a/ui/events/event_dispatcher.cc b/ui/events/event_dispatcher.cc
index f3b451ef..95268c3 100644
--- a/ui/events/event_dispatcher.cc
+++ b/ui/events/event_dispatcher.cc
@@ -31,9 +31,7 @@
 
 }  // namespace
 
-EventDispatcherDelegate::EventDispatcherDelegate()
-    : dispatcher_(NULL) {
-}
+EventDispatcherDelegate::EventDispatcherDelegate() : dispatcher_(nullptr) {}
 
 EventDispatcherDelegate::~EventDispatcherDelegate() {
   if (dispatcher_)
diff --git a/ui/events/event_dispatcher_unittest.cc b/ui/events/event_dispatcher_unittest.cc
index 6b67cb3..f894351 100644
--- a/ui/events/event_dispatcher_unittest.cc
+++ b/ui/events/event_dispatcher_unittest.cc
@@ -21,9 +21,7 @@
 class TestTarget : public EventTarget,
                    public EventHandler {
  public:
-  TestTarget() : parent_(NULL), valid_(true) {
-    SetTargetHandler(this);
-  }
+  TestTarget() : parent_(nullptr), valid_(true) { SetTargetHandler(this); }
   ~TestTarget() override {}
 
   void set_parent(TestTarget* parent) { parent_ = parent; }
@@ -163,8 +161,7 @@
   EventHandlerDestroyer(int id, EventHandler* destroy)
       : TestEventHandler(id),
         to_destroy_(destroy),
-        dispatcher_delegate_(NULL) {
-  }
+        dispatcher_delegate_(nullptr) {}
 
   ~EventHandlerDestroyer() override { CHECK(!to_destroy_); }
 
diff --git a/ui/events/event_rewriter_unittest.cc b/ui/events/event_rewriter_unittest.cc
index 3a5f088..328cde5 100644
--- a/ui/events/event_rewriter_unittest.cc
+++ b/ui/events/event_rewriter_unittest.cc
@@ -111,7 +111,8 @@
 // EVENT_REWRITE_DISPATCH_ANOTHER.
 class TestStateMachineEventRewriterOld : public EventRewriter {
  public:
-  TestStateMachineEventRewriterOld() : last_rewritten_event_(0), state_(0) {}
+  TestStateMachineEventRewriterOld()
+      : last_rewritten_event_(nullptr), state_(0) {}
   void AddRule(int from_state,
                EventType from_type,
                int to_state,
diff --git a/ui/events/ozone/events_ozone.cc b/ui/events/ozone/events_ozone.cc
index a9dae50..fd91a8f 100644
--- a/ui/events/ozone/events_ozone.cc
+++ b/ui/events/ozone/events_ozone.cc
@@ -8,35 +8,44 @@
 
 namespace ui {
 
-void DispatchEventFromNativeUiEvent(
+bool DispatchEventFromNativeUiEvent(
     const PlatformEvent& event,
     base::OnceCallback<void(ui::Event*)> callback) {
   // NB: ui::Events are constructed here using the overload that takes a
   // const PlatformEvent& (here ui::Event* const&) rather than the copy
   // constructor. This has side effects and cannot be changed to use the
   // copy constructor or Event::Clone.
+  bool handled = false;
   if (event->IsKeyEvent()) {
     ui::KeyEvent key_event(event);
     std::move(callback).Run(&key_event);
+    handled = key_event.handled();
   } else if (event->IsMouseWheelEvent()) {
     ui::MouseWheelEvent wheel_event(event);
     std::move(callback).Run(&wheel_event);
+    handled = wheel_event.handled();
   } else if (event->IsMouseEvent()) {
     ui::MouseEvent mouse_event(event);
     std::move(callback).Run(&mouse_event);
+    handled = mouse_event.handled();
   } else if (event->IsTouchEvent()) {
     ui::TouchEvent touch_event(event);
     std::move(callback).Run(&touch_event);
+    handled = touch_event.handled();
   } else if (event->IsScrollEvent()) {
     ui::ScrollEvent scroll_event(event);
     std::move(callback).Run(&scroll_event);
+    handled = scroll_event.handled();
   } else if (event->IsGestureEvent()) {
     std::move(callback).Run(event);
+    handled = event->handled();
     // TODO(mohsen): Use the same pattern for scroll/touch/wheel events.
     // Apparently, there is no need for them to wrap the |event|.
   } else {
     NOTREACHED();
   }
+
+  return handled;
 }
 
 }  // namespace ui
diff --git a/ui/events/ozone/events_ozone.h b/ui/events/ozone/events_ozone.h
index 6a893e1e..d54dc56b 100644
--- a/ui/events/ozone/events_ozone.h
+++ b/ui/events/ozone/events_ozone.h
@@ -30,7 +30,8 @@
 // We are trying to fix both of these issues, but in the meantime we
 // define NativeEvent == ui::Event.
 //
-EVENTS_EXPORT void DispatchEventFromNativeUiEvent(
+// Returns true iff the event was handled.
+EVENTS_EXPORT bool DispatchEventFromNativeUiEvent(
     const PlatformEvent& native_event,
     base::OnceCallback<void(ui::Event*)> callback);
 
diff --git a/ui/events/platform/platform_event_source.cc b/ui/events/platform/platform_event_source.cc
index dfded71..adebfa6 100644
--- a/ui/events/platform/platform_event_source.cc
+++ b/ui/events/platform/platform_event_source.cc
@@ -27,8 +27,7 @@
 bool PlatformEventSource::ignore_native_platform_events_ = false;
 
 PlatformEventSource::PlatformEventSource()
-    : overridden_dispatcher_(NULL),
-      overridden_dispatcher_restored_(false) {
+    : overridden_dispatcher_(nullptr), overridden_dispatcher_restored_(false) {
   CHECK(!lazy_tls_ptr.Pointer()->Get())
       << "Only one platform event source can be created.";
   lazy_tls_ptr.Pointer()->Set(this);
diff --git a/ui/events/scoped_target_handler.cc b/ui/events/scoped_target_handler.cc
index f9cacaa..f5ee457 100644
--- a/ui/events/scoped_target_handler.cc
+++ b/ui/events/scoped_target_handler.cc
@@ -12,7 +12,7 @@
 
 ScopedTargetHandler::ScopedTargetHandler(EventTarget* target,
                                          EventHandler* handler)
-    : destroyed_flag_(NULL), target_(target), new_handler_(handler) {
+    : destroyed_flag_(nullptr), target_(target), new_handler_(handler) {
   original_handler_ = target_->SetTargetHandler(this);
 }
 
diff --git a/ui/events/test/test_event_handler.cc b/ui/events/test/test_event_handler.cc
index f97aad5..d115aaa 100644
--- a/ui/events/test/test_event_handler.cc
+++ b/ui/events/test/test_event_handler.cc
@@ -15,9 +15,8 @@
       num_scroll_events_(0),
       num_touch_events_(0),
       num_gesture_events_(0),
-      recorder_(NULL),
-      handler_name_("unknown") {
-}
+      recorder_(nullptr),
+      handler_name_("unknown") {}
 
 TestEventHandler::~TestEventHandler() {}
 
diff --git a/ui/events/test/test_event_target.cc b/ui/events/test/test_event_target.cc
index 15dc3e41..fd632af 100644
--- a/ui/events/test/test_event_target.cc
+++ b/ui/events/test/test_event_target.cc
@@ -15,9 +15,9 @@
 namespace test {
 
 TestEventTarget::TestEventTarget()
-    : parent_(NULL),
+    : parent_(nullptr),
       mark_events_as_handled_(false),
-      recorder_(NULL),
+      recorder_(nullptr),
       target_name_("unknown") {
   SetTargetHandler(this);
 }
diff --git a/ui/file_manager/gallery/js/ribbon.js b/ui/file_manager/gallery/js/ribbon.js
index 3294abf..c25bce4 100644
--- a/ui/file_manager/gallery/js/ribbon.js
+++ b/ui/file_manager/gallery/js/ribbon.js
@@ -203,23 +203,24 @@
   }
 
   if (event.added.length > 0) {
-    for (var i = 0; i < event.added.length; i++) {
-      var index = this.dataModel_.indexOf(event.added[i]);
+    for (let i = 0; i < event.added.length; i++) {
+      const index = this.dataModel_.indexOf(event.added[i]);
       if (index === -1) {
         continue;
       }
-      var element = this.renderThumbnail_(index);
-      var nextItem = this.dataModel_.item(index + 1);
-      var nextElement =
+      const element = this.renderThumbnail_(index);
+      const nextItem = this.dataModel_.item(index + 1);
+      const nextElement =
           nextItem && this.renderCache_[nextItem.getEntry().toURL()];
       this.insertBefore(element, nextElement);
     }
     return;
   }
 
-  var persistentNodes = this.querySelectorAll('.ribbon-image:not([vanishing])');
+  const persistentNodes =
+      this.querySelectorAll('.ribbon-image:not([vanishing])');
   if (this.lastVisibleIndex_ < this.dataModel_.length) { // Not at the end.
-    var lastNode = persistentNodes[persistentNodes.length - 1];
+    const lastNode = persistentNodes[persistentNodes.length - 1];
     if (lastNode.nextSibling) {
       // Pull back a vanishing node from the right.
       lastNode.nextSibling.removeAttribute('vanishing');
@@ -232,14 +233,14 @@
     this.lastVisibleIndex_--;
     if (this.firstVisibleIndex_) {
       this.firstVisibleIndex_--;
-      var firstNode = persistentNodes[0];
+      const firstNode = persistentNodes[0];
       if (firstNode.previousSibling) {
         // Pull back a vanishing node from the left.
         firstNode.previousSibling.removeAttribute('vanishing');
       } else {
         // Push a new item at the left end.
         if (this.firstVisibleIndex_ < this.dataModel_.length) {
-          var newThumbnail = this.renderThumbnail_(this.firstVisibleIndex_);
+          const newThumbnail = this.renderThumbnail_(this.firstVisibleIndex_);
           newThumbnail.style.marginLeft = -(this.clientHeight - 2) + 'px';
           this.insertBefore(newThumbnail, this.firstChild);
           setTimeout(function() {
@@ -250,9 +251,9 @@
     }
   }
 
-  var removed = false;
-  for (var i = 0; i < event.removed.length; i++) {
-    var removedDom = this.renderCache_[event.removed[i].getEntry().toURL()];
+  let removed = false;
+  for (let i = 0; i < event.removed.length; i++) {
+    const removedDom = this.renderCache_[event.removed[i].getEntry().toURL()];
     if (removedDom) {
       removedDom.removeAttribute('selected');
       removedDom.setAttribute('vanishing', 'smooth');
@@ -272,21 +273,21 @@
  * @private
  */
 Ribbon.prototype.onSelection_ = function() {
-  var indexes = this.selectionModel_.selectedIndexes;
+  const indexes = this.selectionModel_.selectedIndexes;
   if (indexes.length === 0) {
     return;  // Ignore temporary empty selection.
   }
-  var selectedIndex = indexes[0];
+  const selectedIndex = indexes[0];
 
-  var length = this.dataModel_.length;
-  var fullItems = Math.min(this.getItemCount_(), length);
-  var right = Math.floor((fullItems - 1) / 2);
+  const length = this.dataModel_.length;
+  const fullItems = Math.min(this.getItemCount_(), length);
+  const right = Math.floor((fullItems - 1) / 2);
 
-  var lastIndex = selectedIndex + right;
+  let lastIndex = selectedIndex + right;
   lastIndex = Math.max(lastIndex, fullItems - 1);
   lastIndex = Math.min(lastIndex, length - 1);
 
-  var firstIndex = lastIndex - fullItems + 1;
+  const firstIndex = lastIndex - fullItems + 1;
 
   if (this.firstVisibleIndex_ !== firstIndex ||
       this.lastVisibleIndex_ !== lastIndex) {
@@ -299,18 +300,17 @@
     this.removeVanishing_();
 
     this.textContent = '';
-    var startIndex = Math.min(firstIndex, this.firstVisibleIndex_);
+    const startIndex = Math.min(firstIndex, this.firstVisibleIndex_);
     // All the items except the first one treated equally.
-    for (var index = startIndex + 1;
-         index <= Math.max(lastIndex, this.lastVisibleIndex_);
-         ++index) {
+    for (let index = startIndex + 1;
+         index <= Math.max(lastIndex, this.lastVisibleIndex_); ++index) {
       // Only add items that are in either old or the new viewport.
       if (this.lastVisibleIndex_ < index && index < firstIndex ||
           lastIndex < index && index < this.firstVisibleIndex_) {
         continue;
       }
 
-      var box = this.renderThumbnail_(index);
+      const box = this.renderThumbnail_(index);
       box.style.marginLeft = Ribbon.MARGIN + 'px';
       this.appendChild(box);
 
@@ -321,9 +321,9 @@
       }
     }
 
-    var slideCount = this.childNodes.length + 1 - fullItems;
-    var margin = Ribbon.THUMBNAIL_WIDTH * slideCount;
-    var startBox = this.renderThumbnail_(startIndex);
+    const slideCount = this.childNodes.length + 1 - fullItems;
+    const margin = Ribbon.THUMBNAIL_WIDTH * slideCount;
+    const startBox = this.renderThumbnail_(startIndex);
 
     if (startIndex === firstIndex) {
       // Sliding to the right.
@@ -370,12 +370,12 @@
       'fade-right',
       lastIndex < length - 1 && selectedIndex !== lastIndex);
 
-  var oldSelected = this.querySelector('[selected]');
+  const oldSelected = this.querySelector('[selected]');
   if (oldSelected) {
     oldSelected.removeAttribute('selected');
   }
 
-  var newSelected =
+  const newSelected =
       this.renderCache_[this.dataModel_.item(selectedIndex).getEntry().toURL()];
   if (newSelected) {
     newSelected.setAttribute('selected', true);
@@ -408,8 +408,8 @@
     clearTimeout(this.removeTimeout_);
     this.removeTimeout_ = 0;
   }
-  var vanishingNodes = this.querySelectorAll('[vanishing]');
-  for (var i = 0; i != vanishingNodes.length; i++) {
+  const vanishingNodes = this.querySelectorAll('[vanishing]');
+  for (let i = 0; i != vanishingNodes.length; i++) {
     vanishingNodes[i].removeAttribute('vanishing');
     this.removeChild(vanishingNodes[i]);
   }
@@ -423,25 +423,25 @@
  * @private
  */
 Ribbon.prototype.renderThumbnail_ = function(index) {
-  var item = assertInstanceof(this.dataModel_.item(index), GalleryItem);
-  var url = item.getEntry().toURL();
+  const item = assertInstanceof(this.dataModel_.item(index), GalleryItem);
+  const url = item.getEntry().toURL();
 
-  var cached = this.renderCache_[url];
+  const cached = this.renderCache_[url];
   if (cached) {
-    var img = cached.querySelector('img');
+    const img = cached.querySelector('img');
     if (img) {
       img.classList.add('cached');
     }
     return cached;
   }
 
-  var thumbnail = assertInstanceof(this.ownerDocument.createElement('div'),
-      HTMLDivElement);
+  const thumbnail =
+      assertInstanceof(this.ownerDocument.createElement('div'), HTMLDivElement);
   thumbnail.id = `thumbnail-${this.thumbnailElementId_++}`;
   thumbnail.className = 'ribbon-image';
   thumbnail.setAttribute('role', 'listitem');
   thumbnail.addEventListener('click', function() {
-    var index = this.dataModel_.indexOf(item);
+    const index = this.dataModel_.indexOf(item);
     this.selectionModel_.unselectAll();
     this.selectionModel_.setIndexSelected(index, true);
   }.bind(this));
@@ -473,7 +473,7 @@
     return;
   }
 
-  var hideIndicator = function() {
+  const hideIndicator = function() {
     thumbnail.querySelector('.indicator').classList.toggle('loading', false);
   };
 
@@ -499,12 +499,12 @@
  * @private
  */
 Ribbon.prototype.onContentChange_ = function(event) {
-  var url = event.item.getEntry().toURL();
+  const url = event.item.getEntry().toURL();
   if (event.oldEntry.toURL() !== url) {
     this.remapCache_(event.oldEntry.toURL(), url);
   }
 
-  var thumbnail = this.renderCache_[url];
+  const thumbnail = this.renderCache_[url];
   if (thumbnail && event.item) {
     this.setThumbnailImage_(thumbnail, event.item);
   }
diff --git a/ui/gfx/animation/animation.cc b/ui/gfx/animation/animation.cc
index b216afb5..0b1d4f2 100644
--- a/ui/gfx/animation/animation.cc
+++ b/ui/gfx/animation/animation.cc
@@ -26,8 +26,7 @@
 Animation::Animation(base::TimeDelta timer_interval)
     : timer_interval_(timer_interval),
       is_animating_(false),
-      delegate_(NULL) {
-}
+      delegate_(nullptr) {}
 
 Animation::~Animation() {
   // Don't send out notification from the destructor. Chances are the delegate
diff --git a/ui/gfx/codec/png_codec.cc b/ui/gfx/codec/png_codec.cc
index f2176e9..d0064b3 100644
--- a/ui/gfx/codec/png_codec.cc
+++ b/ui/gfx/codec/png_codec.cc
@@ -39,13 +39,12 @@
   PngDecoderState(PNGCodec::ColorFormat ofmt, std::vector<unsigned char>* o)
       : output_format(ofmt),
         output_channels(0),
-        bitmap(NULL),
+        bitmap(nullptr),
         is_opaque(true),
         output(o),
         width(0),
         height(0),
-        done(false) {
-  }
+        done(false) {}
 
   // Output is an SkBitmap.
   explicit PngDecoderState(SkBitmap* skbitmap)
@@ -53,11 +52,10 @@
         output_channels(0),
         bitmap(skbitmap),
         is_opaque(true),
-        output(NULL),
+        output(nullptr),
         width(0),
         height(0),
-        done(false) {
-  }
+        done(false) {}
 
   PNGCodec::ColorFormat output_format;
   int output_channels;
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index b2f8fbf5..aa43cde2 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -247,9 +247,7 @@
 GLApi::~GLApi() {
 }
 
-GLApiBase::GLApiBase()
-    : driver_(NULL) {
-}
+GLApiBase::GLApiBase() : driver_(nullptr) {}
 
 GLApiBase::~GLApiBase() {
 }
diff --git a/ui/gl/scoped_binders.cc b/ui/gl/scoped_binders.cc
index f44272e..9375094 100644
--- a/ui/gl/scoped_binders.cc
+++ b/ui/gl/scoped_binders.cc
@@ -11,7 +11,7 @@
 
 ScopedFramebufferBinder::ScopedFramebufferBinder(unsigned int fbo)
     : state_restorer_(!GLContext::GetCurrent()
-                          ? NULL
+                          ? nullptr
                           : GLContext::GetCurrent()->GetGLStateRestorer()),
       old_fbo_(-1) {
   if (!state_restorer_)
@@ -31,7 +31,7 @@
 
 ScopedActiveTexture::ScopedActiveTexture(unsigned int texture)
     : state_restorer_(!GLContext::GetCurrent()
-                          ? NULL
+                          ? nullptr
                           : GLContext::GetCurrent()->GetGLStateRestorer()),
       old_texture_(-1) {
   if (!state_restorer_)
@@ -51,7 +51,7 @@
 
 ScopedTextureBinder::ScopedTextureBinder(unsigned int target, unsigned int id)
     : state_restorer_(!GLContext::GetCurrent()
-                          ? NULL
+                          ? nullptr
                           : GLContext::GetCurrent()->GetGLStateRestorer()),
       target_(target),
       old_id_(-1) {
@@ -90,7 +90,7 @@
 
 ScopedUseProgram::ScopedUseProgram(unsigned int program)
     : state_restorer_(!GLContext::GetCurrent()
-                          ? NULL
+                          ? nullptr
                           : GLContext::GetCurrent()->GetGLStateRestorer()),
       old_program_(-1) {
   if (!state_restorer_)
@@ -115,7 +115,7 @@
                                                  int stride,
                                                  const void* pointer)
     : state_restorer_(!GLContext::GetCurrent()
-                          ? NULL
+                          ? nullptr
                           : GLContext::GetCurrent()->GetGLStateRestorer()),
       buffer_(0),
       enabled_(GL_FALSE),
@@ -124,7 +124,7 @@
       type_(-1),
       normalized_(GL_FALSE),
       stride_(0),
-      pointer_(0) {
+      pointer_(nullptr) {
   if (!state_restorer_) {
     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &buffer_);
     glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &enabled_);
@@ -154,7 +154,7 @@
 
 ScopedBufferBinder::ScopedBufferBinder(unsigned int target, unsigned int id)
     : state_restorer_(!GLContext::GetCurrent()
-                          ? NULL
+                          ? nullptr
                           : GLContext::GetCurrent()->GetGLStateRestorer()),
       target_(target),
       old_id_(-1) {
diff --git a/ui/login/display_manager.js b/ui/login/display_manager.js
index 7b9824d..b3df385 100644
--- a/ui/login/display_manager.js
+++ b/ui/login/display_manager.js
@@ -13,7 +13,7 @@
 /** @const */ var SCREEN_OOBE_HID_DETECTION = 'hid-detection';
 /** @const */ var SCREEN_OOBE_EULA = 'eula';
 /** @const */ var SCREEN_OOBE_ENABLE_DEBUGGING = 'debugging';
-/** @const */ var SCREEN_OOBE_UPDATE = 'update';
+/** @const */ var SCREEN_OOBE_UPDATE = 'oobe-update';
 /** @const */ var SCREEN_OOBE_RESET = 'reset';
 /** @const */ var SCREEN_OOBE_ENROLLMENT = 'oauth-enrollment';
 /** @const */ var SCREEN_OOBE_DEMO_SETUP = 'demo-setup';
diff --git a/ui/native_theme/native_theme.h b/ui/native_theme/native_theme.h
index fce4c73..12b0869 100644
--- a/ui/native_theme/native_theme.h
+++ b/ui/native_theme/native_theme.h
@@ -276,6 +276,7 @@
     int thumb_x;
     int thumb_y;
     float zoom;
+    bool right_to_left;
   };
 
   struct TextFieldExtraParams {
diff --git a/ui/native_theme/native_theme_base.cc b/ui/native_theme/native_theme_base.cc
index 933324cb..57bd8bf 100644
--- a/ui/native_theme/native_theme_base.cc
+++ b/ui/native_theme/native_theme_base.cc
@@ -1831,11 +1831,16 @@
         std::min(float(slider_rect.right()), mid_x + kAlignment),
         slider_rect.bottom());
   } else {
-    const float right = is_value ? slider_rect.x() + slider.thumb_x + kAlignment
-                                 : slider_rect.right();
+    const float right = is_value && !slider.right_to_left
+                            ? slider_rect.x() + slider.thumb_x + kAlignment
+                            : slider_rect.right();
+    const float left = is_value && slider.right_to_left
+                           ? slider_rect.x() + slider.thumb_x + kAlignment
+                           : slider_rect.x();
+
     aligned_rect.setLTRB(
-        slider_rect.x(), std::max(float(slider_rect.y()), mid_y - kAlignment),
-        right, std::min(float(slider_rect.bottom()), mid_y + kAlignment));
+        left, std::max(float(slider_rect.y()), mid_y - kAlignment), right,
+        std::min(float(slider_rect.bottom()), mid_y + kAlignment));
   }
 
   return aligned_rect;
diff --git a/ui/ozone/ozone.gni b/ui/ozone/ozone.gni
index ca6e9dd..13fecf9 100644
--- a/ui/ozone/ozone.gni
+++ b/ui/ozone/ozone.gni
@@ -4,7 +4,6 @@
 
 import("//build/config/chromecast_build.gni")
 import("//build/config/ui.gni")
-import("//build/toolchain/kythe.gni")
 import("//build/toolchain/toolchain.gni")
 
 declare_args() {
@@ -47,9 +46,6 @@
     ozone_platform = "headless"
     ozone_platform_headless = true
 
-    # Enable the Ozone Wayland platform for codesearch-gen bots so we get cross-references in codesearch.
-    ozone_platform_wayland = enable_kythe_annotations
-
     if (is_cast_audio_only) {
       # Just use headless for audio-only Cast platforms.
     } else if (is_chromecast && !is_fuchsia) {
diff --git a/ui/ozone/platform/wayland/BUILD.gn b/ui/ozone/platform/wayland/BUILD.gn
index 28d1c6c..011b55b 100644
--- a/ui/ozone/platform/wayland/BUILD.gn
+++ b/ui/ozone/platform/wayland/BUILD.gn
@@ -144,6 +144,7 @@
     "//skia",
     "//third_party/wayland:wayland_client",
     "//third_party/wayland-protocols:gtk_primary_selection_protocol",
+    "//third_party/wayland-protocols:keyboard_extension_protocol",
     "//third_party/wayland-protocols:linux_dmabuf_protocol",
     "//third_party/wayland-protocols:presentation_time_protocol",
     "//third_party/wayland-protocols:text_input_protocol",
@@ -335,6 +336,7 @@
     "//testing/gmock",
     "//testing/gtest",
     "//third_party/wayland:wayland_server",
+    "//third_party/wayland-protocols:keyboard_extension_protocol",
     "//third_party/wayland-protocols:linux_dmabuf_protocol",
     "//third_party/wayland-protocols:text_input_protocol",
     "//third_party/wayland-protocols:xdg_shell_protocol",
diff --git a/ui/ozone/platform/wayland/common/wayland_object.cc b/ui/ozone/platform/wayland/common/wayland_object.cc
index d0db092..9f9efea 100644
--- a/ui/ozone/platform/wayland/common/wayland_object.cc
+++ b/ui/ozone/platform/wayland/common/wayland_object.cc
@@ -5,6 +5,7 @@
 #include "ui/ozone/platform/wayland/common/wayland_object.h"
 
 #include <gtk-primary-selection-client-protocol.h>
+#include <keyboard-extension-unstable-v1-client-protocol.h>
 #include <linux-dmabuf-unstable-v1-client-protocol.h>
 #include <presentation-time-client-protocol.h>
 #include <text-input-unstable-v1-client-protocol.h>
@@ -189,6 +190,16 @@
 void (*ObjectTraits<xdg_positioner>::deleter)(xdg_positioner*) =
     &xdg_positioner_destroy;
 
+const wl_interface* ObjectTraits<zcr_keyboard_extension_v1>::interface =
+    &zcr_keyboard_extension_v1_interface;
+void (*ObjectTraits<zcr_keyboard_extension_v1>::deleter)(
+    zcr_keyboard_extension_v1*) = &zcr_keyboard_extension_v1_destroy;
+
+const wl_interface* ObjectTraits<zcr_extended_keyboard_v1>::interface =
+    &zcr_extended_keyboard_v1_interface;
+void (*ObjectTraits<zcr_extended_keyboard_v1>::deleter)(
+    zcr_extended_keyboard_v1*) = &zcr_extended_keyboard_v1_destroy;
+
 const wl_interface* ObjectTraits<zwp_linux_dmabuf_v1>::interface =
     &zwp_linux_dmabuf_v1_interface;
 void (*ObjectTraits<zwp_linux_dmabuf_v1>::deleter)(zwp_linux_dmabuf_v1*) =
diff --git a/ui/ozone/platform/wayland/common/wayland_object.h b/ui/ozone/platform/wayland/common/wayland_object.h
index 2d048ee3..5c639f2 100644
--- a/ui/ozone/platform/wayland/common/wayland_object.h
+++ b/ui/ozone/platform/wayland/common/wayland_object.h
@@ -39,6 +39,8 @@
 struct xdg_toplevel;
 struct xdg_popup;
 struct xdg_positioner;
+struct zcr_keyboard_extension_v1;
+struct zcr_extended_keyboard_v1;
 struct zwp_linux_dmabuf_v1;
 struct zxdg_shell_v6;
 struct zxdg_surface_v6;
@@ -246,6 +248,18 @@
 };
 
 template <>
+struct ObjectTraits<zcr_keyboard_extension_v1> {
+  static const wl_interface* interface;
+  static void (*deleter)(zcr_keyboard_extension_v1*);
+};
+
+template <>
+struct ObjectTraits<zcr_extended_keyboard_v1> {
+  static const wl_interface* interface;
+  static void (*deleter)(zcr_extended_keyboard_v1*);
+};
+
+template <>
 struct ObjectTraits<zwp_linux_dmabuf_v1> {
   static const wl_interface* interface;
   static void (*deleter)(zwp_linux_dmabuf_v1*);
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.cc b/ui/ozone/platform/wayland/host/wayland_connection.cc
index b2e7227..244bfe3 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/host/wayland_connection.cc
@@ -43,6 +43,7 @@
 namespace {
 constexpr uint32_t kMaxCompositorVersion = 4;
 constexpr uint32_t kMaxGtkPrimarySelectionDeviceManagerVersion = 1;
+constexpr uint32_t kMaxKeyboardExtensionVersion = 1;
 constexpr uint32_t kMaxLinuxDmabufVersion = 3;
 constexpr uint32_t kMaxSeatVersion = 4;
 constexpr uint32_t kMaxShmVersion = 1;
@@ -165,13 +166,8 @@
 
   if (!has_keyboard) {
     keyboard_.reset();
-  } else if (wl_keyboard* keyboard = wl_seat_get_keyboard(seat)) {
-    auto* layout_engine =
-        KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
-    keyboard_ = std::make_unique<WaylandKeyboard>(keyboard, this, layout_engine,
-                                                  event_source());
-  } else {
-    LOG(ERROR) << "Failed to get wl_keyboard from seat";
+  } else if (!CreateKeyboard()) {
+    LOG(ERROR) << "Failed to create WaylandKeyboard";
   }
 
   if (!has_touch) {
@@ -183,6 +179,20 @@
   }
 }
 
+bool WaylandConnection::CreateKeyboard() {
+  wl_keyboard* keyboard = wl_seat_get_keyboard(seat_.get());
+  if (!keyboard)
+    return false;
+
+  auto* layout_engine = KeyboardLayoutEngineManager::GetKeyboardLayoutEngine();
+  // Make sure to destroy the old WaylandKeyboard (if it exists) before creating
+  // the new one.
+  keyboard_.reset();
+  keyboard_.reset(new WaylandKeyboard(keyboard, keyboard_extension_v1_.get(),
+                                      this, layout_engine, event_source()));
+  return true;
+}
+
 void WaylandConnection::CreateDataObjectsIfReady() {
   if (data_device_manager_ && seat_) {
     DCHECK(!data_drag_controller_);
@@ -313,6 +323,17 @@
              (strcmp(interface, "wp_presentation") == 0)) {
     connection->presentation_ =
         wl::Bind<wp_presentation>(registry, name, kMaxWpPresentationVersion);
+  } else if (!connection->keyboard_extension_v1_ &&
+             strcmp(interface, "zcr_keyboard_extension_v1") == 0) {
+    connection->keyboard_extension_v1_ = wl::Bind<zcr_keyboard_extension_v1>(
+        registry, name, kMaxKeyboardExtensionVersion);
+    if (!connection->keyboard_extension_v1_) {
+      LOG(ERROR) << "Failed to bind zcr_keyboard_extension_v1";
+      return;
+    }
+    // CreateKeyboard may fail if we do not have keyboard seat capabilities yet.
+    // We will create the keyboard when get them in that case.
+    connection->CreateKeyboard();
   } else if (!connection->text_input_manager_v1_ &&
              strcmp(interface, "zwp_text_input_manager_v1") == 0) {
     connection->text_input_manager_v1_ = wl::Bind<zwp_text_input_manager_v1>(
diff --git a/ui/ozone/platform/wayland/host/wayland_connection.h b/ui/ozone/platform/wayland/host/wayland_connection.h
index d44f35dc..97734b4 100644
--- a/ui/ozone/platform/wayland/host/wayland_connection.h
+++ b/ui/ozone/platform/wayland/host/wayland_connection.h
@@ -124,6 +124,10 @@
   // in place, i.e: wl_seat and wl_data_device_manager.
   void CreateDataObjectsIfReady();
 
+  // Creates WaylandKeyboard with the currently acquired protocol objects, if
+  // possible. Returns true iff WaylandKeyboard was created.
+  bool CreateKeyboard();
+
   // wl_registry_listener
   static void Global(void* data,
                      wl_registry* registry,
@@ -151,6 +155,7 @@
   wl::Object<xdg_wm_base> shell_;
   wl::Object<zxdg_shell_v6> shell_v6_;
   wl::Object<wp_presentation> presentation_;
+  wl::Object<zcr_keyboard_extension_v1> keyboard_extension_v1_;
   wl::Object<zwp_text_input_manager_v1> text_input_manager_v1_;
 
   // Event source instance. Must be declared before input objects so it
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.cc b/ui/ozone/platform/wayland/host/wayland_event_source.cc
index 2222139..de40983 100644
--- a/ui/ozone/platform/wayland/host/wayland_event_source.cc
+++ b/ui/ozone/platform/wayland/host/wayland_event_source.cc
@@ -96,21 +96,21 @@
   keyboard_modifiers_ = modifiers;
 }
 
-void WaylandEventSource::OnKeyboardKeyEvent(EventType type,
-                                            DomCode dom_code,
-                                            DomKey dom_key,
-                                            KeyboardCode key_code,
-                                            bool repeat,
-                                            base::TimeTicks timestamp) {
+uint32_t WaylandEventSource::OnKeyboardKeyEvent(EventType type,
+                                                DomCode dom_code,
+                                                DomKey dom_key,
+                                                KeyboardCode key_code,
+                                                bool repeat,
+                                                base::TimeTicks timestamp) {
   DCHECK(type == ET_KEY_PRESSED || type == ET_KEY_RELEASED);
   if (!keyboard_)
-    return;
+    return POST_DISPATCH_NONE;
 
   // try to decode key, if not yet.
   if (dom_key == DomKey::NONE &&
       !keyboard_->Decode(dom_code, keyboard_modifiers_, &dom_key, &key_code)) {
     LOG(ERROR) << "Failed to decode key event.";
-    return;
+    return POST_DISPATCH_NONE;
   }
 
   if (!repeat) {
@@ -121,7 +121,7 @@
   KeyEvent event(type, key_code, dom_code, keyboard_modifiers_, dom_key,
                  timestamp);
   event.set_source_device_id(keyboard_->device_id());
-  DispatchEvent(&event);
+  return DispatchEvent(&event);
 }
 
 void WaylandEventSource::OnPointerCreated(WaylandPointer* pointer) {
diff --git a/ui/ozone/platform/wayland/host/wayland_event_source.h b/ui/ozone/platform/wayland/host/wayland_event_source.h
index bfbbd99..c00cce9 100644
--- a/ui/ozone/platform/wayland/host/wayland_event_source.h
+++ b/ui/ozone/platform/wayland/host/wayland_event_source.h
@@ -80,12 +80,12 @@
   void OnKeyboardDestroyed(WaylandKeyboard* keyboard) override;
   void OnKeyboardFocusChanged(WaylandWindow* window, bool focused) override;
   void OnKeyboardModifiersChanged(int modifiers) override;
-  void OnKeyboardKeyEvent(EventType type,
-                          DomCode dom_code,
-                          DomKey dom_key,
-                          KeyboardCode key_code,
-                          bool repeat,
-                          base::TimeTicks timestamp) override;
+  uint32_t OnKeyboardKeyEvent(EventType type,
+                              DomCode dom_code,
+                              DomKey dom_key,
+                              KeyboardCode key_code,
+                              bool repeat,
+                              base::TimeTicks timestamp) override;
 
   // WaylandPointer::Delegate
   void OnPointerCreated(WaylandPointer* pointer) override;
diff --git a/ui/ozone/platform/wayland/host/wayland_keyboard.cc b/ui/ozone/platform/wayland/host/wayland_keyboard.cc
index 0258d15..7de0fe69 100644
--- a/ui/ozone/platform/wayland/host/wayland_keyboard.cc
+++ b/ui/ozone/platform/wayland/host/wayland_keyboard.cc
@@ -34,10 +34,12 @@
     WaylandKeyboard::SyncCallback,
 };
 
-WaylandKeyboard::WaylandKeyboard(wl_keyboard* keyboard,
-                                 WaylandConnection* connection,
-                                 KeyboardLayoutEngine* layout_engine,
-                                 Delegate* delegate)
+WaylandKeyboard::WaylandKeyboard(
+    wl_keyboard* keyboard,
+    zcr_keyboard_extension_v1* keyboard_extension_v1,
+    WaylandConnection* connection,
+    KeyboardLayoutEngine* layout_engine,
+    Delegate* delegate)
     : obj_(keyboard),
       connection_(connection),
       delegate_(delegate),
@@ -58,6 +60,10 @@
 
   wl_keyboard_add_listener(obj_.get(), &listener, this);
   // TODO(tonikitoo): Default auto-repeat to ON here?
+
+  if (keyboard_extension_v1)
+    extended_keyboard_v1_.reset(zcr_keyboard_extension_v1_get_extended_keyboard(
+        keyboard_extension_v1, obj_.get()));
 }
 
 WaylandKeyboard::~WaylandKeyboard() {
@@ -193,9 +199,15 @@
 
   // Pass empty DomKey and KeyboardCode here so the delegate can pre-process
   // and decode it when needed.
-  delegate_->OnKeyboardKeyEvent(down ? ET_KEY_PRESSED : ET_KEY_RELEASED,
-                                dom_code, DomKey::NONE,
-                                KeyboardCode::VKEY_UNKNOWN, repeat, timestamp);
+  uint32_t result = delegate_->OnKeyboardKeyEvent(
+      down ? ET_KEY_PRESSED : ET_KEY_RELEASED, dom_code, DomKey::NONE,
+      KeyboardCode::VKEY_UNKNOWN, repeat, timestamp);
+
+  if (extended_keyboard_v1_) {
+    bool handled = result & POST_DISPATCH_STOP_PROPAGATION;
+    zcr_extended_keyboard_v1_ack_key(extended_keyboard_v1_.get(),
+                                     connection_->serial(), handled);
+  }
 }
 
 bool WaylandKeyboard::Decode(DomCode dom_code,
diff --git a/ui/ozone/platform/wayland/host/wayland_keyboard.h b/ui/ozone/platform/wayland/host/wayland_keyboard.h
index 1630d8aa..e449da0b 100644
--- a/ui/ozone/platform/wayland/host/wayland_keyboard.h
+++ b/ui/ozone/platform/wayland/host/wayland_keyboard.h
@@ -5,6 +5,7 @@
 #ifndef UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_KEYBOARD_H_
 #define UI_OZONE_PLATFORM_WAYLAND_HOST_WAYLAND_KEYBOARD_H_
 
+#include <keyboard-extension-unstable-v1-client-protocol.h>
 #include <wayland-client.h>
 
 #include "base/time/time.h"
@@ -30,6 +31,7 @@
   class Delegate;
 
   WaylandKeyboard(wl_keyboard* keyboard,
+                  zcr_keyboard_extension_v1* keyboard_extension_v1,
                   WaylandConnection* connection,
                   KeyboardLayoutEngine* keyboard_layout_engine,
                   Delegate* delegate);
@@ -88,6 +90,7 @@
                    int flags) override;
 
   wl::Object<wl_keyboard> obj_;
+  wl::Object<zcr_extended_keyboard_v1> extended_keyboard_v1_;
   WaylandConnection* const connection_;
   Delegate* const delegate_;
 
@@ -110,12 +113,18 @@
   virtual void OnKeyboardDestroyed(WaylandKeyboard* keyboard) = 0;
   virtual void OnKeyboardFocusChanged(WaylandWindow* window, bool focused) = 0;
   virtual void OnKeyboardModifiersChanged(int modifiers) = 0;
-  virtual void OnKeyboardKeyEvent(EventType type,
-                                  DomCode dom_code,
-                                  DomKey dom_key,
-                                  KeyboardCode key_code,
-                                  bool repeat,
-                                  base::TimeTicks timestamp) = 0;
+  // Returns a mask of ui::PostDispatchAction indicating how the event was
+  // dispatched.
+  virtual uint32_t OnKeyboardKeyEvent(EventType type,
+                                      DomCode dom_code,
+                                      DomKey dom_key,
+                                      KeyboardCode key_code,
+                                      bool repeat,
+                                      base::TimeTicks timestamp) = 0;
+
+ protected:
+  // Prevent deletion through a WaylandKeyboard::Delegate pointer.
+  virtual ~Delegate() = default;
 };
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.cc b/ui/ozone/platform/wayland/host/wayland_surface.cc
index 0548d75c..baa02c0 100644
--- a/ui/ozone/platform/wayland/host/wayland_surface.cc
+++ b/ui/ozone/platform/wayland/host/wayland_surface.cc
@@ -31,9 +31,9 @@
 }
 
 WaylandSurface::~WaylandSurface() {
-  if (drag_closed_callback_) {
-    std::move(drag_closed_callback_)
-        .Run(DragDropTypes::DragOperation::DRAG_NONE);
+  if (drag_handler_delegate_) {
+    drag_handler_delegate_->OnDragFinished(
+        DragDropTypes::DragOperation::DRAG_NONE);
   }
 }
 
@@ -80,9 +80,9 @@
 void WaylandSurface::StartDrag(const ui::OSExchangeData& data,
                                int operation,
                                gfx::NativeCursor cursor,
-                               base::OnceCallback<void(int)> callback) {
-  DCHECK(!drag_closed_callback_);
-  drag_closed_callback_ = std::move(callback);
+                               WmDragHandler::Delegate* delegate) {
+  DCHECK(!drag_handler_delegate_);
+  drag_handler_delegate_ = delegate;
   connection()->data_drag_controller()->StartSession(data, operation);
 }
 
@@ -284,7 +284,9 @@
 }
 
 void WaylandSurface::OnDragSessionClose(uint32_t dnd_action) {
-  std::move(drag_closed_callback_).Run(dnd_action);
+  DCHECK(drag_handler_delegate_);
+  drag_handler_delegate_->OnDragFinished(dnd_action);
+  drag_handler_delegate_ = nullptr;
   connection()->event_source()->ResetPointerFlags();
 }
 
diff --git a/ui/ozone/platform/wayland/host/wayland_surface.h b/ui/ozone/platform/wayland/host/wayland_surface.h
index 6df26cd..f0560a9 100644
--- a/ui/ozone/platform/wayland/host/wayland_surface.h
+++ b/ui/ozone/platform/wayland/host/wayland_surface.h
@@ -37,7 +37,7 @@
   void StartDrag(const ui::OSExchangeData& data,
                  int operation,
                  gfx::NativeCursor cursor,
-                 base::OnceCallback<void(int)> callback) override;
+                 WmDragHandler::Delegate* delegate) override;
 
   // PlatformWindow
   void Show(bool inactive) override;
@@ -83,7 +83,7 @@
   // Wrappers around shell surface.
   std::unique_ptr<ShellSurfaceWrapper> shell_surface_;
 
-  base::OnceCallback<void(int)> drag_closed_callback_;
+  WmDragHandler::Delegate* drag_handler_delegate_ = nullptr;
 
   // These bounds attributes below have suffices that indicate units used.
   // Wayland operates in DIP but the platform operates in physical pixels so
diff --git a/ui/ozone/platform/wayland/host/wayland_window.cc b/ui/ozone/platform/wayland/host/wayland_window.cc
index b0eedfd..25a34f5 100644
--- a/ui/ozone/platform/wayland/host/wayland_window.cc
+++ b/ui/ozone/platform/wayland/host/wayland_window.cc
@@ -499,10 +499,10 @@
   if (event->IsLocatedEvent())
     UpdateCursorPositionFromEvent(Event::Clone(*event));
 
-  DispatchEventFromNativeUiEvent(
+  bool handled = DispatchEventFromNativeUiEvent(
       native_event, base::BindOnce(&PlatformWindowDelegate::DispatchEvent,
                                    base::Unretained(delegate_)));
-  return POST_DISPATCH_STOP_PROPAGATION;
+  return handled ? POST_DISPATCH_STOP_PROPAGATION : POST_DISPATCH_NONE;
 }
 
 // static
diff --git a/ui/ozone/platform/x11/x11_window_ozone.cc b/ui/ozone/platform/x11/x11_window_ozone.cc
index 3f98795..99e323d6e 100644
--- a/ui/ozone/platform/x11/x11_window_ozone.cc
+++ b/ui/ozone/platform/x11/x11_window_ozone.cc
@@ -4,19 +4,8 @@
 
 #include "ui/ozone/platform/x11/x11_window_ozone.h"
 
-#include "ui/base/dragdrop/os_exchange_data.h"
-#include "ui/base/x/x11_os_exchange_data_provider.h"
-#include "ui/base/x/x11_pointer_grab.h"
-#include "ui/base/x/x11_topmost_window_finder.h"
-#include "ui/events/event.h"
-#include "ui/events/platform/scoped_event_dispatcher.h"
-#include "ui/events/platform/x11/x11_event_source.h"
-#include "ui/events/x/x11_window_event_manager.h"
 #include "ui/ozone/platform/x11/x11_cursor_ozone.h"
 #include "ui/platform_window/platform_window_delegate.h"
-#include "ui/platform_window/platform_window_handler/wm_drop_handler.h"
-#include "ui/platform_window/x11/x11_topmost_window_finder.h"
-#include "ui/platform_window/x11/x11_window_manager.h"
 
 namespace ui {
 
@@ -30,145 +19,4 @@
   XWindow::SetCursor(cursor_ozone->xcursor());
 }
 
-void X11WindowOzone::Initialize(PlatformWindowInitProperties properties) {
-  X11Window::Initialize(std::move(properties));
-  // Set a class property key that allows |this| to be used for drag action.
-  SetWmDragHandler(this, this);
-
-  drag_drop_client_ =
-      std::make_unique<XDragDropClient>(this, display(), window());
-}
-
-void X11WindowOzone::StartDrag(const ui::OSExchangeData& data,
-                               int operation,
-                               gfx::NativeCursor cursor,
-                               base::OnceCallback<void(int)> callback) {
-  DCHECK(drag_drop_client_);
-
-  end_drag_callback_ = std::move(callback);
-  drag_drop_client_->InitDrag(operation, &data);
-  drag_operation_ = 0;
-  notified_enter_ = false;
-
-  SetCapture();
-
-  dragging_ = true;
-}
-
-std::unique_ptr<ui::XTopmostWindowFinder> X11WindowOzone::CreateWindowFinder() {
-  return std::make_unique<X11TopmostWindowFinder>();
-}
-
-int X11WindowOzone::UpdateDrag(const gfx::Point& screen_point) {
-  WmDropHandler* drop_handler = GetWmDropHandler(*this);
-  if (!drop_handler)
-    return ui::DragDropTypes::DRAG_NONE;
-  if (!notified_enter_) {
-    DCHECK(drag_drop_client_);
-    auto* target_current_context = drag_drop_client_->target_current_context();
-    DCHECK(target_current_context);
-    drop_handler->OnDragEnter(
-        gfx::PointF(screen_point),
-        std::make_unique<ui::OSExchangeData>(
-            std::make_unique<ui::XOSExchangeDataProvider>(
-                drag_drop_client_->xwindow(),
-                target_current_context->fetched_targets())),
-        ui::DragDropTypes::DRAG_COPY);
-    notified_enter_ = true;
-  }
-
-  drag_operation_ = drop_handler->OnDragMotion(gfx::PointF(screen_point),
-                                               ui::DragDropTypes::DRAG_COPY);
-  return drag_operation_;
-}
-
-void X11WindowOzone::UpdateCursor(
-    ui::DragDropTypes::DragOperation negotiated_operation) {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void X11WindowOzone::OnBeginForeignDrag(XID window) {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void X11WindowOzone::OnEndForeignDrag() {
-  NOTIMPLEMENTED_LOG_ONCE();
-}
-
-void X11WindowOzone::OnBeforeDragLeave() {
-  WmDropHandler* drop_handler = GetWmDropHandler(*this);
-  if (!drop_handler)
-    return;
-  drop_handler->OnDragLeave();
-  notified_enter_ = false;
-}
-
-int X11WindowOzone::PerformDrop() {
-  WmDropHandler* drop_handler = GetWmDropHandler(*this);
-  if (!drop_handler)
-    return ui::DragDropTypes::DRAG_NONE;
-
-  DCHECK(notified_enter_);
-
-  // The drop data has been supplied on entering the window.  The drop handler
-  // should have it since then.
-  drop_handler->OnDragDrop({});
-  notified_enter_ = false;
-  return drag_operation_;
-}
-
-void X11WindowOzone::EndMoveLoop() {
-  std::move(end_drag_callback_).Run(0);
-}
-
-bool X11WindowOzone::DispatchDraggingUiEvent(ui::Event* event) {
-  // Drag and drop have a priority over other processing.
-  if (dragging_) {
-    DCHECK(drag_drop_client_);
-
-    switch (event->type()) {
-      case ui::ET_MOUSE_MOVED:
-      case ui::ET_MOUSE_DRAGGED: {
-        drag_drop_client_->HandleMouseMovement(
-            event->AsLocatedEvent()->root_location(),
-            event->AsMouseEvent()->flags(),
-            event->AsMouseEvent()->time_stamp());
-        return true;
-      }
-      case ui::ET_MOUSE_RELEASED:
-        if (!event->AsMouseEvent()->IsLeftMouseButton())
-          break;
-        // Assume that drags are being done with the left mouse button. Only
-        // break the drag if the left mouse button was released.
-        drag_drop_client_->HandleMouseReleased();
-        dragging_ = false;
-        ReleaseCapture();
-        return true;
-      case ui::ET_KEY_PRESSED:
-        if (event->AsKeyEvent()->key_code() != ui::VKEY_ESCAPE)
-          break;
-        EndMoveLoop();
-        drag_drop_client_->HandleMoveLoopEnded();
-        dragging_ = false;
-        ReleaseCapture();
-        return true;
-      default:
-        break;
-    }
-  }
-  return false;
-}
-
-void X11WindowOzone::OnXWindowSelectionEvent(XEvent* xev) {
-  X11Window::OnXWindowSelectionEvent(xev);
-  DCHECK(drag_drop_client_);
-  drag_drop_client_->OnSelectionNotify(xev->xselection);
-}
-
-void X11WindowOzone::OnXWindowDragDropEvent(XEvent* xev) {
-  X11Window::OnXWindowDragDropEvent(xev);
-  DCHECK(drag_drop_client_);
-  drag_drop_client_->HandleXdndEvent(xev->xclient);
-}
-
 }  // namespace ui
diff --git a/ui/ozone/platform/x11/x11_window_ozone.h b/ui/ozone/platform/x11/x11_window_ozone.h
index c7f8d311..fcf4e67f 100644
--- a/ui/ozone/platform/x11/x11_window_ozone.h
+++ b/ui/ozone/platform/x11/x11_window_ozone.h
@@ -5,8 +5,6 @@
 #ifndef UI_OZONE_PLATFORM_X11_X11_WINDOW_OZONE_H_
 #define UI_OZONE_PLATFORM_X11_X11_WINDOW_OZONE_H_
 
-#include "ui/base/x/x11_drag_drop_client.h"
-#include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
 #include "ui/platform_window/x11/x11_window.h"
 
 namespace ui {
@@ -15,9 +13,7 @@
 
 // PlatformWindow implementation for non-ChromeOS X11 Ozone.
 // PlatformEvents are ui::Events.
-class X11WindowOzone : public X11Window,
-                       public WmDragHandler,
-                       public XDragDropClient::Delegate {
+class X11WindowOzone : public X11Window {
  public:
   explicit X11WindowOzone(PlatformWindowDelegate* delegate);
   ~X11WindowOzone() override;
@@ -27,42 +23,6 @@
 
   // Overridden from PlatformWindow:
   void SetCursor(PlatformCursor cursor) override;
-
-  // Overridden from X11Window:
-  void Initialize(PlatformWindowInitProperties properties) override;
-
- private:
-  // WmDragHandler
-  void StartDrag(const ui::OSExchangeData& data,
-                 int operation,
-                 gfx::NativeCursor cursor,
-                 base::OnceCallback<void(int)> callback) override;
-
-  // ui::XDragDropClient::Delegate
-  std::unique_ptr<ui::XTopmostWindowFinder> CreateWindowFinder() override;
-  int UpdateDrag(const gfx::Point& screen_point) override;
-  void UpdateCursor(
-      ui::DragDropTypes::DragOperation negotiated_operation) override;
-  void OnBeginForeignDrag(XID window) override;
-  void OnEndForeignDrag() override;
-  void OnBeforeDragLeave() override;
-  int PerformDrop() override;
-  void EndMoveLoop() override;
-
-  // X11Window:
-  bool DispatchDraggingUiEvent(ui::Event* event) override;
-  void OnXWindowSelectionEvent(XEvent* xev) override;
-  void OnXWindowDragDropEvent(XEvent* xev) override;
-
-  // True while the drag initiated in this window is in progress.
-  bool dragging_ = false;
-  // Whether the drop handler has notified that the drag has entered.
-  bool notified_enter_ = false;
-  // Keeps the last negotiated operation returned by the drop handler.
-  int drag_operation_ = 0;
-
-  std::unique_ptr<XDragDropClient> drag_drop_client_;
-  base::OnceCallback<void(int)> end_drag_callback_;
 };
 
 }  // namespace ui
diff --git a/ui/platform_window/platform_window_handler/wm_drag_handler.cc b/ui/platform_window/platform_window_handler/wm_drag_handler.cc
index f559d42..5dafa35 100644
--- a/ui/platform_window/platform_window_handler/wm_drag_handler.cc
+++ b/ui/platform_window/platform_window_handler/wm_drag_handler.cc
@@ -13,6 +13,8 @@
 
 DEFINE_UI_CLASS_PROPERTY_KEY(WmDragHandler*, kWmDragHandlerKey, nullptr)
 
+WmDragHandler::Delegate::~Delegate() = default;
+
 void SetWmDragHandler(PlatformWindow* platform_window,
                       WmDragHandler* drag_handler) {
   platform_window->SetProperty(kWmDragHandlerKey, drag_handler);
diff --git a/ui/platform_window/platform_window_handler/wm_drag_handler.h b/ui/platform_window/platform_window_handler/wm_drag_handler.h
index 7f7d793..a18881c 100644
--- a/ui/platform_window/platform_window_handler/wm_drag_handler.h
+++ b/ui/platform_window/platform_window_handler/wm_drag_handler.h
@@ -6,6 +6,8 @@
 #define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_DRAG_HANDLER_H_
 
 #include "base/bind.h"
+#include "base/callback.h"
+#include "ui/gfx/geometry/point.h"
 #include "ui/gfx/native_widget_types.h"
 #include "ui/platform_window/platform_window_handler/wm_platform_export.h"
 
@@ -15,15 +17,28 @@
 
 class WM_PLATFORM_EXPORT WmDragHandler {
  public:
+  // During the drag operation, the handler may send updates
+  class Delegate {
+   public:
+    // Called every time when the drag location has changed.
+    virtual void OnDragLocationChanged(const gfx::Point& screen_point_px) = 0;
+    // Called once when the operation has finished.
+    virtual void OnDragFinished(int operation) = 0;
+
+   protected:
+    virtual ~Delegate();
+  };
+
   // Starts dragging with |data| which it wants to deliver to the destination.
   // |operation| is the suggested operation which is bitmask of DRAG_NONE,
   // DRAG_MOVE, DRAG_COPY and DRAG_LINK in DragDropTypes::DragOperation to the
   // destination and the destination sets the final operation when the drop
-  // action is performed.
+  // action is performed.  In progress updates on the drag operation come back
+  // through the |delegate|.
   virtual void StartDrag(const OSExchangeData& data,
                          int operation,
                          gfx::NativeCursor cursor,
-                         base::OnceCallback<void(int)> callback) = 0;
+                         Delegate* delegate) = 0;
 
  protected:
   virtual ~WmDragHandler() {}
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc
index 0877d88d..a47c8b54 100644
--- a/ui/platform_window/x11/x11_window.cc
+++ b/ui/platform_window/x11/x11_window.cc
@@ -24,7 +24,15 @@
 #include "ui/platform_window/x11/x11_window_manager.h"
 
 #if defined(USE_OZONE)
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/x/x11_os_exchange_data_provider.h"
+#include "ui/base/x/x11_pointer_grab.h"
+#include "ui/base/x/x11_topmost_window_finder.h"
 #include "ui/events/ozone/events_ozone.h"
+#include "ui/platform_window/platform_window_handler/wm_drop_handler.h"
+#include "ui/platform_window/x11/x11_topmost_window_finder.h"
+#else
+#include "ui/base/dragdrop/os_exchange_data_provider_x11.h"
 #endif  // defined(USE_OZONE)
 
 #if BUILDFLAG(USE_ATK)
@@ -35,6 +43,9 @@
 
 namespace {
 
+// Opacity for drag widget windows.
+constexpr float kDragWidgetOpacity = .75f;
+
 XWindow::WindowOpacity GetXWindowOpacity(PlatformWindowOpacity opacity) {
   using WindowOpacity = XWindow::WindowOpacity;
   switch (opacity) {
@@ -130,11 +141,28 @@
   config.override_redirect =
       properties.x11_extension_delegate &&
       properties.x11_extension_delegate->IsOverrideRedirect(IsWmTiling());
+  if (config.type == WindowType::kDrag) {
+    config.opacity = ui::IsCompositingManagerPresent()
+                         ? WindowOpacity::kTranslucentWindow
+                         : WindowOpacity::kOpaqueWindow;
+  }
 
   workspace_extension_delegate_ = properties.workspace_extension_delegate;
   x11_extension_delegate_ = properties.x11_extension_delegate;
 
   Init(config);
+
+  if (config.type == WindowType::kDrag &&
+      config.opacity == WindowOpacity::kTranslucentWindow) {
+    SetOpacity(kDragWidgetOpacity);
+  }
+
+#if defined(USE_OZONE)
+  SetWmDragHandler(this, this);
+
+  drag_drop_client_ =
+      std::make_unique<XDragDropClient>(this, display(), window());
+#endif
 }
 
 void X11Window::SetXEventDelegate(XEventDelegate* delegate) {
@@ -641,10 +669,6 @@
   platform_window_delegate_->OnAcceleratedWidgetAvailable(GetWidget());
 }
 
-bool X11Window::DispatchDraggingUiEvent(ui::Event* event) {
-  return false;
-}
-
 void X11Window::OnXWindowStateChanged() {
   // Determine the new window state information to be propagated to the client.
   // Note that the order of checks is important here, because window can have
@@ -732,11 +756,19 @@
 void X11Window::OnXWindowSelectionEvent(XEvent* xev) {
   if (x_event_delegate_)
     x_event_delegate_->OnXWindowSelectionEvent(xev);
+#if defined(USE_OZONE)
+  DCHECK(drag_drop_client_);
+  drag_drop_client_->OnSelectionNotify(xev->xselection);
+#endif
 }
 
 void X11Window::OnXWindowDragDropEvent(XEvent* xev) {
   if (x_event_delegate_)
     x_event_delegate_->OnXWindowDragDropEvent(xev);
+#if defined(USE_OZONE)
+  DCHECK(drag_drop_client_);
+  drag_drop_client_->HandleXdndEvent(xev->xclient);
+#endif
 }
 
 base::Optional<gfx::Size> X11Window::GetMinimumSizeForXWindow() {
@@ -767,6 +799,135 @@
   x11_window_move_client_->EndMoveLoop();
 }
 
+#if defined(USE_OZONE)
+void X11Window::StartDrag(const OSExchangeData& data,
+                          int operation,
+                          gfx::NativeCursor cursor,
+                          WmDragHandler::Delegate* delegate) {
+  DCHECK(drag_drop_client_);
+  DCHECK(!drag_handler_delegate_);
+
+  drag_handler_delegate_ = delegate;
+  drag_drop_client_->InitDrag(operation, &data);
+  drag_operation_ = 0;
+  notified_enter_ = false;
+
+  SetCapture();
+
+  dragging_ = true;
+}
+
+std::unique_ptr<XTopmostWindowFinder> X11Window::CreateWindowFinder() {
+  return std::make_unique<X11TopmostWindowFinder>();
+}
+
+int X11Window::UpdateDrag(const gfx::Point& screen_point) {
+  WmDropHandler* drop_handler = GetWmDropHandler(*this);
+  if (!drop_handler)
+    return DragDropTypes::DRAG_NONE;
+  if (!notified_enter_) {
+    DCHECK(drag_drop_client_);
+    auto* target_current_context = drag_drop_client_->target_current_context();
+    DCHECK(target_current_context);
+    drop_handler->OnDragEnter(
+        gfx::PointF(screen_point),
+        std::make_unique<ui::OSExchangeData>(
+            std::make_unique<ui::XOSExchangeDataProvider>(
+                drag_drop_client_->xwindow(),
+                target_current_context->fetched_targets())),
+        ui::DragDropTypes::DRAG_COPY);
+    notified_enter_ = true;
+  }
+
+  drag_operation_ = drop_handler->OnDragMotion(gfx::PointF(screen_point),
+                                               ui::DragDropTypes::DRAG_COPY);
+  return drag_operation_;
+}
+
+void X11Window::UpdateCursor(
+    DragDropTypes::DragOperation negotiated_operation) {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void X11Window::OnBeginForeignDrag(XID window) {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void X11Window::OnEndForeignDrag() {
+  NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void X11Window::OnBeforeDragLeave() {
+  WmDropHandler* drop_handler = GetWmDropHandler(*this);
+  if (!drop_handler)
+    return;
+  drop_handler->OnDragLeave();
+  notified_enter_ = false;
+}
+
+int X11Window::PerformDrop() {
+  WmDropHandler* drop_handler = GetWmDropHandler(*this);
+  if (!drop_handler)
+    return DragDropTypes::DRAG_NONE;
+
+  DCHECK(notified_enter_);
+
+  // The drop data has been supplied on entering the window.  The drop handler
+  // should have it since then.
+  drop_handler->OnDragDrop({});
+  notified_enter_ = false;
+  return drag_operation_;
+}
+
+void X11Window::EndDragLoop() {
+  DCHECK(drag_handler_delegate_);
+  drag_handler_delegate_->OnDragFinished(0);
+  drag_handler_delegate_ = nullptr;
+}
+#endif  // defined(USE_OZONE)
+
+bool X11Window::DispatchDraggingUiEvent(Event* event) {
+#if defined(USE_OZONE)
+  // Drag and drop have a priority over other processing.
+  if (dragging_) {
+    DCHECK(drag_drop_client_);
+
+    switch (event->type()) {
+      case ET_MOUSE_MOVED:
+      case ET_MOUSE_DRAGGED: {
+        drag_handler_delegate_->OnDragLocationChanged(
+            event->AsLocatedEvent()->root_location());
+        drag_drop_client_->HandleMouseMovement(
+            event->AsLocatedEvent()->root_location(),
+            event->AsMouseEvent()->flags(),
+            event->AsMouseEvent()->time_stamp());
+        return true;
+      }
+      case ET_MOUSE_RELEASED:
+        if (!event->AsMouseEvent()->IsLeftMouseButton())
+          break;
+        // Assume that drags are being done with the left mouse button. Only
+        // break the drag if the left mouse button was released.
+        drag_drop_client_->HandleMouseReleased();
+        dragging_ = false;
+        ReleaseCapture();
+        return true;
+      case ET_KEY_PRESSED:
+        if (event->AsKeyEvent()->key_code() != VKEY_ESCAPE)
+          break;
+        EndMoveLoop();
+        drag_drop_client_->HandleMoveLoopEnded();
+        dragging_ = false;
+        ReleaseCapture();
+        return true;
+      default:
+        break;
+    }
+  }
+#endif  // defined(USE_OZONE)
+  return false;
+}
+
 gfx::Size X11Window::AdjustSizeForDisplay(
     const gfx::Size& requested_size_in_pixels) {
 #if defined(OS_CHROMEOS)
@@ -796,7 +957,7 @@
 void X11Window::ConvertEventLocationToTargetLocation(
     const gfx::Rect& target_window_bounds,
     const gfx::Rect& current_window_bounds,
-    ui::LocatedEvent* located_event) {
+    LocatedEvent* located_event) {
   // TODO(msisov): for ozone, we need to access PlatformScreen instead and get
   // the displays.
   auto* display = display::Screen::GetScreen();
diff --git a/ui/platform_window/x11/x11_window.h b/ui/platform_window/x11/x11_window.h
index 378512c..b46a4bd 100644
--- a/ui/platform_window/x11/x11_window.h
+++ b/ui/platform_window/x11/x11_window.h
@@ -17,8 +17,14 @@
 #include "ui/platform_window/platform_window_init_properties.h"
 #include "ui/platform_window/x11/x11_window_export.h"
 
+#if defined(USE_OZONE)
+#include "ui/base/x/x11_drag_drop_client.h"
+#include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
+#endif
+
 namespace ui {
 
+class PlatformWindowDelegate;
 class X11ExtensionDelegate;
 class X11DesktopWindowMoveClient;
 class LocatedEvent;
@@ -44,6 +50,10 @@
                                     public XEventDispatcher,
                                     public WorkspaceExtension,
                                     public X11Extension,
+#if defined(USE_OZONE)
+                                    public WmDragHandler,
+                                    public XDragDropClient::Delegate,
+#endif
                                     public WmMoveLoopHandler {
  public:
   explicit X11Window(PlatformWindowDelegate* platform_window_delegate);
@@ -168,6 +178,25 @@
   bool RunMoveLoop(const gfx::Vector2d& drag_offset) override;
   void EndMoveLoop() override;
 
+#if defined(USE_OZONE)
+  // WmDragHandler
+  void StartDrag(const ui::OSExchangeData& data,
+                 int operation,
+                 gfx::NativeCursor cursor,
+                 WmDragHandler::Delegate* delegate) override;
+
+  // ui::XDragDropClient::Delegate
+  std::unique_ptr<ui::XTopmostWindowFinder> CreateWindowFinder() override;
+  int UpdateDrag(const gfx::Point& screen_point) override;
+  void UpdateCursor(
+      ui::DragDropTypes::DragOperation negotiated_operation) override;
+  void OnBeginForeignDrag(XID window) override;
+  void OnEndForeignDrag() override;
+  void OnBeforeDragLeave() override;
+  int PerformDrop() override;
+  void EndDragLoop() override;
+#endif  // defined(USE_OZONE)
+
   // Handles |xevent| as a Atk Key Event
   bool HandleAsAtkEvent(XEvent* xevent);
 
@@ -211,6 +240,19 @@
 
   std::unique_ptr<X11DesktopWindowMoveClient> x11_window_move_client_;
 
+#if defined(USE_OZONE)
+  // True while the drag initiated in this window is in progress.
+  bool dragging_ = false;
+  // Whether the drop handler has notified that the drag has entered.
+  bool notified_enter_ = false;
+  // Keeps the last negotiated operation returned by the drop handler.
+  int drag_operation_ = 0;
+
+  // Handles XDND events going through this window.
+  std::unique_ptr<XDragDropClient> drag_drop_client_;
+  WmDragHandler::Delegate* drag_handler_delegate_ = nullptr;
+#endif  // defined(USE_OZONE)
+
   DISALLOW_COPY_AND_ASSIGN(X11Window);
 };
 
diff --git a/ui/views/controls/button/button_controller.cc b/ui/views/controls/button/button_controller.cc
index 3278b27..f639cf9 100644
--- a/ui/views/controls/button/button_controller.cc
+++ b/ui/views/controls/button/button_controller.cc
@@ -116,6 +116,9 @@
 }
 
 void ButtonController::OnGestureEvent(ui::GestureEvent* event) {
+  if (button_->state() == Button::STATE_DISABLED)
+    return;
+
   if (event->type() == ui::ET_GESTURE_TAP &&
       button_controller_delegate_->IsTriggerableEvent(*event)) {
     // A GESTURE_END event is issued immediately after ET_GESTURE_TAP and will
diff --git a/ui/views/controls/button/button_unittest.cc b/ui/views/controls/button/button_unittest.cc
index 6bfb957..a01120c8 100644
--- a/ui/views/controls/button/button_unittest.cc
+++ b/ui/views/controls/button/button_unittest.cc
@@ -7,6 +7,8 @@
 #include <memory>
 #include <utility>
 
+#include "base/bind.h"
+#include "base/callback_forward.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
@@ -80,6 +82,9 @@
 
   void ButtonPressed(Button* sender, const ui::Event& event) override {
     pressed_ = true;
+
+    if (!on_button_pressed_handler_.is_null())
+      on_button_pressed_handler_.Run();
   }
 
   void OnClickCanceled(const ui::Event& event) override { canceled_ = true; }
@@ -103,6 +108,10 @@
     custom_key_click_action_ = custom_key_click_action;
   }
 
+  void set_on_button_pressed_handler(const base::RepeatingClosure& callback) {
+    on_button_pressed_handler_ = callback;
+  }
+
   void Reset() {
     pressed_ = false;
     canceled_ = false;
@@ -120,6 +129,9 @@
 
   KeyClickAction custom_key_click_action_ = KeyClickAction::kNone;
 
+  // If available, will be triggered when the button is pressed.
+  base::RepeatingClosure on_button_pressed_handler_;
+
   DISALLOW_COPY_AND_ASSIGN(TestButton);
 };
 
@@ -420,6 +432,18 @@
   EXPECT_EQ(Button::STATE_NORMAL, button()->state());
 }
 
+// Tests that if the button was disabled in its button press handler, gesture
+// events will not revert the disabled state back to normal.
+// https://crbug.com/1084241.
+TEST_F(ButtonTest, GestureEventsRespectDisabledState) {
+  button()->set_on_button_pressed_handler(base::BindRepeating(
+      [](TestButton* button) { button->SetEnabled(false); }, button()));
+
+  EXPECT_EQ(Button::STATE_NORMAL, button()->state());
+  event_generator()->GestureTapAt(button()->GetBoundsInScreen().CenterPoint());
+  EXPECT_EQ(Button::STATE_DISABLED, button()->state());
+}
+
 #endif  // !defined(OS_MACOSX) || defined(USE_AURA)
 
 // Ensure subclasses of Button are correctly recognized as Button.
diff --git a/ui/views/controls/editable_combobox/editable_combobox.cc b/ui/views/controls/editable_combobox/editable_combobox.cc
index 01b3a3f..2f752b8 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -37,7 +37,6 @@
 #include "ui/gfx/range/range.h"
 #include "ui/gfx/render_text.h"
 #include "ui/gfx/scoped_canvas.h"
-#include "ui/native_theme/native_theme.h"
 #include "ui/views/animation/flood_fill_ink_drop_ripple.h"
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/animation/ink_drop_host_view.h"
@@ -65,8 +64,7 @@
 
 class Arrow : public Button {
  public:
-  Arrow(const SkColor color, ButtonListener* listener)
-      : Button(listener), color_(color) {
+  explicit Arrow(ButtonListener* listener) : Button(listener) {
     // Similar to Combobox's TransparentButton.
     SetFocusBehavior(FocusBehavior::NEVER);
     button_controller()->set_notify_action(
@@ -93,8 +91,7 @@
   std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override {
     return std::make_unique<views::FloodFillInkDropRipple>(
         size(), GetInkDropCenterBasedOnLastEvent(),
-        GetNativeTheme()->GetSystemColor(
-            ui::NativeTheme::kColorId_LabelEnabledColor),
+        style::GetColor(*this, style::CONTEXT_TEXTFIELD, style::STYLE_PRIMARY),
         ink_drop_visible_opacity());
   }
 
@@ -104,7 +101,11 @@
     canvas->ClipRect(GetContentsBounds());
     gfx::Rect arrow_bounds = GetLocalBounds();
     arrow_bounds.ClampToCenteredSize(ComboboxArrowSize());
-    PaintComboboxArrow(color_, arrow_bounds, canvas);
+    // Make sure the arrow use the same color as the text in the combobox.
+    PaintComboboxArrow(style::GetColor(*this, style::CONTEXT_TEXTFIELD,
+                                       GetEnabled() ? style::STYLE_PRIMARY
+                                                    : style::STYLE_DISABLED),
+                       arrow_bounds, canvas);
   }
 
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
@@ -115,8 +116,6 @@
       node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kOpen);
   }
 
-  const SkColor color_;
-
   DISALLOW_COPY_AND_ASSIGN(Arrow);
 };
 
@@ -334,8 +333,7 @@
     textfield_->SetExtraInsets(gfx::Insets(
         /*top=*/0, /*left=*/0, /*bottom=*/0,
         /*right=*/kComboboxArrowContainerWidth - kComboboxArrowPaddingWidth));
-    arrow_ = new Arrow(textfield_->GetTextColor(), this);
-    AddChildView(arrow_);
+    arrow_ = AddChildView(std::make_unique<Arrow>(this));
   }
   SetLayoutManager(std::make_unique<views::FillLayout>());
 }
@@ -401,11 +399,6 @@
   }
 }
 
-void EditableCombobox::OnThemeChanged() {
-  View::OnThemeChanged();
-  textfield_->OnThemeChanged();
-}
-
 void EditableCombobox::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ax::mojom::Role::kComboBoxGrouping;
 
diff --git a/ui/views/controls/editable_combobox/editable_combobox.h b/ui/views/controls/editable_combobox/editable_combobox.h
index 438d673..e4a0d3c 100644
--- a/ui/views/controls/editable_combobox/editable_combobox.h
+++ b/ui/views/controls/editable_combobox/editable_combobox.h
@@ -124,7 +124,6 @@
 
   // Overridden from View:
   void Layout() override;
-  void OnThemeChanged() override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void RequestFocus() override;
   bool GetNeedsNotificationWhenVisibleBoundsChange() const override;
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h
index 5fab7290..1bc7e68e 100644
--- a/ui/views/controls/menu/menu_controller.h
+++ b/ui/views/controls/menu/menu_controller.h
@@ -125,6 +125,10 @@
   // WARNING: this may be NULL.
   Widget* owner() { return owner_; }
 
+  // Gets the most-current selected menu item, if any, including if the
+  // selection has not been committed yet.
+  views::MenuItemView* GetSelectedMenuItem() { return pending_state_.item; }
+
   // Get the anchor position which is used to show this menu.
   MenuAnchorPosition GetAnchorPosition() { return state_.anchor; }
 
diff --git a/ui/views/examples/examples_window.cc b/ui/views/examples/examples_window.cc
index b35cb1034..c8cb0f2 100644
--- a/ui/views/examples/examples_window.cc
+++ b/ui/views/examples/examples_window.cc
@@ -114,6 +114,8 @@
  public:
   ExamplesWindowContents(base::OnceClosure on_close, ExampleVector examples)
       : on_close_(std::move(on_close)) {
+    SetHasWindowSizeControls(true);
+
     auto combobox_model = std::make_unique<ComboboxModelExampleList>();
     combobox_model_ = combobox_model.get();
     combobox_model_->SetExamples(std::move(examples));
@@ -161,9 +163,6 @@
 
  private:
   // WidgetDelegateView:
-  bool CanResize() const override { return true; }
-  bool CanMaximize() const override { return true; }
-  bool CanMinimize() const override { return true; }
   base::string16 GetWindowTitle() const override {
     return base::ASCIIToUTF16("Views Examples");
   }
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
index 3ee330f3..68db681 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -426,7 +426,7 @@
   return drag_operation;
 }
 
-void DesktopDragDropClientAuraX11::EndMoveLoop() {
+void DesktopDragDropClientAuraX11::EndDragLoop() {
   move_loop_->EndMoveLoop();
 }
 
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
index a06220b..4d791c95 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
@@ -122,7 +122,7 @@
   void OnEndForeignDrag() override;
   void OnBeforeDragLeave() override;
   int PerformDrop() override;
-  void EndMoveLoop() override;
+  void EndDragLoop() override;
 
   // A nested run loop that notifies this object of events through the
   // ui::X11MoveLoopDelegate interface.
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
index 51cc07f5..3e259b3 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
@@ -21,9 +21,13 @@
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/drop_target_event.h"
+#include "ui/base/layout.h"
+#include "ui/display/screen.h"
 #include "ui/platform_window/platform_window_delegate.h"
 #include "ui/platform_window/platform_window_handler/wm_drag_handler.h"
+#include "ui/views/controls/image_view.h"
 #include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
+#include "ui/views/widget/widget.h"
 
 namespace views {
 
@@ -36,8 +40,64 @@
   return root_window->GetEventHandlerForPoint(root_location);
 }
 
+// The minimum alpha required so we would treat the pixel as visible.
+constexpr uint32_t kMinAlpha = 32;
+
+// Returns true if |image| has any visible regions (defined as having a pixel
+// with alpha > |kMinAlpha|).
+bool IsValidDragImage(const gfx::ImageSkia& image) {
+  if (image.isNull())
+    return false;
+
+  // Because we need a GL context per window, we do a quick check so that we
+  // don't make another context if the window would just be displaying a mostly
+  // transparent image.
+  const SkBitmap* in_bitmap = image.bitmap();
+  for (int y = 0; y < in_bitmap->height(); ++y) {
+    uint32_t* in_row = in_bitmap->getAddr32(0, y);
+
+    for (int x = 0; x < in_bitmap->width(); ++x) {
+      if (SkColorGetA(in_row[x]) > kMinAlpha)
+        return true;
+    }
+  }
+
+  return false;
+}
+
+std::unique_ptr<views::Widget> CreateDragWidget(
+    const gfx::Point& root_location,
+    const gfx::ImageSkia& image,
+    const gfx::Vector2d& drag_widget_offset) {
+  auto widget = std::make_unique<views::Widget>();
+  views::Widget::InitParams params(views::Widget::InitParams::TYPE_DRAG);
+  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+  params.accept_events = false;
+
+  gfx::Point location = root_location - drag_widget_offset;
+  params.bounds = gfx::Rect(location, image.size());
+  widget->set_focus_on_creation(false);
+  widget->set_frame_type(views::Widget::FrameType::kForceNative);
+  widget->Init(std::move(params));
+  widget->GetNativeWindow()->SetName("DragWindow");
+
+  std::unique_ptr<views::ImageView> image_view =
+      std::make_unique<views::ImageView>();
+  image_view->SetImage(image);
+  widget->SetContentsView(std::move(image_view));
+  widget->Show();
+  widget->GetNativeWindow()->layer()->SetFillsBoundsOpaquely(false);
+  widget->StackAtTop();
+
+  return widget;
+}
+
 }  // namespace
 
+DesktopDragDropClientOzone::DragContext::DragContext() = default;
+
+DesktopDragDropClientOzone::DragContext::~DragContext() = default;
+
 DesktopDragDropClientOzone::DesktopDragDropClientOzone(
     aura::Window* root_window,
     views::DesktopNativeCursorManager* cursor_manager,
@@ -49,7 +109,7 @@
 DesktopDragDropClientOzone::~DesktopDragDropClientOzone() {
   ResetDragDropTarget();
 
-  if (in_move_loop_)
+  if (IsDragDropInProgress())
     DragCancel();
 }
 
@@ -63,9 +123,11 @@
   if (!drag_handler_)
     return ui::DragDropTypes::DragOperation::DRAG_NONE;
 
-  DCHECK(!in_move_loop_);
+  DCHECK(!drag_context_);
+  drag_context_ = std::make_unique<DragContext>();
+
   base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
-  quit_closure_ = run_loop.QuitClosure();
+  drag_context_->quit_closure = run_loop.QuitClosure();
 
   // Chrome expects starting drag and drop to release capture.
   aura::Window* capture_window =
@@ -83,15 +145,22 @@
         ui::mojom::CursorType::kGrabbing));
   }
 
-  drag_handler_->StartDrag(
-      *data.get(), operation, cursor_client->GetCursor(),
-      base::BindOnce(&DesktopDragDropClientOzone::OnDragSessionClosed,
-                     base::Unretained(this)));
-  in_move_loop_ = true;
+  const auto& provider = data->provider();
+  gfx::ImageSkia drag_image = provider.GetDragImage();
+  if (IsValidDragImage(drag_image)) {
+    drag_context_->size = drag_image.size();
+    drag_context_->offset = provider.GetDragImageOffset();
+    drag_context_->widget =
+        CreateDragWidget(root_location, drag_image, drag_context_->offset);
+  }
+
+  drag_handler_->StartDrag(*data.get(), operation, cursor_client->GetCursor(),
+                           this);
   run_loop.Run();
 
   if (cursor_client)
     cursor_client->SetCursor(initial_cursor);
+  drag_context_.reset();
 
   return drag_operation_;
 }
@@ -101,7 +170,7 @@
 }
 
 bool DesktopDragDropClientOzone::IsDragDropInProgress() {
-  return in_move_loop_;
+  return bool(drag_context_) && bool(drag_context_->quit_closure);
 }
 
 void DesktopDragDropClientOzone::AddObserver(
@@ -193,16 +262,35 @@
   drag_drop_delegate_ = nullptr;
 }
 
-void DesktopDragDropClientOzone::OnDragSessionClosed(int dnd_action) {
+void DesktopDragDropClientOzone::OnDragLocationChanged(
+    const gfx::Point& screen_point_px) {
+  DCHECK(drag_context_);
+
+  if (!drag_context_->widget)
+    return;
+
+  const bool dispatch_mouse_event = !drag_context_->last_screen_location_px;
+  drag_context_->last_screen_location_px = screen_point_px;
+  if (dispatch_mouse_event) {
+    // Post a task to dispatch mouse movement event when control returns to the
+    // message loop. This allows smoother dragging since the events are
+    // dispatched without waiting for the drag widget updates.
+    base::ThreadTaskRunnerHandle::Get()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&DesktopDragDropClientOzone::UpdateDragWidgetLocation,
+                       weak_factory_.GetWeakPtr()));
+  }
+}
+
+void DesktopDragDropClientOzone::OnDragFinished(int dnd_action) {
   drag_operation_ = dnd_action;
   QuitRunLoop();
 }
 
 void DesktopDragDropClientOzone::QuitRunLoop() {
-  in_move_loop_ = false;
-  if (quit_closure_.is_null())
+  if (!drag_context_->quit_closure)
     return;
-  std::move(quit_closure_).Run();
+  std::move(drag_context_->quit_closure).Run();
 }
 
 std::unique_ptr<ui::DropTargetEvent>
@@ -240,6 +328,20 @@
   return event;
 }
 
+void DesktopDragDropClientOzone::UpdateDragWidgetLocation() {
+  DCHECK(drag_context_);
+
+  float scale_factor =
+      ui::GetScaleFactorForNativeView(drag_context_->widget->GetNativeWindow());
+  gfx::Point scaled_point = gfx::ScaleToRoundedPoint(
+      *drag_context_->last_screen_location_px, 1.f / scale_factor);
+  drag_context_->widget->SetBounds(
+      gfx::Rect(scaled_point - drag_context_->offset, drag_context_->size));
+  drag_context_->widget->StackAtTop();
+
+  drag_context_->last_screen_location_px.reset();
+}
+
 void DesktopDragDropClientOzone::ResetDragDropTarget() {
   if (drag_drop_delegate_) {
     drag_drop_delegate_->OnDragExited();
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
index 44dc34e..03a73a9 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/callback.h"
+#include "base/memory/weak_ptr.h"
 #include "ui/aura/client/drag_drop_client.h"
 #include "ui/aura/window_observer.h"
 #include "ui/base/cursor/cursor.h"
@@ -30,9 +31,11 @@
 
 namespace views {
 class DesktopNativeCursorManager;
+class Widget;
 
 class VIEWS_EXPORT DesktopDragDropClientOzone
     : public aura::client::DragDropClient,
+      public ui::WmDragHandler::Delegate,
       public ui::WmDropHandler,
       public aura::WindowObserver {
  public:
@@ -44,6 +47,33 @@
  private:
   friend class DesktopDragDropClientOzoneTest;
 
+  // Holds data related to the drag operation started by this client.
+  struct DragContext {
+    DragContext();
+    ~DragContext();
+
+    // Exits the drag loop.
+    base::OnceClosure quit_closure;
+
+    // Widget that the user drags around.  May be nullptr.
+    std::unique_ptr<Widget> widget;
+
+    // The size of drag image.
+    gfx::Size size;
+
+    // The offset of |drag_widget_| relative to the mouse position.
+    gfx::Vector2d offset;
+
+    // The last received drag location.  The drag widget is moved asynchronously
+    // so its position is updated when the UI thread has time for that.  When
+    // the first change to the location happens, a call to UpdateDragWidget()
+    // is posted, and this location is set.  The location can be updated a few
+    // more times until the posted task is executed, but no more than a single
+    // call to UpdateDragWidget() is scheduled at any time; this optional is set
+    // means that the task is scheduled.
+    base::Optional<gfx::Point> last_screen_location_px;
+  };
+
   // aura::client::DragDropClient
   int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
                        aura::Window* root_window,
@@ -67,7 +97,10 @@
   // aura::WindowObserver
   void OnWindowDestroyed(aura::Window* window) override;
 
-  void OnDragSessionClosed(int operation);
+  // ui::WmDragHandler::Delegate
+  void OnDragLocationChanged(const gfx::Point& screen_point_px) override;
+  void OnDragFinished(int operation) override;
+
   void QuitRunLoop();
 
   // Returns a DropTargetEvent to be passed to the DragDropDelegate.
@@ -78,6 +111,12 @@
   std::unique_ptr<ui::DropTargetEvent> UpdateTargetAndCreateDropEvent(
       const gfx::PointF& point);
 
+  // Updates |drag_drop_delegate_| along with |window|.
+  void UpdateDragDropDelegate(aura::Window* window);
+
+  // Updates |drag_widget_| so it is aligned with the last drag location.
+  void UpdateDragWidgetLocation();
+
   // Resets |drag_drop_delegate_|.  Calls OnDragExited() before resetting.
   void ResetDragDropTarget();
 
@@ -95,20 +134,16 @@
   // The data to be delivered through the drag and drop.
   std::unique_ptr<ui::OSExchangeData> data_to_drop_;
 
-  // The most recent native coordinates of a drag.
+  // The most recent native coordinates of an incoming drag.  Updated while
+  // the mouse is moved, and used at dropping.
   gfx::PointF last_drag_point_;
 
-  // Cursor in use prior to the move loop starting. Restored when the move loop
-  // quits.
-  gfx::NativeCursor initial_cursor_;
-
-  base::OnceClosure quit_closure_;
-
   // The operation bitfield.
   int drag_operation_ = 0;
 
-  //  The flag that controls whether it has a nested run loop.
-  bool in_move_loop_ = false;
+  std::unique_ptr<DragContext> drag_context_;
+
+  base::WeakPtrFactory<DesktopDragDropClientOzone> weak_factory_{this};
 
   DISALLOW_COPY_AND_ASSIGN(DesktopDragDropClientOzone);
 };
diff --git a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
index 04464c0..cfb7bcc 100644
--- a/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
@@ -66,8 +66,8 @@
   void StartDrag(const OSExchangeData& data,
                  int operation,
                  gfx::NativeCursor cursor,
-                 base::OnceCallback<void(int)> callback) override {
-    drag_closed_callback_ = std::move(callback);
+                 WmDragHandler::Delegate* delegate) override {
+    drag_handler_delegate_ = delegate;
     source_data_ = std::make_unique<OSExchangeData>(data.provider().Clone());
     base::ThreadTaskRunnerHandle::Get()->PostTask(
         FROM_HERE,
@@ -107,7 +107,7 @@
   }
 
   void CloseDrag(uint32_t dnd_action) {
-    std::move(drag_closed_callback_).Run(dnd_action);
+    drag_handler_delegate_->OnDragFinished(dnd_action);
   }
 
   void ProcessDrag(std::unique_ptr<OSExchangeData> data, int operation) {
@@ -119,7 +119,7 @@
   }
 
  private:
-  base::OnceCallback<void(int)> drag_closed_callback_;
+  WmDragHandler::Delegate* drag_handler_delegate_ = nullptr;
   std::unique_ptr<ui::OSExchangeData> source_data_;
 
   DISALLOW_COPY_AND_ASSIGN(FakePlatformWindow);
diff --git a/ui/views/widget/native_widget_aura_unittest.cc b/ui/views/widget/native_widget_aura_unittest.cc
index 02c61ee..a0a3fb4 100644
--- a/ui/views/widget/native_widget_aura_unittest.cc
+++ b/ui/views/widget/native_widget_aura_unittest.cc
@@ -318,14 +318,13 @@
 
 class PropertyTestWidgetDelegate : public WidgetDelegate {
  public:
-  explicit PropertyTestWidgetDelegate(Widget* widget) : widget_(widget) {}
+  explicit PropertyTestWidgetDelegate(Widget* widget) : widget_(widget) {
+    SetHasWindowSizeControls(true);
+  }
   ~PropertyTestWidgetDelegate() override = default;
 
  private:
   // WidgetDelegate:
-  bool CanMaximize() const override { return true; }
-  bool CanMinimize() const override { return true; }
-  bool CanResize() const override { return true; }
   void DeleteDelegate() override { delete this; }
   Widget* GetWidget() override { return widget_; }
   const Widget* GetWidget() const override { return widget_; }
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 23a35bb2..a06ebe8 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -1162,6 +1162,8 @@
 }
 
 void Widget::OnNativeWidgetMove() {
+  TRACE_EVENT0("ui", "Widget::OnNativeWidgetMove");
+
   widget_delegate_->OnWidgetMove();
   NotifyCaretBoundsChanged(GetInputMethod());
 
@@ -1170,6 +1172,8 @@
 }
 
 void Widget::OnNativeWidgetSizeChanged(const gfx::Size& new_size) {
+  TRACE_EVENT0("ui", "Widget::OnNativeWidgetSizeChanged");
+
   View* root = GetRootView();
   if (root)
     root->SetSize(new_size);
@@ -1229,6 +1233,8 @@
 //                   RootView from anywhere in Widget. Use
 //                   SendEventToSink() instead. See crbug.com/348087.
 void Widget::OnMouseEvent(ui::MouseEvent* event) {
+  TRACE_EVENT0("ui", "Widget::OnMouseEvent");
+
   View* root_view = GetRootView();
   switch (event->type()) {
     case ui::ET_MOUSE_PRESSED: {
@@ -1472,6 +1478,8 @@
 // Widget, ui::NativeThemeObserver implementation:
 
 void Widget::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
+  TRACE_EVENT0("ui", "Widget::OnNativeThemeUpdated");
+
   DCHECK(observer_manager_.IsObserving(observed_theme));
 
 #if defined(OS_MACOSX) || defined(OS_WIN)
diff --git a/ui/views/widget/widget_delegate.cc b/ui/views/widget/widget_delegate.cc
index 477208d..bd26a66 100644
--- a/ui/views/widget/widget_delegate.cc
+++ b/ui/views/widget/widget_delegate.cc
@@ -282,6 +282,12 @@
 }
 #endif
 
+void WidgetDelegate::SetHasWindowSizeControls(bool has_controls) {
+  SetCanMaximize(has_controls);
+  SetCanMinimize(has_controls);
+  SetCanResize(has_controls);
+}
+
 void WidgetDelegate::RegisterWindowWillCloseCallback(
     base::OnceClosure callback) {
   window_will_close_callbacks_.emplace_back(std::move(callback));
diff --git a/ui/views/widget/widget_delegate.h b/ui/views/widget/widget_delegate.h
index e7160a9..c6b026e 100644
--- a/ui/views/widget/widget_delegate.h
+++ b/ui/views/widget/widget_delegate.h
@@ -79,6 +79,7 @@
   };
 
   WidgetDelegate();
+  virtual ~WidgetDelegate();
 
   // Sets the return value of CanActivate(). Default is true.
   void SetCanActivate(bool can_activate);
@@ -285,6 +286,10 @@
   void SetCenterTitle(bool center_title);
 #endif
 
+  // A convenience wrapper that does all three of SetCanMaximize,
+  // SetCanMinimize, and SetCanResize.
+  void SetHasWindowSizeControls(bool has_controls);
+
   void RegisterWindowWillCloseCallback(base::OnceClosure callback);
   void RegisterWindowClosingCallback(base::OnceClosure callback);
   void RegisterDeleteDelegateCallback(base::OnceClosure callback);
@@ -301,9 +306,6 @@
 
   bool focus_traverses_out() const { return params_.focus_traverses_out; }
 
- protected:
-  virtual ~WidgetDelegate();
-
  private:
   friend class Widget;
 
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 7076b6ba..a47389ee 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -988,6 +988,8 @@
 LRESULT HWNDMessageHandler::OnWndProc(UINT message,
                                       WPARAM w_param,
                                       LPARAM l_param) {
+  TRACE_EVENT1("ui", "HWNDMessageHandler::OnWndProc", "message_id", message);
+
   HWND window = hwnd();
   LRESULT result = 0;
   if (delegate_ && delegate_->PreHandleMSG(message, w_param, l_param, &result))
@@ -1657,6 +1659,8 @@
 
 void HWNDMessageHandler::OnDisplayChange(UINT bits_per_pixel,
                                          const gfx::Size& screen_size) {
+  TRACE_EVENT0("ui", "HWNDMessageHandler::OnDisplayChange");
+
   delegate_->HandleDisplayChange();
   // Force a WM_NCCALCSIZE to occur to ensure that we handle auto hide
   // taskbars correctly.
@@ -1664,8 +1668,10 @@
 }
 
 LRESULT HWNDMessageHandler::OnDwmCompositionChanged(UINT msg,
-                                                    WPARAM w_param,
-                                                    LPARAM l_param) {
+                                                    WPARAM /* w_param */,
+                                                    LPARAM /* l_param */) {
+  TRACE_EVENT0("ui", "HWNDMessageHandler::OnDwmCompositionChanged");
+
   if (!delegate_->HasNonClientView()) {
     SetMsgHandled(FALSE);
     return 0;
@@ -1690,6 +1696,9 @@
   if (LOWORD(w_param) != HIWORD(w_param))
     NOTIMPLEMENTED() << "Received non-square scaling factors";
 
+  TRACE_EVENT1("ui", "HWNDMessageHandler::OnDwmCompositionChanged", "dpi",
+               LOWORD(w_param));
+
   int dpi;
   float scaling_factor;
   if (display::Display::HasForceDeviceScaleFactor()) {
@@ -2726,6 +2735,8 @@
 }
 
 void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
+  TRACE_EVENT0("ui", "HWNDMessageHandler::OnWindowPosChanging");
+
   if (ignore_window_pos_changes_) {
     // If somebody's trying to toggle our visibility, change the nonclient area,
     // change our Z-order, or activate us, we should probably let it go through.
@@ -2877,6 +2888,8 @@
 }
 
 void HWNDMessageHandler::OnWindowPosChanged(WINDOWPOS* window_pos) {
+  TRACE_EVENT0("ui", "HWNDMessageHandler::OnWindowPosChanged");
+
   if (DidClientAreaSizeChange(window_pos))
     ClientAreaSizeChanged();
   if (window_pos->flags & SWP_FRAMECHANGED)
@@ -3301,6 +3314,8 @@
 }
 
 void HWNDMessageHandler::UpdateDwmFrame() {
+  TRACE_EVENT0("ui", "HWNDMessageHandler::UpdateDwmFrame");
+
   gfx::Insets insets;
   if (ui::win::IsAeroGlassEnabled() &&
       delegate_->GetDwmFrameInsetsInPixels(&insets)) {
diff --git a/ui/views/window/custom_frame_view_unittest.cc b/ui/views/window/custom_frame_view_unittest.cc
index d04752c1..37ed1a60 100644
--- a/ui/views/window/custom_frame_view_unittest.cc
+++ b/ui/views/window/custom_frame_view_unittest.cc
@@ -17,33 +17,6 @@
 
 namespace views {
 
-namespace {
-
-// Allows for the control of whether or not the widget can minimize/maximize or
-// not. This can be set after initial setup in order to allow testing of both
-// forms of delegates. By default this can minimize and maximize.
-class MinimizeAndMaximizeStateControlDelegate : public WidgetDelegateView {
- public:
-  MinimizeAndMaximizeStateControlDelegate() = default;
-  ~MinimizeAndMaximizeStateControlDelegate() override = default;
-
-  void set_can_maximize(bool can_maximize) { can_maximize_ = can_maximize; }
-
-  void set_can_minimize(bool can_minimize) { can_minimize_ = can_minimize; }
-
-  // WidgetDelegate:
-  bool CanMaximize() const override { return can_maximize_; }
-  bool CanMinimize() const override { return can_minimize_; }
-
- private:
-  bool can_maximize_ = true;
-  bool can_minimize_ = true;
-
-  DISALLOW_COPY_AND_ASSIGN(MinimizeAndMaximizeStateControlDelegate);
-};
-
-}  // namespace
-
 class CustomFrameViewTest : public ViewsTestBase {
  public:
   CustomFrameViewTest() = default;
@@ -51,11 +24,6 @@
 
   CustomFrameView* custom_frame_view() { return custom_frame_view_; }
 
-  MinimizeAndMaximizeStateControlDelegate*
-  minimize_and_maximize_state_control_delegate() {
-    return minimize_and_maximize_state_control_delegate_;
-  }
-
   Widget* widget() { return widget_; }
 
   // ViewsTestBase:
@@ -90,27 +58,26 @@
       const std::vector<views::FrameButton> trailing_buttons);
 
  private:
+  std::unique_ptr<WidgetDelegate> widget_delegate_;
+
   // Parent container for |custom_frame_view_|
   Widget* widget_;
 
   // Owned by |widget_|
   CustomFrameView* custom_frame_view_;
 
-  // Delegate of |widget_| which controls minimizing and maximizing
-  MinimizeAndMaximizeStateControlDelegate*
-      minimize_and_maximize_state_control_delegate_;
-
   DISALLOW_COPY_AND_ASSIGN(CustomFrameViewTest);
 };
 
 void CustomFrameViewTest::SetUp() {
   ViewsTestBase::SetUp();
 
-  minimize_and_maximize_state_control_delegate_ =
-      new MinimizeAndMaximizeStateControlDelegate;
   widget_ = new Widget;
   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
-  params.delegate = minimize_and_maximize_state_control_delegate_;
+  widget_delegate_ = std::make_unique<WidgetDelegate>();
+  params.delegate = widget_delegate_.get();
+  params.delegate->SetCanMaximize(true);
+  params.delegate->SetCanMinimize(true);
   params.remove_standard_frame = true;
   widget_->Init(std::move(params));
 
@@ -214,9 +181,7 @@
 TEST_F(CustomFrameViewTest, CannotMaximizeHidesButton) {
   Widget* parent = widget();
   CustomFrameView* view = custom_frame_view();
-  MinimizeAndMaximizeStateControlDelegate* delegate =
-      minimize_and_maximize_state_control_delegate();
-  delegate->set_can_maximize(false);
+  widget()->widget_delegate()->SetCanMaximize(false);
 
   view->Init(parent);
   parent->SetBounds(gfx::Rect(0, 0, 300, 100));
@@ -231,9 +196,7 @@
 TEST_F(CustomFrameViewTest, CannotMinimizeHidesButton) {
   Widget* parent = widget();
   CustomFrameView* view = custom_frame_view();
-  MinimizeAndMaximizeStateControlDelegate* delegate =
-      minimize_and_maximize_state_control_delegate();
-  delegate->set_can_minimize(false);
+  widget()->widget_delegate()->SetCanMinimize(false);
 
   view->Init(parent);
   parent->SetBounds(gfx::Rect(0, 0, 300, 100));
diff --git a/ui/webui/resources/cr_elements/cr_input/cr_input.html b/ui/webui/resources/cr_elements/cr_input/cr_input.html
index b8e43fd0..58ec0a3 100644
--- a/ui/webui/resources/cr_elements/cr_input/cr_input.html
+++ b/ui/webui/resources/cr_elements/cr_input/cr_input.html
@@ -13,21 +13,24 @@
     <style include="cr-hidden-style cr-input-style cr-shared-style">
       /*
         A 'suffix' element will be outside the underlined space, while a
-        'prefix' element will be inside the underlined space by default.
+        'inline-prefix' and 'inline-suffix' elements will be inside the
+        underlined space by default.
 
         Regarding cr-input's width:
-        When there's no element in the 'prefix' or 'suffix' slot, setting
-        the width of cr-input as follows will work as expected:
+        When there's no element in the 'inline-prefix', 'inline-suffix' or
+        'suffix' slot, setting the width of cr-input as follows will work as
+        expected:
 
           cr-input {
             width: 200px;
           }
 
-        However, when there's an element in the 'suffix' and/or 'prefix'
-        slot, setting the 'width' will dictate the total width of the input
-        field *plus* the 'prefix' and 'suffix' elements. To set the width
-        of the input field + 'prefix' when a 'suffix' is present, use
-        --cr-input-width.
+        However, when there's an element in the 'suffix', 'inline-suffix' and/or
+        'inline-prefix' slot, setting the 'width' will dictate the total width
+        of the input field *plus* the 'inline-prefix', 'inline-suffix' and
+        'suffix' elements. To set the width of the input field +
+        'inline-prefix' + 'inline-suffix' when a 'suffix' is present,
+        use --cr-input-width.
 
           cr-input {
             --cr-input-width: 200px;
@@ -122,7 +125,7 @@
     <div id="row-container" part="row-container">
       <div id="input-container">
         <div id="inner-input-container">
-          <slot name="prefix"></slot>
+          <slot name="inline-prefix"></slot>
           <!-- Only attributes that are named inconsistently between html and js
               need to use attr$="", such as |tabindex| vs .tabIndex and
               |readonly| vs .readOnly. -->
@@ -136,6 +139,7 @@
               max="[[max]]" min="[[min]]" on-focus="onInputFocus_"
               on-blur="onInputBlur_" on-change="onInputChange_"
               on-keydown="onInputKeydown_" part="input">
+          <slot name="inline-suffix"></slot>
         </div>
         <div id="underline"></div>
       </div>
diff --git a/ui/wm/core/focus_controller_unittest.cc b/ui/wm/core/focus_controller_unittest.cc
index 9bc99863..60e7ad12 100644
--- a/ui/wm/core/focus_controller_unittest.cc
+++ b/ui/wm/core/focus_controller_unittest.cc
@@ -45,8 +45,8 @@
         activation_changed_count_(0),
         focus_changed_count_(0),
         reactivation_count_(0),
-        reactivation_requested_window_(NULL),
-        reactivation_actual_window_(NULL) {}
+        reactivation_requested_window_(nullptr),
+        reactivation_actual_window_(nullptr) {}
   ~FocusNotificationObserver() override {}
 
   void ExpectCounts(int activation_changed_count, int focus_changed_count) {
@@ -367,8 +367,7 @@
 class FocusShiftingActivationObserver : public ActivationChangeObserver {
  public:
   explicit FocusShiftingActivationObserver(aura::Window* activated_window)
-      : activated_window_(activated_window),
-        shift_focus_to_(NULL) {}
+      : activated_window_(activated_window), shift_focus_to_(nullptr) {}
   ~FocusShiftingActivationObserver() override {}
 
   void set_shift_focus_to(aura::Window* shift_focus_to) {
@@ -448,7 +447,7 @@
 // in tests for those FocusRules implementations.
 class TestFocusRules : public BaseFocusRules {
  public:
-  TestFocusRules() : focus_restriction_(NULL) {}
+  TestFocusRules() : focus_restriction_(nullptr) {}
 
   // Restricts focus and activation to this window and its child hierarchy.
   void set_focus_restriction(aura::Window* focus_restriction) {
diff --git a/ui/wm/core/transient_window_manager.cc b/ui/wm/core/transient_window_manager.cc
index 64f74e0e..e5fa6ea 100644
--- a/ui/wm/core/transient_window_manager.cc
+++ b/ui/wm/core/transient_window_manager.cc
@@ -114,8 +114,8 @@
 
 TransientWindowManager::TransientWindowManager(Window* window)
     : window_(window),
-      transient_parent_(NULL),
-      stacking_target_(NULL),
+      transient_parent_(nullptr),
+      stacking_target_(nullptr),
       parent_controls_visibility_(false),
       show_on_parent_visible_(false),
       ignore_visibility_changed_event_(false) {
diff --git a/url/url_canon.h b/url/url_canon.h
index 273f056..3aa0648 100644
--- a/url/url_canon.h
+++ b/url/url_canon.h
@@ -28,8 +28,7 @@
 template<typename T>
 class CanonOutputT {
  public:
-  CanonOutputT() : buffer_(NULL), buffer_len_(0), cur_len_(0) {
-  }
+  CanonOutputT() : buffer_(nullptr), buffer_len_(0), cur_len_(0) {}
   virtual ~CanonOutputT() {
   }
 
@@ -698,15 +697,14 @@
   // will make them all NULL, which is no replacement. The caller would then
   // override the components they want to replace.
   URLComponentSource()
-      : scheme(NULL),
-        username(NULL),
-        password(NULL),
-        host(NULL),
-        port(NULL),
-        path(NULL),
-        query(NULL),
-        ref(NULL) {
-  }
+      : scheme(nullptr),
+        username(nullptr),
+        password(nullptr),
+        host(nullptr),
+        port(nullptr),
+        path(nullptr),
+        query(nullptr),
+        ref(nullptr) {}
 
   // Constructor normally used internally to initialize all the components to
   // point to the same spec.
diff --git a/weblayer/BUILD.gn b/weblayer/BUILD.gn
index 968b0da..048ee48 100644
--- a/weblayer/BUILD.gn
+++ b/weblayer/BUILD.gn
@@ -451,6 +451,10 @@
       "browser/new_tab_callback_proxy.h",
       "browser/tab_callback_proxy.cc",
       "browser/tab_callback_proxy.h",
+      "browser/translate_compact_infobar.cc",
+      "browser/translate_compact_infobar.h",
+      "browser/translate_utils.cc",
+      "browser/translate_utils.h",
       "browser/url_bar/page_info_client_impl.cc",
       "browser/url_bar/page_info_client_impl.h",
       "browser/weblayer_factory_impl_android.cc",
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerJUnit4ClassRunner.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerJUnit4ClassRunner.java
index ff0c7bb..a3bea7c5 100644
--- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerJUnit4ClassRunner.java
+++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/WebLayerJUnit4ClassRunner.java
@@ -6,10 +6,7 @@
 
 import org.junit.runners.model.InitializationError;
 
-import org.chromium.base.CommandLineInitUtil;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
-import org.chromium.base.test.BaseTestResult.PreTestHook;
-import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.SkipCheck;
 
 import java.util.List;
@@ -27,21 +24,8 @@
         super(klass);
     }
 
-    /**
-     * Change this static function to add default {@code PreTestHook}s.
-     */
-    @Override
-    protected List<PreTestHook> getPreTestHooks() {
-        return addToList(super.getPreTestHooks(), CommandLineFlags.getRegistrationHook());
-    }
-
     @Override
     protected List<SkipCheck> getSkipChecks() {
         return addToList(super.getSkipChecks(), new MinWebLayerVersionSkipCheck());
     }
-
-    @Override
-    protected void initCommandLineForTest() {
-        CommandLineInitUtil.initCommandLine(CommandLineFlags.getTestCmdLineFile());
-    }
 }
diff --git a/weblayer/browser/cookie_manager_impl.cc b/weblayer/browser/cookie_manager_impl.cc
index 8cb70b3..ae1392cb 100644
--- a/weblayer/browser/cookie_manager_impl.cc
+++ b/weblayer/browser/cookie_manager_impl.cc
@@ -19,9 +19,9 @@
 namespace {
 
 void GetCookieComplete(CookieManager::GetCookieCallback callback,
-                       const net::CookieStatusList& cookies,
-                       const net::CookieStatusList& excluded_cookies) {
-  net::CookieList cookie_list = net::cookie_util::StripStatuses(cookies);
+                       const net::CookieAccessResultList& cookies,
+                       const net::CookieAccessResultList& excluded_cookies) {
+  net::CookieList cookie_list = net::cookie_util::StripAccessResults(cookies);
   std::move(callback).Run(net::CanonicalCookie::BuildCookieLine(cookie_list));
 }
 
diff --git a/weblayer/browser/java/BUILD.gn b/weblayer/browser/java/BUILD.gn
index 36169c73..33ecc9955 100644
--- a/weblayer/browser/java/BUILD.gn
+++ b/weblayer/browser/java/BUILD.gn
@@ -9,11 +9,18 @@
 
 android_resources("weblayer_resources") {
   sources = [
+    "res/drawable/tab_indicator.xml",
+    "res/layout/infobar_translate_compact_content.xml",
+    "res/layout/infobar_translate_tab_content.xml",
     "res/layout/site_settings_layout.xml",
+    "res/layout/translate_menu_item.xml",
+    "res/layout/translate_menu_item_checked.xml",
     "res/layout/weblayer_url_bar.xml",
+    "res/values/colors.xml",
     "res/values/dimens.xml",
     "res/values/ids.xml",
     "res/values/styles.xml",
+    "res/values/styles.xml",
   ]
   custom_package = "org.chromium.weblayer_private"
   deps = [
@@ -25,6 +32,7 @@
     "//components/browser_ui/styles/android:java_resources",
     "//components/page_info/android:java_resources",
     "//components/permissions/android:java_resources",
+    "//third_party/android_deps:com_google_android_material_material_java",
     "//weblayer:components_java_strings",
   ]
 }
@@ -54,6 +62,7 @@
   sources = [
     "//weblayer/browser/controls_visibility_reason.h",
     "//weblayer/browser/infobar_android.h",
+    "//weblayer/browser/translate_utils.h",
     "//weblayer/public/download.h",
     "//weblayer/public/navigation.h",
     "//weblayer/public/new_tab_delegate.h",
@@ -107,6 +116,12 @@
     "org/chromium/weblayer_private/SwipableOverlayView.java",
     "org/chromium/weblayer_private/TabCallbackProxy.java",
     "org/chromium/weblayer_private/TabImpl.java",
+    "org/chromium/weblayer_private/TranslateCompactInfoBar.java",
+    "org/chromium/weblayer_private/TranslateMenu.java",
+    "org/chromium/weblayer_private/TranslateMenuHelper.java",
+    "org/chromium/weblayer_private/TranslateOptions.java",
+    "org/chromium/weblayer_private/TranslateTabContent.java",
+    "org/chromium/weblayer_private/TranslateTabLayout.java",
     "org/chromium/weblayer_private/UrlBarControllerImpl.java",
     "org/chromium/weblayer_private/WebContentsGestureStateTracker.java",
     "org/chromium/weblayer_private/WebLayerAccessibilityUtil.java",
@@ -141,6 +156,7 @@
     "//components/browser_ui/styles/android:java",
     "//components/browser_ui/util/android:java",
     "//components/browser_ui/webshare/android:java",
+    "//components/browser_ui/widget/android:java",
     "//components/content_settings/android:java",
     "//components/crash/android:handler_java",
     "//components/crash/android:java",
@@ -180,6 +196,7 @@
     "//third_party/android_deps:androidx_core_core_java",
     "//third_party/android_deps:androidx_fragment_fragment_java",
     "//third_party/android_deps:androidx_preference_preference_java",
+    "//third_party/android_deps:com_google_android_material_material_java",
     "//third_party/blink/public/mojom:android_mojo_bindings_java",
     "//ui/android:ui_full_java",
     "//ui/android:ui_java",
@@ -259,6 +276,7 @@
     "org/chromium/weblayer_private/ProfileImpl.java",
     "org/chromium/weblayer_private/TabCallbackProxy.java",
     "org/chromium/weblayer_private/TabImpl.java",
+    "org/chromium/weblayer_private/TranslateCompactInfoBar.java",
     "org/chromium/weblayer_private/UrlBarControllerImpl.java",
     "org/chromium/weblayer_private/WebLayerExceptionFilter.java",
     "org/chromium/weblayer_private/WebLayerFactoryImpl.java",
@@ -285,10 +303,12 @@
     "org/chromium/weblayer_private/interfaces/NavigationState.java",
     "org/chromium/weblayer_private/interfaces/NewTabType.java",
     "org/chromium/weblayer_private/interfaces/ObjectWrapper.java",
+    "org/chromium/weblayer_private/interfaces/SettingType.java",
     "org/chromium/weblayer_private/interfaces/SiteSettingsFragmentArgs.java",
     "org/chromium/weblayer_private/interfaces/SiteSettingsIntentHelper.java",
     "org/chromium/weblayer_private/interfaces/StrictModeWorkaround.java",
     "org/chromium/weblayer_private/interfaces/UrlBarOptionsKeys.java",
+    "org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java",
   ]
 
   deps = [ "//third_party/android_deps:androidx_annotation_annotation_java" ]
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java
index 606e768..ba5cc8c 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/ProfileImpl.java
@@ -21,6 +21,7 @@
 import org.chromium.weblayer_private.interfaces.IObjectWrapper;
 import org.chromium.weblayer_private.interfaces.IProfile;
 import org.chromium.weblayer_private.interfaces.ObjectWrapper;
+import org.chromium.weblayer_private.interfaces.SettingType;
 import org.chromium.weblayer_private.interfaces.StrictModeWorkaround;
 
 import java.util.ArrayList;
@@ -206,6 +207,16 @@
         mDownloadNotificationIntents.clear();
     }
 
+    @Override
+    public void setBooleanSetting(@SettingType int type, boolean value) {
+        ProfileImplJni.get().setBooleanSetting(mNativeProfile, type, value);
+    }
+
+    @Override
+    public boolean getBooleanSetting(@SettingType int type) {
+        return ProfileImplJni.get().getBooleanSetting(mNativeProfile, type);
+    }
+
     @NativeMethods
     interface Natives {
         void enumerateAllProfileNames(Callback<String[]> callback);
@@ -219,5 +230,7 @@
         void setDownloadDirectory(long nativeProfileImpl, String directory);
         long getCookieManager(long nativeProfileImpl);
         void ensureBrowserContextInitialized(long nativeProfileImpl);
+        void setBooleanSetting(long nativeProfileImpl, int type, boolean value);
+        boolean getBooleanSetting(long nativeProfileImpl, int type);
     }
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TranslateCompactInfoBar.java b/weblayer/browser/java/org/chromium/weblayer_private/TranslateCompactInfoBar.java
new file mode 100644
index 0000000..ce7fe24
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TranslateCompactInfoBar.java
@@ -0,0 +1,545 @@
+// 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.
+
+package org.chromium.weblayer_private;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.View.OnLayoutChangeListener;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+
+import androidx.core.content.ContextCompat;
+
+import com.google.android.material.tabs.TabLayout;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+import org.chromium.base.annotations.NativeMethods;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.ui.widget.Toast;
+
+/**
+ * Java version of the compact translate infobar.
+ */
+@JNINamespace("weblayer")
+public class TranslateCompactInfoBar extends InfoBar
+        implements TabLayout.OnTabSelectedListener, TranslateMenuHelper.TranslateMenuListener {
+    public static final int TRANSLATING_INFOBAR = 1;
+    public static final int AFTER_TRANSLATING_INFOBAR = 2;
+
+    private static final int SOURCE_TAB_INDEX = 0;
+    private static final int TARGET_TAB_INDEX = 1;
+
+    // Action ID for Snackbar.
+    // Actions performed by clicking on on the overflow menu.
+    public static final int ACTION_OVERFLOW_ALWAYS_TRANSLATE = 0;
+    public static final int ACTION_OVERFLOW_NEVER_SITE = 1;
+    public static final int ACTION_OVERFLOW_NEVER_LANGUAGE = 2;
+    // Actions triggered automatically. (when translation or denied count reaches the threshold.)
+    public static final int ACTION_AUTO_ALWAYS_TRANSLATE = 3;
+    public static final int ACTION_AUTO_NEVER_LANGUAGE = 4;
+
+    private final int mInitialStep;
+    private final int mDefaultTextColor;
+    private final TranslateOptions mOptions;
+
+    private long mNativeTranslateInfoBarPtr;
+    private TranslateTabLayout mTabLayout;
+
+    // Metric to track the total number of translations in a page, including reverts to original.
+    private int mTotalTranslationCount;
+
+    // Histogram names for logging metrics.
+    private static final String INFOBAR_HISTOGRAM_TRANSLATE_LANGUAGE =
+            "Translate.CompactInfobar.Language.Translate";
+    private static final String INFOBAR_HISTOGRAM_MORE_LANGUAGES_LANGUAGE =
+            "Translate.CompactInfobar.Language.MoreLanguages";
+    private static final String INFOBAR_HISTOGRAM_PAGE_NOT_IN_LANGUAGE =
+            "Translate.CompactInfobar.Language.PageNotIn";
+    private static final String INFOBAR_HISTOGRAM_ALWAYS_TRANSLATE_LANGUAGE =
+            "Translate.CompactInfobar.Language.AlwaysTranslate";
+    private static final String INFOBAR_HISTOGRAM_NEVER_TRANSLATE_LANGUAGE =
+            "Translate.CompactInfobar.Language.NeverTranslate";
+    private static final String INFOBAR_HISTOGRAM = "Translate.CompactInfobar.Event";
+    private static final String INFOBAR_HISTOGRAM_TRANSLATION_COUNT =
+            "Translate.CompactInfobar.TranslationsPerPage";
+
+    /**
+     * This is used to back a UMA histogram, so it should be treated as
+     * append-only. The values should not be changed or reused, and
+     * INFOBAR_HISTOGRAM_BOUNDARY should be the last.
+     */
+    private static final int INFOBAR_IMPRESSION = 0;
+    private static final int INFOBAR_TARGET_TAB_TRANSLATE = 1;
+    private static final int INFOBAR_DECLINE = 2;
+    private static final int INFOBAR_OPTIONS = 3;
+    private static final int INFOBAR_MORE_LANGUAGES = 4;
+    private static final int INFOBAR_MORE_LANGUAGES_TRANSLATE = 5;
+    private static final int INFOBAR_PAGE_NOT_IN = 6;
+    private static final int INFOBAR_ALWAYS_TRANSLATE = 7;
+    private static final int INFOBAR_NEVER_TRANSLATE = 8;
+    private static final int INFOBAR_NEVER_TRANSLATE_SITE = 9;
+    private static final int INFOBAR_SCROLL_HIDE = 10;
+    private static final int INFOBAR_SCROLL_SHOW = 11;
+    private static final int INFOBAR_REVERT = 12;
+    private static final int INFOBAR_SNACKBAR_ALWAYS_TRANSLATE_IMPRESSION = 13;
+    private static final int INFOBAR_SNACKBAR_NEVER_TRANSLATE_IMPRESSION = 14;
+    private static final int INFOBAR_SNACKBAR_NEVER_TRANSLATE_SITE_IMPRESSION = 15;
+    private static final int INFOBAR_SNACKBAR_CANCEL_ALWAYS = 16;
+    private static final int INFOBAR_SNACKBAR_CANCEL_NEVER_SITE = 17;
+    private static final int INFOBAR_SNACKBAR_CANCEL_NEVER = 18;
+    private static final int INFOBAR_ALWAYS_TRANSLATE_UNDO = 19;
+    private static final int INFOBAR_CLOSE_DEPRECATED = 20;
+    private static final int INFOBAR_SNACKBAR_AUTO_ALWAYS_IMPRESSION = 21;
+    private static final int INFOBAR_SNACKBAR_AUTO_NEVER_IMPRESSION = 22;
+    private static final int INFOBAR_SNACKBAR_CANCEL_AUTO_ALWAYS = 23;
+    private static final int INFOBAR_SNACKBAR_CANCEL_AUTO_NEVER = 24;
+    private static final int INFOBAR_HISTOGRAM_BOUNDARY = 25;
+
+    // Need 2 instances of TranslateMenuHelper to prevent a race condition bug which happens when
+    // showing language menu after dismissing overflow menu.
+    private TranslateMenuHelper mOverflowMenuHelper;
+    private TranslateMenuHelper mLanguageMenuHelper;
+
+    private ImageButton mMenuButton;
+    private InfoBarCompactLayout mParent;
+
+    private boolean mMenuExpanded;
+    private boolean mIsFirstLayout = true;
+    private boolean mUserInteracted;
+
+    @CalledByNative
+    private static InfoBar create(TabImpl tab, int initialStep, String sourceLanguageCode,
+            String targetLanguageCode, boolean alwaysTranslate, boolean triggeredFromMenu,
+            String[] languages, String[] languageCodes, int[] hashCodes, int tabTextColor) {
+        recordInfobarAction(INFOBAR_IMPRESSION);
+        return new TranslateCompactInfoBar(initialStep, sourceLanguageCode, targetLanguageCode,
+                alwaysTranslate, triggeredFromMenu, languages, languageCodes, hashCodes,
+                tabTextColor);
+    }
+
+    TranslateCompactInfoBar(int initialStep, String sourceLanguageCode, String targetLanguageCode,
+            boolean alwaysTranslate, boolean triggeredFromMenu, String[] languages,
+            String[] languageCodes, int[] hashCodes, int tabTextColor) {
+        // TODO(crbug.com/1025620): Add support for icons to WebLayer's infobars and supply
+        // translate icon.
+        super(0, 0, null, null);
+
+        mInitialStep = initialStep;
+        mDefaultTextColor = tabTextColor;
+        mOptions = TranslateOptions.create(sourceLanguageCode, targetLanguageCode, languages,
+                languageCodes, alwaysTranslate, triggeredFromMenu, hashCodes);
+    }
+
+    @Override
+    protected boolean usesCompactLayout() {
+        return true;
+    }
+
+    @Override
+    protected void createCompactLayoutContent(InfoBarCompactLayout parent) {
+        LinearLayout content =
+                (LinearLayout) LayoutInflater.from(getContext())
+                        .inflate(R.layout.infobar_translate_compact_content, parent, false);
+
+        // When parent tab is being switched out (view detached), dismiss all menus and snackbars.
+        content.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+            @Override
+            public void onViewAttachedToWindow(View view) {}
+
+            @Override
+            public void onViewDetachedFromWindow(View view) {
+                dismissMenusAndSnackbars();
+            }
+        });
+
+        mTabLayout = (TranslateTabLayout) content.findViewById(R.id.translate_infobar_tabs);
+        if (mDefaultTextColor > 0) {
+            mTabLayout.setTabTextColors(
+                    ContextCompat.getColor(getContext(), R.color.default_text_color),
+                    ContextCompat.getColor(getContext(), R.color.tab_layout_selected_tab_color));
+        }
+        mTabLayout.addTabs(mOptions.sourceLanguageName(), mOptions.targetLanguageName());
+
+        if (mInitialStep == TRANSLATING_INFOBAR) {
+            // Set translating status in the beginning for pages translated automatically.
+            mTabLayout.getTabAt(TARGET_TAB_INDEX).select();
+            mTabLayout.showProgressBarOnTab(TARGET_TAB_INDEX);
+            mUserInteracted = true;
+        } else if (mInitialStep == AFTER_TRANSLATING_INFOBAR) {
+            // Focus on target tab since we are after translation.
+            mTabLayout.getTabAt(TARGET_TAB_INDEX).select();
+        }
+
+        mTabLayout.addOnTabSelectedListener(this);
+
+        // Dismiss all menus and end scrolling animation when there is layout changed.
+        mTabLayout.addOnLayoutChangeListener(new OnLayoutChangeListener() {
+            @Override
+            public void onLayoutChange(View v, int left, int top, int right, int bottom,
+                    int oldLeft, int oldTop, int oldRight, int oldBottom) {
+                if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
+                    // Dismiss all menus to prevent menu misplacement.
+                    dismissMenus();
+
+                    if (mIsFirstLayout) {
+                        // Scrolls to the end to make sure the target language tab is visible when
+                        // language tabs is too long.
+                        mTabLayout.startScrollingAnimationIfNeeded();
+                        mIsFirstLayout = false;
+                        return;
+                    }
+
+                    // End scrolling animation when layout changed.
+                    mTabLayout.endScrollingAnimationIfPlaying();
+                }
+            }
+        });
+
+        mMenuButton = content.findViewById(R.id.translate_infobar_menu_button);
+        mMenuButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                mTabLayout.endScrollingAnimationIfPlaying();
+                recordInfobarAction(INFOBAR_OPTIONS);
+                initMenuHelper(TranslateMenu.MENU_OVERFLOW);
+                mOverflowMenuHelper.show(TranslateMenu.MENU_OVERFLOW, getParentWidth());
+                mMenuExpanded = true;
+            }
+        });
+
+        parent.addContent(content, 1.0f);
+        mParent = parent;
+    }
+
+    private void initMenuHelper(int menuType) {
+        boolean isIncognito = TranslateCompactInfoBarJni.get().isIncognito(
+                mNativeTranslateInfoBarPtr, TranslateCompactInfoBar.this);
+        switch (menuType) {
+            case TranslateMenu.MENU_OVERFLOW:
+                if (mOverflowMenuHelper == null) {
+                    mOverflowMenuHelper = new TranslateMenuHelper(
+                            getContext(), mMenuButton, mOptions, this, isIncognito);
+                }
+                return;
+            case TranslateMenu.MENU_TARGET_LANGUAGE:
+            case TranslateMenu.MENU_SOURCE_LANGUAGE:
+                if (mLanguageMenuHelper == null) {
+                    mLanguageMenuHelper = new TranslateMenuHelper(
+                            getContext(), mMenuButton, mOptions, this, isIncognito);
+                }
+                return;
+            default:
+                assert false : "Unsupported Menu Item Id";
+        }
+    }
+
+    private void startTranslating(int tabPosition) {
+        if (TARGET_TAB_INDEX == tabPosition) {
+            // Already on the target tab.
+            mTabLayout.showProgressBarOnTab(TARGET_TAB_INDEX);
+            onButtonClicked(ActionType.TRANSLATE);
+            mUserInteracted = true;
+        } else {
+            mTabLayout.getTabAt(TARGET_TAB_INDEX).select();
+        }
+    }
+
+    @CalledByNative
+    private void onPageTranslated(int errorType) {
+        incrementAndRecordTranslationsPerPageCount();
+        if (mTabLayout != null) {
+            mTabLayout.hideProgressBar();
+            if (errorType != 0) {
+                Toast.makeText(getContext(), R.string.translate_infobar_error, Toast.LENGTH_SHORT)
+                        .show();
+                // Disable OnTabSelectedListener then revert selection.
+                mTabLayout.removeOnTabSelectedListener(this);
+                mTabLayout.getTabAt(SOURCE_TAB_INDEX).select();
+                // Add OnTabSelectedListener back.
+                mTabLayout.addOnTabSelectedListener(this);
+            }
+        }
+    }
+
+    @CalledByNative
+    private void setNativePtr(long nativePtr) {
+        mNativeTranslateInfoBarPtr = nativePtr;
+    }
+
+    @CalledByNative
+    private void setAutoAlwaysTranslate() {
+        createAndShowSnackbar(ACTION_AUTO_ALWAYS_TRANSLATE);
+    }
+
+    @Override
+    protected void onNativeDestroyed() {
+        mNativeTranslateInfoBarPtr = 0;
+        super.onNativeDestroyed();
+    }
+
+    private void closeInfobar(boolean explicitly) {
+        if (isDismissed()) return;
+
+        if (!mUserInteracted) {
+            recordInfobarAction(INFOBAR_DECLINE);
+        }
+
+        // NOTE: In Chrome there is a check for whether auto "never translate" should be triggered
+        // via a snackbar here. However, WebLayer does not have snackbars and thus does not have
+        // this check as there would be no way to inform the user of the functionality being
+        // triggered. The user of course has the option of choosing "never translate" from the
+        // overflow menu.
+
+        // This line will dismiss this infobar.
+        super.onCloseButtonClicked();
+    }
+
+    @Override
+    public void onCloseButtonClicked() {
+        mTabLayout.endScrollingAnimationIfPlaying();
+        closeInfobar(true);
+    }
+
+    @Override
+    public void onTabSelected(TabLayout.Tab tab) {
+        switch (tab.getPosition()) {
+            case SOURCE_TAB_INDEX:
+                incrementAndRecordTranslationsPerPageCount();
+                recordInfobarAction(INFOBAR_REVERT);
+                onButtonClicked(ActionType.TRANSLATE_SHOW_ORIGINAL);
+                return;
+            case TARGET_TAB_INDEX:
+                recordInfobarAction(INFOBAR_TARGET_TAB_TRANSLATE);
+                recordInfobarLanguageData(
+                        INFOBAR_HISTOGRAM_TRANSLATE_LANGUAGE, mOptions.targetLanguageCode());
+                startTranslating(TARGET_TAB_INDEX);
+                return;
+            default:
+                assert false : "Unexpected Tab Index";
+        }
+    }
+
+    @Override
+    public void onTabUnselected(TabLayout.Tab tab) {}
+
+    @Override
+    public void onTabReselected(TabLayout.Tab tab) {}
+
+    @Override
+    public void onOverflowMenuItemClicked(int itemId) {
+        switch (itemId) {
+            case TranslateMenu.ID_OVERFLOW_MORE_LANGUAGE:
+                recordInfobarAction(INFOBAR_MORE_LANGUAGES);
+                initMenuHelper(TranslateMenu.MENU_TARGET_LANGUAGE);
+                mLanguageMenuHelper.show(TranslateMenu.MENU_TARGET_LANGUAGE, getParentWidth());
+                return;
+            case TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE:
+                // Only show snackbar when "Always Translate" is enabled.
+                if (!mOptions.getTranslateState(TranslateOptions.Type.ALWAYS_LANGUAGE)) {
+                    recordInfobarAction(INFOBAR_ALWAYS_TRANSLATE);
+                    recordInfobarLanguageData(INFOBAR_HISTOGRAM_ALWAYS_TRANSLATE_LANGUAGE,
+                            mOptions.sourceLanguageCode());
+                    createAndShowSnackbar(ACTION_OVERFLOW_ALWAYS_TRANSLATE);
+                } else {
+                    recordInfobarAction(INFOBAR_ALWAYS_TRANSLATE_UNDO);
+                    handleTranslateOptionPostSnackbar(ACTION_OVERFLOW_ALWAYS_TRANSLATE);
+                }
+                return;
+            case TranslateMenu.ID_OVERFLOW_NEVER_LANGUAGE:
+                recordInfobarAction(INFOBAR_NEVER_TRANSLATE);
+                recordInfobarLanguageData(
+                        INFOBAR_HISTOGRAM_NEVER_TRANSLATE_LANGUAGE, mOptions.sourceLanguageCode());
+                createAndShowSnackbar(ACTION_OVERFLOW_NEVER_LANGUAGE);
+                return;
+            case TranslateMenu.ID_OVERFLOW_NEVER_SITE:
+                recordInfobarAction(INFOBAR_NEVER_TRANSLATE_SITE);
+                createAndShowSnackbar(ACTION_OVERFLOW_NEVER_SITE);
+                return;
+            case TranslateMenu.ID_OVERFLOW_NOT_THIS_LANGUAGE:
+                recordInfobarAction(INFOBAR_PAGE_NOT_IN);
+                initMenuHelper(TranslateMenu.MENU_SOURCE_LANGUAGE);
+                mLanguageMenuHelper.show(TranslateMenu.MENU_SOURCE_LANGUAGE, getParentWidth());
+                return;
+            default:
+                assert false : "Unexpected overflow menu code";
+        }
+    }
+
+    @Override
+    public void onTargetMenuItemClicked(String code) {
+        // Reset target code in both UI and native.
+        if (mNativeTranslateInfoBarPtr != 0 && mOptions.setTargetLanguage(code)) {
+            recordInfobarAction(INFOBAR_MORE_LANGUAGES_TRANSLATE);
+            recordInfobarLanguageData(
+                    INFOBAR_HISTOGRAM_MORE_LANGUAGES_LANGUAGE, mOptions.targetLanguageCode());
+            TranslateCompactInfoBarJni.get().applyStringTranslateOption(mNativeTranslateInfoBarPtr,
+                    TranslateCompactInfoBar.this, TranslateOption.TARGET_CODE, code);
+            // Adjust UI.
+            mTabLayout.replaceTabTitle(TARGET_TAB_INDEX, mOptions.getRepresentationFromCode(code));
+            startTranslating(mTabLayout.getSelectedTabPosition());
+        }
+    }
+
+    @Override
+    public void onSourceMenuItemClicked(String code) {
+        // Reset source code in both UI and native.
+        if (mNativeTranslateInfoBarPtr != 0 && mOptions.setSourceLanguage(code)) {
+            recordInfobarLanguageData(
+                    INFOBAR_HISTOGRAM_PAGE_NOT_IN_LANGUAGE, mOptions.sourceLanguageCode());
+            TranslateCompactInfoBarJni.get().applyStringTranslateOption(mNativeTranslateInfoBarPtr,
+                    TranslateCompactInfoBar.this, TranslateOption.SOURCE_CODE, code);
+            // Adjust UI.
+            mTabLayout.replaceTabTitle(SOURCE_TAB_INDEX, mOptions.getRepresentationFromCode(code));
+            startTranslating(mTabLayout.getSelectedTabPosition());
+        }
+    }
+
+    // Dismiss all overflow menus that remains open.
+    // This is called when infobar started hiding or layout changed.
+    private void dismissMenus() {
+        if (mOverflowMenuHelper != null) mOverflowMenuHelper.dismiss();
+        if (mLanguageMenuHelper != null) mLanguageMenuHelper.dismiss();
+    }
+
+    // Dismiss all overflow menus and snackbars that belong to this infobar and remain open.
+    private void dismissMenusAndSnackbars() {
+        dismissMenus();
+    }
+
+    @Override
+    protected void onStartedHiding() {
+        dismissMenusAndSnackbars();
+    }
+
+    @Override
+    protected CharSequence getAccessibilityMessage(CharSequence defaultMessage) {
+        return getContext().getString(R.string.translate_button);
+    }
+
+    /**
+     * Returns true if overflow menu is showing.  This is only used for automation testing.
+     */
+    public boolean isShowingOverflowMenuForTesting() {
+        if (mOverflowMenuHelper == null) return false;
+        return mOverflowMenuHelper.isShowing();
+    }
+
+    /**
+     * Returns true if language menu is showing.  This is only used for automation testing.
+     */
+    public boolean isShowingLanguageMenuForTesting() {
+        if (mLanguageMenuHelper == null) return false;
+        return mLanguageMenuHelper.isShowing();
+    }
+
+    /**
+     * Returns true if the tab at the given |tabIndex| is selected. This is only used for automation
+     * testing.
+     */
+    private boolean isTabSelectedForTesting(int tabIndex) {
+        return mTabLayout.getTabAt(tabIndex).isSelected();
+    }
+
+    /**
+     * Returns true if the target tab is selected. This is only used for automation testing.
+     */
+    public boolean isSourceTabSelectedForTesting() {
+        return this.isTabSelectedForTesting(SOURCE_TAB_INDEX);
+    }
+
+    /**
+     * Returns true if the target tab is selected. This is only used for automation testing.
+     */
+    public boolean isTargetTabSelectedForTesting() {
+        return this.isTabSelectedForTesting(TARGET_TAB_INDEX);
+    }
+
+    private void createAndShowSnackbar(int actionId) {
+        // NOTE: WebLayer doesn't have snackbars, so the relevant action is just taken directly.
+        // TODO(blundell): If WebLayer ends up staying with this implementation long-term, update
+        // the nomenclature of this file to avoid any references to snackbars.
+        handleTranslateOptionPostSnackbar(actionId);
+    }
+
+    private void handleTranslateOptionPostSnackbar(int actionId) {
+        // Quit if native is destroyed.
+        if (mNativeTranslateInfoBarPtr == 0) return;
+
+        switch (actionId) {
+            case ACTION_OVERFLOW_ALWAYS_TRANSLATE:
+                toggleAlwaysTranslate();
+                // Start translating if always translate is selected and if page is not already
+                // translated to the target language.
+                if (mOptions.getTranslateState(TranslateOptions.Type.ALWAYS_LANGUAGE)
+                        && mTabLayout.getSelectedTabPosition() == SOURCE_TAB_INDEX) {
+                    startTranslating(mTabLayout.getSelectedTabPosition());
+                }
+                return;
+            case ACTION_AUTO_ALWAYS_TRANSLATE:
+                toggleAlwaysTranslate();
+                return;
+            case ACTION_OVERFLOW_NEVER_LANGUAGE:
+            case ACTION_AUTO_NEVER_LANGUAGE:
+                mUserInteracted = true;
+                // After applying this option, the infobar will dismiss.
+                TranslateCompactInfoBarJni.get().applyBoolTranslateOption(
+                        mNativeTranslateInfoBarPtr, TranslateCompactInfoBar.this,
+                        TranslateOption.NEVER_TRANSLATE, true);
+                return;
+            case ACTION_OVERFLOW_NEVER_SITE:
+                mUserInteracted = true;
+                // After applying this option, the infobar will dismiss.
+                TranslateCompactInfoBarJni.get().applyBoolTranslateOption(
+                        mNativeTranslateInfoBarPtr, TranslateCompactInfoBar.this,
+                        TranslateOption.NEVER_TRANSLATE_SITE, true);
+                return;
+            default:
+                assert false : "Unsupported Menu Item Id, in handle post snackbar";
+        }
+    }
+
+    private void toggleAlwaysTranslate() {
+        mOptions.toggleAlwaysTranslateLanguageState(
+                !mOptions.getTranslateState(TranslateOptions.Type.ALWAYS_LANGUAGE));
+        TranslateCompactInfoBarJni.get().applyBoolTranslateOption(mNativeTranslateInfoBarPtr,
+                TranslateCompactInfoBar.this, TranslateOption.ALWAYS_TRANSLATE,
+                mOptions.getTranslateState(TranslateOptions.Type.ALWAYS_LANGUAGE));
+    }
+
+    private static void recordInfobarAction(int action) {
+        RecordHistogram.recordEnumeratedHistogram(
+                INFOBAR_HISTOGRAM, action, INFOBAR_HISTOGRAM_BOUNDARY);
+    }
+
+    private void recordInfobarLanguageData(String histogram, String langCode) {
+        Integer hashCode = mOptions.getUMAHashCodeFromCode(langCode);
+        if (hashCode != null) {
+            RecordHistogram.recordSparseHistogram(histogram, hashCode);
+        }
+    }
+
+    private void incrementAndRecordTranslationsPerPageCount() {
+        RecordHistogram.recordCountHistogram(
+                INFOBAR_HISTOGRAM_TRANSLATION_COUNT, ++mTotalTranslationCount);
+    }
+
+    // Return the width of parent in pixels.  Return 0 if there is no parent.
+    private int getParentWidth() {
+        return mParent != null ? mParent.getWidth() : 0;
+    }
+
+    @NativeMethods
+    interface Natives {
+        void applyStringTranslateOption(long nativeTranslateCompactInfoBar,
+                TranslateCompactInfoBar caller, int option, String value);
+        void applyBoolTranslateOption(long nativeTranslateCompactInfoBar,
+                TranslateCompactInfoBar caller, int option, boolean value);
+        boolean shouldAutoNeverTranslate(long nativeTranslateCompactInfoBar,
+                TranslateCompactInfoBar caller, boolean menuExpanded);
+        boolean isIncognito(long nativeTranslateCompactInfoBar, TranslateCompactInfoBar caller);
+    }
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TranslateMenu.java b/weblayer/browser/java/org/chromium/weblayer_private/TranslateMenu.java
new file mode 100644
index 0000000..cfb1a06
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TranslateMenu.java
@@ -0,0 +1,75 @@
+// 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.
+
+package org.chromium.weblayer_private;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Translate menu config and its item entity definition.
+ */
+public final class TranslateMenu {
+    /**
+     * The menu item entity.
+     */
+    static final class MenuItem {
+        public final int mType;
+        public final int mId;
+        public final String mCode;
+        public final boolean mWithDivider;
+
+        MenuItem(int itemType, int itemId, boolean withDivider) {
+            this(itemType, itemId, EMPTY_STRING, withDivider);
+        }
+
+        MenuItem(int itemType, int itemId, String code) {
+            this(itemType, itemId, code, false);
+        }
+
+        MenuItem(int itemType, int itemId, String code, boolean withDivider) {
+            mType = itemType;
+            mId = itemId;
+            mCode = code;
+            mWithDivider = withDivider;
+        }
+    }
+
+    public static final String EMPTY_STRING = "";
+
+    // Menu type config.
+    public static final int MENU_OVERFLOW = 0;
+    public static final int MENU_TARGET_LANGUAGE = 1;
+    public static final int MENU_SOURCE_LANGUAGE = 2;
+
+    // Menu item type config.
+    public static final int ITEM_LANGUAGE = 0;
+    public static final int ITEM_CHECKBOX_OPTION = 1;
+    public static final int MENU_ITEM_TYPE_COUNT = 2;
+
+    // Menu Item ID config for MENU_OVERFLOW.
+    public static final int ID_OVERFLOW_MORE_LANGUAGE = 0;
+    public static final int ID_OVERFLOW_ALWAYS_TRANSLATE = 1;
+    public static final int ID_OVERFLOW_NEVER_SITE = 2;
+    public static final int ID_OVERFLOW_NEVER_LANGUAGE = 3;
+    public static final int ID_OVERFLOW_NOT_THIS_LANGUAGE = 4;
+
+    /**
+     * Build overflow menu item list.
+     */
+    static List<MenuItem> getOverflowMenu(boolean isIncognito) {
+        List<MenuItem> menu = new ArrayList<MenuItem>();
+        menu.add(new MenuItem(ITEM_CHECKBOX_OPTION, ID_OVERFLOW_MORE_LANGUAGE, true));
+        if (!isIncognito) {
+            // "Always translate" does nothing in incognito mode, so just hide it.
+            menu.add(new MenuItem(ITEM_CHECKBOX_OPTION, ID_OVERFLOW_ALWAYS_TRANSLATE, false));
+        }
+        menu.add(new MenuItem(ITEM_CHECKBOX_OPTION, ID_OVERFLOW_NEVER_LANGUAGE, false));
+        menu.add(new MenuItem(ITEM_CHECKBOX_OPTION, ID_OVERFLOW_NEVER_SITE, false));
+        menu.add(new MenuItem(ITEM_CHECKBOX_OPTION, ID_OVERFLOW_NOT_THIS_LANGUAGE, false));
+        return menu;
+    }
+
+    private TranslateMenu() {}
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TranslateMenuHelper.java b/weblayer/browser/java/org/chromium/weblayer_private/TranslateMenuHelper.java
new file mode 100644
index 0000000..8d1eeff
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TranslateMenuHelper.java
@@ -0,0 +1,313 @@
+// 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.
+
+package org.chromium.weblayer_private;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Build;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListPopupWindow;
+import android.widget.PopupWindow;
+import android.widget.TextView;
+
+import androidx.core.content.ContextCompat;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A Helper class for managing the Translate Overflow Menu.
+ */
+public class TranslateMenuHelper implements AdapterView.OnItemClickListener {
+    private final TranslateMenuListener mMenuListener;
+    private final TranslateOptions mOptions;
+
+    private ContextThemeWrapper mContextWrapper;
+    private TranslateMenuAdapter mAdapter;
+    private View mAnchorView;
+    private ListPopupWindow mPopup;
+    private boolean mIsIncognito;
+
+    /**
+     * Interface for receiving the click event of menu item.
+     */
+    public interface TranslateMenuListener {
+        void onOverflowMenuItemClicked(int itemId);
+        void onTargetMenuItemClicked(String code);
+        void onSourceMenuItemClicked(String code);
+    }
+
+    public TranslateMenuHelper(Context context, View anchorView, TranslateOptions options,
+            TranslateMenuListener itemListener, boolean isIncognito) {
+        mContextWrapper = new ContextThemeWrapper(context, R.style.OverflowMenuThemeOverlay);
+        mAnchorView = anchorView;
+        mOptions = options;
+        mMenuListener = itemListener;
+        mIsIncognito = isIncognito;
+    }
+
+    /**
+     * Build translate menu by menu type.
+     */
+    private List<TranslateMenu.MenuItem> getMenuList(int menuType) {
+        List<TranslateMenu.MenuItem> menuList = new ArrayList<TranslateMenu.MenuItem>();
+        if (menuType == TranslateMenu.MENU_OVERFLOW) {
+            // TODO(googleo): Add language short list above static menu after its data is ready.
+            menuList.addAll(TranslateMenu.getOverflowMenu(mIsIncognito));
+        } else {
+            for (int i = 0; i < mOptions.allLanguages().size(); ++i) {
+                String code = mOptions.allLanguages().get(i).mLanguageCode;
+                // Avoid source language in the source language list.
+                if (menuType == TranslateMenu.MENU_SOURCE_LANGUAGE
+                        && code.equals(mOptions.sourceLanguageCode())) {
+                    continue;
+                }
+                // Avoid target language in the target language list.
+                if (menuType == TranslateMenu.MENU_TARGET_LANGUAGE
+                        && code.equals(mOptions.targetLanguageCode())) {
+                    continue;
+                }
+                menuList.add(new TranslateMenu.MenuItem(TranslateMenu.ITEM_LANGUAGE, i, code));
+            }
+        }
+        return menuList;
+    }
+
+    /**
+     * Show the overflow menu.
+     * @param menuType The type of overflow menu to show.
+     * @param maxwidth Maximum width of menu.  Set to 0 when not specified.
+     */
+    public void show(int menuType, int maxWidth) {
+        if (mPopup == null) {
+            mPopup = new ListPopupWindow(mContextWrapper, null, android.R.attr.popupMenuStyle);
+            mPopup.setModal(true);
+            mPopup.setAnchorView(mAnchorView);
+            mPopup.setInputMethodMode(PopupWindow.INPUT_METHOD_NOT_NEEDED);
+
+            // Need to explicitly set the background here.  Relying on it being set in the style
+            // caused an incorrectly drawn background.
+            // TODO(martiw): We might need a new menu background here.
+            mPopup.setBackgroundDrawable(
+                    ContextCompat.getDrawable(mContextWrapper, R.drawable.popup_bg_tinted));
+
+            mPopup.setOnItemClickListener(this);
+
+            // The menu must be shifted down by the height of the anchor view in order to be
+            // displayed over and above it.
+            int anchorHeight = mAnchorView.getHeight();
+            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
+                // Setting a positive offset here shifts the menu down.
+                mPopup.setVerticalOffset(anchorHeight);
+            } else {
+                // The framework's PopupWindow positioning changed between N and M.  Setting
+                // a negative offset here shifts the menu down rather than up.
+                mPopup.setVerticalOffset(-anchorHeight);
+            }
+
+            mAdapter = new TranslateMenuAdapter(menuType);
+            mPopup.setAdapter(mAdapter);
+        } else {
+            mAdapter.refreshMenu(menuType);
+        }
+
+        if (menuType == TranslateMenu.MENU_OVERFLOW) {
+            // Use measured width when it is a overflow menu.
+            Rect bgPadding = new Rect();
+            mPopup.getBackground().getPadding(bgPadding);
+            int measuredWidth = measureMenuWidth(mAdapter) + bgPadding.left + bgPadding.right;
+            mPopup.setWidth((maxWidth > 0 && measuredWidth > maxWidth) ? maxWidth : measuredWidth);
+        } else {
+            // Use fixed width otherwise.
+            int popupWidth = mContextWrapper.getResources().getDimensionPixelSize(
+                    R.dimen.infobar_translate_menu_width);
+            mPopup.setWidth(popupWidth);
+        }
+
+        // When layout is RTL, set the horizontal offset to align the menu with the left side of the
+        // screen.
+        if (mAnchorView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+            int[] tempLocation = new int[2];
+            mAnchorView.getLocationOnScreen(tempLocation);
+            mPopup.setHorizontalOffset(-tempLocation[0]);
+        }
+
+        if (!mPopup.isShowing()) {
+            mPopup.show();
+            mPopup.getListView().setItemsCanFocus(true);
+        }
+    }
+
+    private int measureMenuWidth(TranslateMenuAdapter adapter) {
+        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+
+        final int count = adapter.getCount();
+        int width = 0;
+        int itemType = 0;
+        View itemView = null;
+        for (int i = 0; i < count; i++) {
+            final int positionType = adapter.getItemViewType(i);
+            if (positionType != itemType) {
+                itemType = positionType;
+                itemView = null;
+            }
+            itemView = adapter.getView(i, itemView, null);
+            itemView.measure(widthMeasureSpec, heightMeasureSpec);
+            width = Math.max(width, itemView.getMeasuredWidth());
+        }
+        return width;
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        dismiss();
+
+        TranslateMenu.MenuItem item = mAdapter.getItem(position);
+        switch (mAdapter.mMenuType) {
+            case TranslateMenu.MENU_OVERFLOW:
+                mMenuListener.onOverflowMenuItemClicked(item.mId);
+                return;
+            case TranslateMenu.MENU_TARGET_LANGUAGE:
+                mMenuListener.onTargetMenuItemClicked(item.mCode);
+                return;
+            case TranslateMenu.MENU_SOURCE_LANGUAGE:
+                mMenuListener.onSourceMenuItemClicked(item.mCode);
+                return;
+            default:
+                assert false : "Unsupported Menu Item Id";
+        }
+    }
+
+    /**
+     * Dismisses the translate option menu.
+     */
+    public void dismiss() {
+        if (isShowing()) {
+            mPopup.dismiss();
+        }
+    }
+
+    /**
+     * @return Whether the menu is currently showing.
+     */
+    public boolean isShowing() {
+        if (mPopup == null) {
+            return false;
+        }
+        return mPopup.isShowing();
+    }
+
+    /**
+     * The provides the views of the menu items and dividers.
+     */
+    private final class TranslateMenuAdapter extends ArrayAdapter<TranslateMenu.MenuItem> {
+        private final LayoutInflater mInflater;
+        private int mMenuType;
+
+        public TranslateMenuAdapter(int menuType) {
+            super(mContextWrapper, R.layout.translate_menu_item, getMenuList(menuType));
+            mInflater = LayoutInflater.from(mContextWrapper);
+            mMenuType = menuType;
+        }
+
+        private void refreshMenu(int menuType) {
+            // MENU_OVERFLOW is static and it should not reload.
+            if (menuType == TranslateMenu.MENU_OVERFLOW) return;
+
+            clear();
+
+            mMenuType = menuType;
+            addAll(getMenuList(menuType));
+            notifyDataSetChanged();
+        }
+
+        private String getItemViewText(TranslateMenu.MenuItem item) {
+            if (mMenuType == TranslateMenu.MENU_OVERFLOW) {
+                // Overflow menu items are manually defined one by one.
+                String source = mOptions.sourceLanguageName();
+                switch (item.mId) {
+                    case TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE:
+                        return mContextWrapper.getString(
+                                R.string.translate_option_always_translate, source);
+                    case TranslateMenu.ID_OVERFLOW_MORE_LANGUAGE:
+                        return mContextWrapper.getString(R.string.translate_option_more_language);
+                    case TranslateMenu.ID_OVERFLOW_NEVER_SITE:
+                        return mContextWrapper.getString(R.string.translate_never_translate_site);
+                    case TranslateMenu.ID_OVERFLOW_NEVER_LANGUAGE:
+                        return mContextWrapper.getString(
+                                R.string.translate_option_never_translate, source);
+                    case TranslateMenu.ID_OVERFLOW_NOT_THIS_LANGUAGE:
+                        return mContextWrapper.getString(
+                                R.string.translate_option_not_source_language, source);
+                    default:
+                        assert false : "Unexpected Overflow Item Id";
+                }
+            } else {
+                // Get source and target language menu items text by language code.
+                return mOptions.getRepresentationFromCode(item.mCode);
+            }
+            return "";
+        }
+
+        @Override
+        public int getItemViewType(int position) {
+            return getItem(position).mType;
+        }
+
+        @Override
+        public int getViewTypeCount() {
+            return TranslateMenu.MENU_ITEM_TYPE_COUNT;
+        }
+
+        private View getItemView(
+                View menuItemView, int position, ViewGroup parent, int resourceId) {
+            if (menuItemView == null) {
+                menuItemView = mInflater.inflate(resourceId, parent, false);
+            }
+            ((TextView) menuItemView.findViewById(R.id.menu_item_text))
+                    .setText(getItemViewText(getItem(position)));
+            return menuItemView;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            View menuItemView = convertView;
+            switch (getItemViewType(position)) {
+                case TranslateMenu.ITEM_CHECKBOX_OPTION:
+                    menuItemView = getItemView(
+                            menuItemView, position, parent, R.layout.translate_menu_item_checked);
+
+                    ImageView checkboxIcon = menuItemView.findViewById(R.id.menu_item_icon);
+                    if (getItem(position).mId == TranslateMenu.ID_OVERFLOW_ALWAYS_TRANSLATE
+                            && mOptions.getTranslateState(TranslateOptions.Type.ALWAYS_LANGUAGE)) {
+                        checkboxIcon.setVisibility(View.VISIBLE);
+                    } else {
+                        checkboxIcon.setVisibility(View.INVISIBLE);
+                    }
+
+                    View divider = (View) menuItemView.findViewById(R.id.menu_item_divider);
+                    if (getItem(position).mWithDivider) {
+                        divider.setVisibility(View.VISIBLE);
+                    }
+                    break;
+                case TranslateMenu.ITEM_LANGUAGE:
+                    menuItemView = getItemView(
+                            menuItemView, position, parent, R.layout.translate_menu_item);
+                    break;
+                default:
+                    assert false : "Unexpected MenuItem type";
+            }
+            return menuItemView;
+        }
+    }
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TranslateOptions.java b/weblayer/browser/java/org/chromium/weblayer_private/TranslateOptions.java
new file mode 100644
index 0000000..ba38d4e
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TranslateOptions.java
@@ -0,0 +1,278 @@
+// 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.
+
+package org.chromium.weblayer_private;
+
+import android.text.TextUtils;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A class that keeps the state of the different translation options and
+ * languages.
+ */
+public class TranslateOptions {
+    /**
+     * A container for Language Code and it's translated representation and it's native UMA
+     * specific hashcode.
+     * For example for Spanish when viewed from a French locale, this will contain es, Espagnol,
+     * 114573335
+     **/
+    public static class TranslateLanguageData {
+        public final String mLanguageCode;
+        public final String mLanguageRepresentation;
+        public final Integer mLanguageUMAHashCode;
+
+        public TranslateLanguageData(
+                String languageCode, String languageRepresentation, Integer uMAhashCode) {
+            assert languageCode != null;
+            assert languageRepresentation != null;
+            mLanguageCode = languageCode;
+            mLanguageRepresentation = languageRepresentation;
+            mLanguageUMAHashCode = uMAhashCode;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (!(obj instanceof TranslateLanguageData)) return false;
+            TranslateLanguageData other = (TranslateLanguageData) obj;
+            return this.mLanguageCode.equals(other.mLanguageCode)
+                    && this.mLanguageRepresentation.equals(other.mLanguageRepresentation)
+                    && this.mLanguageUMAHashCode.equals(other.mLanguageUMAHashCode);
+        }
+
+        @Override
+        public int hashCode() {
+            return (mLanguageCode + mLanguageRepresentation).hashCode();
+        }
+
+        @Override
+        public String toString() {
+            return "mLanguageCode:" + mLanguageCode + " - mlanguageRepresentation "
+                    + mLanguageRepresentation + " - mLanguageUMAHashCode " + mLanguageUMAHashCode;
+        }
+    }
+
+    // Values must be numerated from 0 and can't have gaps
+    // (they're used for indexing mOptions).
+    @IntDef({Type.NEVER_LANGUAGE, Type.NEVER_DOMAIN, Type.ALWAYS_LANGUAGE})
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Type {
+        int NEVER_LANGUAGE = 0;
+        int NEVER_DOMAIN = 1;
+        int ALWAYS_LANGUAGE = 2;
+
+        int NUM_ENTRIES = 3;
+    }
+
+    private String mSourceLanguageCode;
+    private String mTargetLanguageCode;
+
+    private final ArrayList<TranslateLanguageData> mAllLanguages;
+
+    // language code to translated language name map
+    // Conceptually final
+    private Map<String, String> mCodeToRepresentation;
+
+    // Language code to its UMA hashcode representation.
+    private Map<String, Integer> mCodeToUMAHashCode;
+
+    // Will reflect the state before the object was ever modified
+    private final boolean[] mOriginalOptions;
+
+    private final String mOriginalSourceLanguageCode;
+    private final String mOriginalTargetLanguageCode;
+    private final boolean mTriggeredFromMenu;
+
+    private final boolean[] mOptions;
+
+    private TranslateOptions(String sourceLanguageCode, String targetLanguageCode,
+            ArrayList<TranslateLanguageData> allLanguages, boolean neverLanguage,
+            boolean neverDomain, boolean alwaysLanguage, boolean triggeredFromMenu,
+            boolean[] originalOptions) {
+        assert Type.NUM_ENTRIES == 3;
+        mOptions = new boolean[Type.NUM_ENTRIES];
+        mOptions[Type.NEVER_LANGUAGE] = neverLanguage;
+        mOptions[Type.NEVER_DOMAIN] = neverDomain;
+        mOptions[Type.ALWAYS_LANGUAGE] = alwaysLanguage;
+
+        mOriginalOptions = originalOptions == null ? mOptions.clone() : originalOptions.clone();
+
+        mSourceLanguageCode = sourceLanguageCode;
+        mTargetLanguageCode = targetLanguageCode;
+        mOriginalSourceLanguageCode = mSourceLanguageCode;
+        mOriginalTargetLanguageCode = mTargetLanguageCode;
+        mTriggeredFromMenu = triggeredFromMenu;
+
+        mAllLanguages = allLanguages;
+        mCodeToRepresentation = new HashMap<String, String>();
+        mCodeToUMAHashCode = new HashMap<String, Integer>();
+        for (TranslateLanguageData language : allLanguages) {
+            mCodeToRepresentation.put(language.mLanguageCode, language.mLanguageRepresentation);
+            mCodeToUMAHashCode.put(language.mLanguageCode, language.mLanguageUMAHashCode);
+        }
+    }
+
+    /**
+     * Creates a TranslateOptions by the given data.
+     */
+    public static TranslateOptions create(String sourceLanguageCode, String targetLanguageCode,
+            String[] languages, String[] codes, boolean alwaysTranslate, boolean triggeredFromMenu,
+            int[] hashCodes) {
+        assert languages.length == codes.length;
+
+        ArrayList<TranslateLanguageData> languageList = new ArrayList<TranslateLanguageData>();
+        for (int i = 0; i < languages.length; ++i) {
+            Integer hashCode = hashCodes != null ? Integer.valueOf(hashCodes[i]) : null;
+            languageList.add(new TranslateLanguageData(codes[i], languages[i], hashCode));
+        }
+        return new TranslateOptions(sourceLanguageCode, targetLanguageCode, languageList, false,
+                false, alwaysTranslate, triggeredFromMenu, null);
+    }
+
+    /**
+     * Returns a copy of the current instance.
+     */
+    TranslateOptions copy() {
+        return new TranslateOptions(mSourceLanguageCode, mTargetLanguageCode, mAllLanguages,
+                mOptions[Type.NEVER_LANGUAGE], mOptions[Type.NEVER_DOMAIN],
+                mOptions[Type.ALWAYS_LANGUAGE], mTriggeredFromMenu, mOriginalOptions);
+    }
+
+    public String sourceLanguageName() {
+        return getRepresentationFromCode(mSourceLanguageCode);
+    }
+
+    public String targetLanguageName() {
+        return getRepresentationFromCode(mTargetLanguageCode);
+    }
+
+    public String sourceLanguageCode() {
+        return mSourceLanguageCode;
+    }
+
+    public String targetLanguageCode() {
+        return mTargetLanguageCode;
+    }
+
+    public boolean triggeredFromMenu() {
+        return mTriggeredFromMenu;
+    }
+
+    public boolean optionsChanged() {
+        return (!mSourceLanguageCode.equals(mOriginalSourceLanguageCode))
+                || (!mTargetLanguageCode.equals(mOriginalTargetLanguageCode))
+                || (mOptions[Type.NEVER_LANGUAGE] != mOriginalOptions[Type.NEVER_LANGUAGE])
+                || (mOptions[Type.NEVER_DOMAIN] != mOriginalOptions[Type.NEVER_DOMAIN])
+                || (mOptions[Type.ALWAYS_LANGUAGE] != mOriginalOptions[Type.ALWAYS_LANGUAGE]);
+    }
+
+    public List<TranslateLanguageData> allLanguages() {
+        return mAllLanguages;
+    }
+
+    public boolean getTranslateState(@Type int type) {
+        return mOptions[type];
+    }
+
+    public boolean setSourceLanguage(String languageCode) {
+        boolean canSet = canSetLanguage(languageCode, mTargetLanguageCode);
+        if (canSet) mSourceLanguageCode = languageCode;
+        return canSet;
+    }
+
+    public boolean setTargetLanguage(String languageCode) {
+        boolean canSet = canSetLanguage(mSourceLanguageCode, languageCode);
+        if (canSet) mTargetLanguageCode = languageCode;
+        return canSet;
+    }
+
+    /**
+     * Sets the new state of never translate domain.
+     *
+     * @return true if the toggling was possible
+     */
+    public void toggleNeverTranslateDomainState(boolean value) {
+        mOptions[Type.NEVER_DOMAIN] = value;
+    }
+
+    /**
+     * Sets the new state of never translate language.
+     *
+     * @return true if the toggling was possible
+     */
+    public boolean toggleNeverTranslateLanguageState(boolean value) {
+        // Do not toggle if we are activating NeverLanguage but AlwaysTranslate
+        // for a language pair with the same source language is already active.
+        if (mOptions[Type.ALWAYS_LANGUAGE] && value) return false;
+        mOptions[Type.NEVER_LANGUAGE] = value;
+        return true;
+    }
+
+    /**
+     * Sets the new state of never translate a language pair.
+     *
+     * @return true if the toggling was possible
+     */
+    public boolean toggleAlwaysTranslateLanguageState(boolean value) {
+        // Do not toggle if we are activating AlwaysLanguage but NeverLanguage is active already.
+        if (mOptions[Type.NEVER_LANGUAGE] && value) return false;
+        mOptions[Type.ALWAYS_LANGUAGE] = value;
+        return true;
+    }
+
+    /**
+     * Gets the language's translated representation from a given language code.
+     * @param languageCode ISO code for the language
+     * @return The translated representation of the language, or "" if not found.
+     */
+    public String getRepresentationFromCode(String languageCode) {
+        return isValidLanguageCode(languageCode) ? mCodeToRepresentation.get(languageCode) : "";
+    }
+
+    /**
+     * Gets the language's UMA hashcode representation from a given language code.
+     * @param languageCode ISO code for the language
+     * @return The UMA hashcode representation of the language, or null if not found.
+     */
+    public Integer getUMAHashCodeFromCode(String languageCode) {
+        return isValidLanguageUMAHashCode(languageCode) ? mCodeToUMAHashCode.get(languageCode)
+                                                        : null;
+    }
+
+    private boolean isValidLanguageCode(String languageCode) {
+        return !TextUtils.isEmpty(languageCode) && mCodeToRepresentation.containsKey(languageCode);
+    }
+
+    private boolean isValidLanguageUMAHashCode(String languageCode) {
+        return !TextUtils.isEmpty(languageCode) && mCodeToUMAHashCode.containsKey(languageCode);
+    }
+
+    private boolean canSetLanguage(String sourceCode, String targetCode) {
+        return isValidLanguageCode(sourceCode) && isValidLanguageCode(targetCode);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder()
+                .append(sourceLanguageCode())
+                .append(" -> ")
+                .append(targetLanguageCode())
+                .append(" - ")
+                .append("Never Language:")
+                .append(mOptions[Type.NEVER_LANGUAGE])
+                .append(" Always Language:")
+                .append(mOptions[Type.ALWAYS_LANGUAGE])
+                .append(" Never Domain:")
+                .append(mOptions[Type.NEVER_DOMAIN])
+                .toString();
+    }
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TranslateTabContent.java b/weblayer/browser/java/org/chromium/weblayer_private/TranslateTabContent.java
new file mode 100644
index 0000000..820ca49
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TranslateTabContent.java
@@ -0,0 +1,63 @@
+// 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.
+
+package org.chromium.weblayer_private;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ProgressBar;
+import android.widget.TextView;
+
+/**
+ * The content of the tab shown in the TranslateTabLayout.
+ */
+public class TranslateTabContent extends FrameLayout {
+    private TextView mTextView;
+    private ProgressBar mProgressBar;
+
+    /**
+     * Constructor for inflating from XML.
+     */
+    public TranslateTabContent(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTextView = (TextView) findViewById(R.id.translate_infobar_tab_text);
+        mProgressBar = (ProgressBar) findViewById(R.id.translate_infobar_tab_progressbar);
+    }
+
+    /**
+     * Sets the text color for all the states (normal, selected, focused) to be this color.
+     * @param colors The color state list of the title text.
+     */
+    public void setTextColor(ColorStateList colors) {
+        mTextView.setTextColor(colors);
+    }
+
+    /**
+     * Set the title text for this tab.
+     * @param tabTitle The new title string.
+     */
+    public void setText(CharSequence tabTitle) {
+        mTextView.setText(tabTitle);
+    }
+
+    /** Hide progress bar and show text. */
+    public void hideProgressBar() {
+        mProgressBar.setVisibility(View.INVISIBLE);
+        mTextView.setVisibility(View.VISIBLE);
+    }
+
+    /** Show progress bar and hide text. */
+    public void showProgressBar() {
+        mTextView.setVisibility(View.INVISIBLE);
+        mProgressBar.setVisibility(View.VISIBLE);
+    }
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/TranslateTabLayout.java b/weblayer/browser/java/org/chromium/weblayer_private/TranslateTabLayout.java
new file mode 100644
index 0000000..d32b09d1
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/TranslateTabLayout.java
@@ -0,0 +1,235 @@
+// 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.
+
+package org.chromium.weblayer_private;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+
+import androidx.annotation.NonNull;
+
+import com.google.android.material.tabs.TabLayout;
+
+import org.chromium.components.browser_ui.widget.animation.Interpolators;
+
+/**
+ * TabLayout shown in the TranslateCompactInfoBar.
+ */
+public class TranslateTabLayout extends TabLayout {
+    /** The tab in which a spinning progress bar is showing. */
+    private Tab mTabShowingProgressBar;
+
+    /** The amount of waiting time before starting the scrolling animation. */
+    private static final long START_POSITION_WAIT_DURATION_MS = 1000;
+
+    /** The amount of time it takes to scroll to the end during the scrolling animation. */
+    private static final long SCROLL_DURATION_MS = 300;
+
+    /** We define the keyframes of the scrolling animation in this object. */
+    ObjectAnimator mScrollToEndAnimator;
+
+    /** Start padding of a Tab.  Used for width calculation only.  Will not be applied to views. */
+    private int mTabPaddingStart;
+
+    /** End padding of a Tab.  Used for width calculation only.  Will not be applied to views. */
+    private int mTabPaddingEnd;
+
+    /**
+     * Constructor for inflating from XML.
+     */
+    @SuppressLint("CustomViewStyleable") // TODO(crbug.com/807725): Remove and fix.
+    public TranslateTabLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        TypedArray a = context.obtainStyledAttributes(
+                attrs, R.styleable.TabLayout, 0, R.style.Widget_Design_TabLayout);
+        mTabPaddingStart = mTabPaddingEnd =
+                a.getDimensionPixelSize(R.styleable.TabLayout_tabPadding, 0);
+        mTabPaddingStart =
+                a.getDimensionPixelSize(R.styleable.TabLayout_tabPaddingStart, mTabPaddingStart);
+        mTabPaddingEnd =
+                a.getDimensionPixelSize(R.styleable.TabLayout_tabPaddingEnd, mTabPaddingEnd);
+    }
+
+    /**
+     * Add new Tabs with title strings.
+     * @param titles Titles of the tabs to be added.
+     */
+    public void addTabs(CharSequence... titles) {
+        for (CharSequence title : titles) {
+            addTabWithTitle(title);
+        }
+    }
+
+    /**
+     * Add a new Tab with the title string.
+     * @param tabTitle Title string of the new tab.
+     */
+    public void addTabWithTitle(CharSequence tabTitle) {
+        TranslateTabContent tabContent =
+                (TranslateTabContent) LayoutInflater.from(getContext())
+                        .inflate(R.layout.infobar_translate_tab_content, this, false);
+        // Set text color using tabLayout's ColorStateList.  So that the title text will change
+        // color when selected and unselected.
+        tabContent.setTextColor(getTabTextColors());
+        tabContent.setText(tabTitle);
+
+        Tab tab = newTab();
+        tab.setCustomView(tabContent);
+        tab.setContentDescription(tabTitle);
+        super.addTab(tab);
+    }
+
+    /**
+     * Replace the title string of a tab.
+     * @param tabPos   The position of the tab to modify.
+     * @param tabTitle The new title string.
+     */
+    public void replaceTabTitle(int tabPos, CharSequence tabTitle) {
+        if (tabPos < 0 || tabPos >= getTabCount()) {
+            return;
+        }
+        Tab tab = getTabAt(tabPos);
+        ((TranslateTabContent) tab.getCustomView()).setText(tabTitle);
+        tab.setContentDescription(tabTitle);
+    }
+
+    /**
+     * Show the spinning progress bar on a specified tab.
+     * @param tabPos The position of the tab to show the progress bar.
+     */
+    public void showProgressBarOnTab(int tabPos) {
+        if (tabPos < 0 || tabPos >= getTabCount() || mTabShowingProgressBar != null) {
+            return;
+        }
+        mTabShowingProgressBar = getTabAt(tabPos);
+
+        // TODO(martiw) See if we need to setContentDescription as "Translating" here.
+
+        if (tabIsSupported(mTabShowingProgressBar)) {
+            ((TranslateTabContent) mTabShowingProgressBar.getCustomView()).showProgressBar();
+        }
+    }
+
+    /**
+     * Hide the spinning progress bar in the tabs.
+     */
+    public void hideProgressBar() {
+        if (mTabShowingProgressBar == null) return;
+
+        if (tabIsSupported(mTabShowingProgressBar)) {
+            ((TranslateTabContent) mTabShowingProgressBar.getCustomView()).hideProgressBar();
+        }
+
+        mTabShowingProgressBar = null;
+    }
+
+    // Overridden to block children's touch event when showing progress bar.
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        // Allow touches to propagate to children only if the layout can be interacted with.
+        if (mTabShowingProgressBar != null) {
+            return true;
+        }
+        endScrollingAnimationIfPlaying();
+        return super.onInterceptTouchEvent(ev);
+    }
+
+    /** Check if the tab is supported in TranslateTabLayout. */
+    private boolean tabIsSupported(Tab tab) {
+        return (tab.getCustomView() instanceof TranslateTabContent);
+    }
+
+    // Overridden to make sure only supported Tabs can be added.
+    @Override
+    public void addTab(@NonNull Tab tab, int position, boolean setSelected) {
+        if (!tabIsSupported(tab)) {
+            throw new IllegalArgumentException();
+        }
+        super.addTab(tab, position, setSelected);
+    }
+
+    // Overrided to make sure only supported Tabs can be added.
+    @Override
+    public void addTab(@NonNull Tab tab, boolean setSelected) {
+        if (!tabIsSupported(tab)) {
+            throw new IllegalArgumentException();
+        }
+        super.addTab(tab, setSelected);
+    }
+
+    /**
+     * Calculate and return the width of a specified tab.  Tab doesn't provide a means of getting
+     * the width so we need to calculate the width by summing up the tab paddings and content width.
+     * @param position Tab position.
+     * @return Tab's width in pixels.
+     */
+    private int getTabWidth(int position) {
+        if (getTabAt(position) == null) return 0;
+        return getTabAt(position).getCustomView().getWidth() + mTabPaddingStart + mTabPaddingEnd;
+    }
+
+    /**
+     * Calculate the total width of all tabs and return it.
+     * @return Total width of all tabs in pixels.
+     */
+    private int getTabsTotalWidth() {
+        int totalWidth = 0;
+        for (int i = 0; i < getTabCount(); i++) {
+            totalWidth += getTabWidth(i);
+        }
+        return totalWidth;
+    }
+
+    /**
+     * Calculate the maximum scroll distance (by subtracting layout width from total width of tabs)
+     * and return it.
+     * @return Maximum scroll distance in pixels.
+     */
+    private int maxScrollDistance() {
+        int scrollDistance = getTabsTotalWidth() - getWidth();
+        return scrollDistance > 0 ? scrollDistance : 0;
+    }
+
+    /**
+     * Perform the scrolling animation if this tablayout has any scrollable distance.
+     */
+    // TODO(crbug.com/900912): Figure out whether setScrollX is actually available.
+    @SuppressLint("ObjectAnimatorBinding")
+    public void startScrollingAnimationIfNeeded() {
+        int maxScrollDistance = maxScrollDistance();
+        if (maxScrollDistance == 0) {
+            return;
+        }
+        // The steps of the scrolling animation:
+        //   1. wait for START_POSITION_WAIT_DURATION_MS.
+        //   2. scroll to the end in SCROLL_DURATION_MS.
+        mScrollToEndAnimator = ObjectAnimator.ofInt(this, "scrollX",
+                getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : maxScrollDistance);
+        mScrollToEndAnimator.setStartDelay(START_POSITION_WAIT_DURATION_MS);
+        mScrollToEndAnimator.setDuration(SCROLL_DURATION_MS);
+        mScrollToEndAnimator.setInterpolator(Interpolators.DECELERATE_INTERPOLATOR);
+        mScrollToEndAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mScrollToEndAnimator = null;
+            }
+        });
+        mScrollToEndAnimator.start();
+    }
+
+    /**
+     * End the scrolling animation if it is playing.
+     */
+    public void endScrollingAnimationIfPlaying() {
+        if (mScrollToEndAnimator != null) mScrollToEndAnimator.end();
+    }
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java
index ad83409..9e79ff71 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerFactoryImpl.java
@@ -12,6 +12,7 @@
 import org.chromium.weblayer_private.interfaces.IWebLayer;
 import org.chromium.weblayer_private.interfaces.IWebLayerFactory;
 import org.chromium.weblayer_private.interfaces.StrictModeWorkaround;
+import org.chromium.weblayer_private.interfaces.WebLayerVersionConstants;
 
 /**
  * Factory used to create WebLayer as well as verify compatibility.
@@ -49,7 +50,13 @@
     @Override
     public boolean isClientSupported() {
         StrictModeWorkaround.apply();
-        return Math.abs(sClientMajorVersion - getImplementationMajorVersion()) <= 4;
+        int implMajorVersion = getImplementationMajorVersion();
+        // While the client always calls this method, the most recently shipped product gets to
+        // decide compatibility. If we instead let the implementation always decide, then we would
+        // not be able to change the allowed skew of older implementations, even if the client could
+        // support it.
+        if (sClientMajorVersion > implMajorVersion) return true;
+        return implMajorVersion - sClientMajorVersion <= WebLayerVersionConstants.MAX_SKEW;
     }
 
     /**
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl
index c52cc4e..75966ad 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/IProfile.aidl
@@ -26,4 +26,8 @@
 
   // Added in Version 83.
   ICookieManager getCookieManager() = 6;
+
+  // Added in Version 84.
+  void setBooleanSetting(int type, boolean value) = 7;
+  boolean getBooleanSetting(int type) = 8;
 }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SettingType.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SettingType.java
new file mode 100644
index 0000000..b6fd35e49
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/SettingType.java
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.weblayer_private.interfaces;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@IntDef({SettingType.BASIC_SAFE_BROWSING_ENABLED})
+@Retention(RetentionPolicy.SOURCE)
+public @interface SettingType {
+    int BASIC_SAFE_BROWSING_ENABLED = 0;
+}
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java
new file mode 100644
index 0000000..a76b13c3
--- /dev/null
+++ b/weblayer/browser/java/org/chromium/weblayer_private/interfaces/WebLayerVersionConstants.java
@@ -0,0 +1,19 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.weblayer_private.interfaces;
+
+/**
+ * Versioning related constants.
+ */
+public interface WebLayerVersionConstants {
+    /**
+     * Maximum allowed version skew. If the skew is greater than this, the implementation and client
+     * are not considered compatible, and WebLayer is unusable. The skew is the absolute value of
+     * the difference between the client major version and the implementation major version.
+     *
+     * @see WebLayer#isAvailable()
+     */
+    int MAX_SKEW = 4;
+}
diff --git a/weblayer/browser/java/res/drawable/tab_indicator.xml b/weblayer/browser/java/res/drawable/tab_indicator.xml
new file mode 100644
index 0000000..8fac8197
--- /dev/null
+++ b/weblayer/browser/java/res/drawable/tab_indicator.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-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. -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:left="@dimen/tab_indicator_padding"
+        android:right="@dimen/tab_indicator_padding" >
+        <shape android:shape="rectangle" >
+            <corners
+                android:topRightRadius="@dimen/tab_indicator_radius"
+                android:topLeftRadius="@dimen/tab_indicator_radius" />
+        </shape>
+    </item>
+</layer-list>
diff --git a/weblayer/browser/java/res/layout/infobar_translate_compact_content.xml b/weblayer/browser/java/res/layout/infobar_translate_compact_content.xml
new file mode 100644
index 0000000..55e827f
--- /dev/null
+++ b/weblayer/browser/java/res/layout/infobar_translate_compact_content.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:id="@+id/translate_infobar_content"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:gravity="center_vertical"
+    android:orientation="horizontal">
+    <!-- TODO(huayinz): Change app:tabIndicatorColor to some common color reference -->
+    <org.chromium.weblayer_private.TranslateTabLayout
+        android:id="@+id/translate_infobar_tabs"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_weight="1"
+        android:requiresFadingEdge="horizontal"
+        android:fadingEdgeLength="@dimen/infobar_translate_fade_edge_length"
+        app:tabIndicator="@drawable/tab_indicator"
+        app:tabIndicatorFullWidth="false"
+        app:tabIndicatorHeight="3dp"
+        app:tabSelectedTextColor="@color/tab_layout_selected_tab_color"
+        app:tabGravity="fill"
+        app:tabMode="scrollable" />
+
+    <org.chromium.ui.widget.ChromeImageButton
+        android:id="@+id/translate_infobar_menu_button"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minHeight="@dimen/min_touch_target_size"
+        android:minWidth="@dimen/min_touch_target_size"
+        android:scaleType="center"
+        android:background="?attr/selectableItemBackground"
+        android:contentDescription="@string/accessibility_toolbar_btn_menu"
+        android:src="@drawable/ic_more_vert_24dp"
+        app:tint="@color/default_icon_color_tint_list" />
+</LinearLayout>
diff --git a/weblayer/browser/java/res/layout/infobar_translate_tab_content.xml b/weblayer/browser/java/res/layout/infobar_translate_tab_content.xml
new file mode 100644
index 0000000..ff3fb0a
--- /dev/null
+++ b/weblayer/browser/java/res/layout/infobar_translate_tab_content.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<org.chromium.weblayer_private.TranslateTabContent
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/translate_tabcontent"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+    <!-- Add both the textView and progressBar to the tab, and only keep one of them visible.
+         This way the width of the Tab will always be fixed no matter which one is visible. -->
+    <TextView
+        android:id="@+id/translate_infobar_tab_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:textAppearance="@style/TextAppearance.Design.Tab"
+        android:visibility="visible"
+        android:singleLine="true" />
+    <ProgressBar
+        android:id="@+id/translate_infobar_tab_progressbar"
+        android:layout_width="@dimen/infobar_small_icon_size"
+        android:layout_height="@dimen/infobar_small_icon_size"
+        android:layout_gravity="center"
+        android:indeterminate="true"
+        android:visibility="invisible" />
+</org.chromium.weblayer_private.TranslateTabContent>
diff --git a/weblayer/browser/java/res/layout/translate_menu_item.xml b/weblayer/browser/java/res/layout/translate_menu_item.xml
new file mode 100644
index 0000000..4bdadd5d8
--- /dev/null
+++ b/weblayer/browser/java/res/layout/translate_menu_item.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/AppMenuItem"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content" >
+
+    <TextView
+        android:id="@+id/menu_item_text"
+        android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="start"
+        android:gravity="center_vertical"
+        android:paddingTop="13dp"
+        android:paddingBottom="13dp" />
+
+</FrameLayout>
diff --git a/weblayer/browser/java/res/layout/translate_menu_item_checked.xml b/weblayer/browser/java/res/layout/translate_menu_item_checked.xml
new file mode 100644
index 0000000..aa0178ed
--- /dev/null
+++ b/weblayer/browser/java/res/layout/translate_menu_item_checked.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <LinearLayout
+        style="@style/AppMenuItem"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+
+        <TextView
+            android:id="@+id/menu_item_text"
+            android:textAppearance="?android:attr/textAppearanceLargePopupMenu"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:layout_gravity="start"
+            android:gravity="center_vertical"
+            android:paddingTop="13dp"
+            android:paddingBottom="13dp"
+            android:paddingEnd="16dp" />
+        <org.chromium.ui.widget.ChromeImageView
+            android:id="@+id/menu_item_icon"
+            android:src="@drawable/ic_check_googblue_24dp"
+            android:layout_width="24dp"
+            android:layout_height="match_parent"
+            android:layout_gravity="end"
+            android:gravity="center_vertical"
+            app:tint="@color/default_icon_color_tint_list" />
+
+    </LinearLayout>
+
+    <View
+        android:id="@+id/menu_item_divider"
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/divider_line_bg_color"
+        android:visibility="gone" />
+
+</LinearLayout>
+
diff --git a/weblayer/browser/java/res/values/colors.xml b/weblayer/browser/java/res/values/colors.xml
new file mode 100644
index 0000000..1621b05d
--- /dev/null
+++ b/weblayer/browser/java/res/values/colors.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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. -->
+
+<resources xmlns:tools="http://schemas.android.com/tools">
+    <!-- Please see src/ui/android/java/res/values/colors.xml for the shared common colors. -->
+
+    <color name="tab_layout_selected_tab_color">@color/default_text_color_blue</color>
+
+</resources>
diff --git a/weblayer/browser/java/res/values/dimens.xml b/weblayer/browser/java/res/values/dimens.xml
index 6d36e5b0..1b4b9606 100644
--- a/weblayer/browser/java/res/values/dimens.xml
+++ b/weblayer/browser/java/res/values/dimens.xml
@@ -7,6 +7,14 @@
     <dimen name="security_status_icon_size">18dp</dimen>
     <dimen name="url_text_edge_padding">5dp</dimen>
   
+    <!-- Dimensions for compact translate infobar. -->
+    <dimen name="infobar_translate_fade_edge_length">18dp</dimen>
+    <dimen name="infobar_translate_menu_width">260dp</dimen>
+
+    <!-- Dimens of tab indicator -->
+    <dimen name="tab_indicator_radius">3dp</dimen>
+    <dimen name="tab_indicator_padding">2dp</dimen>
+
     <!-- Infobar dimensions -->
     <!-- Maximum width of an infobar. -->
     <dimen name="infobar_max_width">600dp</dimen>
@@ -22,5 +30,6 @@
     <dimen name="infobar_compact_message_vertical_padding">8dp</dimen>
 
     <!-- Dimensions applied to InfoBars with differently sized icons. -->
+    <dimen name="infobar_small_icon_size">24dp</dimen>
     <dimen name="infobar_big_icon_size">48dp</dimen>
 </resources>
diff --git a/weblayer/browser/java/res/values/styles.xml b/weblayer/browser/java/res/values/styles.xml
index b90beb2..983b3bea 100644
--- a/weblayer/browser/java/res/values/styles.xml
+++ b/weblayer/browser/java/res/values/styles.xml
@@ -46,4 +46,14 @@
         <item name="android:layout">@layout/preference_compat</item>
         <item name="android:widgetLayout">@layout/preference_widget_switch_compat</item>
     </style>
+
+    <!-- The following styles may be used to style views provided by a CustomViewBinder or attached
+         to the app menu as headers or footers. -->
+
+    <!-- Styling for an app menu item row. -->
+    <style name="AppMenuItem">
+        <item name="android:paddingStart">16dp</item>
+        <item name="android:paddingEnd">16dp</item>
+        <item name="android:background">?attr/listChoiceBackgroundIndicator</item>
+    </style>
 </resources>
diff --git a/weblayer/browser/java/weblayer_strings.grd b/weblayer/browser/java/weblayer_strings.grd
index 188affe..79a4dcdd 100644
--- a/weblayer/browser/java/weblayer_strings.grd
+++ b/weblayer/browser/java/weblayer_strings.grd
@@ -178,6 +178,28 @@
       <message name="IDS_WEBLAYER_INFOBAR_CLOSE" desc="Accessibility label for the dismiss infobar Button">
         Close
       </message>
+      <!-- TranslateInfoBar -->
+      <message name="IDS_TRANSLATE_INFOBAR_ERROR">
+        Oops. This page could not be translated.
+      </message>
+      <message name="IDS_TRANSLATE_BUTTON" desc="Possible texts to display on the translate infobar buttons. [CHAR-LIMIT=24]">
+        Translate
+      </message>
+      <message name="IDS_TRANSLATE_NEVER_TRANSLATE_SITE" desc="Text to display on the never translate site (like www.google.com) button. [CHAR-LIMIT=64]">
+        Never translate this site
+      </message>
+      <message name="IDS_TRANSLATE_OPTION_ALWAYS_TRANSLATE" desc="Option in the Chrome menu. User can click the 'Always Translate' option to indicate that they want Chrome to translate pages in this language automatically. Imperative.">
+        Always translate pages in <ph name="SOURCE_LANGUAGE">%1$s<ex>French</ex></ph>
+      </message>
+      <message name="IDS_TRANSLATE_OPTION_NEVER_TRANSLATE" desc="Option in the Chrome menu. User can click the 'Never Translate' option to indicate that they never want Chrome to translate pages in this language. The variable SOURCE_LANGUAGE could be any of 50+ languages supported by Google Translate, like French, Spanish, German, Italian, Japanese, Korean, etc. Imperative.">
+        Never translate pages in <ph name="SOURCE_LANGUAGE">%1$s<ex>French</ex></ph>
+      </message>
+      <message name="IDS_TRANSLATE_OPTION_MORE_LANGUAGE" desc="Option in the Chrome menu. Lets the user open a dialog to choose other target languages for translation, from a list of available languages. [CHAR-LIMIT=64]">
+        More languages
+      </message>
+      <message name="IDS_TRANSLATE_OPTION_NOT_SOURCE_LANGUAGE" desc="Option in the Chrome menu. Sometimes a web page's source language is not correctly identified by Google Translate, and this menu option lets the user open a submenu to select another language as the source language to translate. Phrased as a question as if to query the user, 'Is this page not in [source language identified]? If so, click here.' [CHAR-LIMIT=64]">
+        Page is not in <ph name="LANGUAGE">%1$s<ex>French</ex></ph>?
+      </message>
     </messages>
   </release>
 </grit>
diff --git a/weblayer/browser/profile_disk_operations_unittests.cc b/weblayer/browser/profile_disk_operations_unittests.cc
index dd1f381..801587d 100644
--- a/weblayer/browser/profile_disk_operations_unittests.cc
+++ b/weblayer/browser/profile_disk_operations_unittests.cc
@@ -6,11 +6,11 @@
 #include <string>
 #include <vector>
 
+#include "base/base_paths.h"
 #include "base/check.h"
 #include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/path_service.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/test/scoped_path_override.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "weblayer/browser/profile_disk_operations.h"
@@ -19,20 +19,10 @@
 namespace weblayer {
 
 class ProfileDiskOperationsTest : public testing::Test {
- public:
-  void SetUp() override {
-    CHECK(data_temp_dir_.CreateUniqueTempDir());
-    base::PathService::Override(DIR_USER_DATA, data_temp_dir_.GetPath());
-#if defined(OS_POSIX)
-    CHECK(cache_temp_dir_.CreateUniqueTempDir());
-    base::PathService::Override(base::DIR_CACHE, cache_temp_dir_.GetPath());
-#endif
-  }
-
  protected:
-  base::ScopedTempDir data_temp_dir_;
+  base::ScopedPathOverride data_dir_override_{DIR_USER_DATA};
 #if defined(OS_POSIX)
-  base::ScopedTempDir cache_temp_dir_;
+  base::ScopedPathOverride cache_dir_override_{base::DIR_CACHE};
 #endif
 };
 
diff --git a/weblayer/browser/profile_impl.cc b/weblayer/browser/profile_impl.cc
index ab25725..4b788ff1 100644
--- a/weblayer/browser/profile_impl.cc
+++ b/weblayer/browser/profile_impl.cc
@@ -33,7 +33,10 @@
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
+#include "weblayer/browser/browser_process.h"
 #include "weblayer/browser/java/jni/ProfileImpl_jni.h"
+#include "weblayer/browser/safe_browsing/safe_browsing_service.h"
+#include "weblayer/browser/user_agent.h"
 #endif
 
 #if defined(OS_POSIX)
@@ -382,6 +385,17 @@
 void ProfileImpl::EnsureBrowserContextInitialized(JNIEnv* env) {
   content::BrowserContext::GetDownloadManager(GetBrowserContext());
 }
+
+void ProfileImpl::SetBooleanSetting(JNIEnv* env,
+                                    jint j_type,
+                                    jboolean j_value) {
+  SetBooleanSetting(static_cast<SettingType>(j_type), j_value);
+}
+
+jboolean ProfileImpl::GetBooleanSetting(JNIEnv* env, jint j_type) {
+  return GetBooleanSetting(static_cast<SettingType>(j_type));
+}
+
 #endif  // OS_ANDROID
 
 void ProfileImpl::IncrementBrowserImplCount() {
@@ -397,4 +411,24 @@
   return ComputeBrowserPersisterDataBaseDir(info_);
 }
 
+void ProfileImpl::SetBooleanSetting(SettingType type, bool value) {
+  switch (type) {
+    case SettingType::BASIC_SAFE_BROWSING_ENABLED:
+      basic_safe_browsing_enabled_ = value;
+#if defined(OS_ANDROID)
+      BrowserProcess::GetInstance()
+          ->GetSafeBrowsingService(weblayer::GetUserAgent())
+          ->SetSafeBrowsingDisabled(!basic_safe_browsing_enabled_);
+#endif
+  }
+}
+
+bool ProfileImpl::GetBooleanSetting(SettingType type) {
+  switch (type) {
+    case SettingType::BASIC_SAFE_BROWSING_ENABLED:
+      return basic_safe_browsing_enabled_;
+  }
+  NOTREACHED();
+}
+
 }  // namespace weblayer
diff --git a/weblayer/browser/profile_impl.h b/weblayer/browser/profile_impl.h
index 7fe0e34..fbd30a8 100644
--- a/weblayer/browser/profile_impl.h
+++ b/weblayer/browser/profile_impl.h
@@ -65,6 +65,8 @@
   void SetDownloadDirectory(const base::FilePath& directory) override;
   void SetDownloadDelegate(DownloadDelegate* delegate) override;
   CookieManager* GetCookieManager() override;
+  void SetBooleanSetting(SettingType type, bool value) override;
+  bool GetBooleanSetting(SettingType type) override;
 
 #if defined(OS_ANDROID)
   ProfileImpl(JNIEnv* env,
@@ -87,6 +89,8 @@
       const base::android::JavaParamRef<jstring>& directory);
   jlong GetCookieManager(JNIEnv* env);
   void EnsureBrowserContextInitialized(JNIEnv* env);
+  void SetBooleanSetting(JNIEnv* env, jint j_type, jboolean j_value);
+  jboolean GetBooleanSetting(JNIEnv* env, jint j_type);
 #endif
 
   void IncrementBrowserImplCount();
@@ -125,6 +129,8 @@
 
   size_t num_browser_impl_ = 0u;
 
+  bool basic_safe_browsing_enabled_ = true;
+
 #if defined(OS_ANDROID)
   base::android::ScopedJavaGlobalRef<jobject> java_profile_;
 #endif
diff --git a/weblayer/browser/safe_browsing/safe_browsing_service.cc b/weblayer/browser/safe_browsing/safe_browsing_service.cc
index ab372e9..1a40b07 100644
--- a/weblayer/browser/safe_browsing/safe_browsing_service.cc
+++ b/weblayer/browser/safe_browsing/safe_browsing_service.cc
@@ -62,7 +62,7 @@
 }  // namespace
 
 SafeBrowsingService::SafeBrowsingService(const std::string& user_agent)
-    : user_agent_(user_agent) {}
+    : user_agent_(user_agent), safe_browsing_disabled_(false) {}
 
 SafeBrowsingService::~SafeBrowsingService() = default;
 
@@ -125,7 +125,8 @@
 
   if (!safe_browsing_url_checker_delegate_) {
     safe_browsing_url_checker_delegate_ = new UrlCheckerDelegateImpl(
-        GetSafeBrowsingDBManager(), GetSafeBrowsingUIManager());
+        GetSafeBrowsingDBManager(), GetSafeBrowsingUIManager(),
+        safe_browsing_disabled_);
   }
 
   return safe_browsing_url_checker_delegate_;
@@ -217,4 +218,15 @@
   }
 }
 
+void SafeBrowsingService::SetSafeBrowsingDisabled(bool disabled) {
+  if (safe_browsing_disabled_ != disabled) {
+    safe_browsing_disabled_ = disabled;
+    // If there is no safe_browsing_url_checker_delegate_ yet the opt_out
+    // setting will be set later during its creation.
+    if (safe_browsing_url_checker_delegate_) {
+      safe_browsing_url_checker_delegate_->SetSafeBrowsingDisabled(disabled);
+    }
+  }
+}
+
 }  // namespace weblayer
diff --git a/weblayer/browser/safe_browsing/safe_browsing_service.h b/weblayer/browser/safe_browsing/safe_browsing_service.h
index f4e21f2..5401456 100644
--- a/weblayer/browser/safe_browsing/safe_browsing_service.h
+++ b/weblayer/browser/safe_browsing/safe_browsing_service.h
@@ -35,6 +35,7 @@
 }  // namespace safe_browsing
 
 namespace weblayer {
+class UrlCheckerDelegateImpl;
 
 // Class for managing safebrowsing related functionality. In particular this
 // class owns both the safebrowsing database and UI managers and provides
@@ -54,6 +55,7 @@
   void AddInterface(service_manager::BinderRegistry* registry,
                     content::RenderProcessHost* render_process_host);
   void StopDBManager();
+  void SetSafeBrowsingDisabled(bool disabled);
 
  private:
   SafeBrowsingUIManager* GetSafeBrowsingUIManager();
@@ -88,14 +90,15 @@
   scoped_refptr<network::WeakWrapperSharedURLLoaderFactory>
       shared_url_loader_factory_on_io_;
 
-  scoped_refptr<safe_browsing::UrlCheckerDelegate>
-      safe_browsing_url_checker_delegate_;
+  scoped_refptr<UrlCheckerDelegateImpl> safe_browsing_url_checker_delegate_;
 
   std::unique_ptr<safe_browsing::SafeBrowsingApiHandler>
       safe_browsing_api_handler_;
 
   std::string user_agent_;
 
+  bool safe_browsing_disabled_;
+
   DISALLOW_COPY_AND_ASSIGN(SafeBrowsingService);
 };
 
diff --git a/weblayer/browser/safe_browsing/url_checker_delegate_impl.cc b/weblayer/browser/safe_browsing/url_checker_delegate_impl.cc
index 73da805e..dd7ad564 100644
--- a/weblayer/browser/safe_browsing/url_checker_delegate_impl.cc
+++ b/weblayer/browser/safe_browsing/url_checker_delegate_impl.cc
@@ -15,9 +15,11 @@
 
 UrlCheckerDelegateImpl::UrlCheckerDelegateImpl(
     scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager,
-    scoped_refptr<SafeBrowsingUIManager> ui_manager)
+    scoped_refptr<SafeBrowsingUIManager> ui_manager,
+    bool disabled)
     : database_manager_(std::move(database_manager)),
       ui_manager_(std::move(ui_manager)),
+      safe_browsing_disabled_(disabled),
       threat_types_(safe_browsing::CreateSBThreatTypeSet(
           {safe_browsing::SB_THREAT_TYPE_URL_MALWARE,
            safe_browsing::SB_THREAT_TYPE_URL_PHISHING,
@@ -68,16 +70,17 @@
   return false;
 }
 
+void UrlCheckerDelegateImpl::SetSafeBrowsingDisabled(bool disabled) {
+  safe_browsing_disabled_ = disabled;
+}
+
 bool UrlCheckerDelegateImpl::ShouldSkipRequestCheck(
     const GURL& original_url,
     int frame_tree_node_id,
     int render_process_id,
     int render_frame_id,
     bool originated_from_service_worker) {
-  // TODO(timvolodine): this is needed when safebrowsing is not enabled.
-  // For now in the context of weblayer we consider safebrowsing as always
-  // enabled. This may change in the future.
-  return false;
+  return safe_browsing_disabled_ ? true : false;
 }
 
 void UrlCheckerDelegateImpl::NotifySuspiciousSiteDetected(
diff --git a/weblayer/browser/safe_browsing/url_checker_delegate_impl.h b/weblayer/browser/safe_browsing/url_checker_delegate_impl.h
index 55814185..d59745b 100644
--- a/weblayer/browser/safe_browsing/url_checker_delegate_impl.h
+++ b/weblayer/browser/safe_browsing/url_checker_delegate_impl.h
@@ -23,7 +23,10 @@
   UrlCheckerDelegateImpl(
       scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager>
           database_manager,
-      scoped_refptr<SafeBrowsingUIManager> ui_manager);
+      scoped_refptr<SafeBrowsingUIManager> ui_manager,
+      bool disabled);
+
+  void SetSafeBrowsingDisabled(bool disabled);
 
  private:
   ~UrlCheckerDelegateImpl() override;
@@ -58,6 +61,7 @@
 
   scoped_refptr<safe_browsing::SafeBrowsingDatabaseManager> database_manager_;
   scoped_refptr<SafeBrowsingUIManager> ui_manager_;
+  bool safe_browsing_disabled_;
   safe_browsing::SBThreatTypeSet threat_types_;
 
   DISALLOW_COPY_AND_ASSIGN(UrlCheckerDelegateImpl);
diff --git a/weblayer/browser/translate_compact_infobar.cc b/weblayer/browser/translate_compact_infobar.cc
new file mode 100644
index 0000000..45c07bf
--- /dev/null
+++ b/weblayer/browser/translate_compact_infobar.cc
@@ -0,0 +1,226 @@
+// 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.
+
+#include "weblayer/browser/translate_compact_infobar.h"
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/jni_weak_ref.h"
+#include "components/translate/core/browser/translate_infobar_delegate.h"
+#include "components/variations/variations_associated_data.h"
+#include "content/public/browser/browser_context.h"
+#include "weblayer/browser/infobar_service.h"
+#include "weblayer/browser/java/jni/TranslateCompactInfoBar_jni.h"
+#include "weblayer/browser/tab_impl.h"
+#include "weblayer/browser/translate_client_impl.h"
+#include "weblayer/browser/translate_utils.h"
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace weblayer {
+
+// Finch parameter names:
+const char kTranslateTabDefaultTextColor[] = "translate_tab_default_text_color";
+
+// TranslateInfoBar -----------------------------------------------------------
+
+TranslateCompactInfoBar::TranslateCompactInfoBar(
+    std::unique_ptr<translate::TranslateInfoBarDelegate> delegate)
+    : InfoBarAndroid(std::move(delegate)), action_flags_(FLAG_NONE) {
+  GetDelegate()->AddObserver(this);
+
+  // Flip the translate bit if auto translate is enabled.
+  if (GetDelegate()->translate_step() == translate::TRANSLATE_STEP_TRANSLATING)
+    action_flags_ |= FLAG_TRANSLATE;
+}
+
+TranslateCompactInfoBar::~TranslateCompactInfoBar() {
+  GetDelegate()->RemoveObserver(this);
+}
+
+ScopedJavaLocalRef<jobject> TranslateCompactInfoBar::CreateRenderInfoBar(
+    JNIEnv* env) {
+  translate::TranslateInfoBarDelegate* delegate = GetDelegate();
+
+  base::android::ScopedJavaLocalRef<jobjectArray> java_languages =
+      TranslateUtils::GetJavaLanguages(env, delegate);
+  base::android::ScopedJavaLocalRef<jobjectArray> java_codes =
+      TranslateUtils::GetJavaLanguageCodes(env, delegate);
+  base::android::ScopedJavaLocalRef<jintArray> java_hash_codes =
+      TranslateUtils::GetJavaLanguageHashCodes(env, delegate);
+
+  ScopedJavaLocalRef<jstring> source_language_code =
+      base::android::ConvertUTF8ToJavaString(
+          env, delegate->original_language_code());
+
+  ScopedJavaLocalRef<jstring> target_language_code =
+      base::android::ConvertUTF8ToJavaString(env,
+                                             delegate->target_language_code());
+  content::WebContents* web_contents =
+      InfoBarService::WebContentsFromInfoBar(this);
+
+  TabImpl* tab =
+      web_contents ? TabImpl::FromWebContents(web_contents) : nullptr;
+
+  return Java_TranslateCompactInfoBar_create(
+      env, tab ? tab->GetJavaTab() : nullptr, delegate->translate_step(),
+      source_language_code, target_language_code,
+      delegate->ShouldAlwaysTranslate(), delegate->triggered_from_menu(),
+      java_languages, java_codes, java_hash_codes, TabDefaultTextColor());
+}
+
+void TranslateCompactInfoBar::ProcessButton(int action) {
+  if (!owner())
+    return;  // We're closing; don't call anything, it might access the owner.
+
+  translate::TranslateInfoBarDelegate* delegate = GetDelegate();
+  if (action == InfoBarAndroid::ACTION_TRANSLATE) {
+    action_flags_ |= FLAG_TRANSLATE;
+    delegate->Translate();
+    if (delegate->ShouldAutoAlwaysTranslate()) {
+      JNIEnv* env = base::android::AttachCurrentThread();
+      Java_TranslateCompactInfoBar_setAutoAlwaysTranslate(env,
+                                                          GetJavaInfoBar());
+    }
+  } else if (action == InfoBarAndroid::ACTION_TRANSLATE_SHOW_ORIGINAL) {
+    action_flags_ |= FLAG_REVERT;
+    delegate->RevertWithoutClosingInfobar();
+  } else {
+    DCHECK_EQ(InfoBarAndroid::ACTION_NONE, action);
+  }
+}
+
+void TranslateCompactInfoBar::SetJavaInfoBar(
+    const base::android::JavaRef<jobject>& java_info_bar) {
+  InfoBarAndroid::SetJavaInfoBar(java_info_bar);
+  JNIEnv* env = base::android::AttachCurrentThread();
+  Java_TranslateCompactInfoBar_setNativePtr(env, java_info_bar,
+                                            reinterpret_cast<intptr_t>(this));
+}
+
+void TranslateCompactInfoBar::ApplyStringTranslateOption(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    int option,
+    const JavaParamRef<jstring>& value) {
+  translate::TranslateInfoBarDelegate* delegate = GetDelegate();
+  if (option == TranslateUtils::OPTION_SOURCE_CODE) {
+    std::string source_code =
+        base::android::ConvertJavaStringToUTF8(env, value);
+    if (delegate->original_language_code().compare(source_code) != 0)
+      delegate->UpdateOriginalLanguage(source_code);
+  } else if (option == TranslateUtils::OPTION_TARGET_CODE) {
+    std::string target_code =
+        base::android::ConvertJavaStringToUTF8(env, value);
+    if (delegate->target_language_code().compare(target_code) != 0)
+      delegate->UpdateTargetLanguage(target_code);
+  } else {
+    DCHECK(false);
+  }
+}
+
+void TranslateCompactInfoBar::ApplyBoolTranslateOption(
+    JNIEnv* env,
+    const JavaParamRef<jobject>& obj,
+    int option,
+    jboolean value) {
+  translate::TranslateInfoBarDelegate* delegate = GetDelegate();
+  if (option == TranslateUtils::OPTION_ALWAYS_TRANSLATE) {
+    if (delegate->ShouldAlwaysTranslate() != value) {
+      action_flags_ |= FLAG_ALWAYS_TRANSLATE;
+      delegate->ToggleAlwaysTranslate();
+    }
+  } else if (option == TranslateUtils::OPTION_NEVER_TRANSLATE) {
+    if (value && delegate->IsTranslatableLanguageByPrefs()) {
+      action_flags_ |= FLAG_NEVER_LANGUAGE;
+      delegate->ToggleTranslatableLanguageByPrefs();
+      RemoveSelf();
+    }
+  } else if (option == TranslateUtils::OPTION_NEVER_TRANSLATE_SITE) {
+    if (value && !delegate->IsSiteBlacklisted()) {
+      action_flags_ |= FLAG_NEVER_SITE;
+      delegate->ToggleSiteBlacklist();
+      RemoveSelf();
+    }
+  } else {
+    DCHECK(false);
+  }
+}
+
+jboolean TranslateCompactInfoBar::ShouldAutoNeverTranslate(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj,
+    jboolean menu_expanded) {
+  // Flip menu expanded bit.
+  if (menu_expanded)
+    action_flags_ |= FLAG_EXPAND_MENU;
+
+  if (!IsDeclinedByUser())
+    return false;
+
+  return GetDelegate()->ShouldAutoNeverTranslate();
+}
+
+// Returns true if the current tab is an incognito tab.
+jboolean TranslateCompactInfoBar::IsIncognito(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj) {
+  content::WebContents* web_contents =
+      InfoBarService::WebContentsFromInfoBar(this);
+  if (!web_contents)
+    return false;
+  return web_contents->GetBrowserContext()->IsOffTheRecord();
+}
+
+int TranslateCompactInfoBar::GetParam(const std::string& paramName,
+                                      int default_value) {
+  std::map<std::string, std::string> params;
+  if (!variations::GetVariationParams(translate::kTranslateCompactUI.name,
+                                      &params))
+    return default_value;
+  int value = 0;
+  base::StringToInt(params[paramName], &value);
+  return value <= 0 ? default_value : value;
+}
+
+int TranslateCompactInfoBar::TabDefaultTextColor() {
+  return GetParam(kTranslateTabDefaultTextColor, 0);
+}
+
+translate::TranslateInfoBarDelegate* TranslateCompactInfoBar::GetDelegate() {
+  return delegate()->AsTranslateInfoBarDelegate();
+}
+
+void TranslateCompactInfoBar::OnTranslateStepChanged(
+    translate::TranslateStep step,
+    translate::TranslateErrors::Type error_type) {
+  if (!owner())
+    return;  // We're closing; don't call anything.
+
+  if ((step == translate::TRANSLATE_STEP_AFTER_TRANSLATE) ||
+      (step == translate::TRANSLATE_STEP_TRANSLATE_ERROR)) {
+    JNIEnv* env = base::android::AttachCurrentThread();
+    Java_TranslateCompactInfoBar_onPageTranslated(env, GetJavaInfoBar(),
+                                                  error_type);
+  }
+}
+
+bool TranslateCompactInfoBar::IsDeclinedByUser() {
+  // Whether there is any affirmative action bit.
+  return action_flags_ == FLAG_NONE;
+}
+
+void TranslateCompactInfoBar::OnTranslateInfoBarDelegateDestroyed(
+    translate::TranslateInfoBarDelegate* delegate) {
+  DCHECK_EQ(GetDelegate(), delegate);
+  GetDelegate()->RemoveObserver(this);
+}
+
+}  // namespace weblayer
diff --git a/weblayer/browser/translate_compact_infobar.h b/weblayer/browser/translate_compact_infobar.h
new file mode 100644
index 0000000..7acd633
--- /dev/null
+++ b/weblayer/browser/translate_compact_infobar.h
@@ -0,0 +1,100 @@
+// 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 WEBLAYER_BROWSER_TRANSLATE_COMPACT_INFOBAR_H_
+#define WEBLAYER_BROWSER_TRANSLATE_COMPACT_INFOBAR_H_
+
+#include "base/android/scoped_java_ref.h"
+#include "base/macros.h"
+#include "components/translate/core/browser/translate_infobar_delegate.h"
+#include "components/translate/core/browser/translate_step.h"
+#include "components/translate/core/common/translate_errors.h"
+#include "weblayer/browser/infobar_android.h"
+
+namespace translate {
+class TranslateInfoBarDelegate;
+}
+
+namespace weblayer {
+
+class TranslateCompactInfoBar
+    : public InfoBarAndroid,
+      public translate::TranslateInfoBarDelegate::Observer {
+ public:
+  explicit TranslateCompactInfoBar(
+      std::unique_ptr<translate::TranslateInfoBarDelegate> delegate);
+  ~TranslateCompactInfoBar() override;
+
+  // JNI method specific to string settings in translate.
+  void ApplyStringTranslateOption(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      int option,
+      const base::android::JavaParamRef<jstring>& value);
+
+  // JNI method specific to boolean settings in translate.
+  void ApplyBoolTranslateOption(JNIEnv* env,
+                                const base::android::JavaParamRef<jobject>& obj,
+                                int option,
+                                jboolean value);
+
+  // Check whether we should automatically trigger "Never Translate Language".
+  jboolean ShouldAutoNeverTranslate(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jboolean menu_expanded);
+
+  // Returns true if the current tab is an incognito tab.
+  jboolean IsIncognito(JNIEnv* env,
+                       const base::android::JavaParamRef<jobject>& obj);
+
+  // TranslateInfoBarDelegate::Observer implementation.
+  void OnTranslateStepChanged(
+      translate::TranslateStep step,
+      translate::TranslateErrors::Type error_type) override;
+  // Returns true if the user didn't take any affirmative action.
+  // The function will be called when the translate infobar is dismissed.
+  // If it's true, we will record a declined event.
+  bool IsDeclinedByUser() override;
+  void OnTranslateInfoBarDelegateDestroyed(
+      translate::TranslateInfoBarDelegate* delegate) override;
+
+ private:
+  // InfoBarAndroid:
+  base::android::ScopedJavaLocalRef<jobject> CreateRenderInfoBar(
+      JNIEnv* env) override;
+  void ProcessButton(int action) override;
+  void SetJavaInfoBar(
+      const base::android::JavaRef<jobject>& java_info_bar) override;
+
+  // Get the value of a specified finch parameter in TranslateCompactUI.  If the
+  // finch parameter does not exist, default_value will be returned.
+  int GetParam(const std::string& paramName, int default_value);
+  // Get the value of the finch parameter: translate_tab_default_text_color.
+  // Default value is 0, which means using TabLayout default color.
+  // If it's not 0, we will set the text color manually based on the value.
+  int TabDefaultTextColor();
+
+  translate::TranslateInfoBarDelegate* GetDelegate();
+
+  // Bits for trace user's affirmative actions.
+  unsigned int action_flags_;
+
+  // Affirmative action flags to record what the user has done in one session.
+  enum ActionFlag {
+    FLAG_NONE = 0,
+    FLAG_TRANSLATE = 1 << 0,
+    FLAG_REVERT = 1 << 1,
+    FLAG_ALWAYS_TRANSLATE = 1 << 2,
+    FLAG_NEVER_LANGUAGE = 1 << 3,
+    FLAG_NEVER_SITE = 1 << 4,
+    FLAG_EXPAND_MENU = 1 << 5,
+  };
+
+  DISALLOW_COPY_AND_ASSIGN(TranslateCompactInfoBar);
+};
+
+}  // namespace weblayer
+
+#endif  // WEBLAYER_BROWSER_TRANSLATE_COMPACT_INFOBAR_H_
diff --git a/weblayer/browser/translate_utils.cc b/weblayer/browser/translate_utils.cc
new file mode 100644
index 0000000..aac744a
--- /dev/null
+++ b/weblayer/browser/translate_utils.cc
@@ -0,0 +1,54 @@
+// 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.
+
+#include "weblayer/browser/translate_utils.h"
+
+#include <stddef.h>
+
+#include "base/android/jni_array.h"
+#include "base/android/jni_string.h"
+#include "base/android/jni_weak_ref.h"
+#include "components/metrics/metrics_log.h"
+#include "components/translate/core/browser/translate_infobar_delegate.h"
+
+using base::android::JavaParamRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace weblayer {
+
+ScopedJavaLocalRef<jobjectArray> TranslateUtils::GetJavaLanguages(
+    JNIEnv* env,
+    translate::TranslateInfoBarDelegate* delegate) {
+  std::vector<base::string16> languages;
+  languages.reserve(delegate->num_languages());
+  for (size_t i = 0; i < delegate->num_languages(); ++i) {
+    languages.push_back(delegate->language_name_at(i));
+  }
+  return base::android::ToJavaArrayOfStrings(env, languages);
+}
+
+ScopedJavaLocalRef<jobjectArray> TranslateUtils::GetJavaLanguageCodes(
+    JNIEnv* env,
+    translate::TranslateInfoBarDelegate* delegate) {
+  std::vector<std::string> codes;
+  codes.reserve(delegate->num_languages());
+  for (size_t i = 0; i < delegate->num_languages(); ++i) {
+    codes.push_back(delegate->language_code_at(i));
+  }
+  return base::android::ToJavaArrayOfStrings(env, codes);
+}
+
+ScopedJavaLocalRef<jintArray> TranslateUtils::GetJavaLanguageHashCodes(
+    JNIEnv* env,
+    translate::TranslateInfoBarDelegate* delegate) {
+  std::vector<int> hashCodes;
+  hashCodes.reserve(delegate->num_languages());
+  for (size_t i = 0; i < delegate->num_languages(); ++i) {
+    hashCodes.push_back(
+        metrics::MetricsLog::Hash(delegate->language_code_at(i)));
+  }
+  return base::android::ToJavaIntArray(env, hashCodes);
+}
+
+}  // namespace weblayer
diff --git a/weblayer/browser/translate_utils.h b/weblayer/browser/translate_utils.h
new file mode 100644
index 0000000..9bee56b
--- /dev/null
+++ b/weblayer/browser/translate_utils.h
@@ -0,0 +1,43 @@
+// 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 WEBLAYER_BROWSER_TRANSLATE_UTILS_H_
+#define WEBLAYER_BROWSER_TRANSLATE_UTILS_H_
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+
+namespace translate {
+class TranslateInfoBarDelegate;
+}
+
+namespace weblayer {
+
+class TranslateUtils {
+ public:
+  // A Java counterpart will be generated for this enum.
+  // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.weblayer_private
+  // GENERATED_JAVA_PREFIX_TO_STRIP:OPTION_
+  enum TranslateOption {
+    OPTION_SOURCE_CODE,
+    OPTION_TARGET_CODE,
+    OPTION_ALWAYS_TRANSLATE,
+    OPTION_NEVER_TRANSLATE,
+    OPTION_NEVER_TRANSLATE_SITE
+  };
+
+  static base::android::ScopedJavaLocalRef<jobjectArray> GetJavaLanguages(
+      JNIEnv* env,
+      translate::TranslateInfoBarDelegate* delegate);
+  static base::android::ScopedJavaLocalRef<jobjectArray> GetJavaLanguageCodes(
+      JNIEnv* env,
+      translate::TranslateInfoBarDelegate* delegate);
+  static base::android::ScopedJavaLocalRef<jintArray> GetJavaLanguageHashCodes(
+      JNIEnv* env,
+      translate::TranslateInfoBarDelegate* delegate);
+};
+
+}  // namespace weblayer
+
+#endif  // WEBLAYER_BROWSER_TRANSLATE_UTILS_H_
diff --git a/weblayer/public/java/BUILD.gn b/weblayer/public/java/BUILD.gn
index fdffd280..de73b7f 100644
--- a/weblayer/public/java/BUILD.gn
+++ b/weblayer/public/java/BUILD.gn
@@ -68,6 +68,7 @@
     "org/chromium/weblayer/ObserverList.java",
     "org/chromium/weblayer/Profile.java",
     "org/chromium/weblayer/RemoteFragment.java",
+    "org/chromium/weblayer/SettingType.java",
     "org/chromium/weblayer/SiteSettingsActivity.java",
     "org/chromium/weblayer/SiteSettingsFragment.java",
     "org/chromium/weblayer/Tab.java",
diff --git a/weblayer/public/java/org/chromium/weblayer/Profile.java b/weblayer/public/java/org/chromium/weblayer/Profile.java
index fc490c1d..9ed8ce8 100644
--- a/weblayer/public/java/org/chromium/weblayer/Profile.java
+++ b/weblayer/public/java/org/chromium/weblayer/Profile.java
@@ -213,6 +213,37 @@
         return mCookieManager;
     }
 
+    /**
+     * Allows the embedder to set a boolean value for a specific setting, see {@link SettingType}
+     * for more details and the possible options.
+     *
+     * @param type See {@link SettingType}.
+     * @param value The value to set for the setting.
+     *
+     * @since 84
+     */
+    public void setBooleanSetting(@SettingType int type, boolean value) {
+        try {
+            mImpl.setBooleanSetting(type, value);
+        } catch (RemoteException e) {
+            throw new APICallException(e);
+        }
+    }
+
+    /**
+     * Returns the current value for the given setting type, see {@link SettingType} for more
+     * details and the possible options.
+     *
+     * @since 84
+     */
+    public boolean getBooleanSetting(@SettingType int type) {
+        try {
+            return mImpl.getBooleanSetting(type);
+        } catch (RemoteException e) {
+            throw new APICallException(e);
+        }
+    }
+
     static final class DownloadCallbackClientImpl extends IDownloadCallbackClient.Stub {
         private final DownloadCallback mCallback;
 
diff --git a/weblayer/public/java/org/chromium/weblayer/SettingType.java b/weblayer/public/java/org/chromium/weblayer/SettingType.java
new file mode 100644
index 0000000..c5e800e
--- /dev/null
+++ b/weblayer/public/java/org/chromium/weblayer/SettingType.java
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.weblayer;
+
+import androidx.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * @hide
+ */
+@IntDef({SettingType.BASIC_SAFE_BROWSING_ENABLED})
+@Retention(RetentionPolicy.SOURCE)
+public @interface SettingType {
+    /**
+     * Allows the embedder to set whether it wants to disable/enable the Safe Browsing functionality
+     * (which checks that the loaded URLs are safe). Safe Browsing is enabled by default.
+     */
+    int BASIC_SAFE_BROWSING_ENABLED =
+            org.chromium.weblayer_private.interfaces.SettingType.BASIC_SAFE_BROWSING_ENABLED;
+}
diff --git a/weblayer/public/java/org/chromium/weblayer/WebLayer.java b/weblayer/public/java/org/chromium/weblayer/WebLayer.java
index 8fd16b0..157ac12b 100644
--- a/weblayer/public/java/org/chromium/weblayer/WebLayer.java
+++ b/weblayer/public/java/org/chromium/weblayer/WebLayer.java
@@ -32,6 +32,7 @@
 import org.chromium.weblayer_private.interfaces.IWebLayerFactory;
 import org.chromium.weblayer_private.interfaces.ObjectWrapper;
 import org.chromium.weblayer_private.interfaces.StrictModeWorkaround;
+import org.chromium.weblayer_private.interfaces.WebLayerVersionConstants;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
@@ -278,6 +279,12 @@
                 available = mFactory.isClientSupported();
                 majorVersion = mFactory.getImplementationMajorVersion();
                 version = mFactory.getImplementationVersion();
+                // See comment in WebLayerFactoryImpl.isClientSupported() for details on this.
+                if (available
+                        && WebLayerClientVersionConstants.PRODUCT_MAJOR_VERSION > majorVersion) {
+                    available = WebLayerClientVersionConstants.PRODUCT_MAJOR_VERSION - majorVersion
+                            <= WebLayerVersionConstants.MAX_SKEW;
+                }
             } catch (Exception e) {
                 Log.e(TAG, "Unable to create WebLayerFactory", e);
             }
diff --git a/weblayer/public/profile.h b/weblayer/public/profile.h
index f482203..f878ed67 100644
--- a/weblayer/public/profile.h
+++ b/weblayer/public/profile.h
@@ -23,6 +23,10 @@
   CACHE = 1,
 };
 
+enum class SettingType {
+  BASIC_SAFE_BROWSING_ENABLED = 0,
+};
+
 class Profile {
  public:
   // Pass an empty |name| for an in-memory profile.
@@ -56,6 +60,12 @@
 
   // Gets the cookie manager for this profile.
   virtual CookieManager* GetCookieManager() = 0;
+
+  // Set the boolean value of the given setting type.
+  virtual void SetBooleanSetting(SettingType type, bool value) = 0;
+
+  // Get the boolean value of the given setting type.
+  virtual bool GetBooleanSetting(SettingType type) = 0;
 };
 
 }  // namespace weblayer
diff --git a/weblayer/shell/browser/shell_views.cc b/weblayer/shell/browser/shell_views.cc
index 5c88a7679..b742632 100644
--- a/weblayer/shell/browser/shell_views.cc
+++ b/weblayer/shell/browser/shell_views.cc
@@ -55,6 +55,7 @@
   enum UIControl { BACK_BUTTON, FORWARD_BUTTON, STOP_BUTTON };
 
   explicit ShellWindowDelegateView(Shell* shell) : shell_(shell) {
+    SetHasWindowSizeControls(true);
     InitShellWindow();
   }
 
@@ -243,9 +244,6 @@
   }
 
   // Overridden from WidgetDelegateView
-  bool CanResize() const override { return true; }
-  bool CanMaximize() const override { return true; }
-  bool CanMinimize() const override { return true; }
   base::string16 GetWindowTitle() const override { return title_; }
 
   // Overridden from View
diff --git a/weblayer/test/BUILD.gn b/weblayer/test/BUILD.gn
index 26a1baa..8dbe7bb5 100644
--- a/weblayer/test/BUILD.gn
+++ b/weblayer/test/BUILD.gn
@@ -210,5 +210,8 @@
     ":run_all_unittests",
     "//weblayer:weblayer_lib_base",
   ]
+  if (is_android) {
+    deps += [ ":weblayer_test_assets" ]
+  }
   sources = [ "../browser/profile_disk_operations_unittests.cc" ]
 }